module Rubikon::Application::InstanceMethods

This module contains internal instance methods of Application::Base and its subclasses.

@author Sebastian Staudt @see Application::Base @since 0.2.0

Attributes

current_param[RW]

@return [Parameter] The parameter that’s currently executed

sandbox[R]

@return [Application::Sandbox] The sandbox this application runs in

Public Class Methods

new() click to toggle source

Initialize with default settings

If you really need to override this in your application class, be sure to call super

@see set

# File lib/rubikon/application/instance_methods.rb, line 44
def initialize
  @commands          = {}
  @current_command   = nil
  @current_param     = nil
  @default_config    = {}
  @global_parameters = {}
  @hooks             = {}
  @initialized       = false
  @parameters        = []
  @sandbox           = Sandbox.new(self)
  @settings          = {
    :autohelp        => true,
    :autorun         => true,
    :colors          => true,
    :config_file     => "#{self.class.to_s.downcase}.yml",
    :help_as_default => true,
    :istream         => $stdin,
    :name            => self.class.to_s,
    :raise_errors    => false
  }

  if RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
    global_config_path = ENV['ALLUSERSPROFILE']
  else
    global_config_path = '/etc'
  end

  @settings[:config_paths] = [
    global_config_path, File.expand_path('~'), File.expand_path('.')
  ]

  self.estream = $stderr
  self.ostream = $stdout
end

Public Instance Methods

run(args = ARGV) click to toggle source

Run this application

Calling this method explicitly is not required when you want to create a simple application (having one main class inheriting from Rubikon::Application). But it’s useful for testing or if you want to have some sort of sub-applications.

@param [Array<String>] args The command line arguments that should be

given to the application as options
# File lib/rubikon/application/instance_methods.rb, line 88
def run(args = ARGV)
  hook = InstanceMethods.instance_method(:hook).bind(self)

  begin
    InstanceMethods.instance_method(:init).bind(self).call
    global_params, command, command_params = InstanceMethods.
      instance_method(:parse_arguments).bind(self).call(args)

    @config_factory = Config::Factory.new(@settings[:config_file],
      @settings[:config_paths], @settings[:config_format])
    @config = @default_config.merge @config_factory.config

    global_params.each do |param|
      @current_param = param
      param.send :active!
      @current_param = nil
    end

    @current_command = command
    hook.call(:pre_execute)

    command_params.each do |param|
      @current_param = param
      param.send :active!
      @current_param = nil
    end

    result = command.send(:run)
    hook.call(:post_execute)
    @current_command = nil

    result
  rescue Interrupt
    error "\nInterrupted... exiting."
  rescue
    raise $! if @settings[:raise_errors]

    if @settings[:autohelp] && @commands.key?(:help) &&
       $!.is_a?(UnknownCommandError)
      call :help, $!.command
    else
      error "r{Error:}\n    #{$!.message}"
      error "     at #{$!.backtrace.join("\n     at ")}" if $DEBUG
      exit 1
    end
  ensure
    InstanceMethods.instance_method(:reset).bind(self).call
  end
end

Private Instance Methods

base_file=(file) click to toggle source

Sets the (first) file this application has been defined in.

This also sets the path of the application used to load external command code and the default banner for the help screen.

@param [String] file The (first) file of the class definition @see DSLMethods#base_file @see DSLMethods#path @since 0.4.0

# File lib/rubikon/application/instance_methods.rb, line 149
def base_file=(file)
  @base_file = file
  @path      = File.dirname(file)

  @settings[:help_banner] ||= "Usage: #{Pathname.new(file).relative_path_from(Pathname.new(Dir.getwd))}"
end
debug_flag() click to toggle source

Defines a global Flag for enabling debug output

This will define a Flag --debug (with alias -d) to enable debug output. Using it sets Ruby’s global variable $DEBUG to true.

@return [Flag] The debug flag

# File lib/rubikon/application/instance_methods.rb, line 163
def debug_flag
  global_flag :debug do
    $DEBUG = true
  end
  global_flag :d => :debug
end
estream=(estream) click to toggle source

Sets the error output stream of the application

If colors are enabled, this checks if the stream supports the color_filter method and enables the ColoredIO if not.

@param [IO] estream The output stream to use @see ColoredIO.add_color_filter @since 0.6.0

# File lib/rubikon/application/instance_methods.rb, line 178
def estream=(estream)
  if !estream.respond_to?(:color_filter)
    ColoredIO.add_color_filter(estream, @settings[:colors])
  end
  @settings[:estream] = estream
end
help(info = nil) click to toggle source

Prints a help screen for this application

@param [String] info A additional information string to be displayed

right after usage information

@since 0.6.0

# File lib/rubikon/application/instance_methods.rb, line 190
def help(info = nil)
  help = {}
  @commands.each_value do |command|
    help[command.name.to_s] = command.description
  end
  help.delete('__default')

  if @commands.key? :__default
    puts " [command] [args]\n\n"
  else
    puts " command [args]\n\n"
  end

  puts "#{info}\n\n" unless info.nil?

  puts 'Commands:'
  max_command_length = help.keys.max_by { |a| a.size }.size
  help.sort_by { |name, description| name }.each do |name, description|
    puts "  #{name.ljust(max_command_length)}    #{description}"
  end

  if @commands.key?(:__default) &&
     @commands[:__default].description != '<hidden>'
    put "\nYou can also call this application without a command:"
    puts @commands[:__default].help(false) + "\n"
  end
end
help_command() click to toggle source

Defines a command for displaying a help screen

This takes any defined commands and it’s corresponding options and descriptions and displays them in a user-friendly manner.

# File lib/rubikon/application/instance_methods.rb, line 222
def help_command
  commands = @commands
  global_parameters = @global_parameters
  settings = @settings

  command :help, 'Show help for the application or a single command',
          :cmd => :optional do
    put settings[:help_banner]

    global_params = ''
    global_parameters.values.uniq.sort_by { |a| a.name.to_s }.each do |param|
      global_params << ' ['
      ([param.name] + param.aliases).each_with_index do |name, index|
        name = name.to_s
        global_params << '|' if index > 0
        global_params << '-' if name.size > 1
        global_params << "-#{name}"
      end
      global_params << ' ...' if param.is_a?(Option)
      global_params << ']'
    end
    put global_params

    app_help = lambda { |info| @__app__.instance_eval { help(info) } }

    unless cmd.nil?
      name = cmd.to_sym
      if commands.key? name
        puts commands[name].help
      else
        app_help.call("The command \"#{cmd}\" is undefined. The following commands are available:")
      end
    else
      app_help.call(nil)
    end
  end
end
hidden_output(&block) click to toggle source

Hide output inside the given block and print it after the block has finished

@param [Proc] block The block that should not print output while it’s

running

If the block needs to print to the real IO stream, it can access it using its first parameter.

# File lib/rubikon/application/instance_methods.rb, line 268
def hidden_output(&block)
  current_ostream = ostream
  self.ostream = StringIO.new

  block.call(current_ostream)

  current_ostream << ostream.string
  self.ostream = current_ostream
end
hook(name) click to toggle source

Executes the hook with the secified name

@param [Symbol] name The name of the hook to execute @since 0.4.0

# File lib/rubikon/application/instance_methods.rb, line 282
def hook(name)
  @sandbox.instance_eval(&@hooks[name]) unless @hooks[name].nil?
end
init() click to toggle source

This method is called once for each application and is used to initialize anything that needs to be ready before the application is run, but after the application is setup, i.e. after the user has defined the application class.

# File lib/rubikon/application/instance_methods.rb, line 290
def init
  return if @initialized

  hook = InstanceMethods.instance_method(:hook).bind(self)

  @current_command      = nil
  @current_param        = nil
  @current_global_param = nil

  hook.call(:pre_init)

  InstanceMethods.instance_method(:debug_flag).bind(self).call
  InstanceMethods.instance_method(:help_command).bind(self).call
  InstanceMethods.instance_method(:verbose_flag).bind(self).call

  if @settings[:help_as_default] && @commands.key?(:help) &&
     !@commands.key?(:__default)
    default :help
  end

  @initialized = true

  hook.call(:post_init)
end
method_missing(name, *args, &block) click to toggle source

This is used to determine the receiver of a method call inside the application code.

This is used to have a convenient way to access e.g. paramter arguments.

This will delegate a method call to the currently executed parameter if the receiving object exists and responds to the desired method. Currently executed means the application’s execution is inside a parameter’s code block at the moment, i.e. a call to a missing method inside a parameter’s code block will trigger this behavior.

@example Access a command’s arguments

command :args, [:one, :two] do
  puts "One: #{one}, Two: #{two}"
end

@since 0.4.0

Calls superclass method
# File lib/rubikon/application/instance_methods.rb, line 332
def method_missing(name, *args, &block)
  receiver = @current_param || @current_command
  if receiver.nil? || (!receiver.respond_to?(name) &&
     !receiver.public_methods(false).include?(name))
    super
  else
    receiver.send(name, *args, &block)
  end
end
ostream=(ostream) click to toggle source

Sets the output stream of the application

If colors are enabled, this checks if the stream supports the color_filter method and enables the ColoredIO if not.

@param [IO] ostream The output stream to use @see ColoredIO.add_color_filter

# File lib/rubikon/application/instance_methods.rb, line 349
def ostream=(ostream)
  if !ostream.respond_to?(:color_filter)
    ColoredIO.add_color_filter(ostream, @settings[:colors])
  end
  @settings[:ostream] = ostream
end
parse_arguments(argv) click to toggle source

Parses the command-line arguments given to the application by the user. This distinguishes between commands, global flags and command flags

@param [String] argv The command-line arguments @raise [NoDefaultCommandError] if no command can be found and no

default command exists

@raise [UnknownParameterError] if an unknown parameter is found @raise [UnknownParameterError] if an unknown command is found @return [Array<Parameter>] one All global parameters that have been

supplied

@return [Command] two The command to execute, the parameters of this

command that have been supplied

@return [Array<Parameter>] three All parameters of that command that have

been supplied
# File lib/rubikon/application/instance_methods.rb, line 371
def parse_arguments(argv)
  argv.extend ArgumentVector

  argv.expand!

  command, command_index = argv.command! @commands
  raise NoDefaultCommandError if command.nil?

  command_params = argv.params! command.params, command_index
  global_params  = argv.params! @global_parameters

  argv.scoped_args! command

  unless argv.empty?
    first = argv.first
    if first.start_with? '-'
      raise UnknownParameterError.new(first)
    else
      raise UnknownCommandError.new(first)
    end
  end

  return global_params, command, command_params
end
reset() click to toggle source

Resets this application to its initial state

This rewinds the output stream, removes the color features from the and resets all commands and global parameters.

@see ColoredIO.remove_color_filter @see Command#reset @see HasArguments#reset @see IO#rewind @see Parameter#reset @since 0.4.0

# File lib/rubikon/application/instance_methods.rb, line 407
def reset
  [estream, ostream].each do |stream|
    stream.rewind if stream.is_a? StringIO || !stream.stat.chardev?
    ColoredIO.remove_color_filter(estream)
  end
  (@commands.values + @global_parameters.values).uniq.each do |param|
    param.send :reset
  end
end
verbose_flag() click to toggle source

Defines a global Flag for enabling verbose output

This will define a Flag --verbose and -v to enable verbose output. Using it sets Ruby’s global variable $VERBOSE to true.

@return [Flag] The verbose Flag object

# File lib/rubikon/application/instance_methods.rb, line 424
def verbose_flag
  global_flag :verbose do
    $VERBOSE = true
  end
  global_flag :v => :verbose
end