class Tryouts::Tryout

def add_drill(d)

more dreams in +@dream_catcher+, it will be added to drill +d+.
Add a Drill object to the list for this Tryout. If there is one or
def add_drill(d)
  unless @dream_catcher.empty?
    d.add_dreams *@dream_catcher.clone   # We need to clone here b/c
    @dream_catcher.clear                 # Ruby passes by reference.
  end
  drills << d
  d
end

def clean(&block)

A block to executed one time _after_ the drills
def clean(&block)
  return @clean unless block
  @clean = block
end

def dream(*args, &definition)

NOTE: This method is DSL-only. It's not intended to be used in OO syntax.
def dream(*args, &definition) 
  if args.empty?
    dobj = Tryouts::Drill::Dream.from_block definition
  else
    args = args.size == 1 ? [args.first] : args.reverse
    dobj = Tryouts::Drill::Dream.new(*args)
  end
  @dream_catcher.push dobj
  dobj
end

def drill(dname, *args, &definition)

+args+ is sent directly to the Drill class. The values are specific on the Sergeant.
+name+ is the name of the drill.
Create and add a Drill object to the list for this Tryout
def drill(dname, *args, &definition)
  raise "Empty drill name (#{@name})" if dname.nil? || dname.empty?
  drill = Tryouts::Drill.new(dname, @dtype, *args, &definition)
  self.add_drill drill
end

def from_block(b=nil, &inline)

the external DSL methods: dream, drill, xdrill
Populate this Tryout from a block. The block should contain calls to
def from_block(b=nil, &inline)
  runtime = b.nil? ? inline : b
  begin
    instance_eval &runtime
  rescue => ex
    raise ex
  end
end

def initialize(name, dtype, command=nil, *args)

def initialize(name, dtype, command=nil, *args)
  raise "Must supply command for dtype :cli" if dtype == :cli && command.nil?
  raise "#{dtype} is not a valid drill type" if !Drill.valid_dtype?(dtype)
  @name, @dtype, @command = name, dtype, command
  @drills, @dream_catcher = [], []
  @passed, @failed, @skipped = 0, 0, 0
end

def report

Prints error output. If there are no errors, it prints nothing.
def report
  return if Tryouts.verbose < 0
  failed = @drills.select { |d| !d.skip? && !d.success? }
  failed.each_with_index do |drill,index|
    title = ' %-69s %2d/%-2d  ' % ["\"#{drill.name}\"", index+1, failed.size]
    puts $/, ' ' << title.color(:red).att(:reverse)
    puts drill.report
  end
  # Print errors for successful runs too
  success = @drills.select { |d| !d.skip? && d.success? }
  success.each do |drill,index|
    next unless drill.has_error?
    title = ' %-69s ' % ["\"#{drill.name}\""]
    puts $/, ' ' << title.color(:red).att(:reverse)
    puts drill.report
  end
end

def run

Execute all Drill objects
def run
  DrillContext.module_eval &setup if setup.is_a?(Proc)
  puts "\n  %s ".bright % @name unless Tryouts.verbose < 0
  @drills.each do |drill|
    print '   %-69s ' % "\"#{drill.name}\"" unless Tryouts.verbose < 0
    drill.run DrillContext.new
    if drill.skip?
      @skipped += 1
    elsif drill.success?
      @passed += 1
    else
      @failed += 1
    end
    puts drill.flag                           # PASS, FAIL, SKIP
    puts drill.info if Tryouts.verbose > 0 && !drill.skip?  
  end
  DrillContext.module_eval &clean if clean.is_a?(Proc)
end

def setup(&block)

A block to executed one time _before_ starting the drills
def setup(&block)
  return @setup unless block
  @setup = block
end

def success?

Did every Tryout finish successfully?
def success?
  return @success unless @success.nil?
  # Returns true only when every Tryout result returns true
  @success = !(@drills.collect { |r| r.success? }.member?(false))
end

def xdream(*args, &b); end

A quick way to comment out a dream
def xdream(*args, &b); end

def xdrill(dname, *args, &b)

A quick way to comment out a drill
def xdrill(dname, *args, &b)
  @dream_catcher.clear     # Otherwise the next drill will get them...
  self.add_drill Tryouts::Drill.new(dname, :skip)
end