class Cucumber::StepMother

This is the meaty part of Cucumber that ties everything together.

def after(scenario) #:nodoc:

:nodoc:
def after(scenario) #:nodoc:
  @current_scenario = nil
  return if options[:dry_run]
  @programming_languages.each do |programming_language|
    programming_language.after(scenario)
  end
end

def after_configuration(configuration) #:nodoc

:nodoc
def after_configuration(configuration) #:nodoc
  @programming_languages.each do |programming_language|
    programming_language.after_configuration(configuration)
  end
end

def after_step #:nodoc:

:nodoc:
def after_step #:nodoc:
  return if options[:dry_run]
  @programming_languages.each do |programming_language|
    programming_language.execute_after_step(@current_scenario)
  end
end

def announce(msg)


nicer, and in all outputs (in case you use several formatters)
This is an alternative to using Kernel#puts - it will display
Output +announcement+ alongside the formatted output.
def announce(msg)
  msg.respond_to?(:join) ? @visitor.announce(msg.join("\n")) : @visitor.announce(msg.to_s)
end

def ask(question, timeout_seconds)


that makes a sound before invoking #ask.
If that doesn't issue a beep, you can shell out to something else

ask("#{7.chr}How many cukes are in the external system?")

just prepend ASCII character 7 to the question:
If you want a beep to happen (to grab the manual tester's attention),

the result is added to the output using #announce.
. The entered text is returned, and both +question+ and
An operator (manual tester) can then enter a line of text and hit
Suspends execution and prompts +question+ to the console (STDOUT).
def ask(question, timeout_seconds)
  STDOUT.puts(question)
  STDOUT.flush
  announce(question)
  if(Cucumber::JRUBY)
    answer = jruby_gets(timeout_seconds)
  else
    answer = mri_gets(timeout_seconds)
  end
  
  if(answer)
    announce(answer)
    answer
  else
    raise("Waited for input for #{timeout_seconds} seconds, then timed out.")
  end
end

def before(scenario) #:nodoc:

:nodoc:
def before(scenario) #:nodoc:
  return if options[:dry_run] || @current_scenario
  @current_scenario = scenario
  @programming_languages.each do |programming_language|
    programming_language.before(scenario)
  end
end

def before_and_after(scenario, skip_hooks=false) #:nodoc:

:nodoc:
def before_and_after(scenario, skip_hooks=false) #:nodoc:
  before(scenario) unless skip_hooks
  yield scenario
  after(scenario) unless skip_hooks
  scenario_visited(scenario)
end

def best_matches(step_name, step_matches) #:nodoc:

:nodoc:
def best_matches(step_name, step_matches) #:nodoc:
  no_groups      = step_matches.select {|step_match| step_match.args.length == 0}
  max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
  top_groups     = step_matches.select {|step_match| step_match.args.length == max_arg_length }
  if no_groups.any?
    longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
    no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
  elsif top_groups.any?
    shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } }.min
    top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.to_s.length } == shortest_capture_length }
  else
    top_groups
  end
end

def embed(file, mime_type)


not be ignored, depending on what kind of formatter(s) are active.
Embed +file+ of MIME type +mime_type+ into the output. This may or may
def embed(file, mime_type)
  @visitor.embed(file, mime_type)
end

def initialize

def initialize
  @unsupported_programming_languages = []
  @programming_languages = []
  @language_map = {}
  @current_scenario = nil
end

def invoke(step_name, multiline_argument=nil)

def invoke(step_name, multiline_argument=nil)
  begin
    step_match(step_name).invoke(multiline_argument)
  rescue Exception => e
    e.nested! if Undefined === e
    raise e
  end
end

def invoke_steps(steps_text, natural_language)

})
Then I should not be thirsty
Given I have 8 cukes in my belly
invoke(%Q{

Invokes a series of steps +steps_text+. Example:
def invoke_steps(steps_text, natural_language)
  ored_keywords = natural_language.step_keywords.map{|kw| Regexp.escape(kw)}.join("|")
  # TODO Gherkin:
  # This a bit hacky and fragile. When we move to Gherkin we should replace this entire method body
  # with a call to the parser - parsing the body of a scenario. We may need to put the parser/policy in the
  # appropriate state (the same state it's in after parsing a Scenario: line).
  steps_text.strip.split(/(?=^\s*(?:#{ored_keywords}))/).map { |step| step.strip }.each do |step|
    output = step.match(/^\s*(#{ored_keywords})([^\n]+)(\n.*)?$/m)
    action, step_name, table_or_string = output[1], output[2], output[3]
    if table_or_string.to_s.strip =~ /^\|/
      table_or_string = table(table_or_string) 
    elsif table_or_string.to_s.strip =~ /^"""/
      table_or_string = py_string(table_or_string.gsub(/^\n/, ""))
    end
    args = [step_name, table_or_string].compact
    invoke(*args)
  end
end

def jruby_gets(timeout_seconds)

def jruby_gets(timeout_seconds)
  answer = nil
  t = java.lang.Thread.new do
    answer = STDIN.gets
  end
  t.start
  t.join(timeout_seconds * 1000)
  answer
end

def load_code_file(step_def_file)

def load_code_file(step_def_file)
  if programming_language = programming_language_for(step_def_file)
    log.debug("  * #{step_def_file}\n")
    programming_language.load_code_file(step_def_file)
  else
    log.debug("  * #{step_def_file} [NOT SUPPORTED]\n")
  end
end

def load_code_files(step_def_files)

def load_code_files(step_def_files)
  log.debug("Code:\n")
  step_def_files.each do |step_def_file|
    load_code_file(step_def_file)
  end
  log.debug("\n")
end

def load_plain_text_features(feature_files)

def load_plain_text_features(feature_files)
  features = Ast::Features.new
  start = Time.new
  log.debug("Features:\n")
  feature_files.each do |f|
    feature_file = FeatureFile.new(f)
    feature = feature_file.parse(self, options)
    if feature
      features.add_feature(feature)
      log.debug("  * #{f}\n")
    end
  end
  duration = Time.now - start
  log.debug("Parsing feature files took #{format_duration(duration)}\n\n")
  features
end

def load_programming_language(ext)


twice will return the same instance.
Instances are cached, so calling with the same argument
Loads and registers programming language implementation.
def load_programming_language(ext)
  return @language_map[ext] if @language_map[ext]
  programming_language_class = constantize("Cucumber::#{ext.capitalize}Support::#{ext.capitalize}Language")
  programming_language = programming_language_class.new(self)
  @programming_languages << programming_language
  @language_map[ext] = programming_language
  programming_language
end

def log

def log
  @log ||= Logger.new(STDOUT)
end

def max_step_definition_length #:nodoc:

:nodoc:
def max_step_definition_length #:nodoc:
  @max_step_definition_length ||= step_definitions.map{|step_definition| step_definition.text_length}.max
end

def mri_gets(timeout_seconds)

def mri_gets(timeout_seconds)
  begin
    Timeout.timeout(timeout_seconds) do
      STDIN.gets
    end
  rescue Timeout::Error => e
    nil
  end
end

def options

Returns the options passed on the command line.
def options
  @options ||= {}
end

def programming_language_for(step_def_file) #:nodoc:

:nodoc:
def programming_language_for(step_def_file) #:nodoc:
  if ext = File.extname(step_def_file)[1..-1]
    return nil if @unsupported_programming_languages.index(ext)
    begin
      load_programming_language(ext)
    rescue LoadError => e
      log.debug("Failed to load '#{ext}' programming language for file #{step_def_file}: #{e.message}\n")
      @unsupported_programming_languages << ext
      nil
    end
  else
    nil
  end
end

def py_string(string_with_triple_quotes, file=nil, line_offset=0)


Is retured as: " hello\nworld"

"""
world
hello
"""

Returns a regular String for +string_with_triple_quotes+. Example:
def py_string(string_with_triple_quotes, file=nil, line_offset=0)
  Ast::PyString.parse(string_with_triple_quotes)
end

def scenario_visited(scenario) #:nodoc:

:nodoc:
def scenario_visited(scenario) #:nodoc:
  scenarios << scenario unless scenarios.index(scenario)
end

def scenarios(status = nil) #:nodoc:

:nodoc:
def scenarios(status = nil) #:nodoc:
  @scenarios ||= []
  if(status)
    @scenarios.select{|scenario| scenario.status == status}
  else
    @scenarios
  end
end

def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:

:nodoc:
def snippet_text(step_keyword, step_name, multiline_arg_class) #:nodoc:
  load_programming_language('rb') if unknown_programming_language?
  @programming_languages.map do |programming_language|
    programming_language.snippet_text(step_keyword, step_name, multiline_arg_class)
  end.join("\n")
end

def step_match(step_name, name_to_report=nil) #:nodoc:

:nodoc:
def step_match(step_name, name_to_report=nil) #:nodoc:
  matches = @programming_languages.map do |programming_language| 
    programming_language.step_matches(step_name, name_to_report).to_a
  end.flatten
  raise Undefined.new(step_name) if matches.empty?
  matches = best_matches(step_name, matches) if matches.size > 1 && options[:guess]
  raise Ambiguous.new(step_name, matches, options[:guess]) if matches.size > 1
  matches[0]
end

def step_visited(step) #:nodoc:

:nodoc:
def step_visited(step) #:nodoc:
  steps << step unless steps.index(step)
end

def steps(status = nil) #:nodoc:

:nodoc:
def steps(status = nil) #:nodoc:
  @steps ||= []
  if(status)
    @steps.select{|step| step.status == status}
  else
    @steps
  end
end

def table(text_or_table, file=nil, line_offset=0)


])
%w{ CUC-101 Peeler 22 }
%w{ INT-100 Taxi 114 },
%w{ account description amount },
table([

or a 2D Array:

})
| CUC-101 | Peeler | 22 |
| INT-100 | Taxi | 114 |
| account | description | amount |
table(%{

be a String:
Returns a Cucumber::Ast::Table for +text_or_table+, which can either
def table(text_or_table, file=nil, line_offset=0)
  if Array === text_or_table
    Ast::Table.new(text_or_table)
  else
    Ast::Table.parse(text_or_table)
  end
end

def unknown_programming_language?

def unknown_programming_language?
  @programming_languages.empty?
end

def unmatched_step_definitions

def unmatched_step_definitions
  @programming_languages.map do |programming_language| 
    programming_language.unmatched_step_definitions
  end.flatten
end