# Weskit [![Build Status](https://secure.travis-ci.org/f6p/weskit.png?branch=master)](http://travis-ci.org/f6p/weskit) Weskit gem consists of tools for interaction with Wesnoth Markup Langage and Wesnoth infrastructure. Amog this tools Ruby classes representing WML objects and WML parser are most important as understanding them is the key to understaning any other stuff bundled. This README gives quick albeit incomplete overview of Weskit WML capabilities. For more information you have to check source code and [generated documentation](http://www.rubydoc.info/github/f6p/weskit/frames). ## Containers Elements in WML document dosn't have one parent. Instead of using arrays to store multiple WML objects create instance of Weskit::WML::Root. It will let you to call advanced features avaiable for other WML objects (like formatting, modification or searching for nodes) and it is enumerable as well. ```ruby require 'weskit' include Weskit::WML root = Root.new ``` While root object can store any type of WML item there are also containers for specific item types, for example to store attributes you want to use instance of Weskit::WML::Attributes. All WML containers include Weskit::WML::Mixins::Container module and some of them are subclasses of Weskit::WML::Items. ## Altering objects While you can push instances of WML objects to elements or containers and change identifiers or values manually there is a better way of doing that. Each container has build method that comes in handy. For example: ```ruby root.build do side { id 1 name 'First Side', :translatable => true unit { name :John } } end ``` becomes: ``` [side] id=1 name=_"First Side" [unit] name=John [/unit] [/side] ``` Basically Builder takes advantage of method_missing and creates attributes or elements depending of method call parameters. If there is no block suppiled new attribute is created otherwise new element is added and contents of the block are evaluated in its context. Some of the calls may interfere with existing methods of Ruby objects and to solve that issue Builder provides attribute and element methods. In such case instead of calling: ```ruby object_id 1 object_id { name 'foo' } ``` you can do this: ```ruby attribute(:object_id, 1) element(:object_id) {} ``` id is a helper method (as it interfers with Object#id) that is equivalent to: ```ruby attribute(:id, value) ``` And oh well... Let's not forget that after all builder block is Ruby code so you can use any langague construct inside it as well. ## Tree searching You can search WML elements and containers for nodes of specific type. For example lets say there is a object tree representing such WML structure: ``` [a] [b] [c] name=foo [/c] [/b] [b] name=bar [c] [/c] [/b] [/a] ``` To get Weskit::WML::Elements container with references to all b elements you can do this: ```ruby root.a.b ``` This code takes advantage of method_missing as well and if you can't use it that (because of method name conflicts) its equivalent can be used: ```ruby root.find(:a).find(:b) ``` as missing calls are delegated to find method. There is also find_recursively method that lets you to find elements using object criteria specified in block. ## Representation Weskit::WML objects dosn't have any representation code coupled. Special class of objects called Formatters is used to handle their display. Most commonly you will use plain text representation (default formatter) or terminal friendly colorful version of it (color formatter). Most of WML objects provide formatter seter to replace formatter associated with them but you can as well change default formatter globally by calling Formatter.default= method. Whatever representation you need (JSON, XML, YAML) creating new formaters shouldn't be hard. Take look at Weskit::WML::Formatters module for further reference on that matter. ## Parser Parser provides two methods: string - for parsing strings and uri - for parsing files. uri method can load remote files as well as it transparently handles archive extraction. Parsing results in return of WML object tree with one Weskit::WML::Root as the top-most element. ## Limitations Lack of preprocessor support as WML module is supposed to work with preprocessed files (at least for now). Preprocessor directives will be consumed as comments and that can lead to unexpected behaviour at times. For example if you have macro defined its contents will be added to parent element. ## TODO Implement preprocessor directives as first class memebers that could be manipulated like any other WML node.