Drydock

Drydock is a DSL for command-line apps. See bin/example for usage examples.

Constants

VERSION

Public Instance Methods

about(txt) click to toggle source

Provide a description for a command

# File lib/drydock.rb, line 706
def about(txt)
  @@command_descriptions += [txt]
  return if get_current_option_parser.is_a?(Symbol)
  get_current_option_parser.on "ABOUT: #{txt}"
end
action(*args, &b) click to toggle source

Define a command-specific action.

This is functionally very similar to option, but with an exciting and buoyant twist: Drydock keeps track of actions for each command (in addition to treating it like an option). When an action is specified on the command line Drydock looks for command_action or action_command methods in the command class.

action :E, :eat, "Eat something"
command :oysters => Fresh::Oysters

# Drydock will look for Fresh::Oysters#eat_oysters and Fresh::Oysters#oysters_eat.
# File lib/drydock.rb, line 593
def action(*args, &b)
  ret = option(*args, &b) # returns an array of all the current option names
  current_command_action << ret.last # the most recent is last
end
after(&b) click to toggle source

Define a block to be called after the command. This is useful for stopping, closing, etc... the stuff in the before block.

# File lib/drydock.rb, line 507
def after(&b)
  @@after_block = b
end
alias_command(aliaz, cmd) click to toggle source

Used to create an alias to a defined command. Here's an example:

command :task do; ...; end
alias_command :pointer, :task

Either name can be used on the command-line:

$ yourscript task [options]
$ yourscript pointer [options]

Inside of the command definition, you have access to the command name that was used via obj.alias.

# File lib/drydock.rb, line 667
def alias_command(aliaz, cmd)
  return unless commands.has_key? cmd
  commands[canonize(aliaz)] = commands[cmd]
end
argv(*args) click to toggle source

Provide names for CLI arguments, in the order they appear.

$ yourscript sample malpeque zinqy
argv :name, :flavour
command :sample do |obj|
  obj.argv.name        # => malpeque
  obj.argv.flavour     # => zinqy
end
# File lib/drydock.rb, line 421
def argv(*args)
  @@command_argv_names[@@command_index] ||= []
  @@command_argv_names[@@command_index] += args.flatten
end
before(&b) click to toggle source

Define a block to be called before the command. This is useful for opening database connections, etc...

# File lib/drydock.rb, line 501
def before(&b)
  @@before_block = b
end
canonize(cmd) click to toggle source

Canonizes a string (cmd) to the symbol for command names '-' is replaced with '_'

# File lib/drydock.rb, line 784
def canonize(cmd)
  return unless cmd
  return cmd if cmd.kind_of?(Symbol)
  cmd.to_s.tr('-', '_').to_sym
end
capture(io) click to toggle source
# File lib/drydock.rb, line 764
def capture(io)
  @@capture = io
end
capture?() click to toggle source
# File lib/drydock.rb, line 772
def capture?
  !@@capture.nil?
end
capture_io(stream, &block) click to toggle source

Capture STDOUT or STDERR to prevent it from being printed.

capture(:stdout) do
  ...
end
# File lib/drydock.rb, line 803
def capture_io(stream, &block)
  raise "We can only capture STDOUT or STDERR" unless stream == :stdout || stream == :stderr
  begin
    eval "$#{stream} = StringIO.new"
    block.call
    eval("$#{stream}").rewind                  # Otherwise we'll get nil 
    result = eval("$#{stream}").read
  ensure
    eval "$#{stream} = #{stream.to_s.upcase}"  # Put it back!
  end
end
captured() click to toggle source
# File lib/drydock.rb, line 768
def captured
  @@captured
end
command(*cmds, &b) click to toggle source

Define a command.

command :task do
  ...
end

A custom command class can be specified using Hash syntax. The class must inherit from Drydock::Command (class CustomeClass < Drydock::Command)

command :task => CustomCommand do
  ...
end
# File lib/drydock.rb, line 611
def command(*cmds, &b)
  cmd = cmds.shift # Should we accept aliases here?
  
  if cmd.is_a? Hash
    klass = cmd.values.first
    names = cmd.keys.first
    if names.is_a? Array
      cmd, cmds = names.shift, [names].flatten.compact
    else
      cmd = names
    end
    raise "#{klass} is not a subclass of Drydock::Command" unless klass.ancestors.member?(Drydock::Command)
    c = klass.new(cmd, &b)          # A custom class was specified
  else
    c = Drydock::Command.new(cmd, &b)
  end
  
  @@command_descriptions[@@command_index] ||= ""
  @@command_actions[@@command_index] ||= []
  @@command_argv_names[@@command_index] ||= []
  
  c.desc = @@command_descriptions[@@command_index]
  c.actions = @@command_actions[@@command_index]
  c.argv.fields = @@command_argv_names[@@command_index]
  
  # Default Usage Banner. 
  # Without this, there's no help displayed for the command. 
  option_parser = get_option_parser(@@command_index)
  if option_parser.is_a?(OptionParser) && option_parser.banner !~ /^USAGE/
    usage "#{c.executable} #{c.cmd}"
  end
  
  @@commands[c.cmd] = c
  @@command_index_map[c.cmd] = @@command_index
  @@command_index += 1 # This will point to the next command
  
  # Created aliases to the command using any additional command names 
  # i.e. command :something, :sumpin => Something
  cmds.each { |aliaz| command_alias(cmd, aliaz); } unless cmds.empty?
  
  c  # Return the Command object
end
command?(cmd) click to toggle source

Returns true if a command with the name cmd has been defined.

# File lib/drydock.rb, line 777
def command?(cmd)
  name = canonize(cmd)
  @@commands.has_key? name
end
command_alias(cmd, aliaz) click to toggle source

Identical to alias_command with reversed arguments. For whatever reason I forget the order so Drydock supports both. Tip: the argument order matches the method name.

# File lib/drydock.rb, line 675
def command_alias(cmd, aliaz)
  return unless commands.has_key? cmd
  commands[canonize(aliaz)] = commands[cmd]
end
command_names() click to toggle source

An array of the currently defined commands names

# File lib/drydock.rb, line 686
def command_names
  @@commands.keys.collect { |cmd| decanonize(cmd); }
end
commands() click to toggle source

A hash of the currently defined Drydock::Command objects

# File lib/drydock.rb, line 681
def commands
  @@commands
end
debug(toggle=false) click to toggle source

Enable or disable debug output.

debug :on
debug :off

Calling without :on or :off will toggle the value.

# File lib/drydock.rb, line 398
def debug(toggle=false)
  if toggle.is_a? Symbol
    @@debug = true if toggle == :on
    @@debug = false if toggle == :off
  else
    @@debug = (!@@debug)
  end
end
debug?() click to toggle source

Returns true if debug output is enabled.

# File lib/drydock.rb, line 408
def debug?
  @@debug
end
decanonize(cmd) click to toggle source

Returns a string version of cmd, decanonized. Lowercase, '_' is replaced with '-'

# File lib/drydock.rb, line 792
def decanonize(cmd)
  return unless cmd
  cmd.to_s.tr('_', '-')
end
default(cmd=nil, with_args=false, &b) click to toggle source

Define a default command. You can specify a command name that has been or will be defined in your script:

default :task

Or you can supply a block which will be used as the default command:

default do |obj|            # This command will be named "default"
  # ...
end

default :hullinspector do   # This one will be named "hullinspector"
  # ...
end

If with_args is specified, the default command will receive all unknown values as arguments. This is necessary to define explicitly because drydock parses arguments expecting a command name. If the default command accepts arguments and with_args is not specified, drydock will raise an unknown command exception for the first argument.

# File lib/drydock.rb, line 468
def default(cmd=nil, with_args=false, &b)
  raise "Calling default requires a command name or a block" unless cmd || b
  # Creates the command and returns the name or just stores given name
  @@default_command = (b) ? command(cmd || :default, &b).cmd : canonize(cmd)
  # IDEA: refactor out the argument parser to support different types of CLI
  @@default_command_with_args = with_args ? true : false
  @@default_command
end
default?(cmd) click to toggle source

Is cmd the default command?

# File lib/drydock.rb, line 478
def default?(cmd)
  return false if @@default_command.nil?
  (@@default_command == canonize(cmd))
end
default_with_args?() click to toggle source
# File lib/drydock.rb, line 484
def default_with_args?; @@default_command_with_args; end
desc(txt) click to toggle source

Deprecated. Use about.

# File lib/drydock.rb, line 712
def desc(txt)
  STDERR.puts "'desc' is deprecated. Please use 'about' instead."
  about(txt) 
end
global(*args, &b) click to toggle source
Alias for: global_option
global_option(*args, &b) click to toggle source

Define a global option. See option for more info.

# File lib/drydock.rb, line 539
def global_option(*args, &b)
  args.unshift(@@global_opts_parser)
  @@global_option_names << option_parser(args, &b)
end
Also aliased as: global
global_usage(msg) click to toggle source

Define the default global usage banner. This is displayed with "script -h".

# File lib/drydock.rb, line 513
def global_usage(msg)
  @@global_opts_parser.banner = "USAGE: #{msg}"
end
has_run?() click to toggle source

Return true if a command has been executed.

# File lib/drydock.rb, line 730
def has_run?
  @@has_run
end
ignore(what=:nothing) click to toggle source

Tell the Drydock parser to ignore something. Drydock will currently only listen to you if you tell it to "ignore :options", otherwise it will ignore you!

what the thing to ignore. When it equals :options Drydock will not parse the command-specific arguments. It will pass the arguments directly to the Command object. This is useful when you want to parse the arguments in some a way that's too crazy, dangerous for Drydock to handle automatically.

# File lib/drydock.rb, line 534
def ignore(what=:nothing)
  @@command_opts_parser[@@command_index] = :ignore if what == :options || what == :all
end
option(*args, &b) click to toggle source

Define a command-specific option.

args is passed directly to OptionParser.on so it can contain anything that's valid to that method. If a class is included, it will tell OptionParser to expect a value otherwise it assumes a boolean value. Some examples:

option :h, :help, "Displays this message"
option '-l x,y,z', '--lang=x,y,z', Array, "Requested languages"

You can also supply a block to fiddle with the values. The final 
value becomes the option's value:

option :m, :max, Integer, "Maximum threshold" do |v|
  v = 100 if v > 100
  v
end

All calls to option must come before the command they're associated to. Example:

option :t, :tasty,          "A boolean switch"
option     :reason, String, "Requires a parameter"
command :task do |obj|; 
  obj.options.tasty       # => true
  obj.options.reason      # => I made the sandwich!
end

When calling your script with a specific command-line option, the value is available via obj.longname inside the command block.

# File lib/drydock.rb, line 576
def option(*args, &b)
  args.unshift(get_current_option_parser)
  current_command_option_names << option_parser(args, &b)
end
project(txt=nil) click to toggle source

The project name. This is currently only used when printing list of commands (see: Drydock::Command#show_commands). It may be used elsewhere in the future.

# File lib/drydock.rb, line 429
def project(txt=nil)
  
  return @@project unless txt
  
  #begin
  #  require txt.downcase
  #rescue LoadError => ex
  #  Drydock.run = false  # Prevent execution at_exit
  #  abort "Problem during require: #{ex.message}"
  #end
  @@project = txt
end
project?() click to toggle source

Has the project been set?

# File lib/drydock.rb, line 443
def project?
  (defined?(@@project) && !@@project.nil?)
end
run!(argv=[], stdin=STDIN) click to toggle source

Execute the given command. By default, Drydock automatically executes itself and provides handlers for known errors. You can override this functionality by calling Drydock.run! yourself. Drydock will only call run! once.

# File lib/drydock.rb, line 738
def run!(argv=[], stdin=STDIN)
  return if has_run?
  @@has_run = true
  raise NoCommandsDefined.new if commands.empty?
  
  global_options, cmd_name, command_options, argv = process_arguments(argv)
  stdin = (defined? @@stdin_block) ? @@stdin_block.call(stdin, []) : stdin
  
  command_obj = get_command(cmd_name)
  command_obj.prepare(cmd_name, argv, stdin, global_options, command_options)
  
  # Execute before block
  @@before_block.call(command_obj) if defined? @@before_block
  
  # Execute the requested command. We'll capture STDERR or STDOUT if desired. 
  @@captured = capture? ? capture_io(@@capture) { command_obj.call } : command_obj.call
      
  # Execute after block
  @@after_block.call(command_obj) if defined? @@after_block
  
rescue OptionParser::InvalidOption => ex
  raise Drydock::InvalidArgument.new(ex.args)
rescue OptionParser::MissingArgument => ex
  raise Drydock::MissingArgument.new(ex.args)
end
run=(v) click to toggle source

Disable automatic execution (enabled by default)

Drydock.run = false
# File lib/drydock.rb, line 725
def run=(v)
  @@run = (v.is_a?(TrueClass)) ? true : false 
end
run?() click to toggle source

Returns true if automatic execution is enabled.

# File lib/drydock.rb, line 718
def run?
  @@run && has_run? == false
end
stdin(&b) click to toggle source

Define a block for processing STDIN before the command is called. The command block receives the return value of this block as obj.stdin:

command :task do |obj|; 
  obj.stdin   # => ...
end

If a stdin block isn't defined, stdin above will be the STDIN IO handle.

# File lib/drydock.rb, line 495
def stdin(&b)
  @@stdin_block = b
end
trawler(cmd) click to toggle source

The trawler catches any and all unknown commands that pass through Drydock. It's like the captain of aliases. cmd is the name of the command to direct unknowns to.

trawler :command_name
# File lib/drydock.rb, line 696
def trawler(cmd)
  @@trawler = cmd
end
trawler?() click to toggle source

Has the trawler been set?

# File lib/drydock.rb, line 701
def trawler?
  !@@trawler.nil? && !@@trawler.to_s.empty?
end
usage(msg) click to toggle source

Define a command-specific usage banner. This is displayed with "script command -h"

# File lib/drydock.rb, line 519
def usage(msg)
  # The default value given by OptionParser starts with "Usage". That's how
  # we know we can clear it. 
  get_current_option_parser.banner = "" if get_current_option_parser.banner =~ /^Usage:/
  get_current_option_parser.banner << "USAGE: #{msg}" << $/
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.