weskit 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. data/.gitignore +4 -3
  2. data/.rspec +1 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +2 -2
  5. data/LICENSE +339 -0
  6. data/README.md +135 -0
  7. data/Rakefile +4 -0
  8. data/lib/weskit/mp/adapter.rb +81 -0
  9. data/lib/weskit/mp/connection.rb +74 -0
  10. data/lib/weskit/mp/errors/error.rb +3 -0
  11. data/lib/weskit/mp/errors/response_error.rb +3 -0
  12. data/lib/weskit/mp/worker.rb +35 -0
  13. data/lib/weskit/mp.rb +13 -0
  14. data/lib/weskit/version.rb +1 -1
  15. data/lib/weskit/wml/attribute.rb +65 -0
  16. data/lib/weskit/wml/attributes.rb +16 -0
  17. data/lib/weskit/wml/builder.rb +66 -0
  18. data/lib/weskit/wml/element.rb +34 -0
  19. data/lib/weskit/wml/elements.rb +27 -0
  20. data/lib/weskit/wml/errors/error.rb +3 -0
  21. data/lib/weskit/wml/errors/invalid_identifier.rb +3 -0
  22. data/lib/weskit/wml/errors/invalid_item.rb +3 -0
  23. data/lib/weskit/wml/errors/invalid_option.rb +3 -0
  24. data/lib/weskit/wml/errors/invalid_parameters.rb +3 -0
  25. data/lib/weskit/wml/errors/parse_error.rb +3 -0
  26. data/lib/weskit/wml/errors/read_error.rb +3 -0
  27. data/lib/weskit/wml/extensions/object.rb +19 -0
  28. data/lib/weskit/wml/formatter.rb +82 -0
  29. data/lib/weskit/wml/formatters/ansi_color.rb +49 -0
  30. data/lib/weskit/wml/formatters/ansi_color_attribute.rb +31 -0
  31. data/lib/weskit/wml/formatters/ansi_color_element.rb +22 -0
  32. data/lib/weskit/wml/formatters/attribute.rb +62 -0
  33. data/lib/weskit/wml/formatters/element.rb +44 -0
  34. data/lib/weskit/wml/formatters/item_formatter.rb +17 -0
  35. data/lib/weskit/wml/grammars/wml.treetop +195 -0
  36. data/lib/weskit/wml/item.rb +89 -0
  37. data/lib/weskit/wml/items.rb +29 -0
  38. data/lib/weskit/wml/mixins/container.rb +96 -0
  39. data/lib/weskit/wml/mixins/grammar.rb +17 -0
  40. data/lib/weskit/wml/mixins/searchable.rb +43 -0
  41. data/lib/weskit/wml/mixins/validator.rb +29 -0
  42. data/lib/weskit/wml/parser.rb +47 -0
  43. data/lib/weskit/wml/root.rb +17 -0
  44. data/lib/weskit/wml/wml.rb +1580 -0
  45. data/lib/weskit/wml.rb +12 -6
  46. data/lib/weskit.rb +2 -2
  47. data/spec/spec_helper.rb +1 -0
  48. data/spec/wml/attribute_spec.rb +51 -0
  49. data/spec/wml/attributes_spec.rb +19 -0
  50. data/spec/wml/builder_spec.rb +52 -0
  51. data/spec/wml/element_spec.rb +20 -0
  52. data/spec/wml/elements_spec.rb +25 -0
  53. data/spec/wml/formatter_spec.rb +42 -0
  54. data/spec/wml/item_spec.rb +25 -0
  55. data/spec/wml/items_spec.rb +15 -0
  56. data/spec/wml/parser_spec.rb +60 -0
  57. data/spec/wml/root_spec.rb +15 -0
  58. data/spec/wml_helpers.rb +40 -0
  59. data/spec/wml_matchers.rb +17 -0
  60. data/spec/wml_shared_examples.rb +68 -0
  61. data/spec/wml_spec_helper.rb +5 -0
  62. data/weskit.gemspec +8 -5
  63. metadata +192 -50
  64. data/README +0 -2
  65. data/lib/weskit/lobby/bot.rb +0 -85
  66. data/lib/weskit/lobby/bot_error.rb +0 -3
  67. data/lib/weskit/lobby.rb +0 -11
  68. data/lib/weskit/wml/node.rb +0 -76
  69. data/lib/weskit/wml/node_array.rb +0 -25
  70. data/lib/weskit/wml/node_error.rb +0 -3
  71. data/lib/weskit/wml/reader.rb +0 -67
  72. data/lib/weskit/wml/reader_error.rb +0 -3
  73. data/lib/weskit/wml/string_extensions.rb +0 -59
@@ -0,0 +1,195 @@
1
+ require 'treetop'
2
+ require 'weskit/wml'
3
+
4
+ grammar WesnothMarkupLanguage
5
+ rule document
6
+ contents {
7
+ def wml
8
+ ::Weskit::WML::Root.new.push *::Weskit::WML::Mixins::Grammar.reject_non_wml(elements)
9
+ end
10
+ }
11
+ end
12
+
13
+ # parts -------------------------------------------------------------------------------
14
+
15
+ rule identifier
16
+ [a-z] [a-z_]* {
17
+ def name
18
+ text_value
19
+ end
20
+ }
21
+ end
22
+
23
+ rule raw_string
24
+ (!eol .)* {
25
+ def data
26
+ text_value
27
+ end
28
+ }
29
+ end
30
+
31
+ rule code_content
32
+ (!'>>' content)* {
33
+ def contents
34
+ text_value
35
+ end
36
+ }
37
+ end
38
+
39
+ rule code_string
40
+ '<<' string:code_content '>>' {
41
+ def data
42
+ string.contents
43
+ end
44
+ }
45
+ end
46
+
47
+ rule multiline_content
48
+ (!quote content)* {
49
+ def contents
50
+ text_value
51
+ end
52
+ }
53
+ end
54
+
55
+ rule multiline_string
56
+ (quote string:multiline_content quote)* {
57
+ def data
58
+ elements.collect(&:string).collect(&:contents).join '"'
59
+ end
60
+ }
61
+ end
62
+
63
+ rule translatable_string
64
+ '_' lws string:multiline_string {
65
+ def data
66
+ string.contents
67
+ end
68
+ }
69
+ end
70
+
71
+ rule opening_tag
72
+ lws '[' tag:identifier ']' fws {
73
+ def name
74
+ tag.name
75
+ end
76
+ }
77
+ end
78
+
79
+ rule amending_tag
80
+ lws '[+' tag:identifier ']' fws {
81
+ def name
82
+ tag.name
83
+ end
84
+ }
85
+ end
86
+
87
+ rule closing_tag
88
+ lws '[/' tag:identifier ']' fws {
89
+ def name
90
+ tag.name
91
+ end
92
+ }
93
+ end
94
+
95
+ rule blank_line
96
+ ws* "\n"
97
+ end
98
+
99
+ rule item
100
+ code_attribute / multiline_attribute / translatable_attribute / attribute / amending_element / element
101
+ end
102
+
103
+ rule contents
104
+ (blank_line / item)* {
105
+ def items
106
+ ::Weskit::WML::Mixins::Grammar.reject_non_wml elements
107
+ end
108
+ }
109
+ end
110
+
111
+ # items -------------------------------------------------------------------------------
112
+
113
+ rule attribute
114
+ lws id:identifier lws equals value:raw_string eol {
115
+ def item
116
+ ::Weskit::WML::Attribute.new id.name, value.data
117
+ end
118
+ }
119
+ end
120
+
121
+ rule code_attribute
122
+ lws id:identifier lws equals lws value:code_string fws {
123
+ def item
124
+ ::Weskit::WML::Attribute.new id.name, value.data, :code => true
125
+ end
126
+ }
127
+ end
128
+
129
+ rule multiline_attribute
130
+ lws id:identifier lws equals lws value:multiline_string fws {
131
+ def item
132
+ ::Weskit::WML::Attribute.new id.name, value.data
133
+ end
134
+ }
135
+ end
136
+
137
+ rule translatable_attribute
138
+ lws id:identifier lws equals lws '_' lws value:multiline_string fws {
139
+ def item
140
+ ::Weskit::WML::Attribute.new id.name, value.data, :translatable => true
141
+ end
142
+ }
143
+ end
144
+
145
+ rule element
146
+ open:opening_tag nested:contents close:closing_tag {
147
+ def item
148
+ ::Weskit::WML::Mixins::Grammar.raise_on_mismatching open, close
149
+ ::Weskit::WML::Element.new(open.name).push *nested.items
150
+ end
151
+ }
152
+ end
153
+
154
+ rule amending_element
155
+ open:amending_tag nested:contents close:closing_tag {
156
+ def item
157
+ ::Weskit::WML::Mixins::Grammar.raise_on_mismatching open, close
158
+ ::Weskit::WML::Element.new(open.name, :amendment => true).push *nested.items
159
+ end
160
+ }
161
+ end
162
+
163
+ # helpers -----------------------------------------------------------------------------
164
+
165
+ rule content
166
+ "\n" / .
167
+ end
168
+
169
+ rule eol
170
+ "\n" / !.
171
+ end
172
+
173
+ rule equals
174
+ '='
175
+ end
176
+
177
+ rule quote
178
+ '"'
179
+ end
180
+
181
+ # whitespace
182
+ rule ws
183
+ "\s" / "\t"
184
+ end
185
+
186
+ # leading whitespaces
187
+ rule lws
188
+ ws*
189
+ end
190
+
191
+ # following whitespaces
192
+ rule fws
193
+ ws* eol
194
+ end
195
+ end
@@ -0,0 +1,89 @@
1
+ module Weskit::WML
2
+ class Item
3
+ include Comparable, Mixins::Validator
4
+
5
+ attr_reader :name
6
+
7
+ def <=> other
8
+ case other
9
+ when self.class then "#{name}" <=> "#{other.name}"
10
+ when Item then "#{self.class}" <=> "#{other.class}"
11
+ else nil
12
+ end
13
+ end
14
+
15
+ def formatter= item
16
+ raise_unless Formatter, item
17
+ @formatter = item
18
+ end
19
+
20
+ def initialize name, defaults = {}
21
+ self.name = name
22
+ merge defaults
23
+ end
24
+
25
+ def merge options = {}
26
+ raise_unless Hash, options
27
+
28
+ options.each do |option, value|
29
+ raise_if_missing self, option
30
+ send "#{option}=", value
31
+ end
32
+
33
+ self
34
+ end
35
+
36
+ def name= name
37
+ raise_if_invalid name
38
+ @name = Item.identifier name
39
+ end
40
+
41
+ def to_s
42
+ formatter.format_detached self
43
+ end
44
+
45
+ alias_method :to_str, :to_s
46
+
47
+ class << self
48
+ def identifier name
49
+ "#{name}".to_sym
50
+ end
51
+
52
+ private
53
+
54
+ def attachable_to name
55
+ class_eval <<-code
56
+ attr_reader :#{name}
57
+
58
+ def #{name}= item
59
+ raise_unless Element, item
60
+ @#{name} = item
61
+ end
62
+
63
+ def #{name}?
64
+ !!#{name}
65
+ end
66
+
67
+ alias_method :attach_to, :#{name}=
68
+
69
+ def detach
70
+ if #{name}?
71
+ @#{name}.delete self
72
+ @#{name} = nil
73
+ end
74
+ self
75
+ end
76
+
77
+ def distance
78
+ #{name} ? #{name}.distance + 1 : 0
79
+ end
80
+
81
+ def formatter
82
+ current_formatter = @formatter || Formatter.default
83
+ #{name} ? #{name}.formatter : current_formatter
84
+ end
85
+ code
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,29 @@
1
+ module Weskit::WML
2
+ class Items
3
+ include Enumerable, Mixins::Container, Mixins::Validator
4
+
5
+ attr_reader :contents
6
+
7
+ def formatter
8
+ @formatter or Formatter.default
9
+ end
10
+
11
+ def formatter= item
12
+ raise_unless Formatter, item
13
+ @formatter = item
14
+ end
15
+
16
+ def initialize *items
17
+ @contents = []
18
+ push *items
19
+ end
20
+
21
+ def to_s
22
+ @contents.collect do |item|
23
+ formatter.format_detached item, formatter
24
+ end.join formatter.separator
25
+ end
26
+
27
+ alias_method :to_str, :to_s
28
+ end
29
+ end
@@ -0,0 +1,96 @@
1
+ require 'forwardable'
2
+
3
+ module Weskit::WML::Mixins
4
+ module Container
5
+ extend Forwardable
6
+ include ::Weskit::WML::Mixins::Validator
7
+
8
+ def_delegators :contents, :each, :empty?, :first, :last, :size, :to_a
9
+
10
+ def [] key
11
+ case key
12
+ when Integer then elements[key]
13
+ else attributes[key] rescue nil
14
+ end
15
+ end
16
+
17
+ def << item
18
+ raise_unless ::Weskit::WML::Item, item
19
+ add item
20
+ self
21
+ end
22
+
23
+ def attributes
24
+ ::Weskit::WML::Attributes.new *(select_type_of ::Weskit::WML::Attribute)
25
+ end
26
+
27
+ alias_method :attrs, :attributes
28
+
29
+ def build &contents
30
+ push *(::Weskit::WML::Builder.build &contents)
31
+ end
32
+
33
+ def delete item
34
+ contents.delete_if {|i| i.equal? item}
35
+ end
36
+
37
+ def elements
38
+ ::Weskit::WML::Elements.new *(select_type_of ::Weskit::WML::Element)
39
+ end
40
+
41
+ alias_method :elems, :elements
42
+
43
+ def exists? item
44
+ contents.any? {|i| i.equal? item}
45
+ end
46
+
47
+ def push *items
48
+ items.each {|i| self << i}
49
+ self
50
+ end
51
+
52
+ private
53
+
54
+ def add item
55
+ return nil if exists? item
56
+
57
+ case item
58
+ when ::Weskit::WML::Attribute then append_attribute item
59
+ else contents << item
60
+ end
61
+
62
+ item
63
+ end
64
+
65
+ def append item
66
+ raise_unless ::Weskit::WML::Element, item
67
+ find(item.name, false).last.push(*item.contents) rescue nil
68
+ end
69
+
70
+ def append_attribute item
71
+ raise_unless ::Weskit::WML::Attribute, item
72
+ index = attribute_index item
73
+ index ? contents[index] = item : contents << item
74
+ end
75
+
76
+ def attribute name
77
+ name = ::Weskit::WML::Item.identifier name
78
+ contents.detect do |item|
79
+ item.is_a? ::Weskit::WML::Attribute and item.name == name
80
+ end
81
+ end
82
+
83
+ def attribute_index item
84
+ contents.find_index {|i| i == item}
85
+ end
86
+
87
+ def attribute_value name
88
+ found = attribute name
89
+ found ? found.value : nil
90
+ end
91
+
92
+ def select_type_of constant
93
+ contents.select {|i| i.is_a? constant}
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,17 @@
1
+ module Weskit::WML::Mixins
2
+ module Grammar
3
+ module_function
4
+
5
+ def raise_on_mismatching opening, closing
6
+ unless opening.name == closing.name
7
+ raise ::Weskit::WML::Errors::ParseError, 'Invalid element'
8
+ end
9
+ end
10
+
11
+ def reject_non_wml elements
12
+ elements.reduce(Array.new) do |array, element|
13
+ array << element.item if element.respond_to? :item ; array
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,43 @@
1
+ module Weskit::WML::Mixins
2
+ module Searchable
3
+ def find_recursively &criteria
4
+ ::Weskit::WML::Elements.new *elements_recursively.select(&criteria)
5
+ end
6
+
7
+ def elements_recursively
8
+ element_contents + element_contents.reduce(Array.new) do |r, i|
9
+ r + i.elements_recursively
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def append item
16
+ find_elements(item.name, false).last.push(*item.contents) rescue nil
17
+ end
18
+
19
+ def append? item
20
+ item.is_a? ::Weskit::WML::Element and item.amendment?
21
+ end
22
+
23
+ def base nested
24
+ nested ? nested_contents : contents
25
+ end
26
+
27
+ def element_contents
28
+ contents.select {|i| i.is_a? ::Weskit::WML::Element}
29
+ end
30
+
31
+ def find_elements name, nested = false
32
+ name = ::Weskit::WML::Item.identifier name
33
+ found = base(nested).select {|i| i.is_a? ::Weskit::WML::Element and i.name == name}
34
+ ::Weskit::WML::Elements.new *found
35
+ end
36
+
37
+ def nested_contents
38
+ contents.reduce(Array.new) do |r, i|
39
+ r + i.contents
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,29 @@
1
+ module Weskit::WML::Mixins
2
+ module Validator
3
+ module_function
4
+
5
+ def raise_unless type, item
6
+ unless item.is_a? type
7
+ raise ::Weskit::WML::Errors::InvalidItem, "Invalid #{type}"
8
+ end
9
+ end
10
+
11
+ def raise_if_invalid identifier
12
+ unless "#{identifier}".match identifier_pattern
13
+ raise ::Weskit::WML::Errors::InvalidIdentifier, "Invalid identifier"
14
+ end
15
+ end
16
+
17
+ def raise_if_missing object, method
18
+ unless object.respond_to? "#{method}="
19
+ raise ::Weskit::WML::Errors::InvalidOption, "Object doesn't have #{method}"
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def identifier_pattern
26
+ %r{^[a-z][a-z_0-9]*$}
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'polyglot'
2
+ require 'treetop'
3
+
4
+ require 'open-uri'
5
+ require 'stringio'
6
+ require 'zlib'
7
+
8
+ module Weskit::WML
9
+ class Parser
10
+ private_class_method :new
11
+
12
+ class << self
13
+ def string str
14
+ parse str
15
+ end
16
+
17
+ def uri uri
18
+ begin
19
+ str = open(uri).read
20
+ rescue
21
+ raise Errrors::ReadError, "Coldn't open URI"
22
+ ensure
23
+ str = Zlib::GzipReader.new(StringIO.new str).read rescue str
24
+ end
25
+
26
+ parse str
27
+ end
28
+
29
+ private
30
+
31
+ def parse data
32
+ parsed = parser.parse data.strip, :consume_all_input => false
33
+
34
+ unless parsed
35
+ msg = parser.failure_reason or 'Invalid data'
36
+ raise Errors::ParseError, msg
37
+ end
38
+
39
+ parsed.wml
40
+ end
41
+
42
+ def parser
43
+ @parser ||= WesnothMarkupLanguageParser.new
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module Weskit::WML
2
+ class Root < Items
3
+ include Mixins::Searchable, Mixins::Validator
4
+
5
+ def << item
6
+ raise_unless Item, item
7
+ (append? item) ? append(item) : add(item)
8
+ self
9
+ end
10
+
11
+ def find name, nested = false
12
+ find_elements name, nested
13
+ end
14
+
15
+ alias_method :method_missing, :find
16
+ end
17
+ end