gherkin 2.2.5-x86-mingw32

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 (132) hide show
  1. data/.gitattributes +2 -0
  2. data/.gitignore +11 -0
  3. data/.mailmap +2 -0
  4. data/.rspec +1 -0
  5. data/.rvmrc +1 -0
  6. data/Gemfile +5 -0
  7. data/History.txt +306 -0
  8. data/LICENSE +20 -0
  9. data/README.rdoc +59 -0
  10. data/Rakefile +16 -0
  11. data/VERSION +1 -0
  12. data/bin/gherkin +5 -0
  13. data/build_native_gems.sh +8 -0
  14. data/cucumber.yml +3 -0
  15. data/features/escaped_pipes.feature +8 -0
  16. data/features/feature_parser.feature +237 -0
  17. data/features/json_formatter.feature +278 -0
  18. data/features/json_parser.feature +318 -0
  19. data/features/native_lexer.feature +19 -0
  20. data/features/parser_with_native_lexer.feature +205 -0
  21. data/features/pretty_formatter.feature +15 -0
  22. data/features/step_definitions/eyeball_steps.rb +3 -0
  23. data/features/step_definitions/gherkin_steps.rb +29 -0
  24. data/features/step_definitions/json_formatter_steps.rb +28 -0
  25. data/features/step_definitions/json_parser_steps.rb +20 -0
  26. data/features/step_definitions/pretty_formatter_steps.rb +82 -0
  27. data/features/steps_parser.feature +46 -0
  28. data/features/support/env.rb +38 -0
  29. data/gherkin.gemspec +59 -0
  30. data/ikvm/.gitignore +3 -0
  31. data/java/.gitignore +2 -0
  32. data/java/src/main/java/gherkin/lexer/i18n/.gitignore +1 -0
  33. data/java/src/main/resources/gherkin/.gitignore +1 -0
  34. data/lib/.gitignore +4 -0
  35. data/lib/gherkin.rb +2 -0
  36. data/lib/gherkin/c_lexer.rb +17 -0
  37. data/lib/gherkin/cli/main.rb +33 -0
  38. data/lib/gherkin/formatter/argument.rb +28 -0
  39. data/lib/gherkin/formatter/colors.rb +119 -0
  40. data/lib/gherkin/formatter/escaping.rb +15 -0
  41. data/lib/gherkin/formatter/filter_formatter.rb +136 -0
  42. data/lib/gherkin/formatter/json_formatter.rb +72 -0
  43. data/lib/gherkin/formatter/line_filter.rb +26 -0
  44. data/lib/gherkin/formatter/model.rb +231 -0
  45. data/lib/gherkin/formatter/monochrome_format.rb +9 -0
  46. data/lib/gherkin/formatter/pretty_formatter.rb +174 -0
  47. data/lib/gherkin/formatter/regexp_filter.rb +21 -0
  48. data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
  49. data/lib/gherkin/formatter/tag_filter.rb +19 -0
  50. data/lib/gherkin/i18n.rb +180 -0
  51. data/lib/gherkin/i18n.yml +601 -0
  52. data/lib/gherkin/json_parser.rb +88 -0
  53. data/lib/gherkin/lexer/i18n_lexer.rb +47 -0
  54. data/lib/gherkin/listener/event.rb +45 -0
  55. data/lib/gherkin/listener/formatter_listener.rb +113 -0
  56. data/lib/gherkin/native.rb +7 -0
  57. data/lib/gherkin/native/ikvm.rb +55 -0
  58. data/lib/gherkin/native/java.rb +55 -0
  59. data/lib/gherkin/native/null.rb +9 -0
  60. data/lib/gherkin/parser/meta.txt +5 -0
  61. data/lib/gherkin/parser/parser.rb +164 -0
  62. data/lib/gherkin/parser/root.txt +11 -0
  63. data/lib/gherkin/parser/steps.txt +4 -0
  64. data/lib/gherkin/rb_lexer.rb +8 -0
  65. data/lib/gherkin/rb_lexer/.gitignore +1 -0
  66. data/lib/gherkin/rb_lexer/README.rdoc +8 -0
  67. data/lib/gherkin/rubify.rb +24 -0
  68. data/lib/gherkin/tag_expression.rb +62 -0
  69. data/lib/gherkin/tools.rb +8 -0
  70. data/lib/gherkin/tools/files.rb +34 -0
  71. data/lib/gherkin/tools/reformat.rb +20 -0
  72. data/lib/gherkin/tools/stats.rb +20 -0
  73. data/lib/gherkin/tools/stats_listener.rb +60 -0
  74. data/lib/gherkin/version.rb +3 -0
  75. data/ragel/i18n/.gitignore +1 -0
  76. data/ragel/lexer.c.rl.erb +459 -0
  77. data/ragel/lexer.java.rl.erb +224 -0
  78. data/ragel/lexer.rb.rl.erb +179 -0
  79. data/ragel/lexer_common.rl.erb +50 -0
  80. data/spec/gherkin/c_lexer_spec.rb +21 -0
  81. data/spec/gherkin/fixtures/1.feature +8 -0
  82. data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
  83. data/spec/gherkin/fixtures/complex.feature +45 -0
  84. data/spec/gherkin/fixtures/complex.json +143 -0
  85. data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
  86. data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
  87. data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
  88. data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
  89. data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
  90. data/spec/gherkin/fixtures/i18n_no.feature +7 -0
  91. data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
  92. data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
  93. data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
  94. data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
  95. data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
  96. data/spec/gherkin/fixtures/with_bom.feature +3 -0
  97. data/spec/gherkin/formatter/argument_spec.rb +28 -0
  98. data/spec/gherkin/formatter/colors_spec.rb +18 -0
  99. data/spec/gherkin/formatter/filter_formatter_spec.rb +165 -0
  100. data/spec/gherkin/formatter/model_spec.rb +15 -0
  101. data/spec/gherkin/formatter/pretty_formatter_spec.rb +140 -0
  102. data/spec/gherkin/formatter/spaces.feature +9 -0
  103. data/spec/gherkin/formatter/tabs.feature +9 -0
  104. data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
  105. data/spec/gherkin/i18n_spec.rb +149 -0
  106. data/spec/gherkin/java_lexer_spec.rb +20 -0
  107. data/spec/gherkin/json.rb +5 -0
  108. data/spec/gherkin/json_parser_spec.rb +67 -0
  109. data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
  110. data/spec/gherkin/output_stream_string_io.rb +24 -0
  111. data/spec/gherkin/parser/parser_spec.rb +16 -0
  112. data/spec/gherkin/rb_lexer_spec.rb +19 -0
  113. data/spec/gherkin/sexp_recorder.rb +56 -0
  114. data/spec/gherkin/shared/lexer_group.rb +592 -0
  115. data/spec/gherkin/shared/py_string_group.rb +153 -0
  116. data/spec/gherkin/shared/row_group.rb +120 -0
  117. data/spec/gherkin/shared/tags_group.rb +54 -0
  118. data/spec/gherkin/tag_expression_spec.rb +137 -0
  119. data/spec/spec_helper.rb +68 -0
  120. data/tasks/bench.rake +184 -0
  121. data/tasks/bench/feature_builder.rb +49 -0
  122. data/tasks/bench/generated/.gitignore +1 -0
  123. data/tasks/bench/null_listener.rb +4 -0
  124. data/tasks/compile.rake +102 -0
  125. data/tasks/cucumber.rake +18 -0
  126. data/tasks/gems.rake +42 -0
  127. data/tasks/ikvm.rake +54 -0
  128. data/tasks/ragel_task.rb +70 -0
  129. data/tasks/rdoc.rake +9 -0
  130. data/tasks/release.rake +30 -0
  131. data/tasks/rspec.rake +8 -0
  132. metadata +447 -0
@@ -0,0 +1,15 @@
1
+ Feature: Pretty Formatter
2
+ In order to have pretty gherkin
3
+ I want to verify that all prettified cucumber features parse OK
4
+
5
+ Scenario: Parse all the features in Cucumber
6
+ Given I have Cucumber's source code next to Gherkin's
7
+ And I find all of the .feature files
8
+ When I send each prettified original through the "pretty" machinery
9
+ Then the machinery output should be identical to the prettified original
10
+
11
+ Scenario: Parse all the features in Cucumber with JSON
12
+ Given I have Cucumber's source code next to Gherkin's
13
+ And I find all of the .feature files
14
+ When I send each prettified original through the "json" machinery
15
+ Then the machinery output should be identical to the prettified original
@@ -0,0 +1,3 @@
1
+ Given /^they have arrived$/ do |table|
2
+ announce table.raw
3
+ end
@@ -0,0 +1,29 @@
1
+ Given /^a "(ruby|native)" "([^\"]*)" parser$/ do |ruby_or_native, parser_name|
2
+ @parser = Gherkin::Parser::Parser.new(@formatter, false, parser_name, ruby_or_native=="ruby")
3
+ end
4
+
5
+ Given "the following text is parsed:" do |text|
6
+ @parser.parse(text, "test.feature", 0)
7
+ end
8
+
9
+ Then "there should be no parse errors" do
10
+ @formatter.errors.should == []
11
+ end
12
+
13
+ Then /^there should be a parse error on (line \d+)$/ do |line|
14
+ @formatter.line(line).should include(:syntax_error, line)
15
+ end
16
+
17
+ Then /^there should be parse errors on (lines .*)$/ do |lines|
18
+ lines.each do |line|
19
+ Then "there should be a parse error on line #{line}"
20
+ end
21
+ end
22
+
23
+ Transform /^line \d+$/ do |step_arg|
24
+ tr_line_number(step_arg)
25
+ end
26
+
27
+ Transform /^lines .*$/ do |step_arg|
28
+ tr_line_numbers(step_arg)
29
+ end
@@ -0,0 +1,28 @@
1
+ require 'ap' # awesome_print gem
2
+ require 'stringio'
3
+ require 'gherkin/formatter/json_formatter'
4
+ require 'gherkin/listener/formatter_listener'
5
+
6
+ # Monkey patching so that Hash.to_json has a predictable result.
7
+ class Hash
8
+ alias orig_keys keys
9
+ def keys
10
+ orig_keys.sort
11
+ end
12
+ end
13
+
14
+ Given /^a JSON formatter$/ do
15
+ @io = StringIO.new
16
+ @formatter = Gherkin::Formatter::JSONFormatter.new(@io)
17
+ end
18
+
19
+ Then /^the outputted JSON should be:$/ do |expected_json|
20
+ require 'json'
21
+ announce JSON.pretty_generate(JSON.parse(@io.string))
22
+ expected = JSON.parse(expected_json).ai
23
+ actual = JSON.parse(@io.string).ai
24
+ actual.should == expected
25
+ end
26
+
27
+
28
+
@@ -0,0 +1,20 @@
1
+ require 'stringio'
2
+ require 'gherkin/formatter/pretty_formatter'
3
+ require 'gherkin/json_parser'
4
+
5
+ Given /^a PrettyFormatter$/ do
6
+ @io = StringIO.new
7
+ @formatter = Gherkin::Formatter::PrettyFormatter.new(@io, true)
8
+ end
9
+
10
+ Given /^a JSON lexer$/ do
11
+ @json_parser = Gherkin::JSONParser.new(@formatter)
12
+ end
13
+
14
+ Given /^the following JSON is parsed:$/ do |text|
15
+ @json_parser.parse(JSON.pretty_generate(JSON.parse(text)), "unknown.json", 0)
16
+ end
17
+
18
+ Then /^the outputted text should be:$/ do |expected_text|
19
+ @io.string.strip.should == expected_text
20
+ end
@@ -0,0 +1,82 @@
1
+ require 'stringio'
2
+ require 'fileutils'
3
+ require 'gherkin'
4
+ require 'gherkin/formatter/pretty_formatter'
5
+ require 'gherkin/formatter/json_formatter'
6
+ require 'gherkin/json_parser'
7
+
8
+ module PrettyPlease
9
+ def pretty_machinery(gherkin, feature_path)
10
+ io = StringIO.new
11
+ formatter = Gherkin::Formatter::PrettyFormatter.new(io, false)
12
+ parser = Gherkin::Parser::Parser.new(formatter, true)
13
+ parse(parser, gherkin, feature_path)
14
+ io.string
15
+ end
16
+
17
+ def json_machinery(gherkin, feature_path)
18
+ json = StringIO.new
19
+ json_formatter = Gherkin::Formatter::JSONFormatter.new(json)
20
+ gherkin_parser = Gherkin::Parser::Parser.new(json_formatter, true)
21
+ parse(gherkin_parser, gherkin, feature_path)
22
+
23
+ result = StringIO.new
24
+ pretty_formatter = Gherkin::Formatter::PrettyFormatter.new(result, false)
25
+ json_parser = Gherkin::JSONParser.new(pretty_formatter)
26
+ json_parser.parse(json.string, "#{feature_path}.json", 0)
27
+
28
+ result.string
29
+ end
30
+
31
+ def parse(parser, gherkin, feature_path)
32
+ begin
33
+ parser.parse(gherkin, feature_path, 0)
34
+ rescue => e
35
+ if e.message =~ /Lexing error/
36
+ FileUtils.mkdir "tmp" unless File.directory?("tmp")
37
+ written_path = "tmp/#{File.basename(feature_path)}"
38
+ File.open(written_path, "w") {|io| io.write(gherkin)}
39
+ e.message << "\nSee #{written_path}"
40
+ end
41
+ raise e
42
+ end
43
+ end
44
+ end
45
+
46
+ World(PrettyPlease)
47
+
48
+ Given /^I have Cucumber's source code next to Gherkin's$/ do
49
+ @cucumber_home = File.dirname(__FILE__) + '/../../../cucumber'
50
+ raise "No Cucumber source in #{@cucumber_home}" unless File.file?(@cucumber_home + '/bin/cucumber')
51
+ end
52
+
53
+ Given /^I find all of the \.feature files$/ do
54
+ @feature_paths = Dir["#{@cucumber_home}/**/*.feature"].sort
55
+ end
56
+
57
+ When /^I send each prettified original through the "([^"]*)" machinery$/ do |machinery|
58
+ @error = false
59
+ @feature_paths.each do |feature_path|
60
+ begin
61
+ original = pretty_machinery(IO.read(feature_path), feature_path)
62
+ via_machinery = self.__send__("#{machinery}_machinery", original, feature_path)
63
+ via_machinery.should == original
64
+ rescue RSpec::Expectations::ExpectationNotMetError => e
65
+ announce "=========="
66
+ announce feature_path
67
+ if(e.message =~ /(@@.*)/m)
68
+ announce $1
69
+ @error = true
70
+ else
71
+ announce "Identical, except for newlines"
72
+ end
73
+ rescue => e
74
+ e.message << "\nFatal error happened when parsing #{feature_path}."
75
+ raise e
76
+ end
77
+ end
78
+ end
79
+
80
+ Then /^the machinery output should be identical to the prettified original$/ do
81
+ raise "Some features didn't make it through the machinery" if @error
82
+ end
@@ -0,0 +1,46 @@
1
+ Feature: Gherkin Steps parser
2
+ In order to save time and make my features clearer
3
+ As a Cucumber developer
4
+ I want a steps parser to make writing compound steps easier
5
+
6
+ Background:
7
+ Given a "ruby" "steps" parser
8
+
9
+ Scenario: Parsing steps
10
+ Given the following text is parsed:
11
+ """
12
+ Given a one step
13
+ And a two step
14
+ \"\"\"
15
+ Here is a multiline string
16
+ That follows a step
17
+ With an argument #{arg}
18
+ \"\"\"
19
+ And a one two three step
20
+ When another step
21
+ Then there should be a table
22
+ | one | two | three |
23
+ | foo | bar | #{arg} |
24
+ """
25
+ Then there should be no parse errors
26
+
27
+ Scenario: Trying to parse a full feature with the step parser
28
+ Given the following text is parsed:
29
+ """
30
+ Feature: A Feature
31
+ Scenario: Yes, there is one
32
+ Given I have a step
33
+ When I execute this step
34
+ Then something should happen
35
+ """
36
+ Then there should be parse errors on lines 1 and 2
37
+
38
+ Scenario: Tags
39
+ Given the following text is parsed:
40
+ """
41
+ @a_tag
42
+ Given a step
43
+ When I trip
44
+ Then I should sign up for dancing lessons
45
+ """
46
+ Then there should be a parse error on line 1
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ # I'm sure there's a better way than this...
6
+ %w{ /../../spec /../../lib}.each do |path|
7
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + path)
8
+ end
9
+ require 'gherkin'
10
+ require 'gherkin/sexp_recorder'
11
+ require 'gherkin/output_stream_string_io'
12
+ require 'gherkin/json'
13
+
14
+ module TransformHelpers
15
+ def tr_line_number(step_arg)
16
+ /(\d+)$/.match(step_arg)[0].to_i
17
+ end
18
+
19
+ def tr_line_numbers(step_arg)
20
+ if step_arg =~ /through/
21
+ Range.new(*step_arg.scan(/\d+/).collect { |i| i.to_i })
22
+ else
23
+ step_arg.scan(/\d+/).collect { |i| i.to_i }
24
+ end
25
+ end
26
+ end
27
+
28
+ class GherkinWorld
29
+ include TransformHelpers
30
+
31
+ def initialize
32
+ @formatter = Gherkin::SexpRecorder.new
33
+ end
34
+ end
35
+
36
+ World do
37
+ GherkinWorld.new
38
+ end
@@ -0,0 +1,59 @@
1
+ # -*- encoding: utf-8 -*-
2
+ gherkin_dir = Dir.pwd =~ /gherkin\/tmp/ ? File.expand_path("../../../..", Dir.pwd) : File.expand_path("..", __FILE__)
3
+ $LOAD_PATH.unshift File.join(gherkin_dir, 'lib')
4
+ require "gherkin/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "gherkin"
8
+ s.version = Gherkin::VERSION
9
+ s.authors = ["Mike Sassak", "Gregory Hnatiuk", "Aslak Hellesøy"]
10
+ s.description = "A fast Gherkin lexer/parser based on the Ragel State Machine Compiler."
11
+ s.summary = "gherkin-#{Gherkin::VERSION}"
12
+ s.email = "cukes@googlegroups.com"
13
+ s.homepage = "http://github.com/aslakhellesoy/gherkin"
14
+
15
+ s.rubygems_version = "1.3.7"
16
+ s.default_executable = "gherkin"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.extra_rdoc_files = ["LICENSE", "README.rdoc", "History.txt"]
22
+ s.rdoc_options = ["--charset=UTF-8"]
23
+ s.require_path = "lib"
24
+
25
+ s.files -= Dir['ikvm/**/*']
26
+ s.files -= Dir['java/**/*']
27
+ s.files -= Dir['ext/**/*']
28
+ s.files -= Dir['lib/gherkin.jar']
29
+ s.files -= Dir['lib/**/*.dll']
30
+ s.files -= Dir['lib/**/*.bundle']
31
+ s.files -= Dir['lib/**/*.so']
32
+
33
+ if ENV['GEM_PLATFORM']
34
+ puts "GEM_PLATFORM:#{ENV['GEM_PLATFORM']}"
35
+ end
36
+ s.platform = ENV['GEM_PLATFORM'] if ENV['GEM_PLATFORM']
37
+ case s.platform.to_s
38
+ when /java/
39
+ s.files += ['lib/gherkin.jar']
40
+ when /mswin|mingw32/
41
+ s.files += Dir['lib/*/*.so']
42
+ when /dotnet/
43
+ s.files += Dir['lib/*.dll']
44
+ else # MRI or Rubinius
45
+ s.files += Dir['lib/gherkin/rb_lexer/*.rb']
46
+ s.files += Dir['ext/**/*.c']
47
+ s.extensions = Dir['ext/**/extconf.rb']
48
+ s.add_development_dependency('rake-compiler', '~> 0.7.1')
49
+ end
50
+
51
+ s.add_dependency('trollop', '~> 1.16.2')
52
+ s.add_dependency('json', '~> 1.4.6')
53
+ s.add_dependency('term-ansicolor','~> 1.0.5')
54
+
55
+ s.add_development_dependency('rake', '~> 0.8.7')
56
+ s.add_development_dependency('awesome_print', '~> 0.2.1')
57
+ s.add_development_dependency('rspec', '~> 2.0.0.beta.22')
58
+ s.add_development_dependency('cucumber', '~> 0.9.0')
59
+ end
@@ -0,0 +1,3 @@
1
+ bin
2
+ *.pidb
3
+ *.userprefs
@@ -0,0 +1,2 @@
1
+ .idea
2
+ target
@@ -0,0 +1 @@
1
+ *.properties
@@ -0,0 +1,4 @@
1
+ *.bundle
2
+ *.dll
3
+ *.so
4
+ *.jar
@@ -0,0 +1,2 @@
1
+ require 'gherkin/lexer/i18n_lexer'
2
+ require 'gherkin/parser/parser'
@@ -0,0 +1,17 @@
1
+ require 'rbconfig'
2
+
3
+ module Gherkin
4
+ module CLexer
5
+ def self.[](i18n_underscored_iso_code)
6
+ begin
7
+ prefix = Config::CONFIG['arch'] =~ /mswin|mingw/ ? "#{Config::CONFIG['MAJOR']}.#{Config::CONFIG['MINOR']}/" : ''
8
+ lib = "#{prefix}gherkin_lexer_#{i18n_underscored_iso_code}"
9
+ require lib
10
+ const_get(i18n_underscored_iso_code.capitalize)
11
+ rescue LoadError => e
12
+ e.message << %{\nCouldn't load #{lib}\nThe $LOAD_PATH was:\n#{$LOAD_PATH.join("\n")}}
13
+ raise e
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ begin
2
+ require 'trollop'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'trollop'
6
+ end
7
+ require 'gherkin/tools'
8
+
9
+ module Gherkin
10
+ module Cli
11
+ class Main
12
+ def self.run(args)
13
+ Trollop::options(args) do
14
+ banner "Super fast gherkin parser"
15
+ stop_on Tools::SUB_COMMANDS
16
+ end
17
+
18
+ cmd_name = args.shift
19
+ die("Missing command") if cmd_name.nil?
20
+ begin
21
+ cmd = Tools.const_get(cmd_name.capitalize.to_sym).new(args)
22
+ cmd.run
23
+ rescue => e
24
+ Trollop::die(e.message + "\n#{e.backtrace.join("\n")}\n\nCommand: #{cmd_name}")
25
+ end
26
+ end
27
+
28
+ def self.die(msg)
29
+ Trollop::die("#{msg}\nusage: gherkin COMMAND [ARGS]\nAvailable commands: #{Tools::SUB_COMMANDS.join(' ')}")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ require 'gherkin/native'
2
+
3
+ module Gherkin
4
+ module Formatter
5
+ class Argument
6
+ native_impl('gherkin')
7
+ attr_reader :byte_offset, :val
8
+
9
+ def initialize(byte_offset, val)
10
+ @byte_offset, @val = byte_offset, val
11
+ end
12
+
13
+ def self.format(string, argument_format, arguments)
14
+ arguments ||= []
15
+ s = string.dup
16
+ offset = past_offset = 0
17
+ arguments.each do |arg|
18
+ next if arg.byte_offset.nil? || arg.byte_offset < past_offset
19
+ replacement = argument_format.format_argument(arg.val)
20
+ s[arg.byte_offset + offset, arg.val.length] = replacement
21
+ offset += replacement.unpack("U*").length - arg.val.unpack("U*").length
22
+ past_offset = arg.byte_offset + arg.val.length
23
+ end
24
+ s
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,119 @@
1
+ require 'term/ansicolor'
2
+
3
+ module Gherkin
4
+ module Formatter
5
+ # Defines aliases for coloured output. You don't invoke any methods from this
6
+ # module directly, but you can change the output colours by defining
7
+ # a <tt>GHERKIN_COLORS</tt> variable in your shell, very much like how you can
8
+ # tweak the familiar POSIX command <tt>ls</tt> with
9
+ # <a href="http://mipsisrisc.com/rambling/2008/06/27/lscolorsls_colors-now-with-linux-support/">$LSCOLORS/$LS_COLORS</a>
10
+ #
11
+ # The colours that you can change are:
12
+ #
13
+ # * <tt>undefined</tt> - defaults to <tt>yellow</tt>
14
+ # * <tt>pending</tt> - defaults to <tt>yellow</tt>
15
+ # * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
16
+ # * <tt>failed</tt> - defaults to <tt>red</tt>
17
+ # * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
18
+ # * <tt>passed</tt> - defaults to <tt>green</tt>
19
+ # * <tt>passed_param</tt> - defaults to <tt>green,bold</tt>
20
+ # * <tt>outline</tt> - defaults to <tt>cyan</tt>
21
+ # * <tt>outline_param</tt> - defaults to <tt>cyan,bold</tt>
22
+ # * <tt>skipped</tt> - defaults to <tt>cyan</tt>
23
+ # * <tt>skipped_param</tt> - defaults to <tt>cyan,bold</tt>
24
+ # * <tt>comment</tt> - defaults to <tt>grey</tt>
25
+ # * <tt>tag</tt> - defaults to <tt>cyan</tt>
26
+ #
27
+ # For instance, if your shell has a black background and a green font (like the
28
+ # "Homebrew" settings for OS X' Terminal.app), you may want to override passed
29
+ # steps to be white instead of green. Examples:
30
+ #
31
+ # export GHERKIN_COLORS="passed=white"
32
+ # export GHERKIN_COLORS="passed=white,bold:passed_param=white,bold,underline"
33
+ #
34
+ # (If you're on Windows, use SET instead of export).
35
+ # To see what colours and effects are available, just run this in your shell:
36
+ #
37
+ # ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Term::ANSIColor.attributes"
38
+ #
39
+ # Although not listed, you can also use <tt>grey</tt>
40
+ module Colors
41
+ include Term::ANSIColor
42
+
43
+ ALIASES = Hash.new do |h,k|
44
+ if k.to_s =~ /(.*)_param/
45
+ h[$1] + ',bold'
46
+ end
47
+ end.merge({
48
+ 'undefined' => 'yellow',
49
+ 'pending' => 'yellow',
50
+ 'failed' => 'red',
51
+ 'passed' => 'green',
52
+ 'outline' => 'cyan',
53
+ 'skipped' => 'cyan',
54
+ 'comments' => 'grey',
55
+ 'tag' => 'cyan'
56
+ })
57
+
58
+ if ENV['GHERKIN_COLORS'] # Example: export GHERKIN_COLORS="passed=red:failed=yellow"
59
+ ENV['GHERKIN_COLORS'].split(':').each do |pair|
60
+ a = pair.split('=')
61
+ ALIASES[a[0]] = a[1]
62
+ end
63
+ end
64
+
65
+ ALIASES.each do |method, color|
66
+ unless method =~ /.*_param/
67
+ code = <<-EOF
68
+ def #{method}(string=nil, monochrome=false, &proc)
69
+ return string if monochrome
70
+ #{ALIASES[method].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method].split(",").length}
71
+ end
72
+ # This resets the colour to the non-param colour
73
+ def #{method}_param(string=nil, monochrome=false, &proc)
74
+ return string if monochrome
75
+ #{ALIASES[method+'_param'].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method+'_param'].split(",").length} + #{ALIASES[method].split(",").join(' + ')}
76
+ end
77
+ EOF
78
+ eval(code)
79
+ end
80
+ end
81
+
82
+ def self.define_grey #:nodoc:
83
+ begin
84
+ gem 'genki-ruby-terminfo'
85
+ require 'terminfo'
86
+ case TermInfo.default_object.tigetnum("colors")
87
+ when 0
88
+ raise "Your terminal doesn't support colours"
89
+ when 1
90
+ ::Term::ANSIColor.coloring = false
91
+ alias grey white
92
+ when 2..8
93
+ alias grey white
94
+ else
95
+ define_real_grey
96
+ end
97
+ rescue Exception => e
98
+ if e.class.name == 'TermInfo::TermInfoError'
99
+ STDERR.puts "*** WARNING ***"
100
+ STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
101
+ STDERR.puts "Try setting it to TERM=xterm-256color to get grey colour in output"
102
+ STDERR.puts "\n"
103
+ alias grey white
104
+ else
105
+ define_real_grey
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.define_real_grey #:nodoc:
111
+ def grey(m) #:nodoc:
112
+ "\e[90m#{m}\e[0m"
113
+ end
114
+ end
115
+
116
+ define_grey
117
+ end
118
+ end
119
+ end