Class: ShellOpts::Command

Inherits:
BasicObject
Defined in:
lib/shellopts/program.rb,
lib/shellopts/dump.rb

Overview

Command represents a program or a subcommand. It is derived from BasicObject to have only a minimum of inherited member methods.

The names of the inherited methods can’t be used as options or command namess. They are: instance_eval, instance_exec method_missing, singleton_method_added, singleton_method_removed, and singleton_method_undefined.

Additional methods defined in Command use the ‘__<identifier>__’ naming convention that doesn’t collide with option or subcommand names but they’re rarely used in application code

Command also defines #subcommand and #subcommand! but they can be overshadowed by an option or command declaration. Their values can still be accessed using the dashed name, though

Option and Command objects can be accessed using #[]. #key? is also defined

The following methods are created dynamically for each declared option with an attribute name

<identifier>(default = nil)
<identifier>=(value)
<identifier>?()

The default value is used if the option or its value is missing

Options without an an attribute can still be accessed using #[] or trough #option_values, #__option_hash, or #options_list

Each subcommand has a single method:

# Return the subcommand object or nil if not present
def <identifier>!() subcommand == :<identifier> ? @__subcommand__ : nil end

The general #subcommand method can be used to find out which subcommand is used

Direct Known Subclasses

Program

Constant Summary collapse

RESERVED_OPTION_NAMES =

These names can’t be used as option or command names

%w(
    is_a to_h instance_eval instance_exec method_missing singleton_method_added
    singleton_method_removed singleton_method_undefined
)
OVERRIDEABLE_METHOD_NAMES =

These methods can be overridden by an option or a command (this constant is not used - it is just for informational purposes)

%w(
    subcommand subcommand! subcommands subcommands! supercommand!
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#__grammar__Object (readonly)

Grammar object



161
162
163
# File 'lib/shellopts/program.rb', line 161

def __grammar__
  @__grammar__
end

#__option_hash__Object (readonly)

Map from identifier to option object or to a list of option objects if the option is repeatable



177
178
179
# File 'lib/shellopts/program.rb', line 177

def __option_hash__
  @__option_hash__
end

#__option_list__Object (readonly)

List of Option objects for the subcommand in the same order as given by the user but note that options are reordered to come after their associated subcommand if float is true. Repeated options are not collapsed



173
174
175
# File 'lib/shellopts/program.rb', line 173

def __option_list__
  @__option_list__
end

#__option_values__Object (readonly)

Hash from identifier to value. Can be Integer, Float, or String depending on the option’s type. Repeated options options without arguments have the number of occurences as value, repeated option with arguments have the array of values as value



167
168
169
# File 'lib/shellopts/program.rb', line 167

def __option_values__
  @__option_values__
end

#__supercommand__Object

The parent command or nil. Initialized by #add_command



180
181
182
# File 'lib/shellopts/program.rb', line 180

def __supercommand__
  @__supercommand__
end

Class Method Details

.dump(expr, argv = []) ⇒ Object

Class-level accessor methods



149
# File 'lib/shellopts/dump.rb', line 149

def self.dump(expr, argv = []) expr.__dump__(argv) end

.new(grammar) ⇒ Object

Redefine ::new to call #__initialize__



59
60
61
62
63
# File 'lib/shellopts/program.rb', line 59

def self.new(grammar)
  object = super()
  object.__send__(:__initialize__, grammar)
  object
end

Instance Method Details

#[](key) ⇒ Object

Return command or option object if present, otherwise nil. Returns a possibly empty array of option objects if the option is repeatable

The key is the name or identifier of the object or any any option alias. Eg. :f, ‘-f’, :file, or ‘–file’ are all usable as option keys and :cmd! or ‘cmd’ as command keys



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

def [](key)
  case object = __grammar__[key]
    when ::ShellOpts::Grammar::Command
      object.ident == __subcommand__!.__ident__ ? __subcommand__! : nil
    when ::ShellOpts::Grammar::Option
      if object.repeatable?
        __option_hash__[object.ident] || []
      else
        __option_hash__[object.ident]
      end
    else
      ::Kernel.raise ::ArgumentError, "Unknown command or option: '#{key}'"
  end
end

#__dump__(argv = []) ⇒ Object



139
140
141
142
143
144
145
146
# File 'lib/shellopts/dump.rb', line 139

def __dump__(argv = [])
  ::Kernel.puts __name__
  ::Kernel.indent {
    __options__.each { |ident, value| ::Kernel.puts "#{ident}: #{value.inspect}" }
    __subcommand__!&.__dump__
    ::Kernel.puts argv.map(&:inspect).join(" ") if !argv.empty?
  }
end

#__ident__Object

Identfier including the exclamation mark (Symbol)



155
# File 'lib/shellopts/program.rb', line 155

def __ident__() @__grammar__.ident end

#__name__Object

Name of command/program without the exclamation mark (String)



158
# File 'lib/shellopts/program.rb', line 158

def __name__() @__grammar__.name end

#__subcommand__Object

The subcommand identifier (a Symbol incl. the exclamation mark) or nil if not present. Use #subcommand!, or the dynamically generated ‘#<identifier>!’ method to get the actual subcommand object



185
# File 'lib/shellopts/program.rb', line 185

def __subcommand__() @__subcommand__&.__ident__ end

#__subcommand__!Object

The actual subcommand object or nil if not present



188
# File 'lib/shellopts/program.rb', line 188

def __subcommand__!() @__subcommand__ end

#__subcommands__Object

Implementation of the #subcommands method



191
192
193
# File 'lib/shellopts/program.rb', line 191

def __subcommands__()
  __subcommands__!.last&.__uid__&.to_sym
end

#__subcommands__!Object

Implementation of the #subcommands! method



196
197
198
# File 'lib/shellopts/program.rb', line 196

def __subcommands__!()
  ::Algorithm.follow(self.__subcommand__!, :__subcommand__!).to_a
end

#__uid__Object

UID of command/program



152
# File 'lib/shellopts/program.rb', line 152

def __uid__() @__grammar__.uid end

#key?(key) ⇒ Boolean

Return true if the given command or option is present

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
# File 'lib/shellopts/program.rb', line 88

def key?(key)
  case object = __grammar__[key]
    when ::ShellOpts::Grammar::Command
      object.ident == __subcommand__
    when ::ShellOpts::Grammar::Option
      __option_hash__.key?(object.ident)
    else
      ::Kernel.raise ::ArgumentError, "Unknown command or option: '#{key}'"
  end
end

#subcommandObject

Subcommand identifier or nil if not present. #subcommand is often used in case statement to branch out to code that handles the given subcommand:

prog, args = ShellOpts.parse("do_this! do_that!", ARGV)
case prog.subcommand
  when :do_this!; prog.do_this.operation # or prog[:subcommand!] or prog.subcommand!
  when :do_that!; prog.do_that.operation
end

Note: Can be overridden by option, in that case use #__subcommand__ or ShellOpts.subcommand(object) instead



124
# File 'lib/shellopts/program.rb', line 124

def subcommand() __subcommand__ end

#subcommand!Object

The subcommand object or nil if not present. Per-subcommand methods (#<identifier>!) are often used instead of #subcommand! to get the subcommand

Note: Can be overridden by a subcommand declaration (but not an option), in that case use #__subcommand__! or ShellOpts.subcommand!(object) instead



134
# File 'lib/shellopts/program.rb', line 134

def subcommand!() __subcommand__! end

#subcommandsObject

Returns the concatenated identifier of subcommands (eg. :cmd.subcmd!)



137
# File 'lib/shellopts/program.rb', line 137

def subcommands() __subcommands__ end

#subcommands!Object

Returns the subcommands in an array. This doesn’t include the top-level program object



141
# File 'lib/shellopts/program.rb', line 141

def subcommands!() __subcommands__! end

#supercommand!Object

The parent command or nil. Initialized by #add_command

Note: Can be overridden by a subcommand declaration (but not an option), in that case use #__supercommand__! or ShellOpts.supercommand!(object) instead



149
# File 'lib/shellopts/program.rb', line 149

def supercommand!() __supercommand__ end

#to_h(*keys) ⇒ Object

Returns a hash of the given options if defined. Returns all options if no options are given



101
102
103
104
105
106
107
108
109
110
# File 'lib/shellopts/program.rb', line 101

def to_h(*keys)
  keys = ::Kernel::Array(keys).flatten
  if keys.empty?
    self.to_h(@__grammar__.options.map(&:ident))
  else
    keys.map { |key|
      self.__send__("#{key}?".to_sym) ? [key, self.__send__(key)] : nil
    }.compact.to_h
  end
end