class Cucumber::Formatters::PrettyFormatter

def dump

def dump
  @io.puts
  print_pending_messages if @pending_messages.any?
  @io.puts dump_count(@total_scenario_count, "scenario")
  @io.puts pending(dump_count(@pending_scenarios.length, "scenario", "pending")) if @pending_scenarios.any?
  @io.puts passed(dump_count(@passed.length, "step", "passed"))   if @passed.any?
  @io.puts failed(dump_count(@failed.length, "step", "failed"))   if @failed.any?
  @io.puts skipped(dump_count(@skipped.length, "step", "skipped")) if @skipped.any?
  if @pending_steps.any?
    @io.print pending(dump_count(@pending_steps.length, "step", "pending")) 
    @io.print pending(" (#{number_of_unimplemented_steps} with no step definition)") if number_of_unimplemented_steps > 0
    @io.puts
  end
  @io.print reset
  print_snippets if @options[:snippets]
end

def dump_count(count, what, state=nil)

def dump_count(count, what, state=nil)
  return [count, "#{what}#{count == 1 ? '' : 's'}", state].compact.join(" ")
end

def escape_regexp_characters(string)

def escape_regexp_characters(string)
  Regexp.escape(string).gsub('\ ', ' ').gsub('/', '\/') unless string.nil?
end

def feature_executing(feature)

def feature_executing(feature)
  @feature = feature
end

def header_executing(header)

def header_executing(header)
  @io.puts if @feature_newline
  @feature_newline = true
  header_lines = header.split("\n")
  header_lines.each_with_index do |line, index|
    @io.print line
    if @options[:source] && index==0
      @io.print padding_spaces(@feature)
      @io.print comment("# #{@feature.file}")
    end
    @io.puts
  end
end

def initialize(io, step_mother, options={})

def initialize(io, step_mother, options={})
  @io = (io == STDOUT) ? Kernel : io
  @options = options
  @step_mother = step_mother
  @pending_scenarios  = []
  @passed             = []
  @failed             = []
  @pending_steps      = []
  @skipped            = []
  @last_executed_was_row = false
  @pending_messages = {}
  @forced_pending_step_count = 0
  
  @total_scenario_count = 0
end

def next_column_index

def next_column_index
  @current_column ||= -1
  @current_column += 1
  @current_column = 0 if @current_column >= @table_column_widths.size
  @current_column
end

def number_of_unimplemented_steps

def number_of_unimplemented_steps
  @pending_steps.length - @forced_pending_step_count
end

def output_failing_step(step)

def output_failing_step(step)
  @io.puts failed("      #{step.error.message.split("\n").join(INDENT)} (#{step.error.class})")
  @io.puts failed("      #{step.error.cucumber_backtrace.join(INDENT)}")
end

def padding_spaces(tree_item)

def padding_spaces(tree_item)
  " " * tree_item.padding_length
end

def print_failed_args(args)

def print_failed_args(args)
  print_row(args) {|arg| failed(arg)}
end

def print_passed_args(args)

def print_passed_args(args)
  print_row(args) {|arg| passed(arg)}
end

def print_pending_args(args)

def print_pending_args(args)
  print_row(args) {|arg| pending(arg)}
end

def print_pending_messages

def print_pending_messages
  @io.puts "Pending Notes:"
  @pending_messages.each_value do |message|
    @io.puts message
  end
  @io.puts
end

def print_row(row_args, &colorize_proc)

def print_row(row_args, &colorize_proc)
  colorize_proc = Proc.new{|row_element| row_element} unless colorize_proc
  row_args.each do |row_arg|
    column_index = next_column_index
    @io.print colorize_proc[row_arg.ljust(@table_column_widths[column_index])]
    @io.print "|"
  end
end

def print_skipped_args(args)

def print_skipped_args(args)
  print_row(args) {|arg| skipped(arg)}
end

def print_snippets

def print_snippets
  snippets = @pending_steps
  snippets.delete_if {|snippet| snippet.row? || @step_mother.has_step_definition?(snippet.name)}
  unless snippets.empty?
    @io.puts "\nYou can use these snippets to implement pending steps which have no step definition:\n\n"
    prev_keyword = nil
    snippets = snippets.map do |step|
      snippet = "#{step.actual_keyword} /^#{escape_regexp_characters(step.name)}$/ do\nend\n\n"
      prev_keyword = step.keyword
      snippet
    end.compact.uniq
    snippets.each do |snippet|
      @io.puts snippet
    end
  end
end

def scenario_executed(scenario)

def scenario_executed(scenario)
  @io.puts
  if !scenario.row? && scenario.table_header
    @table_column_widths = scenario.table_column_widths
    @current_column = -1
    @io.print "    |"
    print_row(scenario.table_header)
    @io.puts
  elsif scenario.row? && @scenario_failed
    @io.puts
    output_failing_step(@failed.last)
  end
  @total_scenario_count += 1
end

def scenario_executing(scenario)

def scenario_executing(scenario)
  scenario_or_scenario_outline_keyword = scenario.outline? ? Cucumber.language['scenario_outline'] : Cucumber.language['scenario']
  
  @scenario_failed = false
  @io.puts if @last_executed_was_row && !scenario.row?
  if scenario.row?
    @last_executed_was_row = true
    @io.print "    |"
  else
    scenario_text = "#{scenario_or_scenario_outline_keyword}: #{scenario.name}"
    
    if scenario.pending?
      @pending_scenarios << scenario
      @io.print pending("  #{scenario_text}")
    elsif scenario.outline?
      @io.print skipped("  #{scenario_text}")
    else
      @io.print passed("  #{scenario_text}")
    end
    @last_executed_was_row = false
    if @options[:source]
      @io.print padding_spaces(scenario)
      @io.print comment("# #{scenario.file}:#{scenario.line}")
    end
    @io.puts
  end
end

def source_comment(step)

def source_comment(step)
  _, _, proc = step.regexp_args_proc(@step_mother)
  comment(proc.to_comment_line)
end

def step_failed(step, regexp, args)

def step_failed(step, regexp, args)
  @scenario_failed = true
  if step.row?
    args = step.visible_args if step.outline?
    @failed << step
    print_failed_args(args)
  else
    @failed << step
    @io.print failed("    #{step.keyword} #{step.format(regexp){|param| failed_param(param) << failed}}")
    if @options[:source]
      @io.print padding_spaces(step)
      @io.print source_comment(step)
    end
    @io.puts
    output_failing_step(step)
  end
end

def step_passed(step, regexp, args)

def step_passed(step, regexp, args)
  if step.row?
    args = step.visible_args if step.outline?
    @passed << step
    print_passed_args(args)
  else
    @passed << step
    @io.print passed("    #{step.keyword} #{step.format(regexp){|param| passed_param(param) << passed}}")
    if @options[:source]
      @io.print padding_spaces(step)
      @io.print source_comment(step)
    end
    @io.puts
  end
end

def step_pending(step, regexp, args)

def step_pending(step, regexp, args)
  if step.row?
    args = step.visible_args if step.outline?
    @pending_steps << step
    print_pending_args(args)
  else
    @pending_steps << step
    @io.print pending("    #{step.keyword} #{step.name}")
    if @options[:source]
      @io.print padding_spaces(step)
      @io.print comment("# #{step.file}:#{step.line}")
    end
    @io.puts
  end
  if step.forced_to_pending?
    @pending_messages[regexp.inspect] ||= "#{step.keyword} #{regexp.inspect} (#{step.error.message}) #{source_comment(step)}" 
    @forced_pending_step_count += 1
  end
end

def step_skipped(step, regexp, args)

def step_skipped(step, regexp, args)
  @skipped << step
  if step.row?
    args = step.visible_args if step.outline?
    print_skipped_args(args)
  else
    @io.print skipped("    #{step.keyword} #{step.format(regexp){|param| skipped_param(param) << skipped}}")
    if @options[:source]
      @io.print padding_spaces(step)
      if step.outline?
        @io.print comment("# #{step.file}:#{step.line}")
      else
        @io.print source_comment(step)
      end
    end
    @io.puts
  end
end

def step_traced(step, regexp, args)

def step_traced(step, regexp, args)
  @io.print skipped("    #{step.keyword} #{step.format(regexp){|param| skipped_param(param) << skipped}}")
  if @options[:source]
    @io.print padding_spaces(step)
    @io.print comment("# #{step.file}:#{step.line}")
  end
  @io.puts
end