Class: Commander::Runner

Inherits:
Object show all
Defined in:
lib/commander/runner.rb

Defined Under Namespace

Classes: CommandError, InvalidCommandError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = ARGV) ⇒ Runner

Initialize a new command runner. Optionally supplying args for mocking, or arbitrary usage.



28
29
30
31
32
# File 'lib/commander/runner.rb', line 28

def initialize args = ARGV
  @args, @commands, @aliases, @options = args, {}, {}, []
  @program = program_defaults
  create_default_commands
end

Instance Attribute Details

#commandsObject (readonly)

Array of commands.



17
18
19
# File 'lib/commander/runner.rb', line 17

def commands
  @commands
end

#optionsObject (readonly)

Global options.



22
23
24
# File 'lib/commander/runner.rb', line 22

def options
  @options
end

Instance Method Details

#active_commandObject

Get active command within arguments passed to this runner.



193
194
195
# File 'lib/commander/runner.rb', line 193

def active_command
  @__active_command ||= command(command_name_from_args)
end

#add_command(command) ⇒ Object

Add a command object to this runner.



172
173
174
# File 'lib/commander/runner.rb', line 172

def add_command command
  @commands[command.name] = command
end

#alias?(name) ⇒ Boolean

Check if command name is an alias.

Returns:

  • (Boolean)


179
180
181
# File 'lib/commander/runner.rb', line 179

def alias? name
  @aliases.include? name.to_s
end

#alias_command(alias_name, name, *args) ⇒ Object

Alias command name with alias_name. Optionally args may be passed as if they were being passed straight to the original command via the command-line.



156
157
158
159
# File 'lib/commander/runner.rb', line 156

def alias_command alias_name, name, *args
  @commands[alias_name.to_s] = command name
  @aliases[alias_name.to_s] = args
end

#args_without_command_nameObject

Return arguments without the command name.



223
224
225
226
227
228
229
# File 'lib/commander/runner.rb', line 223

def args_without_command_name
  removed = []
  parts = command_name_from_args.split rescue []
  @args.dup.delete_if do |arg|
    removed << arg if parts.include?(arg) and not removed.include?(arg)
  end
end

#command(name) {|add_command(Commander::Command.new(name))| ... } ⇒ Object

Creates and yields a command instance when a block is passed. Otherwise attempts to return the command, raising InvalidCommandError when it does not exist.

Examples:

command :my_command do |c|
  c.when_called do |args|
    # Code
  end
end

Yields:



133
134
135
136
# File 'lib/commander/runner.rb', line 133

def command name, &block
  yield add_command(Commander::Command.new(name)) if block
  @commands[name.to_s]
end

#command_exists?(name) ⇒ Boolean

Check if a command name exists.

Returns:

  • (Boolean)


186
187
188
# File 'lib/commander/runner.rb', line 186

def command_exists? name
  @commands[name.to_s]
end

#command_name_from_argsObject

Attempts to locate a command name from within the arguments. Supports multi-word commands, using the largest possible match.



201
202
203
# File 'lib/commander/runner.rb', line 201

def command_name_from_args
  @__command_name_from_args ||= (valid_command_names_from(*@args.dup).sort.last || @default_command)
end

#default_command(name) ⇒ Object

Default command name to be used when no other command is found in the arguments.



165
166
167
# File 'lib/commander/runner.rb', line 165

def default_command name
  @default_command = name
end

#global_option(*args, &block) ⇒ Object

Add a global option; follows the same syntax as Command#option This would be used for switches such as –version, –trace, etc.



142
143
144
145
146
147
148
149
150
# File 'lib/commander/runner.rb', line 142

def global_option *args, &block
  switches, description = Runner.seperate_switches_from_description *args
  @options << {
    :args => args,
    :proc => block,
    :switches => switches,
    :description => description,
  }
end

#help_formatterObject

Help formatter instance.



216
217
218
# File 'lib/commander/runner.rb', line 216

def help_formatter
  @__help_formatter ||= program(:help_formatter).new self
end

#program(key, *args) ⇒ Object

Assign program information.

Examples:

# Set data
program :name, 'Commander'
program :version, Commander::VERSION
program :description, 'Commander utility program.'
program :help, 'Copyright', '2008 TJ Holowaychuk'
program :help, 'Anything', 'You want'
program :int_message 'Bye bye!'

# Get data
program :name # => 'Commander'

Keys:

:version         (required) Program version triple, ex: '0.0.1'
:description     (required) Program description
:name            Program name, defaults to basename of executable
:help_formatter  Defaults to Commander::HelpFormatter::Terminal
:help            Allows addition of arbitrary global help blocks
:int_message     Message to display when interrupted (CTRL + C)


109
110
111
112
113
114
115
116
117
# File 'lib/commander/runner.rb', line 109

def program key, *args
  if key == :help and !args.empty?
    @program[:help] ||= {}
    @program[:help][args.first] = args[1]
  else
    @program[key] = *args unless args.empty?
    @program[key]
  end
end

#run!Object

Run command parsing and execution process.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/commander/runner.rb', line 37

def run!
  trace = false
  require_program :version, :description
  trap('INT') { abort program(:int_message) }
  global_option('-h', '--help', 'Display help documentation') { command(:help).run *@args[1..-1]; return }
  global_option('-v', '--version', 'Display version information') { say version; return } 
  global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true }
  parse_global_options
  remove_global_options
  unless trace
    begin
      run_active_command
    rescue InvalidCommandError => e
      abort "#{e}. Use --help for more information"
    rescue \
      OptionParser::InvalidOption, 
      OptionParser::InvalidArgument,
      OptionParser::MissingArgument => e
      abort e
    rescue => e
      abort "error: #{e}. Use --trace to view backtrace"
    end
  else
    run_active_command
  end
end

#run_active_commandObject

Run the active command.



74
75
76
77
78
79
80
81
# File 'lib/commander/runner.rb', line 74

def run_active_command
  require_valid_command
  if alias? command_name_from_args
    active_command.run *(@aliases[command_name_from_args.to_s] + args_without_command_name)
  else
    active_command.run *args_without_command_name
  end      
end

#valid_command_names_from(*args) ⇒ Object

Returns array of valid command names found within args.



208
209
210
211
# File 'lib/commander/runner.rb', line 208

def valid_command_names_from *args
  arg_string = args.delete_switches.join ' '
  commands.keys.find_all { |name| name if /^#{name}/.match arg_string }
end

#versionObject

Return program version.



67
68
69
# File 'lib/commander/runner.rb', line 67

def version
  '%s %s' % [program(:name), program(:version)]
end