Class: Command::Parser

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(definition, argv) ⇒ Parser

Returns a new instance of Parser.



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/command/parser.rb', line 16

def initialize(definition, argv)
  @definition = definition
  @argv       = argv
  @affix      = [] # arguments after '--'
  if i = argv.index('--')
    @affix     = argv[(i+1)..-1]
    @arguments = argv.first(i)
  else
    @arguments = @argv.dup
  end
  @options    = {}
end

Instance Attribute Details

#argvObject (readonly)

Returns the value of attribute argv.



14
15
16
# File 'lib/command/parser.rb', line 14

def argv
  @argv
end

#commandObject (readonly)

Returns the value of attribute command.



12
13
14
# File 'lib/command/parser.rb', line 12

def command
  @command
end

#definitionObject (readonly)

Returns the value of attribute definition.



11
12
13
# File 'lib/command/parser.rb', line 11

def definition
  @definition
end

#optionsObject (readonly)

Returns the value of attribute options.



13
14
15
# File 'lib/command/parser.rb', line 13

def options
  @options
end

Instance Method Details

#argument(name) ⇒ Object

Raises:

  • (ArgumentError)


29
30
31
32
33
# File 'lib/command/parser.rb', line 29

def argument(name)
  position = @definition.argument_position[name]
  raise ArgumentError, "No argument #{name.inspect} available" unless position
  arguments[position]
end

#argumentsObject



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

def arguments
  @arguments+@affix
end

#command!Object



43
44
45
46
47
48
49
50
51
# File 'lib/command/parser.rb', line 43

def command!
  if @definition.commands_by_name.include?(@arguments.first)
    @command = @arguments.shift
  else
    @command = @definition.default_command
  end

  @command
end

#normalize_arguments!Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/command/parser.rb', line 53

def normalize_arguments!
  options    = @definition[@command].options_by_flag
  parse_argv = @arguments
  @arguments = []
  while arg = parse_argv.shift
    if arg =~ /\A-([^-]{2,})/ then
      flags  = $1
      until flags.empty?
        flag = flags.slice!(0,1)
        if opt  = options["-#{flag}"] then
          case opt.necessity
            when :required
              @arguments << "-#{flag}"
              @arguments << flags unless flags.empty?
              flags = ""
            when :optional
              raise "Invalid option - can't merge short options with optional arguments"
            when :none
              @arguments << "-#{flag}"
            else
              raise "Unknown necessity #{opt.necessity.inspect} for option #{opt}"
          end
        else
          @arguments << "-#{flag}#{flags}"
        end
      end
    else
      @arguments << arg
    end
  end
end

#option(name) ⇒ Object



35
36
37
# File 'lib/command/parser.rb', line 35

def option(name)
  @options[name]
end

#options!(*flags) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/command/parser.rb', line 85

def options!(*flags)
  ignore_invalid_options = flags.delete(:ignore_invalid_options)
  options                = @definition[@command].options_by_flag # options available to this command
  env                    = @definition[@command].env_by_variable # options available to this command
  defaults               = @definition[@command].default_options # options available to this command

  normalize_arguments!

  parse_argv             = @arguments
  @arguments             = []

  defaults.each do |key, default|
    @options[key] = default unless @options.has_key?(key)
  end

  env.each do |key, definition|
    if ENV.has_key?(key) && !@options.has_key?(key) then
      mapped = options[definition.name]
      value  = mapped.process!(ENV[key])
      @options[key] = value
    end
  end

  while arg = parse_argv.shift
    if option = options[arg] then
      case option.necessity
        when :required
          value = option.process!(parse_argv.shift)
        when :optional
          if parse_argv.first && parse_argv.first !~ /\A-/ then
            value = option.process!(parse_argv.shift)
          else
            value = true
          end
        when :none
          value = true
      end
      @options[option.name] = (arg == option.negated) ? !value : value
    elsif arg =~ /\A-/ then
      raise "Invalid option #{arg}" unless ignore_invalid_options
      @arguments << arg
    else
      @arguments << arg
    end
  end

  @options
end

#parse(*flags) ⇒ Object



138
139
140
141
142
143
# File 'lib/command/parser.rb', line 138

def parse(*flags)
  command!
  options!(*flags)

  result
end

#resultObject



134
135
136
# File 'lib/command/parser.rb', line 134

def result
  Result.new(@command, @options, @arguments+@affix)
end