Class Clio::Usage::Subcommand
In: lib/clio/usage/subcommand.rb
Parent: Object

Commandline Usage Command

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

  usage = Usage.new

Methods

===   []   arg   argument   cmd   command   completion   full_name   help   help!   initialize_copy   inspect   key   method_missing   new   opt   option   option?   parse   subcommand   switch   switch?   swt   to_s   to_s_help  

External Aliases

options -> switches
  Widely accepted alternate term for options.
subcommands -> commands

Attributes

arguments  [R]  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.

help  [R]  Help text.
name  [R]  Name of the command.
options  [R]  Array of options.
parent  [R]  Parent command. This is needed to support cascading options.
subcommands  [R]  Array of subcommands.

Public Class methods

[Source]

# File lib/clio/usage/subcommand.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

Public Instance methods

[Source]

# File lib/clio/usage/subcommand.rb, line 341
      def ===(other_name)
        name == other_name.to_s
      end

Super shorthand notation.

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

[Source]

# File lib/clio/usage/subcommand.rb, line 292
      def [](*x)
        case x[0].to_s[0,1]
        when '-'
          opt(*x)
        when '<'
          arg(*x)
        else
          subcommand(*x)
        end
      end
arg(*n_type, &block)

Alias for argument

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

Indexing of arguments starts at 1, not 0.

Examples

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

[Source]

# File lib/clio/usage/subcommand.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

        #if type.index(':')
        #  name, type = *type.split(':')
        #  name = name.downcase
        #  type = type.upcase
        #else
        #  if type.upcase == type
        #    name = nil
        #  else
        #    name = type
        #    type = type.upcase
        #  end
        #end

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

        if arg = @arguments[index]
          arg.type(type) if type
          #arg.name(name) if name
          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.name(name) if name
            arg.help(help) if help
            arg.splat(splat) if splat
            @arguments[index] = arg
          end
        end
        return arg
      end
cmd(name, help=nil, &block)

Alias for subcommand

command(name, help=nil, &block)

Alias for subcommand

[Source]

# File lib/clio/usage/subcommand.rb, line 307
      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 callable command name.

[Source]

# File lib/clio/usage/subcommand.rb, line 359
      def full_name
        if parent && parent.full_name
          "#{parent.full_name} #{name}"
        else
          "#{name}"
        end
      end

[Source]

# File lib/clio/usage/subcommand.rb, line 280
      def help(string=nil)
        @help.replace(string.to_s) if string
        @help
      end

[Source]

# File lib/clio/usage/subcommand.rb, line 87
      def help!(*args)
        Hash[*args].each do |key, desc|
          self[key, desc]
        end
      end

[Source]

# File lib/clio/usage/subcommand.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

[Source]

# File lib/clio/usage/subcommand.rb, line 346
      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

[Source]

# File lib/clio/usage/subcommand.rb, line 68
      def key ; @name.to_sym ; end

METHOD MISSING

[Source]

# File lib/clio/usage/subcommand.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

Option shorthand.

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

[Source]

# File lib/clio/usage/subcommand.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

Define an option.

  option(:output, :o)

[Source]

# File lib/clio/usage/subcommand.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 defined?

[Source]

# File lib/clio/usage/subcommand.rb, line 319
      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 usage.

[Source]

# File lib/clio/usage/subcommand.rb, line 428
      def parse(argv, index=0)
        @parser ||= Parser.new(self, argv, index)
        @parser.parse
      end

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')

[Source]

# File lib/clio/usage/subcommand.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 = Subcommand.new(name, self)
            subcommands << cmd
          end
        end
        cmd.help(help) if help
        cmd.instance_eval(&block) if block
        cmd
      end
switch(name, *aliases, &block)

Alias for option

switch?(name, *aliases, &block)

Alias for option

swt(name, help=nil)

Alias for opt

Usage text.

[Source]

# File lib/clio/usage/subcommand.rb, line 369
      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

Help text.

[Source]

# File lib/clio/usage/subcommand.rb, line 398
      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

[Validate]