Class: Cri::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/cri/command.rb

Overview

Cri::Command represents a command that can be executed on the commandline. It is also used for the commandline tool itself.

Defined Under Namespace

Classes: OptionParserPartitioningDelegate

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Command) initialize

Returns a new instance of Command



129
130
131
132
133
# File 'lib/cri/command.rb', line 129

def initialize
  @aliases            = Set.new
  @commands           = Set.new
  @option_definitions = Set.new
end

Instance Attribute Details

- (Array<String>) aliases

Returns A list of aliases for this command that can be used to invoke this command

Returns:

  • (Array<String>)

    A list of aliases for this command that can be used to invoke this command



61
62
63
# File 'lib/cri/command.rb', line 61

def aliases
  @aliases
end

- (Proc) block

Returns The block that should be executed when invoking this command (ignored for commands with subcommands)

Returns:

  • (Proc)

    The block that should be executed when invoking this command (ignored for commands with subcommands)



83
84
85
# File 'lib/cri/command.rb', line 83

def block
  @block
end

- (Set<Cri::Command>) commands Also known as: subcommands

Returns This command’s subcommands

Returns:



53
54
55
# File 'lib/cri/command.rb', line 53

def commands
  @commands
end

- (String) description

Returns The long description (“description”)

Returns:

  • (String)

    The long description (“description”)



67
68
69
# File 'lib/cri/command.rb', line 67

def description
  @description
end

- (Boolean) hidden Also known as: hidden?

Returns true if the command is hidden (e.g. because it is deprecated), false otherwise

Returns:

  • (Boolean)

    true if the command is hidden (e.g. because it is deprecated), false otherwise



75
76
77
# File 'lib/cri/command.rb', line 75

def hidden
  @hidden
end

- (String) name

Returns The name

Returns:



57
58
59
# File 'lib/cri/command.rb', line 57

def name
  @name
end

- (Array<Hash>) option_definitions

Returns The list of option definitions

Returns:

  • (Array<Hash>)

    The list of option definitions



79
80
81
# File 'lib/cri/command.rb', line 79

def option_definitions
  @option_definitions
end

- (String) summary

Returns The short description (“summary”)

Returns:

  • (String)

    The short description (“summary”)



64
65
66
# File 'lib/cri/command.rb', line 64

def summary
  @summary
end

- (Cri::Command?) supercommand

Returns This command’s supercommand, or nil if the command has no supercommand

Returns:

  • (Cri::Command, nil)

    This command’s supercommand, or nil if the command has no supercommand



50
51
52
# File 'lib/cri/command.rb', line 50

def supercommand
  @supercommand
end

- (String) usage

Returns The usage, without the “usage:” prefix and without the supercommands’ names.

Returns:

  • (String)

    The usage, without the “usage:” prefix and without the supercommands’ names.



71
72
73
# File 'lib/cri/command.rb', line 71

def usage
  @usage
end

Class Method Details

+ (Cri::Command) define(string = nil, filename = nil, &block)

Creates a new command using the DSL. If a string is given, the command will be defined using the string; if a block is given, the block will be used instead.

If the block has one parameter, the block will be executed in the same context with the command DSL as its parameter. If the block has no parameters, the block will be executed in the context of the DSL.

Parameters:

  • string (String, nil) (defaults to: nil)

    The command definition as a string

  • filename (String, nil) (defaults to: nil)

    The filename corresponding to the string parameter (only useful if a string is given)

Returns:



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/cri/command.rb', line 98

def self.define(string=nil, filename=nil, &block)
  dsl = Cri::CommandDSL.new
  if string
    args = filename ? [ string, filename ] : [ string ]
    dsl.instance_eval(*args)
  elsif [ -1, 0 ].include? block.arity
    dsl.instance_eval(&block)
  else
    block.call(dsl)
  end
  dsl.command
end

+ (Cri::Command) new_basic_help

Returns a new command that implements showing help.

Returns:



124
125
126
127
# File 'lib/cri/command.rb', line 124

def self.new_basic_help
  filename = File.dirname(__FILE__) + '/commands/basic_help.rb'
  self.define(File.read(filename))
end

+ (Cri::Command) new_basic_root

Returns a new command that has support for the -h/--help option and also has a help subcommand. It is intended to be modified (adding name, summary, description, other subcommands, …)

Returns:



116
117
118
119
# File 'lib/cri/command.rb', line 116

def self.new_basic_root
  filename = File.dirname(__FILE__) + '/commands/basic_root.rb'
  self.define(File.read(filename))
end

Instance Method Details

- (-1, ...) <=>(other)

Compares this command's name to the other given command's name.

Parameters:

Returns:

  • (-1, 0, 1)

    The result of the comparison between names

See Also:

  • Object<=>


316
317
318
# File 'lib/cri/command.rb', line 316

def <=>(other)
  self.name <=> other.name
end

- (void) add_command(command)

This method returns an undefined value.

Adds the given command as a subcommand to the current command.

Parameters:

  • command (Cri::Command)

    The command to add as a subcommand



166
167
168
169
# File 'lib/cri/command.rb', line 166

def add_command(command)
  @commands << command
  command.supercommand = self
end

- (Cri::Command) command_named(name)

Returns the command with the given name. This method will display error messages and exit in case of an error (unknown or ambiguous command).

The name can be a full command name, a partial command name (e.g. “com” for “commit”) or an aliased command name (e.g. “ci” for “commit”).

Parameters:

  • name (String)

    The full, partial or aliases name of the command

Returns:



221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/cri/command.rb', line 221

def command_named(name)
  commands = commands_named(name)

  if commands.size < 1
    $stderr.puts "#{self.name}: unknown command '#{name}'\n"
    exit 1
  elsif commands.size > 1
    $stderr.puts "#{self.name}: '#{name}' is ambiguous:"
    $stderr.puts "  #{commands.map { |c| c.name }.sort.join(' ') }"
    exit 1
  else
    commands[0]
  end
end

- (Array<Cri::Command>) commands_named(name)

Returns the commands that could be referred to with the given name. If the result contains more than one command, the name is ambiguous.

Parameters:

  • name (String)

    The full, partial or aliases name of the command

Returns:

  • (Array<Cri::Command>)

    A list of commands matching the given name



199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/cri/command.rb', line 199

def commands_named(name)
  # Find by exact name or alias
  @commands.each do |cmd|
    found = cmd.name == name || cmd.aliases.include?(name)
    return [ cmd ] if found
  end

  # Find by approximation
  @commands.select do |cmd|
    cmd.name[0, name.length] == name
  end
end

- (Cri::Command) define_command(name = nil, &block)

Defines a new subcommand for the current command using the DSL.

Parameters:

  • name (String, nil) (defaults to: nil)

    The name of the subcommand, or nil if no name should be set (yet)

Returns:



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/cri/command.rb', line 177

def define_command(name=nil, &block)
  # Execute DSL
  dsl = Cri::CommandDSL.new
  dsl.name name unless name.nil?
  if [ -1, 0 ].include? block.arity
    dsl.instance_eval(&block)
  else
    block.call(dsl)
  end

  # Create command
  cmd = dsl.command
  self.add_command(cmd)
  cmd
end

- (Hash) global_option_definitions

Returns The option definitions for the command itself and all its ancestors

Returns:

  • (Hash)

    The option definitions for the command itself and all its ancestors



154
155
156
157
158
159
# File 'lib/cri/command.rb', line 154

def global_option_definitions
  res = Set.new
  res.merge(option_definitions)
  res.merge(supercommand.global_option_definitions) if supercommand
  res
end

- (String) help(params = {})

Returns The help text for this command

Parameters:

  • params (Hash) (defaults to: {})

    a customizable set of options

Options Hash (params):

  • :verbose (Boolean)

    true if the help output should be verbose, false otherwise.

Returns:

  • (String)

    The help text for this command



305
306
307
# File 'lib/cri/command.rb', line 305

def help(params={})
  HelpRenderer.new(self, params).render
end

- (Cri::Command) modify(&block)

Modifies the command using the DSL.

If the block has one parameter, the block will be executed in the same context with the command DSL as its parameter. If the block has no parameters, the block will be executed in the context of the DSL.

Returns:



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

def modify(&block)
  dsl = Cri::CommandDSL.new(self)
  if [ -1, 0 ].include? block.arity
    dsl.instance_eval(&block)
  else
    block.call(dsl)
  end
  self
end

- (void) run(opts_and_args, parent_opts = {})

This method returns an undefined value.

Runs the command with the given commandline arguments, possibly invoking subcommands and passing on the options and arguments.

Parameters:

  • opts_and_args (Array<String>)

    A list of unparsed arguments

  • parent_opts (Hash) (defaults to: {})

    A hash of options already handled by the supercommand



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'lib/cri/command.rb', line 245

def run(opts_and_args, parent_opts={})
  # Parse up to command name
  stuff = partition(opts_and_args)
  opts_before_subcmd, subcmd_name, opts_and_args_after_subcmd = *stuff

  if subcommands.empty? || (subcmd_name.nil? && !self.block.nil?)
    run_this(opts_and_args, parent_opts)
  else
    # Handle options
    handle_options(opts_before_subcmd)

    # Get command
    if subcmd_name.nil?
      $stderr.puts "#{name}: no command given"
      exit 1
    end
    subcommand = self.command_named(subcmd_name)

    # Run
    subcommand.run(opts_and_args_after_subcmd, opts_before_subcmd)
  end
end

- (void) run_this(opts_and_args, parent_opts = {})

This method returns an undefined value.

Runs the actual command with the given commandline arguments, not invoking any subcommands. If the command does not have an execution block, an error ir raised.

Parameters:

  • opts_and_args (Array<String>)

    A list of unparsed arguments

  • parent_opts (Hash) (defaults to: {})

    A hash of options already handled by the supercommand

Raises:



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/cri/command.rb', line 281

def run_this(opts_and_args, parent_opts={})
  # Parse
  parser = Cri::OptionParser.new(
    opts_and_args, self.global_option_definitions)
  handle_parser_errors_while { parser.run }
  local_opts  = parser.options
  global_opts = parent_opts.merge(parser.options)
  args = parser.arguments

  # Handle options
  handle_options(local_opts)

  # Execute
  if self.block.nil?
    raise NotImplementedError,
      "No implementation available for '#{self.name}'"
  end
  self.block.call(global_opts, args, self)
end