Module: Climate::ParsingMethods

Included in:
Command, Parser, Script
Defined in:
lib/climate/parser.rb

Instance Method Summary collapse

Instance Method Details

#arg(*args) ⇒ Object

Raises:



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/climate/parser.rb', line 97

def arg(*args)
  arg = Argument.new(*args)

  raise DefinitionError, "can not define more arguments after a multi " +
    " argument" if cli_arguments.any?(&:multi?)

  raise DefinitionError, "can not define a required argument after an " +
    "optional one" if cli_arguments.any?(&:optional?) && arg.required?

  cli_arguments << arg
end

#cli_argumentsObject



193
# File 'lib/climate/parser.rb', line 193

def cli_arguments ; @cli_arguments ||= [] ; end

#cli_optionsObject



192
# File 'lib/climate/parser.rb', line 192

def cli_options   ; @cli_options ||= []   ; end

#has_arguments?Boolean

Returns:

  • (Boolean)


196
# File 'lib/climate/parser.rb', line 196

def has_arguments? ;   not cli_arguments.empty? ; end

#has_options?Boolean

Returns:

  • (Boolean)


195
# File 'lib/climate/parser.rb', line 195

def has_options? ;     not cli_options.empty?   ; end

#opt(*args) ⇒ Object



109
110
111
# File 'lib/climate/parser.rb', line 109

def opt(*args)
  cli_options << Option.new(*args)
end

#parse(arguments, command = self) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/climate/parser.rb', line 166

def parse(arguments, command=self)
  parser = self.trollop_parser
  begin
    options = parser.parse(arguments)
  rescue Trollop::CommandlineError => e
    if (m = /unknown argument '(.+)'/.match(e.message))
      raise UnexpectedArgumentError.new(m[1], command)
    elsif (m = /option (.+) must be specified/.match(e.message))
      raise MissingArgumentError.new(m[1], command)
    else
      raise CommandError.new(e.message, command)
    end
  end

  # it would get weird if we allowed arguments alongside options, so
  # lets keep it one or t'other
  arguments, leftovers =
    if @stop_on
      [{}, parser.leftovers]
    else
      [self.parse_arguments(parser.leftovers), []]
    end

  [arguments, options, leftovers]
end

#parse_arguments(args, command = self) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/climate/parser.rb', line 127

def parse_arguments(args, command=self)

  arg_list = cli_arguments

  if arg_list.none?(&:multi?) && args.size > arg_list.size
    raise UnexpectedArgumentError.new("#{args.size} for #{arg_list.size}", command)
  end

  # mung the last arguments to appear as one for multi args, this is fairly
  # ugly - thank heavens for unit tests
  if arg_list.last && arg_list.last.multi?
    multi_arg = arg_list.last
    last_args = args[(arg_list.size - 1)..-1] || []

    # depending on the number of args that were supplied, you may get nil
    # or an empty array because of how slicing works, either way we want nil
    # if no args were supplied so `required?` detection works below
    args = args[0...(arg_list.size - 1)] +
      [last_args.empty?? nil : last_args].compact
  end

  arg_list.zip(args).map do |argument, arg_value|
    arg_value ||= argument.default
    if argument.required? && arg_value.nil?
      raise MissingArgumentError.new(argument.name, command)
    end

    # empty list is nil for multi arg
    arg_value = [] if argument.multi? && arg_value.nil?

    # no arg given is different to an empty arg
    if arg_value.nil?
      {}
    else
      {argument.name => arg_value}
    end
  end.inject {|a,b| a.merge(b) } || {}
end

#stop_on(args) ⇒ Object



113
114
115
# File 'lib/climate/parser.rb', line 113

def stop_on(args)
  @stop_on = args
end

#trollop_parserObject



117
118
119
120
121
122
123
124
125
# File 'lib/climate/parser.rb', line 117

def trollop_parser
  Trollop::Parser.new.tap do |parser|
    parser.stop_on @stop_on

    cli_options.each do |option|
      option.add_to(parser)
    end
  end
end