Class: Climate::Command

Inherits:
Object
  • Object
show all
Extended by:
ParsingMethods
Defined in:
lib/climate/command.rb,
lib/climate/command_compat.rb

Overview

require this file to monkey patch Command to have old <= 0.4 Command.name method that was removed to fix github.com/playlouder/climate/issues/6

Defined Under Namespace

Classes: Chain

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ParsingMethods

arg, cli_arguments, cli_options, conflicting_options, conflicts, dependent_options, depends, has_argument?, has_arguments?, has_multi_argument?, has_options?, has_required_argument?, opt, parse, parse_arguments, stop_on, trollop_parser

Constructor Details

#initialize(argv, options = {}) ⇒ Command

Create an instance of this command to be run. You’ll probably want to use {Command.run

Parameters:

  • arguments (Array<String>)

    ARGV style arguments to be parsed

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

    a customizable set of options

Options Hash (options):

  • :parent (Command)

    The parent command, made available as #parent

  • :stdout (IO)

    stream to use as stdout, defaulting to ‘$stdout`

  • :stderr (IO)

    stream to use as stderr, defaulting to ‘$stderr`

  • :stdin (IO)

    stream to use as stdin, defaulting to ‘$stdin`



212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/climate/command.rb', line 212

def initialize(argv, options={})
  @argv = argv.clone
  @parent = options[:parent]

  @stdout = options[:stdout] || $stdout
  @stderr = options[:stderr] || $stderr
  @stdin =  options[:stdin]  || $stdin

  if ! self.class.parsing_disabled
    @arguments, @options, @leftovers = self.class.parse(argv)
  end
end

Class Attribute Details

.parentObject

Set the parent of this command



145
146
147
# File 'lib/climate/command.rb', line 145

def parent
  @parent
end

.parsing_disabledObject

Returns true if parsing is disabled



142
143
144
# File 'lib/climate/command.rb', line 142

def parsing_disabled
  @parsing_disabled
end

Instance Attribute Details

#argumentsHash

Arguments that were given on the command line

Returns:

  • (Hash)


236
237
238
# File 'lib/climate/command.rb', line 236

def arguments
  @arguments
end

#argvArray

The original list of unparsed argv style arguments that were given to the command

Returns:

  • (Array)


228
229
230
# File 'lib/climate/command.rb', line 228

def argv
  @argv
end

#leftoversArray

Unparsed arguments, usually for subcommands

Returns:

  • (Array)


240
241
242
# File 'lib/climate/command.rb', line 240

def leftovers
  @leftovers
end

#optionsHash

Options that were parsed from the command line

Returns:

  • (Hash)


232
233
234
# File 'lib/climate/command.rb', line 232

def options
  @options
end

#parentCommand

The parent command, or nil if this is not a subcommand

Returns:



244
245
246
# File 'lib/climate/command.rb', line 244

def parent
  @parent
end

#stderrIO

a possibly redirected stream

Returns:

  • (IO)


248
249
250
# File 'lib/climate/command.rb', line 248

def stderr
  @stderr
end

#stdinIO

a possibly redirected stream

Returns:

  • (IO)


248
249
250
# File 'lib/climate/command.rb', line 248

def stdin
  @stdin
end

#stdoutIO

a possibly redirected stream

Returns:

  • (IO)


248
249
250
# File 'lib/climate/command.rb', line 248

def stdout
  @stdout
end

Class Method Details

.add_subcommand(subcommand) ⇒ Object



147
148
149
150
151
152
153
154
155
# File 'lib/climate/command.rb', line 147

def add_subcommand(subcommand)
  if cli_arguments.empty?
    subcommands << subcommand
    subcommand.parent = self
    stop_on(subcommands.map(&:command_name))
  else
    raise DefinitionError, 'can not mix subcommands with arguments'
  end
end

.ancestors(exclude_self = false) ⇒ Object



98
99
100
101
# File 'lib/climate/command.rb', line 98

def ancestors(exclude_self=false)
  our_list = exclude_self ? [] : [self]
  parent.nil?? our_list : parent.ancestors + our_list
end

.arg(*args) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/climate/command.rb', line 161

def arg(*args)
  if subcommands.empty?
    super(*args)
  else
    raise DefinitionError, 'can not mix subcommands with arguments'
  end
end

.build(argv, options = {}) ⇒ Object

Recursively construct an array of commands

Parameters:

  • argv (Array<String>)

    A list of arguments, ARGV style

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


72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/climate/command.rb', line 72

def build(argv, options={})
  begin
    instance = new(argv, options)
  rescue Trollop::HelpNeeded
    raise HelpNeeded.new(self)
  end

  if subcommands.empty?
    [instance]
  else
    [instance, *find_and_build_subcommand(instance, options)]
  end
end

.class_nameObject

because we’ve extended Class.name, we expose the original method under another name. Can be removed once we move away from Command.name method FIXME: surely there is a saner way of doing this?



14
15
16
# File 'lib/climate/command_compat.rb', line 14

def self.class_name
  Class.method(:name).unbind.bind(self).call
end

.command_nameObject

Return the name of the command



110
111
112
# File 'lib/climate/command.rb', line 110

def command_name
  @name
end

.description(string = nil) ⇒ Object

Set the description for this command

Parameters:

  • string (String) (defaults to: nil)

    Description/Banner/Help text



127
128
129
130
131
132
133
# File 'lib/climate/command.rb', line 127

def description(string=nil)
  if string
    @description = string
  else
    @description
  end
end

.disable_parsingObject

Call this during class definition time if you don’t want any of the usual command line parsing to happen



137
138
139
# File 'lib/climate/command.rb', line 137

def disable_parsing
  @parsing_disabled = true
end

.expose_ancestor_method(ancestor_class, method_name) ⇒ Object



172
173
174
175
176
# File 'lib/climate/command.rb', line 172

def expose_ancestor_method(ancestor_class, method_name)
  define_method(method_name) do |*args|
    ancestor(ancestor_class).send(method_name, *args)
  end
end

.expose_ancestor_methods(ancestor_class, *method_names) ⇒ Object



178
179
180
181
182
# File 'lib/climate/command.rb', line 178

def expose_ancestor_methods(ancestor_class, *method_names)
  method_names.each do |method_name|
    expose_ancestor_method(ancestor_class, method_name)
  end
end

.has_subcommand?(subcommand) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/climate/command.rb', line 157

def has_subcommand?(subcommand)
  subcommands.include?(subcommand)
end

.has_subcommands?Boolean

Returns:

  • (Boolean)


169
# File 'lib/climate/command.rb', line 169

def has_subcommands? ; not subcommands.empty?   ; end

.name(name = nil) ⇒ Object



5
6
7
8
# File 'lib/climate/command_compat.rb', line 5

def self.name(name=nil)
  set_name(name) if name
  command_name
end

.run(argv, options = {}) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/climate/command.rb', line 86

def run(argv, options={})
  command_instance_list = build(argv, options)
  final_command = command_instance_list.last

  if ! final_command.has_run?
    raise NotImplementedError, "leaf command #{final_command} must implement #run"
  end

  runnable_commands = command_instance_list.select {|command| command.has_run? }
  Chain.new(runnable_commands).run
end

.set_name(command_name) ⇒ Object

Set the name of this command, use if you don’t want to use the class function to define your command



105
106
107
# File 'lib/climate/command.rb', line 105

def set_name(command_name)
  @name = command_name
end

.subcommand_of(parent_class) ⇒ Object

Register this class as being a subcommand of another Climate::Command class

Parameters:

  • parent_class (Command)

    The parent we hang off of

Raises:



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

def subcommand_of(parent_class)
  raise DefinitionError, 'can not set subcommand before name' unless command_name
  parent_class.add_subcommand(self)
end

.subcommand_of?(parent_class) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/climate/command.rb', line 121

def subcommand_of?(parent_class)
  parent_class.has_subcommand?(self)
end

.subcommandsObject



170
# File 'lib/climate/command.rb', line 170

def subcommands ; @subcommands ||= [] ; end

Instance Method Details

#ancestor(ancestor_class, include_self = true) ⇒ Object



250
251
252
253
254
255
256
257
258
259
# File 'lib/climate/command.rb', line 250

def ancestor(ancestor_class, include_self=true)
  if include_self && self.class == ancestor_class
    self
  elsif parent.nil?
    raise "no ancestor exists: #{ancestor_class}"
    nil
  else
    parent.ancestor(ancestor_class)
  end
end

#exit(status) ⇒ Object



265
266
267
# File 'lib/climate/command.rb', line 265

def exit(status)
  raise Climate::ExitException.new(nil, status)
end

#has_run?Boolean

Returns:

  • (Boolean)


261
262
263
# File 'lib/climate/command.rb', line 261

def has_run?
  self.methods.include? :run
end