class Tryouts


May all your dreams come true!
==== Are you ready to run some drills?
* It stores all known instances of Tryouts objects in a class variable @@instances.
are modified to support DSL syntax by acting like setters when given arguments)
class methods are the handlers for the DSL syntax (some instance getter methods
* The tryouts and dreams DSLs are executed within its namespace. In general the
* It represents the Tryouts object which is a group of Tryout objects.
This class has three purposes:
= Tryouts

def self.command(*args)

NOTE: this is a standalone DSL-syntax method.

Calls Tryouts#command on the current instance of Tryouts
def self.command(*args)
  @@instances.last.command(*args)
end

def self.debug?; @@debug; end

def self.debug?; @@debug; end

def self.disable_debug; @@debug = false; end

def self.disable_debug; @@debug = false; end

def self.enable_debug; @@debug = true; end

def self.enable_debug; @@debug = true; end

def self.failed=(v); @@failed = v; end

def self.failed=(v); @@failed = v; end

def self.failed?; @@failed; end

def self.failed?; @@failed; end

def self.group(*args)

NOTE: this is a standalone DSL-syntax method.

because the group name is taken from the name of the class. See inherited.
Raises a Tryouts::Exception. +group+ is not support in the standalone syntax
def self.group(*args)
  raise "Group is already set: #{@@instances.last.group}"
end

def self.inherited(klass)

NOTE: this is a standalone DSL-syntax method.

to +@@instances+.
of Tryouts, sets group to the name of the new class, and adds the instance
Called when a new class inherits from Tryouts. This creates a new instance
def self.inherited(klass)
  to = @@instances[ klass ]
  to ||= Tryouts.new
  to.paths << __FILE__
  to.group = klass
  @@instances[to.group] = to
end

def self.instances; @@instances; end

Returns +@@instances+
def self.instances; @@instances; end

def self.library(*args)

NOTE: this is a standalone DSL-syntax method.

Calls Tryouts#library on the current instance of Tryouts
def self.library(*args)
  @@instances.last.library(*args)
end

def self.parse_file(fpath)

NOTE: this is an OO syntax method

Parse a +_tryouts.rb+ file. See Tryouts::CLI::Run for an example.
def self.parse_file(fpath)
  raise "No such file: #{fpath}" unless File.exists?(fpath)
  file_content = File.read(fpath)
  to = Tryouts.new
  begin
    to.paths << fpath
    to.instance_eval file_content, fpath
    # After parsing the DSL, we'll know the group name.
    # If a Tryouts object already exists for that group
    # we'll use that instead and re-parse the DSL. 
    if @@instances.has_key? to.group
      to = @@instances[to.group]
      to.instance_eval file_content, fpath
    end
  rescue SyntaxError, LoadError, Exception, TypeError,
         RuntimeError, NoMethodError, NameError => ex
    to.errors << ex
    Tryouts.failed = true
    # It's helpful to display the group name
    file_content.match(/^group (.+?)$/) do |x,t|
      # We use eval as a quick cheat so we don't have
      # to parse all the various kinds of quotes.
      to.group = eval x.captures.first
    end
  end
  @@instances[to.group] = to
  to
end

def self.run

NOTE: this is an OO syntax method

Run all Tryout objects in +@tryouts+
def self.run
  @@instances.each_pair do |group, inst|
    inst.tryouts.each_pair do |name,to|
      to.run
      to.report
    end
  end
end

def self.sysinfo; @@sysinfo; end

Returns +@@sysinfo+
def self.sysinfo;   @@sysinfo;   end

def self.tryout(*args, &block)

NOTE: this is a standalone DSL-syntax method.

Calls Tryouts#tryout on the current instance of Tryouts
def self.tryout(*args, &block)
  @@instances.last.tryout(*args, &block)
end

def self.tryouts(*args, &block)

An alias for Tryouts.tryout.
def self.tryouts(*args, &block)
  tryout(args, &block)
end

def self.verbose; @@verbose; end

def self.verbose; @@verbose; end

def self.verbose=(v); @@verbose = (v == true) ? 1 : v; end

def self.verbose=(v); @@verbose = (v == true) ? 1 : v; end

def self.xtryout(*args, &block); end

NOTE: this is a standalone DSL-syntax method.

This method does nothing. It provides a quick way to disable a tryout.
def self.xtryout(*args, &block); end

def self.xtryouts(*args, &block); end

NOTE: this is a standalone DSL-syntax method.

This method does nothing. It provides a quick way to disable a tryout.
def self.xtryouts(*args, &block); end

def command(name=nil, path=nil)

in @@commands so it can be used as the default for drills
Add a shell command to Rye::Cmd and save the command name
def command(name=nil, path=nil)
  return @command if name.nil?
  require 'rye'
  @command = name.to_sym
  @dtype = :cli
  Rye::Cmd.module_eval do
    define_method(name) do |*args|
      cmd(path || name, *args)
    end
  end
  @command
end

def find_tryout(name, dtype=nil)

+dtype+ if specified. Returns a Tryout object or nil.
Find matching Tryout objects by +name+ and filter by
def find_tryout(name, dtype=nil)
  by_name = @tryouts.values.select { |t| t.name == name }
  by_name = by_name.select { |t| t.dtype == dtype } if dtype
  by_name.first  # by_name is an Array. We just want the Object. 
end

def from_block(b, &inline)

the external DSL methods: tryout, command, library, group
Populate this Tryouts from a block. The block should contain calls to
def from_block(b, &inline)
  instance_eval &b
end

def group(name=nil)

def group(name=nil)
  return @group if name.nil?
  @group = name unless name.nil?
  @group
end

def initialize(group=nil)

def initialize(group=nil)
  @group = group || "Default Group"
  @tryouts = HASH_TYPE.new
  @paths, @errors = [], []
  @command = nil
end

def library(name=nil, *path)


library __FILE__, '..', 'lib'
library '/an/absolute/path'

in specified in multiple arguments they are joined and expanded.
a specific copy of the library. Otherwise, it loads from the system path. If the path
* +path+ Add a path to the front of $LOAD_PATH (optional). Use this if you want to load
* +name+ The name of the library in question (required). Stored as a Symbol to +@library+.
Require +name+. If +path+ is supplied, it will "require path".
def library(name=nil, *path)
  return @library if name.nil?
  @library, @dtype = name.to_sym, :api
  path = File.expand_path(File.join(*path))
  $LOAD_PATH.unshift path unless path.nil?
  begin
    require @library.to_s
  rescue LoadError => ex
    newex = Tryouts::Exception.new(ex.message)
    trace = ex.backtrace
    trace.unshift @paths.last
    newex.set_backtrace trace
    @errors << newex
    Tryouts.failed = true
  rescue SyntaxError, Exception, TypeError, 
         RuntimeError, NoMethodError, NameError => ex
    @errors << ex
    Tryouts.failed = true
  end
end

def report

Execute Tryout#report for each Tryout in +@tryouts+
def report
  successes = []
  @tryouts.each_pair { |n,to| successes << to.report }
  puts $/, "All your dreams came true" unless successes.member?(false)
end

def run; @tryouts.each_pair { |n,to| to.run }; end

Execute Tryout#run for each Tryout in +@tryouts+
def run; @tryouts.each_pair { |n,to| to.run }; end

def tryout(name, dtype=nil, command=nil, &block)

NOTE: This is a DSL-only method and is not intended for OO use.

* +b+ is a block definition for the Tryout. See Tryout#from_block
* +command+ when type is :cli, this is the name of the Rye::Box method that we're testing. Otherwise ignored.
* +dtype+ is the default drill type for the Tryout.
* +name+ is the name of the Tryout
Create a new Tryout object and add it to the list for this Tryouts class.
def tryout(name, dtype=nil, command=nil, &block)
  return if name.nil?
  dtype ||= @dtype
  command ||= @command if dtype == :cli
  
  raise NoDrillType, name if dtype.nil?
  
  to = find_tryout(name, dtype)
  if to.nil?
    to = Tryouts::Tryout.new(name, dtype, command)
    @tryouts[name] = to
  end
  
  # Process the rest of the DSL
  begin
    to.from_block block if block
  rescue SyntaxError, LoadError, Exception, TypeError,
         RuntimeError, NoMethodError, NameError => ex
    @errors << ex
    Tryouts.failed = true
  end
  to
end

def tryouts(*args, &block)

specifies "tryouts 'name' do ..." in the DSL.
Also acts as a stub for Tryouts#tryout in case someone

Returns +@tryouts+.
def tryouts(*args, &block)
  return tryout(*args, &block) unless args.empty?
  @tryouts
end

def xtryout(*args, &block); end

NOTE: This is a DSL-only method and is not intended for OO use.

This method does nothing. It provides a quick way to disable a tryout.
def xtryout(*args, &block); end

def xtryouts(*args, &block); end

NOTE: This is a DSL-only method and is not intended for OO use.

This method does nothing. It provides a quick way to disable a tryout.
def xtryouts(*args, &block); end