lucid 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/.gitignore +30 -10
  2. data/.rspec +1 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +15 -0
  6. data/Gemfile +4 -2
  7. data/HISTORY.md +22 -0
  8. data/{LICENSE.txt → LICENSE} +6 -3
  9. data/README.md +22 -8
  10. data/Rakefile +2 -1
  11. data/bin/lucid +10 -10
  12. data/bin/lucid-gen +4 -0
  13. data/lib/autotest/discover.rb +11 -0
  14. data/lib/autotest/lucid.rb +6 -0
  15. data/lib/autotest/lucid_mixin.rb +135 -0
  16. data/lib/autotest/lucid_rails.rb +6 -0
  17. data/lib/autotest/lucid_rails_rspec.rb +6 -0
  18. data/lib/autotest/lucid_rails_rspec2.rb +6 -0
  19. data/lib/autotest/lucid_rspec.rb +6 -0
  20. data/lib/autotest/lucid_rspec2.rb +6 -0
  21. data/lib/lucid.rb +32 -1
  22. data/lib/lucid/ast.rb +20 -0
  23. data/lib/lucid/ast/background.rb +116 -0
  24. data/lib/lucid/ast/comment.rb +24 -0
  25. data/lib/lucid/ast/doc_string.rb +44 -0
  26. data/lib/lucid/ast/empty_background.rb +33 -0
  27. data/lib/lucid/ast/examples.rb +49 -0
  28. data/lib/lucid/ast/feature.rb +99 -0
  29. data/lib/lucid/ast/has_steps.rb +74 -0
  30. data/lib/lucid/ast/location.rb +41 -0
  31. data/lib/lucid/ast/multiline_argument.rb +31 -0
  32. data/lib/lucid/ast/names.rb +13 -0
  33. data/lib/lucid/ast/outline_table.rb +194 -0
  34. data/lib/lucid/ast/scenario.rb +103 -0
  35. data/lib/lucid/ast/scenario_outline.rb +144 -0
  36. data/lib/lucid/ast/specs.rb +38 -0
  37. data/lib/lucid/ast/step.rb +122 -0
  38. data/lib/lucid/ast/step_collection.rb +92 -0
  39. data/lib/lucid/ast/step_invocation.rb +196 -0
  40. data/lib/lucid/ast/table.rb +730 -0
  41. data/lib/lucid/ast/tags.rb +28 -0
  42. data/lib/lucid/ast/tdl_walker.rb +195 -0
  43. data/lib/lucid/cli/app.rb +78 -0
  44. data/lib/lucid/cli/configuration.rb +261 -0
  45. data/lib/lucid/cli/options.rb +463 -0
  46. data/lib/lucid/cli/profile.rb +101 -0
  47. data/lib/lucid/configuration.rb +53 -0
  48. data/lib/lucid/core_ext/disable_autorunners.rb +15 -0
  49. data/lib/lucid/core_ext/instance_exec.rb +70 -0
  50. data/lib/lucid/core_ext/proc.rb +36 -0
  51. data/lib/lucid/core_ext/string.rb +9 -0
  52. data/lib/lucid/errors.rb +40 -0
  53. data/lib/lucid/factory.rb +43 -0
  54. data/lib/lucid/formatter/ansicolor.rb +168 -0
  55. data/lib/lucid/formatter/console.rb +218 -0
  56. data/lib/lucid/formatter/debug.rb +33 -0
  57. data/lib/lucid/formatter/duration.rb +11 -0
  58. data/lib/lucid/formatter/gherkin_formatter_adapter.rb +94 -0
  59. data/lib/lucid/formatter/gpretty.rb +24 -0
  60. data/lib/lucid/formatter/html.rb +610 -0
  61. data/lib/lucid/formatter/interceptor.rb +66 -0
  62. data/lib/lucid/formatter/io.rb +31 -0
  63. data/lib/lucid/formatter/jquery-min.js +154 -0
  64. data/lib/lucid/formatter/json.rb +19 -0
  65. data/lib/lucid/formatter/json_pretty.rb +10 -0
  66. data/lib/lucid/formatter/junit.rb +177 -0
  67. data/lib/lucid/formatter/lucid.css +283 -0
  68. data/lib/lucid/formatter/lucid.sass +244 -0
  69. data/lib/lucid/formatter/ordered_xml_markup.rb +24 -0
  70. data/lib/lucid/formatter/progress.rb +95 -0
  71. data/lib/lucid/formatter/rerun.rb +91 -0
  72. data/lib/lucid/formatter/standard.rb +235 -0
  73. data/lib/lucid/formatter/stepdefs.rb +14 -0
  74. data/lib/lucid/formatter/steps.rb +49 -0
  75. data/lib/lucid/formatter/summary.rb +35 -0
  76. data/lib/lucid/formatter/unicode.rb +53 -0
  77. data/lib/lucid/formatter/usage.rb +132 -0
  78. data/lib/lucid/generator.rb +21 -0
  79. data/lib/lucid/generators/project.rb +70 -0
  80. data/lib/lucid/generators/project/Gemfile.tt +6 -0
  81. data/lib/lucid/generators/project/browser-symbiont.rb +24 -0
  82. data/lib/lucid/generators/project/driver-symbiont.rb +4 -0
  83. data/lib/lucid/generators/project/errors.rb +26 -0
  84. data/lib/lucid/generators/project/events-symbiont.rb +36 -0
  85. data/lib/lucid/generators/project/lucid-symbiont.yml +6 -0
  86. data/lib/lucid/interface.rb +8 -0
  87. data/lib/lucid/interface_methods.rb +125 -0
  88. data/lib/lucid/interface_rb/matcher.rb +108 -0
  89. data/lib/lucid/interface_rb/rb_hook.rb +18 -0
  90. data/lib/lucid/interface_rb/rb_language.rb +190 -0
  91. data/lib/lucid/interface_rb/rb_lucid.rb +119 -0
  92. data/lib/lucid/interface_rb/rb_step_definition.rb +122 -0
  93. data/lib/lucid/interface_rb/rb_transform.rb +57 -0
  94. data/lib/lucid/interface_rb/rb_world.rb +136 -0
  95. data/lib/lucid/interface_rb/regexp_argument_matcher.rb +21 -0
  96. data/lib/lucid/load_path.rb +13 -0
  97. data/lib/lucid/parser.rb +2 -126
  98. data/lib/lucid/platform.rb +27 -0
  99. data/lib/lucid/rspec/allow_doubles.rb +20 -0
  100. data/lib/lucid/rspec/disallow_options.rb +27 -0
  101. data/lib/lucid/runtime.rb +200 -0
  102. data/lib/lucid/runtime/facade.rb +60 -0
  103. data/lib/lucid/runtime/interface_io.rb +60 -0
  104. data/lib/lucid/runtime/orchestrator.rb +218 -0
  105. data/lib/lucid/runtime/results.rb +64 -0
  106. data/lib/lucid/runtime/specs_loader.rb +79 -0
  107. data/lib/lucid/spec_file.rb +112 -0
  108. data/lib/lucid/step_definition_light.rb +20 -0
  109. data/lib/lucid/step_definitions.rb +13 -0
  110. data/lib/lucid/step_match.rb +99 -0
  111. data/lib/lucid/tdl_builder.rb +282 -0
  112. data/lib/lucid/term/ansicolor.rb +118 -0
  113. data/lib/lucid/unit.rb +11 -0
  114. data/lib/lucid/wire_support/configuration.rb +38 -0
  115. data/lib/lucid/wire_support/connection.rb +61 -0
  116. data/lib/lucid/wire_support/request_handler.rb +32 -0
  117. data/lib/lucid/wire_support/wire_exception.rb +32 -0
  118. data/lib/lucid/wire_support/wire_language.rb +54 -0
  119. data/lib/lucid/wire_support/wire_packet.rb +34 -0
  120. data/lib/lucid/wire_support/wire_protocol.rb +43 -0
  121. data/lib/lucid/wire_support/wire_protocol/requests.rb +125 -0
  122. data/lib/lucid/wire_support/wire_step_definition.rb +26 -0
  123. data/lucid.gemspec +25 -14
  124. metadata +220 -12
  125. data/lib/lucid/app.rb +0 -103
  126. data/lib/lucid/options.rb +0 -168
  127. data/lib/lucid/version.rb +0 -3
  128. data/lucid.yml +0 -8
@@ -0,0 +1,101 @@
1
+ require 'yaml'
2
+
3
+ module Lucid
4
+ module CLI
5
+ class Profile
6
+
7
+ def initialize
8
+ @lucid_yml = nil
9
+ end
10
+
11
+ def args_from(profile)
12
+ unless lucid_yml.has_key?(profile)
13
+ raise(ProfileNotFound, <<-END_OF_ERROR)
14
+ Could not find profile: '#{profile}'
15
+
16
+ Defined profiles in lucid.yml:
17
+ * #{lucid_yml.keys.sort.join("\n * ")}
18
+ END_OF_ERROR
19
+ end
20
+
21
+ args_from_yml = lucid_yml[profile] || ''
22
+
23
+ case(args_from_yml)
24
+ when String
25
+ raise YmlLoadError, ["The '#{profile}' profile in lucid.yml was blank. You must define",
26
+ "command line arguments if you are are going to include a profile",
27
+ "in lucid.yml.\n"].join("\n") if args_from_yml =~ /^\s*$/
28
+ if(Lucid::WINDOWS)
29
+ args_from_yml = args_from_yml.split
30
+ args_from_yml = args_from_yml.collect {|x| x.gsub(/^\"(.*)\"/,'\1') }
31
+ else
32
+ require 'shellwords'
33
+ args_from_yml = Shellwords.shellwords(args_from_yml)
34
+ end
35
+ when Array
36
+ raise YmlLoadError, ["The '#{profile}' profile in lucid.yml contained an empty array.",
37
+ "You must define any command line arguments within the array.\n"].join("\n") if args_from_yml.empty?
38
+ else
39
+ raise YmlLoadError, ["The '#{profile}' profile in lucid.yml was a #{args_from_yml.class}.",
40
+ "A profile must be a a String or an Array."].join("\n")
41
+ end
42
+ args_from_yml
43
+ end
44
+
45
+ def has_profile?(profile)
46
+ lucid_yml.has_key?(profile)
47
+ end
48
+
49
+ def lucid_yml_defined?
50
+ lucid_file && File.exist?(lucid_file)
51
+ end
52
+
53
+ private
54
+
55
+ # Loads the profile, processing it through ERB and YAML, and returns it as a hash.
56
+ def lucid_yml
57
+ return @lucid_yml if @lucid_yml
58
+ unless lucid_yml_defined?
59
+ raise ProfilesNotDefinedError, ["A lucid.yml file was not found. The current directory is #{Dir.pwd}.",
60
+ "Refer to Lucid's documentation on defining profiles in lucid.yml.",
61
+ "You must define a 'default' profile to use the lucid command without",
62
+ "any arguments.\nType 'lucid --help' for usage.\n"].join("\n")
63
+ end
64
+
65
+ require 'erb'
66
+ require 'yaml'
67
+ begin
68
+ @lucid_erb = ERB.new(IO.read(lucid_file)).result(binding)
69
+ rescue Exception => e
70
+ raise YmlLoadError, ["A lucid.yml file was found, but could not be parsed. Double-check",
71
+ "the contents of the file. Refer to Lucid's documentation on correct",
72
+ "profile usage.\n#{$!.inspect}"].join("\n")
73
+ end
74
+
75
+ begin
76
+ @lucid_yml = YAML::load(@lucid_erb)
77
+ rescue StandardError => e
78
+ raise YmlLoadError, ["A lucid.yml file was found, but could not be parsed. Double-check",
79
+ "the contents of the file. Refer to Lucid's documentation on correct",
80
+ "profile usage.\n"].join("\n")
81
+ end
82
+
83
+ if @lucid_yml.nil? || !@lucid_yml.is_a?(Hash)
84
+ raise YmlLoadError, ["The lucid.yml file was found, but was blank or malformed. Please",
85
+ "refer to Lucid's documentation on defining profiles in lucid.yml.\n"].join("\n")
86
+ end
87
+
88
+ return @lucid_yml
89
+ end
90
+
91
+ # Locates lucid.yml file. The file can end in .yml or .yaml, and be
92
+ # located in the current directory (e.g., project root) or in a
93
+ # .config/ or config/ subdirectory of the current directory.
94
+ def lucid_file
95
+ @lucid_file ||= Dir.glob('{,.config/,config/}lucid{.yml,.yaml}').first
96
+ end
97
+
98
+ end
99
+ end
100
+ end
101
+
@@ -0,0 +1,53 @@
1
+ module Lucid
2
+ # The base class for configuring settings for a Lucid run.
3
+ class Configuration
4
+ def self.default
5
+ new
6
+ end
7
+
8
+ def self.parse(argument)
9
+ return new(argument) if argument.is_a?(Hash)
10
+ argument
11
+ end
12
+
13
+ def initialize(user_options = {})
14
+ @options = default_options.merge(user_options)
15
+ end
16
+
17
+ def dry_run?
18
+ @options[:dry_run]
19
+ end
20
+
21
+ def guess?
22
+ @options[:guess]
23
+ end
24
+
25
+ def strict?
26
+ @options[:strict]
27
+ end
28
+
29
+ def expand?
30
+ @options[:expand]
31
+ end
32
+
33
+ def spec_source
34
+ @options[:spec_source]
35
+ end
36
+
37
+ def autoload_code_paths
38
+ @options[:autoload_code_paths]
39
+ end
40
+
41
+ def matcher_type
42
+ @options[:matcher_type]
43
+ end
44
+
45
+ private
46
+
47
+ def default_options
48
+ {
49
+ :autoload_code_paths => ['common', 'steps']
50
+ }
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'test/unit'
3
+
4
+ if defined?(Test::Unit::AutoRunner.need_auto_run?)
5
+ # For test-unit gem >= 2.4.9
6
+ Test::Unit::AutoRunner.need_auto_run = false
7
+ elsif defined?(Test::Unit.run?)
8
+ # For test-unit gem < 2.4.9
9
+ Test::Unit.run = true
10
+ elsif defined?(Test::Unit::Runner)
11
+ # For test/unit bundled in Ruby >= 1.9.3
12
+ Test::Unit::Runner.module_eval("@@stop_auto_run = true")
13
+ end
14
+ rescue LoadError => ignore
15
+ end
@@ -0,0 +1,70 @@
1
+ require 'lucid/platform'
2
+
3
+ module Lucid
4
+ # Raised if the number of a StepDefinition's Regexp match groups
5
+ # is different from the number of Proc arguments.
6
+ class ArityMismatchError < StandardError
7
+ end
8
+ end
9
+
10
+ class Object #:nodoc:
11
+ # TODO: Move most of this stuff out to an InstanceExecutor class.
12
+ def lucid_instance_exec(check_arity, pseudo_method, *args, &block)
13
+ lucid_run_with_backtrace_filtering(pseudo_method) do
14
+ if check_arity && !lucid_compatible_arity?(args, block)
15
+ instance_exec do
16
+ ari = block.arity
17
+ ari = ari < 0 ? (ari.abs-1).to_s+"+" : ari
18
+ s1 = ari == 1 ? "" : "s"
19
+ s2 = args.length == 1 ? "" : "s"
20
+ raise Lucid::ArityMismatchError.new(
21
+ "Your block takes #{ari} argument#{s1}, but the regexp matched #{args.length} argument#{s2}."
22
+ )
23
+ end
24
+ else
25
+ instance_exec(*args, &block)
26
+ end
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def lucid_compatible_arity?(args, block)
33
+ return true if block.arity == args.length
34
+ if block.arity < 0
35
+ return true if args.length >= (block.arity.abs - 1)
36
+ end
37
+ false
38
+ end
39
+
40
+ def lucid_run_with_backtrace_filtering(pseudo_method)
41
+ begin
42
+ yield
43
+ rescue Exception => e
44
+ instance_exec_invocation_line = "#{__FILE__}:#{__LINE__ - 2}:in `lucid_run_with_backtrace_filtering'"
45
+ replace_instance_exec_invocation_line!((e.backtrace || []), instance_exec_invocation_line, pseudo_method)
46
+ raise e
47
+ end
48
+ end
49
+
50
+ INSTANCE_EXEC_OFFSET = (Lucid::RUBY_2_0 || Lucid::RUBY_1_9 || Lucid::JRUBY) ? -3 : -4
51
+
52
+ def replace_instance_exec_invocation_line!(backtrace, instance_exec_invocation_line, pseudo_method)
53
+ return if Lucid.use_full_backtrace
54
+
55
+ instance_exec_pos = backtrace.index(instance_exec_invocation_line)
56
+ if instance_exec_pos
57
+ replacement_line = instance_exec_pos + INSTANCE_EXEC_OFFSET
58
+ backtrace[replacement_line].gsub!(/`.*'/, "`#{pseudo_method}'") if pseudo_method
59
+
60
+ depth = backtrace.count { |line| line == instance_exec_invocation_line }
61
+ end_pos = depth > 1 ? instance_exec_pos : -1
62
+
63
+ backtrace[replacement_line+1..end_pos] = nil
64
+ backtrace.compact!
65
+ else
66
+ # This happens with rails, because they screw up the backtrace
67
+ # before we get here (injecting erb stacktrace and such)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,36 @@
1
+ # Proc extension to get more location info out of a proc
2
+ require 'lucid/platform'
3
+ class Proc #:nodoc:
4
+ PROC_PATTERN = /[\d\w]+@(.+):(\d+).*>/
5
+ PWD = Dir.pwd
6
+
7
+ def to_comment_line
8
+ "# #{file_colon_line}"
9
+ end
10
+
11
+ def backtrace_line(name)
12
+ "#{file_colon_line}:in `#{name}'"
13
+ end
14
+
15
+ if Proc.new{}.to_s =~ PROC_PATTERN
16
+ def file_colon_line
17
+ path, line = *to_s.match(PROC_PATTERN)[1..2]
18
+ path = File.expand_path(path)
19
+ pwd = File.expand_path(PWD)
20
+ pwd.force_encoding(path.encoding)
21
+ if path.index(pwd)
22
+ path = path[pwd.length+1..-1]
23
+ elsif path =~ /.*\/gems\/(.*\.rb)$/
24
+ path = $1
25
+ end
26
+ "#{path}:#{line}"
27
+ end
28
+ else
29
+ # This Ruby implementation doesn't implement Proc#to_s correctly
30
+ STDERR.puts "*** THIS RUBY IMPLEMENTATION DOESN'T REPORT FILE AND LINE FOR PROCS ***"
31
+
32
+ def file_colon_line
33
+ "UNKNOWN:-1"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ class String #:nodoc:
2
+ def indent(n)
3
+ if n >= 0
4
+ gsub(/^/, ' ' * n)
5
+ else
6
+ gsub(/^ {0,#{-n}}/, "")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ module Lucid
2
+ # Raised when there is no matching StepDefinition for a step.
3
+ class Undefined < StandardError
4
+ attr_reader :step_name
5
+
6
+ def initialize(step_name)
7
+ super %{Undefined step: "#{step_name}"}
8
+ @step_name = step_name
9
+ end
10
+
11
+ def nested!
12
+ @nested = true
13
+ end
14
+
15
+ def nested?
16
+ @nested
17
+ end
18
+ end
19
+
20
+ # Raised when a StepDefinition's block invokes Domain#pending
21
+ class Pending < StandardError
22
+ end
23
+
24
+ # Raised when a step matches 2 or more StepDefinitions
25
+ class Ambiguous < StandardError
26
+ def initialize(step_name, step_definitions, used_guess)
27
+ message = "Ambiguous match of \"#{step_name}\":\n\n"
28
+ message << step_definitions.map{|sd| sd.backtrace_line}.join("\n")
29
+ message << "\n\n"
30
+ message << "You can run again with --guess to make Lucid be a little more smart about it.\n" unless used_guess
31
+ super(message)
32
+ end
33
+ end
34
+
35
+ class TagExcess < StandardError
36
+ def initialize(messages)
37
+ super(messages.join("\n"))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,43 @@
1
+ module Lucid
2
+ module ObjectFactory #:nodoc:
3
+ def create_object_of(phrase)
4
+ try = 0
5
+ begin
6
+ try += 1
7
+ names = phrase.split('::')
8
+ names.shift if names.empty? || names.first.empty?
9
+
10
+ constant = ::Object
11
+ names.each do |name|
12
+ constant = provide_object_name(constant, name)
13
+ end
14
+ constant
15
+ rescue NameError => e
16
+ require underscore(phrase)
17
+ if try < 2
18
+ retry
19
+ else
20
+ raise e
21
+ end
22
+ end
23
+ end
24
+
25
+ def underscore(phrase)
26
+ phrase.to_s.gsub(/::/, '/').
27
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
28
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
29
+ tr("-", "_").
30
+ downcase
31
+ end
32
+
33
+ private
34
+
35
+ def provide_object_name(constant, name)
36
+ if constant.const_defined?(name, false)
37
+ constant.const_get(name, false)
38
+ else
39
+ constant.const_missing(name)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,168 @@
1
+ require 'lucid/platform'
2
+ require 'lucid/term/ansicolor'
3
+
4
+ if Lucid::IRONRUBY
5
+ begin
6
+ require 'iron-term-ansicolor'
7
+ rescue LoadError
8
+ STDERR.puts %{*** WARNING: You must "igem install iron-term-ansicolor" to get coloured ouput in on IronRuby}
9
+ end
10
+ end
11
+
12
+ if Lucid::WINDOWS_MRI
13
+ unless ENV['ANSICON']
14
+ STDERR.puts %{*** WARNING: You must use ANSICON 1.31 or higher (https://github.com/adoxa/ansicon/) to get coloured output on Windows}
15
+ Lucid::Term::ANSIColor.coloring = false
16
+ end
17
+ end
18
+
19
+ Lucid::Term::ANSIColor.coloring = false if !STDOUT.tty? && !ENV.has_key?("AUTOTEST")
20
+
21
+ module Lucid
22
+ module Formatter
23
+ # Defines aliases for coloured output. You don't invoke any methods from this
24
+ # module directly, but you can change the output colours by defining
25
+ # a <tt>CUCUMBER_COLORS</tt> variable in your shell, very much like how you can
26
+ # tweak the familiar POSIX command <tt>ls</tt> with
27
+ # <a href="http://mipsisrisc.com/rambling/2008/06/27/lscolorsls_colors-now-with-linux-support/">$LSCOLORS/$LS_COLORS</a>
28
+ #
29
+ # The colours that you can change are:
30
+ #
31
+ # * <tt>undefined</tt> - defaults to <tt>yellow</tt>
32
+ # * <tt>pending</tt> - defaults to <tt>yellow</tt>
33
+ # * <tt>pending_param</tt> - defaults to <tt>yellow,bold</tt>
34
+ # * <tt>failed</tt> - defaults to <tt>red</tt>
35
+ # * <tt>failed_param</tt> - defaults to <tt>red,bold</tt>
36
+ # * <tt>passed</tt> - defaults to <tt>green</tt>
37
+ # * <tt>passed_param</tt> - defaults to <tt>green,bold</tt>
38
+ # * <tt>outline</tt> - defaults to <tt>cyan</tt>
39
+ # * <tt>outline_param</tt> - defaults to <tt>cyan,bold</tt>
40
+ # * <tt>skipped</tt> - defaults to <tt>cyan</tt>
41
+ # * <tt>skipped_param</tt> - defaults to <tt>cyan,bold</tt>
42
+ # * <tt>comment</tt> - defaults to <tt>grey</tt>
43
+ # * <tt>tag</tt> - defaults to <tt>cyan</tt>
44
+ #
45
+ # For instance, if your shell has a black background and a green font (like the
46
+ # "Homebrew" settings for OS X' Terminal.app), you may want to override passed
47
+ # steps to be white instead of green.
48
+ #
49
+ # Although not listed, you can also use <tt>grey</tt>.
50
+ #
51
+ # Examples: (On Windows, use SET instead of export.)
52
+ #
53
+ # export CUCUMBER_COLORS="passed=white"
54
+ # export CUCUMBER_COLORS="passed=white,bold:passed_param=white,bold,underline"
55
+ #
56
+ # To see what colours and effects are available, just run this in your shell:
57
+ #
58
+ # ruby -e "require 'rubygems'; require 'term/ansicolor'; puts Lucid::Term::ANSIColor.attributes"
59
+ #
60
+ module ANSIColor
61
+ include Lucid::Term::ANSIColor
62
+
63
+ ALIASES = Hash.new do |h,k|
64
+ if k.to_s =~ /(.*)_param/
65
+ h[$1] + ',bold'
66
+ end
67
+ end.merge({
68
+ 'undefined' => 'yellow',
69
+ 'pending' => 'yellow',
70
+ 'failed' => 'red',
71
+ 'passed' => 'green',
72
+ 'outline' => 'cyan',
73
+ 'skipped' => 'cyan',
74
+ 'comment' => 'grey',
75
+ 'tag' => 'cyan'
76
+ })
77
+
78
+ if ENV['CUCUMBER_COLORS'] # Example: export CUCUMBER_COLORS="passed=red:failed=yellow"
79
+ ENV['CUCUMBER_COLORS'].split(':').each do |pair|
80
+ a = pair.split('=')
81
+ ALIASES[a[0]] = a[1]
82
+ end
83
+ end
84
+
85
+ # Eval to define the color-named methods required by Term::ANSIColor.
86
+ #
87
+ # Examples:
88
+ #
89
+ # def failed(string=nil, &proc)
90
+ # red(string, &proc)
91
+ # end
92
+ #
93
+ # def failed_param(string=nil, &proc)
94
+ # red(bold(string, &proc)) + red
95
+ # end
96
+ ALIASES.each_key do |method_name|
97
+ unless method_name =~ /.*_param/
98
+ code = <<-EOF
99
+ def #{method_name}(string=nil, &proc)
100
+ #{ALIASES[method_name].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method_name].split(",").length}
101
+ end
102
+ # This resets the colour to the non-param colour
103
+ def #{method_name}_param(string=nil, &proc)
104
+ #{ALIASES[method_name+'_param'].split(",").join("(") + "(string, &proc" + ")" * ALIASES[method_name+'_param'].split(",").length} + #{ALIASES[method_name].split(",").join(' + ')}
105
+ end
106
+ EOF
107
+ eval(code)
108
+ end
109
+ end
110
+
111
+ def self.define_grey #:nodoc:
112
+ begin
113
+ gem 'genki-ruby-terminfo'
114
+ require 'terminfo'
115
+ case TermInfo.default_object.tigetnum("colors")
116
+ when 0
117
+ raise "Your terminal doesn't support colours."
118
+ when 1
119
+ ::Lucid::Term::ANSIColor.coloring = false
120
+ alias grey white
121
+ when 2..8
122
+ alias grey white
123
+ else
124
+ define_real_grey
125
+ end
126
+ rescue Exception => e
127
+ if e.class.name == 'TermInfo::TermInfoError'
128
+ STDERR.puts "*** WARNING ***"
129
+ STDERR.puts "You have the genki-ruby-terminfo gem installed, but you haven't set your TERM variable."
130
+ STDERR.puts "Try setting it to TERM=xterm-256color to get grey colour in output."
131
+ STDERR.puts "\n"
132
+ alias grey white
133
+ else
134
+ define_real_grey
135
+ end
136
+ end
137
+ end
138
+
139
+ def self.define_real_grey #:nodoc:
140
+ def grey(string) #:nodoc:
141
+ if ::Lucid::Term::ANSIColor.coloring?
142
+ "\e[90m#{string}\e[0m"
143
+ else
144
+ string
145
+ end
146
+ end
147
+ end
148
+
149
+ define_grey
150
+
151
+ def cukes(n)
152
+ ("(::) " * n).strip
153
+ end
154
+
155
+ def green_cukes(n)
156
+ blink(green(cukes(n)))
157
+ end
158
+
159
+ def red_cukes(n)
160
+ blink(red(cukes(n)))
161
+ end
162
+
163
+ def yellow_cukes(n)
164
+ blink(yellow(cukes(n)))
165
+ end
166
+ end
167
+ end
168
+ end