Class: Clio::Usage::Command

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

Overview

Commandline Usage Command

This is the heart of usage; subclassed by Main and containing together Options and Arguments.

usage = Usage.new

Direct Known Subclasses

Main

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, parent = nil, &block) ⇒ Command

Returns a new instance of Command.



48
49
50
51
52
53
54
55
56
# File 'lib/clio/usage/command.rb', line 48

def initialize(name, parent=nil, &block)
  @name        = name.to_s
  @parent      = parent
  @subcommands = []
  @options     = []
  @arguments   = []
  @help        = ''
  instance_eval(&block) if block
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(key, *args, &blk) ⇒ Object

METHOD MISSING




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

def method_missing(key, *args, &blk)
  key = key.to_s
  case key
  when /\?$/
    option(key.chomp('?'), *args, &blk)
  else
    #k = full_name ? "#{full_name} #{key}" : "#{key}"
    c = command(key, &blk)
    args.each{ |a| c[a] }
    c
  end
end

Instance Attribute Details

#argumentsObject (readonly)

Array of arguments. Arguments and subcommands are mutually exclusive, ie. either @arguments or @subcommands will be empty.

TODO: Could use single attribute for both subcommands and arguments and use a flag to designate which type.



36
37
38
# File 'lib/clio/usage/command.rb', line 36

def arguments
  @arguments
end

#help(string = nil) ⇒ Object (readonly)

Help text.



42
43
44
# File 'lib/clio/usage/command.rb', line 42

def help
  @help
end

#nameObject (readonly)

Name of the command.



25
26
27
# File 'lib/clio/usage/command.rb', line 25

def name
  @name
end

#optionsObject (readonly) Also known as: switches

Array of options.



39
40
41
# File 'lib/clio/usage/command.rb', line 39

def options
  @options
end

#parentObject (readonly)

Parent command. This is needed to support cascading options. – NOTE: If it were possible to have this it would be better. ++



22
23
24
# File 'lib/clio/usage/command.rb', line 22

def parent
  @parent
end

#subcommandsObject (readonly) Also known as: commands

Array of subcommands.



28
29
30
# File 'lib/clio/usage/command.rb', line 28

def subcommands
  @subcommands
end

Instance Method Details

#===(other_name) ⇒ Object



326
327
328
# File 'lib/clio/usage/command.rb', line 326

def ===(other_name)
  name == other_name.to_s
end

#[](*x) ⇒ Object

Super shorthand notation.

cli['document']['--output=FILE -o']['<files>']


277
278
279
280
281
282
283
284
285
286
# File 'lib/clio/usage/command.rb', line 277

def [](*x)
  case x[0].to_s[0,1]
  when '-'
    opt(*x)
  when '<'
    arg(*x)
  else
    subcommand(*x)
  end
end

#argument(*n_type, &block) ⇒ Object Also known as: arg

Define an argument. Takes a name, optional index and block.

Indexing of arguments starts at 1, not 0.

Examples

argument(:path)
argument(1, :path)


216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/clio/usage/command.rb', line 216

def argument(*n_type, &block)
  index = Integer===n_type[0] ? n_type.shift : @arguments.size + 1
  type  = n_type.shift
  help  = n_type.shift

  index = index - 1
  type = type.to_s.sub(/^\</,'').chomp('>')

  if type[0,1] == '*'
    type.sub!('*', '')
    splat = true
  elsif type[-1,1] == '*'
    type.sub!(/[*]$/, '')
    splat = true
  else
    splat = false
  end

  raise "Command cannot have both arguments (eg. #{type}) and subcommands." unless subcommands.empty?

  if arg = @arguments[index]
    arg.type(type) if type
    arg.help(help) if help
    arg.splat(splat) if splat
    arg.instance_eval(&block) if block
  else
    if type || block
      arg = Argument.new(type, &block) #self, &block)
      arg.help(help) if help
      arg.splat(splat) if splat
      @arguments[index] = arg
    end
  end
  return arg
end

#completionObject



292
293
294
295
296
297
298
299
300
# File 'lib/clio/usage/command.rb', line 292

def completion
  if subcommands.empty?
    options.collect{|o| o.to_s.strip } +
    arguments.collect{|c| c.name}
  else
    options.collect{|o| o.to_s.strip } +
    subcommands.collect{|c| c.name}
  end
end

#full_nameObject

Full callable command name.



344
345
346
347
348
349
350
# File 'lib/clio/usage/command.rb', line 344

def full_name
  if parent && parent.full_name
    "#{parent.full_name} #{name}"
  else
    "#{name}"
  end
end

#help!(*args) ⇒ Object



87
88
89
90
91
# File 'lib/clio/usage/command.rb', line 87

def help!(*args)
  Hash[*args].each do |key, desc|
    self[key, desc]
  end
end

#initialize_copy(c) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/clio/usage/command.rb', line 59

def initialize_copy(c)
  @parent      = c.parent
  @name        = c.name.dup
  @options     = c.options.dup
  @arguments   = c.arguments.dup
  @subcommands = c.subcommands.dup
  @help        = c.help.dup
end

#inspectObject



331
332
333
334
335
336
337
338
339
340
341
# File 'lib/clio/usage/command.rb', line 331

def inspect
  s = ''
  s << "#<#{self.class}:#{object_id} #{@name}"
  s << " @arguments=#{@arguments.inspect} " unless @arguments.empty?
  s << " @options=#{@options.inspect} "     unless @options.empty?
  #s << "@switches=#{@switches.inspect} "   unless @switches.empty?
  s << " @help=#{@help.inspect}"            unless @help.empty?
  #s << "@commands=#{@commands.inspect} "  unless @commands.empty?
  s << ">"
  s
end

#keyObject



68
# File 'lib/clio/usage/command.rb', line 68

def key ; @name.to_sym ; end

#opt(name, help = nil) ⇒ Object Also known as: swt

Option shorthand.

opt('--output=FILE -o', 'output directory')


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/clio/usage/command.rb', line 150

def opt(name, help=nil)
  name, *aliases = name.split(/\s+/)
  name, type = *name.split('=')
  mult = false
  if type && type[0,1] == '*'
    mult = true
    type = type[1..-1]
  end
  name = option_name(name).to_sym
  o = option(name, *aliases)
  o.help(help) if help
  o.argument(type) if type
  o.multiple(mult)
  self
end

#option(name, *aliases, &block) ⇒ Object Also known as: switch, switch?

Define an option.

option(:output, :o)


132
133
134
135
136
137
138
139
140
141
142
# File 'lib/clio/usage/command.rb', line 132

def option(name, *aliases, &block)
  opt = options.find{|o| o === name}
  if not opt
    opt = Option.new(name) #, self)
    #opt.aliases(*aliases)
    @options << opt
  end
  opt.aliases(*aliases) unless aliases.empty?
  opt.instance_eval(&block) if block
  opt
end

#option?(name) ⇒ Boolean

Option defined?

Returns:

  • (Boolean)


304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/clio/usage/command.rb', line 304

def option?(name)
  opt = options.find{|o| o === name}
  if parent && !opt
    opt = parent.option?(name)
  end
  opt
  #return opt if opt
  #options.each do |o|
  #  return o if o.aliases.include?(key)
  #end
  #nil
end

#parse(argv, index = 0) ⇒ Object

Parse usage.



413
414
415
416
# File 'lib/clio/usage/command.rb', line 413

def parse(argv, index=0)
  @parser ||= Parser.new(self, argv, index)
  @parser.parse
end

#subcommand(name, help = nil, &block) ⇒ Object Also known as: cmd, command

Define or retrieve a command.

subcommand('remote')

A shortcut to accessing subcommands of subcommands, the following statements are equivalent:

subcommand('remote').subcommand('add')

subcommand('remote add')


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/clio/usage/command.rb', line 104

def subcommand(name, help=nil, &block)
  name, names = *name.to_s.strip.split(/\s+/)
  if names
    names = [name, *names]
    cmd = names.inject(self) do |c, n|
      c.subcommand(n)
    end
  else
    cmd = subcommands.find{ |c| c === name }
    unless cmd
      cmd = Command.new(name, self)
      subcommands << cmd
    end
  end
  cmd.help(help) if help
  cmd.instance_eval(&block) if block
  cmd
end

#to_sObject

Usage text.



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/clio/usage/command.rb', line 354

def to_s
  #s = [full_name]
  s = [name]

  case options.size
  when 0
  when 1, 2, 3
    s.concat(options.collect{ |o| "[#{o.to_s.strip}]" })
  else
    s << "[switches]"  # switches? vs. options
  end

  s << arguments.join(' ') unless arguments.empty?

  case subcommands.size
  when 0
  when 1
    s << subcommands.join('')
  when 2, 3
    s << '[' + subcommands.join(' | ') + ']'
  else
    s << 'command'
  end

  s.flatten.join(' ')
end

#to_s_helpObject

Help text.



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/clio/usage/command.rb', line 383

def to_s_help
  s = []
  unless help.empty?
    s << help
    s << ''
  end
  s << "Usage:"
  s << "  " + to_s
  unless subcommands.empty?
    s << ''
    s << 'Commands:'
    s.concat(subcommands.collect{ |x| "  %-20s %s" % [x.name, x.help] }.sort)
  end
  unless arguments.empty?
    s << ''
    s << "Arguments:"
    s.concat(arguments.collect{ |x| "  %-20s %s" % [x, x.help] })
  end
  unless options.empty?
    s << ''
    s << 'Switches:'
    s.concat(options.collect{ |x| "  %-20s %s" % [x, x.help] })
  end
  s.flatten.join("\n")
end