bryanl-gherkin 2.11.1.1
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.
- data/.gitattributes +2 -0
- data/.mailmap +2 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +16 -0
- data/.yardopts +5 -0
- data/Gemfile +5 -0
- data/History.md +788 -0
- data/LICENSE +20 -0
- data/README.md +272 -0
- data/Rakefile +26 -0
- data/build_native_gems.sh +7 -0
- data/cucumber.yml +4 -0
- data/examples/parse_and_output_json.rb +19 -0
- data/features/.cucumber/stepdefs.json +244 -0
- data/features/escaped_pipes.feature +8 -0
- data/features/feature_parser.feature +237 -0
- data/features/json_formatter.feature +498 -0
- data/features/json_parser.feature +331 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_formatter.feature +16 -0
- data/features/step_definitions/eyeball_steps.rb +3 -0
- data/features/step_definitions/gherkin_steps.rb +29 -0
- data/features/step_definitions/json_formatter_steps.rb +30 -0
- data/features/step_definitions/json_parser_steps.rb +20 -0
- data/features/step_definitions/pretty_formatter_steps.rb +85 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +42 -0
- data/gherkin.gemspec +77 -0
- data/install_mingw_os_x.sh +7 -0
- data/js/.npmignore +1 -0
- data/js/lib/gherkin/lexer/.npmignore +0 -0
- data/lib/gherkin.rb +2 -0
- data/lib/gherkin/c_lexer.rb +17 -0
- data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
- data/lib/gherkin/formatter/argument.rb +16 -0
- data/lib/gherkin/formatter/escaping.rb +15 -0
- data/lib/gherkin/formatter/filter_formatter.rb +146 -0
- data/lib/gherkin/formatter/hashable.rb +19 -0
- data/lib/gherkin/formatter/json_formatter.rb +122 -0
- data/lib/gherkin/formatter/line_filter.rb +26 -0
- data/lib/gherkin/formatter/model.rb +281 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
- data/lib/gherkin/formatter/regexp_filter.rb +21 -0
- data/lib/gherkin/formatter/step_printer.rb +21 -0
- data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
- data/lib/gherkin/formatter/tag_filter.rb +19 -0
- data/lib/gherkin/i18n.rb +180 -0
- data/lib/gherkin/i18n.yml +613 -0
- data/lib/gherkin/js_lexer.rb +20 -0
- data/lib/gherkin/json_parser.rb +177 -0
- data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
- data/lib/gherkin/listener/event.rb +45 -0
- data/lib/gherkin/listener/formatter_listener.rb +143 -0
- data/lib/gherkin/native.rb +7 -0
- data/lib/gherkin/native/java.rb +72 -0
- data/lib/gherkin/native/null.rb +5 -0
- data/lib/gherkin/native/therubyracer.rb +39 -0
- data/lib/gherkin/parser/meta.txt +5 -0
- data/lib/gherkin/parser/parser.rb +164 -0
- data/lib/gherkin/parser/root.txt +11 -0
- data/lib/gherkin/parser/steps.txt +4 -0
- data/lib/gherkin/rb_lexer.rb +8 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rb_lexer/ar.rb +1165 -0
- data/lib/gherkin/rb_lexer/bg.rb +1377 -0
- data/lib/gherkin/rb_lexer/bm.rb +1081 -0
- data/lib/gherkin/rb_lexer/ca.rb +1305 -0
- data/lib/gherkin/rb_lexer/cs.rb +1157 -0
- data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
- data/lib/gherkin/rb_lexer/da.rb +1043 -0
- data/lib/gherkin/rb_lexer/de.rb +1151 -0
- data/lib/gherkin/rb_lexer/en.rb +1151 -0
- data/lib/gherkin/rb_lexer/en_au.rb +971 -0
- data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
- data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
- data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
- data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
- data/lib/gherkin/rb_lexer/eo.rb +990 -0
- data/lib/gherkin/rb_lexer/es.rb +1135 -0
- data/lib/gherkin/rb_lexer/et.rb +985 -0
- data/lib/gherkin/rb_lexer/fi.rb +964 -0
- data/lib/gherkin/rb_lexer/fr.rb +1223 -0
- data/lib/gherkin/rb_lexer/he.rb +1113 -0
- data/lib/gherkin/rb_lexer/hr.rb +1061 -0
- data/lib/gherkin/rb_lexer/hu.rb +1113 -0
- data/lib/gherkin/rb_lexer/id.rb +958 -0
- data/lib/gherkin/rb_lexer/is.rb +1115 -0
- data/lib/gherkin/rb_lexer/it.rb +1081 -0
- data/lib/gherkin/rb_lexer/ja.rb +1413 -0
- data/lib/gherkin/rb_lexer/ko.rb +1097 -0
- data/lib/gherkin/rb_lexer/lt.rb +1040 -0
- data/lib/gherkin/rb_lexer/lu.rb +1127 -0
- data/lib/gherkin/rb_lexer/lv.rb +1161 -0
- data/lib/gherkin/rb_lexer/nl.rb +1110 -0
- data/lib/gherkin/rb_lexer/no.rb +1055 -0
- data/lib/gherkin/rb_lexer/pl.rb +1452 -0
- data/lib/gherkin/rb_lexer/pt.rb +1425 -0
- data/lib/gherkin/rb_lexer/ro.rb +1159 -0
- data/lib/gherkin/rb_lexer/ru.rb +1749 -0
- data/lib/gherkin/rb_lexer/sk.rb +1041 -0
- data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
- data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
- data/lib/gherkin/rb_lexer/sv.rb +1065 -0
- data/lib/gherkin/rb_lexer/tr.rb +1087 -0
- data/lib/gherkin/rb_lexer/uk.rb +1641 -0
- data/lib/gherkin/rb_lexer/uz.rb +1371 -0
- data/lib/gherkin/rb_lexer/vi.rb +1193 -0
- data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
- data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
- data/lib/gherkin/rubify.rb +24 -0
- data/lib/gherkin/tag_expression.rb +62 -0
- data/ragel/lexer.c.rl.erb +454 -0
- data/ragel/lexer.java.rl.erb +219 -0
- data/ragel/lexer.js.rl.erb +227 -0
- data/ragel/lexer.rb.rl.erb +174 -0
- data/ragel/lexer_common.rl.erb +50 -0
- data/spec/gherkin/c_lexer_spec.rb +22 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +45 -0
- data/spec/gherkin/fixtures/complex.json +139 -0
- data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
- data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
- data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
- data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
- data/spec/gherkin/fixtures/i18n_no.feature +7 -0
- data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
- data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
- data/spec/gherkin/fixtures/issue_145.feature +22 -0
- data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/fixtures/with_bom.feature +3 -0
- data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
- data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
- data/spec/gherkin/formatter/model_spec.rb +28 -0
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
- data/spec/gherkin/formatter/spaces.feature +9 -0
- data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
- data/spec/gherkin/formatter/tabs.feature +9 -0
- data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
- data/spec/gherkin/i18n_spec.rb +241 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/js_lexer_spec.rb +23 -0
- data/spec/gherkin/json_parser_spec.rb +176 -0
- data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
- data/spec/gherkin/output_stream_string_io.rb +20 -0
- data/spec/gherkin/parser/parser_spec.rb +16 -0
- data/spec/gherkin/rb_lexer_spec.rb +20 -0
- data/spec/gherkin/sexp_recorder.rb +59 -0
- data/spec/gherkin/shared/bom_group.rb +20 -0
- data/spec/gherkin/shared/doc_string_group.rb +163 -0
- data/spec/gherkin/shared/lexer_group.rb +591 -0
- data/spec/gherkin/shared/row_group.rb +125 -0
- data/spec/gherkin/shared/tags_group.rb +54 -0
- data/spec/gherkin/tag_expression_spec.rb +142 -0
- data/spec/spec_helper.rb +75 -0
- data/tasks/bench.rake +184 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/compile.rake +120 -0
- data/tasks/cucumber.rake +22 -0
- data/tasks/gems.rake +31 -0
- data/tasks/ikvm.rake +124 -0
- data/tasks/ragel_task.rb +100 -0
- data/tasks/release.rake +49 -0
- data/tasks/rspec.rake +8 -0
- data/tasks/yard.rake +7 -0
- data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
- data/tasks/yard/default/layout/html/footer.erb +5 -0
- data/tasks/yard/default/layout/html/index.erb +1 -0
- data/tasks/yard/default/layout/html/layout.erb +25 -0
- data/tasks/yard/default/layout/html/logo.erb +1 -0
- data/tasks/yard/default/layout/html/setup.rb +4 -0
- metadata +473 -0
@@ -0,0 +1,244 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'gherkin/formatter/ansi_escapes'
|
3
|
+
require 'gherkin/formatter/step_printer'
|
4
|
+
require 'gherkin/formatter/argument'
|
5
|
+
require 'gherkin/formatter/escaping'
|
6
|
+
require 'gherkin/formatter/model'
|
7
|
+
require 'gherkin/native'
|
8
|
+
|
9
|
+
module Gherkin
|
10
|
+
module Formatter
|
11
|
+
class PrettyFormatter
|
12
|
+
native_impl('gherkin')
|
13
|
+
|
14
|
+
include AnsiEscapes
|
15
|
+
include Escaping
|
16
|
+
|
17
|
+
def initialize(io, monochrome, executing)
|
18
|
+
@io = io
|
19
|
+
@step_printer = StepPrinter.new
|
20
|
+
@monochrome = monochrome
|
21
|
+
@executing = executing
|
22
|
+
@background = nil
|
23
|
+
@tag_statement = nil
|
24
|
+
@steps = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def uri(uri)
|
28
|
+
@uri = uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def feature(feature)
|
32
|
+
print_comments(feature.comments, '')
|
33
|
+
print_tags(feature.tags, '')
|
34
|
+
@io.puts "#{feature.keyword}: #{feature.name}"
|
35
|
+
print_description(feature.description, ' ', false)
|
36
|
+
end
|
37
|
+
|
38
|
+
def background(background)
|
39
|
+
replay
|
40
|
+
@statement = background
|
41
|
+
end
|
42
|
+
|
43
|
+
def scenario(scenario)
|
44
|
+
replay
|
45
|
+
@statement = scenario
|
46
|
+
end
|
47
|
+
|
48
|
+
def scenario_outline(scenario_outline)
|
49
|
+
replay
|
50
|
+
@statement = scenario_outline
|
51
|
+
end
|
52
|
+
|
53
|
+
def replay
|
54
|
+
print_statement
|
55
|
+
print_steps
|
56
|
+
end
|
57
|
+
|
58
|
+
def print_statement
|
59
|
+
return if @statement.nil?
|
60
|
+
calculate_location_indentations
|
61
|
+
@io.puts
|
62
|
+
print_comments(@statement.comments, ' ')
|
63
|
+
print_tags(@statement.tags, ' ') if @statement.respond_to?(:tags) # Background doesn't
|
64
|
+
@io.write " #{@statement.keyword}: #{@statement.name}"
|
65
|
+
location = @executing ? "#{@uri}:#{@statement.line}" : nil
|
66
|
+
@io.puts indented_location(location, true)
|
67
|
+
print_description(@statement.description, ' ')
|
68
|
+
@statement = nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def print_steps
|
72
|
+
while(@steps.any?)
|
73
|
+
print_step('skipped', [], nil, true)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def examples(examples)
|
78
|
+
replay
|
79
|
+
@io.puts
|
80
|
+
print_comments(examples.comments, ' ')
|
81
|
+
print_tags(examples.tags, ' ')
|
82
|
+
@io.puts " #{examples.keyword}: #{examples.name}"
|
83
|
+
print_description(examples.description, ' ')
|
84
|
+
table(examples.rows)
|
85
|
+
end
|
86
|
+
|
87
|
+
def step(step)
|
88
|
+
@steps << step
|
89
|
+
end
|
90
|
+
|
91
|
+
def match(match)
|
92
|
+
@match = match
|
93
|
+
print_statement
|
94
|
+
print_step('executing', @match.arguments, @match.location, false)
|
95
|
+
end
|
96
|
+
|
97
|
+
def result(result)
|
98
|
+
@io.write(up(1))
|
99
|
+
print_step(result.status, @match.arguments, @match.location, true)
|
100
|
+
end
|
101
|
+
|
102
|
+
def print_step(status, arguments, location, proceed)
|
103
|
+
step = proceed ? @steps.shift : @steps[0]
|
104
|
+
|
105
|
+
text_format = format(status)
|
106
|
+
arg_format = arg_format(status)
|
107
|
+
|
108
|
+
print_comments(step.comments, ' ')
|
109
|
+
@io.write(' ')
|
110
|
+
@io.write(text_format.text(step.keyword))
|
111
|
+
@step_printer.write_step(@io, text_format, arg_format, step.name, arguments)
|
112
|
+
@io.puts(indented_location(location, proceed))
|
113
|
+
|
114
|
+
doc_string(step.doc_string) if step.doc_string
|
115
|
+
table(step.rows) if step.rows
|
116
|
+
end
|
117
|
+
|
118
|
+
class MonochromeFormat
|
119
|
+
def text(text)
|
120
|
+
text
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class ColorFormat
|
125
|
+
include AnsiEscapes
|
126
|
+
|
127
|
+
def initialize(status)
|
128
|
+
@status = status
|
129
|
+
end
|
130
|
+
|
131
|
+
def text(text)
|
132
|
+
self.__send__(@status) + text + reset
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def arg_format(key)
|
137
|
+
format("#{key}_arg")
|
138
|
+
end
|
139
|
+
|
140
|
+
def format(key)
|
141
|
+
if @formats.nil?
|
142
|
+
if @monochrome
|
143
|
+
@formats = Hash.new(MonochromeFormat.new)
|
144
|
+
else
|
145
|
+
@formats = Hash.new do |formats, status|
|
146
|
+
formats[status] = ColorFormat.new(status)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
@formats[key]
|
151
|
+
end
|
152
|
+
|
153
|
+
def eof
|
154
|
+
replay
|
155
|
+
# NO-OP
|
156
|
+
end
|
157
|
+
|
158
|
+
def done
|
159
|
+
# NO-OP
|
160
|
+
end
|
161
|
+
|
162
|
+
def table(rows)
|
163
|
+
cell_lengths = rows.map do |row|
|
164
|
+
row.cells.map do |cell|
|
165
|
+
escape_cell(cell).unpack("U*").length
|
166
|
+
end
|
167
|
+
end
|
168
|
+
max_lengths = cell_lengths.transpose.map { |col_lengths| col_lengths.max }.flatten
|
169
|
+
|
170
|
+
rows.each_with_index do |row, i|
|
171
|
+
row.comments.each do |comment|
|
172
|
+
@io.puts " #{comment.value}"
|
173
|
+
end
|
174
|
+
j = -1
|
175
|
+
@io.puts ' | ' + row.cells.zip(max_lengths).map { |cell, max_length|
|
176
|
+
j += 1
|
177
|
+
color(cell, nil, j) + ' ' * (max_length - cell_lengths[i][j])
|
178
|
+
}.join(' | ') + ' |'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def doc_string(doc_string)
|
185
|
+
@io.puts " \"\"\"" + doc_string.content_type + "\n" + escape_triple_quotes(indent(doc_string.value, ' ')) + "\n \"\"\""
|
186
|
+
end
|
187
|
+
|
188
|
+
def exception(exception)
|
189
|
+
exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ')
|
190
|
+
@io.puts(failed(exception_text))
|
191
|
+
end
|
192
|
+
|
193
|
+
def color(cell, statuses, col)
|
194
|
+
if statuses
|
195
|
+
self.__send__(statuses[col], escape_cell(cell)) + reset
|
196
|
+
else
|
197
|
+
escape_cell(cell)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if(RUBY_VERSION =~ /^1\.9/)
|
202
|
+
START = /#{'^'.encode('UTF-8')}/
|
203
|
+
TRIPLE_QUOTES = /#{'"""'.encode('UTF-8')}/
|
204
|
+
else
|
205
|
+
START = /^/
|
206
|
+
TRIPLE_QUOTES = /"""/
|
207
|
+
end
|
208
|
+
|
209
|
+
def indent(string, indentation)
|
210
|
+
string.gsub(START, indentation)
|
211
|
+
end
|
212
|
+
|
213
|
+
def escape_triple_quotes(s)
|
214
|
+
s.gsub(TRIPLE_QUOTES, '\"\"\"')
|
215
|
+
end
|
216
|
+
|
217
|
+
def print_tags(tags, indent)
|
218
|
+
@io.write(tags.empty? ? '' : indent + tags.map{|tag| tag.name}.join(' ') + "\n")
|
219
|
+
end
|
220
|
+
|
221
|
+
def print_comments(comments, indent)
|
222
|
+
@io.write(comments.empty? ? '' : indent + comments.map{|comment| comment.value}.join("\n#{indent}") + "\n")
|
223
|
+
end
|
224
|
+
|
225
|
+
def print_description(description, indent, newline=true)
|
226
|
+
if description != ""
|
227
|
+
@io.puts indent(description, indent)
|
228
|
+
@io.puts if newline
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def indented_location(location, proceed)
|
233
|
+
indentation = proceed ? @indentations.shift : @indentations[0]
|
234
|
+
location ? (' ' * indentation + ' ' + comments + "# #{location}" + reset) : ''
|
235
|
+
end
|
236
|
+
|
237
|
+
def calculate_location_indentations
|
238
|
+
line_widths = ([@statement] + @steps).map {|step| (step.keyword+step.name).unpack("U*").length}
|
239
|
+
max_line_width = line_widths.max
|
240
|
+
@indentations = line_widths.map{|w| max_line_width - w}
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gherkin
|
2
|
+
module Formatter
|
3
|
+
class RegexpFilter
|
4
|
+
def initialize(regexen)
|
5
|
+
@regexen = regexen
|
6
|
+
end
|
7
|
+
|
8
|
+
def eval(tags, names, ranges)
|
9
|
+
@regexen.detect do |regexp|
|
10
|
+
names.detect do |name|
|
11
|
+
name =~ regexp
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def filter_table_body_rows(rows)
|
17
|
+
rows
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gherkin
|
2
|
+
module Formatter
|
3
|
+
class StepPrinter
|
4
|
+
def write_step(io, text_format, arg_format, step_name, arguments)
|
5
|
+
unpacked_step_name = step_name.unpack("U*")
|
6
|
+
|
7
|
+
text_start = 0
|
8
|
+
arguments.each do |arg|
|
9
|
+
if(arg.offset != 0 && !arg.offset.nil?)
|
10
|
+
io.write(text_format.text(unpacked_step_name[text_start..arg.offset-1].pack("U*")))
|
11
|
+
end
|
12
|
+
if(!arg.val.nil?)
|
13
|
+
io.write(arg_format.text(arg.val))
|
14
|
+
text_start = arg.offset + arg.val.unpack("U*").length
|
15
|
+
end
|
16
|
+
end
|
17
|
+
io.write(text_format.text(unpacked_step_name[text_start..-1].pack("U*"))) unless text_start == unpacked_step_name.length
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Gherkin
|
2
|
+
module Formatter
|
3
|
+
class TagCountFormatter
|
4
|
+
def initialize(formatter, tag_counts)
|
5
|
+
@formatter = formatter
|
6
|
+
@tag_counts = tag_counts
|
7
|
+
end
|
8
|
+
|
9
|
+
def uri(uri)
|
10
|
+
@uri = uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def feature(feature)
|
14
|
+
@feature_tags = feature.tags
|
15
|
+
@formatter.feature(feature)
|
16
|
+
end
|
17
|
+
|
18
|
+
def scenario(scenario)
|
19
|
+
record_tags((@feature_tags.to_a + scenario.tags.to_a).uniq, scenario.line)
|
20
|
+
@formatter.scenario(scenario)
|
21
|
+
end
|
22
|
+
|
23
|
+
def scenario_outline(scenario_outline)
|
24
|
+
@scenario_outline_tags = scenario_outline.tags
|
25
|
+
@formatter.scenario_outline(scenario_outline)
|
26
|
+
end
|
27
|
+
|
28
|
+
def examples(examples)
|
29
|
+
record_tags((@feature_tags.to_a + @scenario_outline_tags.to_a + examples.tags.to_a).uniq, examples.line)
|
30
|
+
@formatter.examples(examples)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def record_tags(tags, line)
|
36
|
+
tags.each do |tag|
|
37
|
+
@tag_counts[tag.name] ||= []
|
38
|
+
@tag_counts[tag.name] << "#{@uri}:#{line}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(*args)
|
43
|
+
@formatter.__send__(*args)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'gherkin/tag_expression'
|
2
|
+
|
3
|
+
module Gherkin
|
4
|
+
module Formatter
|
5
|
+
class TagFilter
|
6
|
+
def initialize(tags)
|
7
|
+
@tag_expression = TagExpression.new(tags)
|
8
|
+
end
|
9
|
+
|
10
|
+
def eval(tags, names, ranges)
|
11
|
+
@tag_expression.eval(tags.uniq)
|
12
|
+
end
|
13
|
+
|
14
|
+
def filter_table_body_rows(rows)
|
15
|
+
rows
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/gherkin/i18n.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'gherkin/rubify'
|
3
|
+
require 'gherkin/native'
|
4
|
+
|
5
|
+
module Gherkin
|
6
|
+
class I18n
|
7
|
+
LexerNotFound = Class.new(LoadError)
|
8
|
+
|
9
|
+
native_impl('gherkin') unless defined?(BYPASS_NATIVE_IMPL)
|
10
|
+
|
11
|
+
FEATURE_ELEMENT_KEYS = %w{feature background scenario scenario_outline examples}
|
12
|
+
STEP_KEYWORD_KEYS = %w{given when then and but}
|
13
|
+
KEYWORD_KEYS = FEATURE_ELEMENT_KEYS + STEP_KEYWORD_KEYS
|
14
|
+
LANGUAGES = YAML.load_file(File.dirname(__FILE__) + '/i18n.yml')
|
15
|
+
|
16
|
+
class << self
|
17
|
+
include Rubify
|
18
|
+
|
19
|
+
# Used by code generators for other lexer tools like pygments lexer and textmate bundle
|
20
|
+
def all
|
21
|
+
LANGUAGES.keys.sort.map{|iso_code| get(iso_code)}
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(iso_code)
|
25
|
+
languages[iso_code] ||= new(iso_code)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns all keyword translations and aliases of +keywords+, escaped and joined with <tt>|</tt>.
|
29
|
+
# This method is convenient for editor support and syntax highlighting engines for Gherkin, where
|
30
|
+
# there is typically a code generation tool to generate regular expressions for recognising the
|
31
|
+
# various I18n translations of Gherkin's keywords.
|
32
|
+
#
|
33
|
+
# The +keywords+ arguments can be one of <tt>:feature</tt>, <tt>:background</tt>, <tt>:scenario</tt>,
|
34
|
+
# <tt>:scenario_outline</tt>, <tt>:examples</tt>, <tt>:step</tt>.
|
35
|
+
def keyword_regexp(*keywords)
|
36
|
+
unique_keywords = all.map do |i18n|
|
37
|
+
keywords.map do |keyword|
|
38
|
+
if keyword.to_s == 'step'
|
39
|
+
i18n.step_keywords.to_a
|
40
|
+
else
|
41
|
+
i18n.keywords(keyword).to_a
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
unique_keywords.flatten.compact.map{|kw| kw.to_s}.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
|
47
|
+
end
|
48
|
+
|
49
|
+
def code_keywords
|
50
|
+
rubify(all.map{|i18n| i18n.code_keywords}).flatten.uniq.sort
|
51
|
+
end
|
52
|
+
|
53
|
+
def code_keyword_for(gherkin_keyword)
|
54
|
+
gherkin_keyword.gsub(/[\s',!]/, '').strip
|
55
|
+
end
|
56
|
+
|
57
|
+
def language_table
|
58
|
+
require 'stringio'
|
59
|
+
require 'gherkin/formatter/pretty_formatter'
|
60
|
+
require 'gherkin/formatter/model'
|
61
|
+
io = StringIO.new
|
62
|
+
pf = Gherkin::Formatter::PrettyFormatter.new(io, true, false)
|
63
|
+
table = all.map do |i18n|
|
64
|
+
Formatter::Model::DataTableRow.new([], [i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], nil)
|
65
|
+
end
|
66
|
+
pf.table(table)
|
67
|
+
io.string
|
68
|
+
end
|
69
|
+
|
70
|
+
def unicode_escape(word, prefix="\\u")
|
71
|
+
word = word.unpack("U*").map do |c|
|
72
|
+
if c > 127 || c == 32
|
73
|
+
"#{prefix}%04x" % c
|
74
|
+
else
|
75
|
+
c.chr
|
76
|
+
end
|
77
|
+
end.join
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def languages
|
83
|
+
@languages ||= {}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
attr_reader :iso_code
|
88
|
+
|
89
|
+
def initialize(iso_code)
|
90
|
+
@iso_code = iso_code
|
91
|
+
@keywords = LANGUAGES[iso_code]
|
92
|
+
raise "Language not supported: #{iso_code.inspect}" if @iso_code.nil?
|
93
|
+
@keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
|
94
|
+
end
|
95
|
+
|
96
|
+
def lexer(listener, force_ruby=false)
|
97
|
+
if force_ruby
|
98
|
+
rb(listener)
|
99
|
+
else
|
100
|
+
begin
|
101
|
+
c(listener)
|
102
|
+
rescue NameError, LoadError => e
|
103
|
+
warn("WARNING: #{e.message}. Reverting to Ruby lexer.")
|
104
|
+
rb(listener)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
rescue LoadError => e
|
108
|
+
raise LexerNotFound, "No lexer was found for #{iso_code} (#{e.message}). Supported languages are listed in gherkin/i18n.yml."
|
109
|
+
end
|
110
|
+
|
111
|
+
def c(listener)
|
112
|
+
require 'gherkin/c_lexer'
|
113
|
+
CLexer[underscored_iso_code].new(listener)
|
114
|
+
end
|
115
|
+
|
116
|
+
def rb(listener)
|
117
|
+
require 'gherkin/rb_lexer'
|
118
|
+
RbLexer[underscored_iso_code].new(listener)
|
119
|
+
end
|
120
|
+
|
121
|
+
def js(listener)
|
122
|
+
require 'gherkin/js_lexer'
|
123
|
+
JsLexer[underscored_iso_code].new(listener)
|
124
|
+
end
|
125
|
+
|
126
|
+
def underscored_iso_code
|
127
|
+
@iso_code.gsub(/[\s-]/, '_').downcase
|
128
|
+
end
|
129
|
+
|
130
|
+
# Keywords that can be used in Gherkin source
|
131
|
+
def step_keywords
|
132
|
+
STEP_KEYWORD_KEYS.map{|iso_code| keywords(iso_code)}.flatten.uniq
|
133
|
+
end
|
134
|
+
|
135
|
+
# Keywords that can be used in code
|
136
|
+
def code_keywords
|
137
|
+
result = step_keywords.map{|keyword| self.class.code_keyword_for(keyword)}
|
138
|
+
result.delete('*')
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
def keywords(key)
|
143
|
+
key = key.to_s
|
144
|
+
raise "No #{key.inspect} in #{@keywords.inspect}" if @keywords[key].nil?
|
145
|
+
@keywords[key].split('|').map{|keyword| real_keyword(key, keyword)}
|
146
|
+
end
|
147
|
+
|
148
|
+
def keyword_table
|
149
|
+
require 'stringio'
|
150
|
+
require 'gherkin/formatter/pretty_formatter'
|
151
|
+
require 'gherkin/formatter/model'
|
152
|
+
io = StringIO.new
|
153
|
+
pf = Gherkin::Formatter::PrettyFormatter.new(io, false, false)
|
154
|
+
|
155
|
+
gherkin_keyword_table = KEYWORD_KEYS.map do |key|
|
156
|
+
Formatter::Model::Row.new([], [key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], nil)
|
157
|
+
end
|
158
|
+
|
159
|
+
code_keyword_table = STEP_KEYWORD_KEYS.map do |key|
|
160
|
+
code_keywords = keywords(key).reject{|keyword| keyword == '* '}.map do |keyword|
|
161
|
+
%{"#{self.class.code_keyword_for(keyword)}"}
|
162
|
+
end.join(', ')
|
163
|
+
Formatter::Model::Row.new([], ["#{key} (code)", code_keywords], nil)
|
164
|
+
end
|
165
|
+
|
166
|
+
pf.table(gherkin_keyword_table + code_keyword_table)
|
167
|
+
io.string
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def real_keyword(key, keyword)
|
173
|
+
if(STEP_KEYWORD_KEYS.index(key))
|
174
|
+
(keyword + ' ').sub(/< $/, '')
|
175
|
+
else
|
176
|
+
keyword
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|