Class: Drydock::Command
Overview
The base class for all command objects. There is an instance of this class for every command defined. Global and command-specific options are added as attributes to this class dynamically.
i.e. "example -v select --location kumamoto"
global :v, :verbose, "I want mooooore!"
option :l, :location, String, "Source location"
command :select do |obj|
puts obj.global.verbose #=> true
puts obj.option.location #=> "kumamoto"
end
You can sub-class it to create your own:
class Malpeque < Drydock::Command
# ... sea to it
end
And then specify your class in the command definition:
command :eat => Malpeque do |obj|
# ... do stuff with your obj
end
Constant Summary collapse
- VERSION =
"0.6.9"
Instance Attribute Summary collapse
-
#actions ⇒ Object
An array of action names specified in the command definition.
-
#alias ⇒ Object
readonly
The name used to evoke this command (it’s either the canonical name or the alias used).
-
#argv ⇒ Object
An instance of Drydock::FancyArray.
-
#b ⇒ Object
readonly
The block that will be executed when this command is evoked.
-
#cmd ⇒ Object
readonly
The canonical name of the command (the one used in the command definition).
-
#desc ⇒ Object
A friendly description of the command.
-
#executable ⇒ Object
readonly
The basename of the executable or script: File.basename($0).
-
#global ⇒ Object
readonly
An OpenStruct object containing the global options specified at run-time.
-
#option ⇒ Object
readonly
An OpenStruct object containing the command options specified at run-time.
-
#stdin ⇒ Object
readonly
Either an IO handle to STDIN or the output of the Drydock#stdin handler.
Instance Method Summary collapse
-
#call ⇒ Object
Calls the command in the following order:.
-
#initialize(cmd, &b) ⇒ Command
constructor
The default constructor sets the short name of the command and stores a reference to the block (if supplied).
-
#name ⇒ Object
Returns the command name (not the alias).
-
#prepare(cmd_str = nil, argv = [], stdin = [], global_options = {}, options = {}) ⇒ Object
Prepare this command object to be called.
-
#show_commands ⇒ Object
Print the list of available commands to STDOUT.
-
#to_s ⇒ Object
The name of the command.
Constructor Details
#initialize(cmd, &b) ⇒ Command
The default constructor sets the short name of the command and stores a reference to the block (if supplied). You don’t need to override this method to add functionality to your custom Command classes. Define an init
method instead. It will be called just before the block is executed. cmd
is the short name of this command. b
is the block associated to this command.
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/drydock.rb', line 117 def initialize(cmd, &b) @cmd = (cmd.kind_of?(Symbol)) ? cmd : cmd.to_sym @b = b @actions = [] @argv = Drydock::FancyArray.new # an array with field names @stdin = STDIN @option = OpenStruct.new @global = OpenStruct.new @executable = File.basename($0) @global.verbose = 0 @global.quiet = false end |
Instance Attribute Details
#actions ⇒ Object
An array of action names specified in the command definition
101 102 103 |
# File 'lib/drydock.rb', line 101 def actions @actions end |
#alias ⇒ Object (readonly)
The name used to evoke this command (it’s either the canonical name or the alias used).
90 91 92 |
# File 'lib/drydock.rb', line 90 def alias @alias end |
#argv ⇒ Object
An instance of Drydock::FancyArray. Acts like an array of unnamed arguments but also allows field names if supplied.
104 105 106 |
# File 'lib/drydock.rb', line 104 def argv @argv end |
#b ⇒ Object (readonly)
The block that will be executed when this command is evoked. If the block is nil it will check if there is a method named cmd
. If so, that will be executed.
93 94 95 |
# File 'lib/drydock.rb', line 93 def b @b end |
#cmd ⇒ Object (readonly)
The canonical name of the command (the one used in the command definition). If you inherit from this class and add a method named cmd
, you can leave omit the block in the command definition. That method will be called instead. See bin/examples.
88 89 90 |
# File 'lib/drydock.rb', line 88 def cmd @cmd end |
#desc ⇒ Object
A friendly description of the command.
99 100 101 |
# File 'lib/drydock.rb', line 99 def desc @desc end |
#executable ⇒ Object (readonly)
The basename of the executable or script: File.basename($0)
108 109 110 |
# File 'lib/drydock.rb', line 108 def executable @executable end |
#global ⇒ Object (readonly)
An OpenStruct object containing the global options specified at run-time.
97 98 99 |
# File 'lib/drydock.rb', line 97 def global @global end |
#option ⇒ Object (readonly)
An OpenStruct object containing the command options specified at run-time.
95 96 97 |
# File 'lib/drydock.rb', line 95 def option @option end |
#stdin ⇒ Object (readonly)
Either an IO handle to STDIN or the output of the Drydock#stdin handler.
106 107 108 |
# File 'lib/drydock.rb', line 106 def stdin @stdin end |
Instance Method Details
#call ⇒ Object
Calls the command in the following order:
-
print_header
-
validation (if methodname_valid? exists)
-
command block (@b)
-
print_footer
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/drydock.rb', line 174 def call self.print_header if self.respond_to? :print_header # Execute the command block if it exists if @b run_validation @b.call(self) # Otherwise check to see if an action was specified elsif !(chosen = find_action(self.option)).empty? raise "Only one action at a time please! I can't #{chosen.join(' AND ')}." if chosen.size > 1 criteria = [[@cmd, chosen.first], [chosen.first, @cmd]] meth = name = nil # Try command_action, then action_command criteria.each do |tuple| name = tuple.join('_') meth = name if self.respond_to?(name) end raise "#{self.class} needs a #{name} method!" unless meth run_validation(meth) self.send(meth) # No block and no action. We'll try for the method name in the Drydock::Command class. elsif self.respond_to? @cmd.to_sym run_validation(@cmd) self.send(@cmd) # Well, then I have no idea what you want me to do! else raise "The command #{@alias} has no block and #{self.class} has no #{@cmd} method!" end self. if respond_to? :print_footer end |
#name ⇒ Object
Returns the command name (not the alias)
131 132 133 |
# File 'lib/drydock.rb', line 131 def name @cmd end |
#prepare(cmd_str = nil, argv = [], stdin = [], global_options = {}, options = {}) ⇒ Object
Prepare this command object to be called.
Calls self.init after setting attributes (if the method exists). You can implement an init method in your subclasses of Drydock::Command to handle your own initialization stuff.
<li>cmd_str
is the short name used to evoke this command. It will equal @cmd unless an alias was used used to evoke this command.</li> <li>argv
an array of unnamed arguments. If ignore :options was declared this</li> will contain the arguments exactly as they were defined on the command-line.</li> <li>stdin
contains the output of stdin do; …; end otherwise it’s a STDIN IO handle.</li> <li>global_options
a hash of the global options specified on the command-line</li> <li>options
a hash of the command-specific options specific on the command-line.</li>
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/drydock.rb', line 148 def prepare(cmd_str=nil, argv=[], stdin=[], ={}, ={}) @alias = cmd_str.nil? ? @cmd : cmd_str .each_pair do |n,v| self.global.send("#{n}=", v) # Populate the object's globals end .each_pair do |n,v| self.option.send("#{n}=", v) # ... and also the command options end @argv << argv # TODO: Using += returns an Array instead of FancyArray @argv.flatten! # NOTE: << creates @argv[[]] @stdin = stdin self.init if self.respond_to? :init # Must be called first! end |
#show_commands ⇒ Object
Print the list of available commands to STDOUT. This is used as the “default” command unless another default commands is supplied. You can also write your own Drydock::Command#show_commands to override this default behaviour.
The output was worked on here: etherpad.com/SXjqQGRr8M
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/drydock.rb', line 256 def show_commands project = " for #{Drydock.project}" if Drydock.project? cmds = {} Drydock.commands.keys.each do |cmd| next if cmd == :show_commands pretty = Drydock.decanonize(cmd) # Out to sea cmds[Drydock.commands[cmd].cmd] ||= {} unless cmd === Drydock.commands[cmd].cmd (cmds[Drydock.commands[cmd].cmd][:aliases] ||= []) << pretty next end cmds[cmd][:desc] = Drydock.commands[cmd].desc cmds[cmd][:desc] = nil if cmds[cmd][:desc] && cmds[cmd][:desc].empty? cmds[cmd][:pretty] = pretty end cmd_names_sorted = cmds.keys.sort{ |a,b| a.to_s <=> b.to_s } if @global.quiet puts "Commands: " line = [] cmd_names_sorted.each_with_index do |cmd,i| line << cmd if (line.size % 4 == 0) || i == (cmd_names_sorted.size - 1) puts " %s" % line.join(', ') line.clear end end return end puts "%5s: %s" % ["Usage", "#{@executable} [global options] COMMAND [command options]"] puts "%5s: %s" % ["Try", "#{@executable} -h"] puts "%5s %s" % ["", "#{@executable} COMMAND -h"] puts puts "Commands: " if @global.verbose > 0 puts # empty line cmd_names_sorted.each do |cmd| puts "$ %s" % [@executable] if Drydock.default?(cmd) puts "$ %s %s" % [@executable, cmds[cmd][:pretty]] puts "%10s: %s" % ["About", cmds[cmd][:desc]] if cmds[cmd][:desc] if cmds[cmd][:aliases] cmds[cmd][:aliases].sort!{ |a,b| a.size <=> b.size } puts "%10s: %s" % ["Aliases", cmds[cmd][:aliases].join(', ')] end puts end else cmd_names_sorted.each do |cmd| aliases = cmds[cmd][:aliases] || [] aliases.sort!{ |a,b| a.size <=> b.size } aliases = aliases.empty? ? '' : "(aliases: #{aliases.join(', ')})" pattern = Drydock.default?(cmd) ? "* %-16s %s" : " %-16s %s" puts pattern % [cmds[cmd][:pretty], aliases] end end end |
#to_s ⇒ Object
The name of the command
319 320 321 |
# File 'lib/drydock.rb', line 319 def to_s @cmd.to_s end |