Class: Nucleon::Util::CLI::Parser

Inherits:
Object
  • Object
show all
Includes:
Mixin::Colors
Defined in:
lib/core/util/cli.rb

Overview


Parser

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixin::Colors

#black, #blue, #cyan, #green, #grey, #purple, #red, #yellow

Constructor Details

#initialize(args, banner = '', help = '', split_help = false) {|_self| ... } ⇒ Parser


Yields:

  • (_self)

Yield Parameters:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/core/util/cli.rb', line 39

def initialize(args, banner = '', help = '', split_help = false)
  @parser = OptionParser.new

  self.options   = {}
  self.arguments = {}
  self.extra     = {}
  self.processed = false
  self.strict    = true

  @arg_settings  = []

  self.banner  = banner
  self.help    = help

  yield(self) if block_given?

  parse_command(args, split_help)
end

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def arguments
  @arguments
end

#extraObject

Returns the value of attribute extra.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def extra
  @extra
end

#optionsObject

Returns the value of attribute options.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def options
  @options
end

#parserObject

Returns the value of attribute parser.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def parser
  @parser
end

#processedObject

Returns the value of attribute processed.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def processed
  @processed
end

#strictObject

Returns the value of attribute strict.



31
32
33
# File 'lib/core/util/cli.rb', line 31

def strict
  @strict
end

Class Method Details

.split(args, banner, separator = '') ⇒ Object




60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/core/util/cli.rb', line 60

def self.split(args, banner, separator = '')
  check_args  = []
  main_args   = nil
  sub_command = nil
  sub_args    = []

  # Log level gets processed in main args so we can log executable init
  parse_log_value = false

  args.each do |arg|
    if arg =~ /^\-\-log_level(?=\=(.*))?/
      if $1
        Nucleon.log_level = $1
      else
        parse_log_value = true
      end
    elsif parse_log_value
      Nucleon.log_level = arg
      parse_log_value = false
    else
      check_args << arg
    end
  end

  check_args.each_index do |index|
    if !check_args[index].start_with?('-')
      main_args   = check_args[0, index]
      sub_command = check_args[index]
      sub_args    = check_args[index + 1, check_args.length - index + 1]
      break
    end
  end

  main_args = check_args.dup if main_args.nil?
  results   = [ Parser.new(main_args, banner, separator, true) ]

  if sub_command
    results << [ sub_command, sub_args ]
  end

  return results.flatten
end

Instance Method Details

#arg(name, default, allowed_values, message_id, config = {}, &block) ⇒ Object




373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/core/util/cli.rb', line 373

def arg(name, default, allowed_values, message_id, config = {}, &block)
  config       = Config.ensure(config)
  name         = name.to_sym

  message_name = name.to_s + '_message'
  message      = CLI.message(message_id, arguments[name])

  settings     = {
    :name    => name,
    :default => config.get(name, default),
    :message => config.get(message_name.to_sym, message)
  }
  settings[:allowed] = allowed_values if allowed_values
  settings[:block]   = block if block

  settings.delete(:default) if settings[:default].nil?

  @arg_settings << settings
end

#arg_array(name, default, message_id, config = {}) ⇒ Object




477
478
479
480
481
# File 'lib/core/util/cli.rb', line 477

def arg_array(name, default, message_id, config = {})
  arg(name, default, Array, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#arg_bool(name, default, message_id, config = {}) ⇒ Object




408
409
410
411
412
413
414
415
416
417
# File 'lib/core/util/cli.rb', line 408

def arg_bool(name, default, message_id, config = {})
  arg(name, default, nil, message_id, config) do |value|
    value = Util::Data.value(value)
    if value == true || value == false
      block_given? ? yield(value) : value
    else
      nil
    end
  end
end

#arg_float(name, default, message_id, config = {}) ⇒ Object




445
446
447
448
449
# File 'lib/core/util/cli.rb', line 445

def arg_float(name, default, message_id, config = {})
  arg(name, default, Float, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#arg_int(name, default, message_id, config = {}) ⇒ Object




429
430
431
432
433
# File 'lib/core/util/cli.rb', line 429

def arg_int(name, default, message_id, config = {})
  arg(name, default, Integer, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#arg_str(name, default, message_id, config = {}) ⇒ Object




461
462
463
464
465
# File 'lib/core/util/cli.rb', line 461

def arg_str(name, default, message_id, config = {})
  arg(name, default, nil, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#banner=(banner) ⇒ Object




105
106
107
# File 'lib/core/util/cli.rb', line 105

def banner=banner
  parser.banner = banner
end

#helpObject




111
112
113
# File 'lib/core/util/cli.rb', line 111

def help
  return parser.help
end

#help=(help) ⇒ Object



115
116
117
118
119
120
121
122
123
# File 'lib/core/util/cli.rb', line 115

def help=help
  if help.is_a?(Array)
    help.each do |line|
      parser.separator line
    end
  else
    parser.separator help
  end
end

#option(name, default, option_str, allowed_values, message_id, config = {}) ⇒ Object




348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
# File 'lib/core/util/cli.rb', line 348

def option(name, default, option_str, allowed_values, message_id, config = {})
  config        = Config.ensure(config)
  name          = name.to_sym
  options[name] = config.get(name, default)

  message_name = name.to_s + '_message'
  message      = CLI.message(message_id, options[name])

  option_str   = Util::Data.array(option_str)

  if allowed_values
    parser.on(*option_str, allowed_values, config.get(message_name.to_sym, message)) do |value|
      value         = yield(value) if block_given?
      options[name] = value unless value.nil?
    end
  else
    parser.on(*option_str, config.get(message_name.to_sym, message)) do |value|
      value         = yield(value) if block_given?
      options[name] = value unless value.nil?
    end
  end
end

#option_array(name, default, option_str, message_id, config = {}) ⇒ Object




469
470
471
472
473
# File 'lib/core/util/cli.rb', line 469

def option_array(name, default, option_str, message_id, config = {})
  option(name, default, option_str, Array, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#option_bool(name, default, option_str, message_id, config = {}) ⇒ Object




395
396
397
398
399
400
401
402
403
404
# File 'lib/core/util/cli.rb', line 395

def option_bool(name, default, option_str, message_id, config = {})
  option(name, default, option_str, nil, message_id, config) do |value|
    value = Util::Data.value(value)
    if value == true || value == false
      block_given? ? yield(value) : value
    else
      nil
    end
  end
end

#option_float(name, default, option_str, message_id, config = {}) ⇒ Object




437
438
439
440
441
# File 'lib/core/util/cli.rb', line 437

def option_float(name, default, option_str, message_id, config = {})
  option(name, default, option_str, Float, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#option_int(name, default, option_str, message_id, config = {}) ⇒ Object




421
422
423
424
425
# File 'lib/core/util/cli.rb', line 421

def option_int(name, default, option_str, message_id, config = {})
  option(name, default, option_str, Integer, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#option_str(name, default, option_str, message_id, config = {}) ⇒ Object




453
454
455
456
457
# File 'lib/core/util/cli.rb', line 453

def option_str(name, default, option_str, message_id, config = {})
  option(name, default, option_str, nil, message_id, config) do |value|
    block_given? ? yield(value) : value
  end
end

#parse_command(args, split_help = false) ⇒ Object




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
165
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/core/util/cli.rb', line 133

def parse_command(args, split_help = false)
  args  = args.dup
  error = false

  self.processed = false

  option_bool(:version, false,
    '--version',
    'nucleon.core.util.cli.options.version'
  )
  option_bool(:color, Util::Console.use_colors,
    '--[no-]color',
    'nucleon.core.util.cli.options.color'
  )
  option_str(:log_level, nil,
    '--log_level STR',
    'nucleon.core.util.cli.options.log_level'
  )
  option_str(:exec_dir, nil,
    '--exec_dir STR',
    'nucleon.core.util.cli.options.exec_dir'
  )
  option_str(:encoded_params, false,
    '--encoded STR',
    'nucleon.core.util.cli.options.encoded'
  )
  if split_help
    parser.on_tail('-h', CLI.message('nucleon.core.util.cli.options.short_help')) do
      options[:help] = true
    end
    parser.on_tail('--help', CLI.message('nucleon.core.util.cli.options.extended_help')) do
      options[:help]          = true
      options[:extended_help] = true
    end
  else
    parser.on_tail('-h', '--help', CLI.message('nucleon.core.util.cli.options.short_help')) do
      options[:help] = true
    end
  end

  if strict
    parser.parse!(args)
    extra_args = {}
  else
    args, extra_args = parse_known_args(parser, args)
  end

  # Now we can act on options given
  options[:color] = Util::Console.use_colors

  if options[:version]
    puts version
    exit 0
  end

  if options[:exec_dir]
    Dir.chdir(options[:exec_dir])
  end

  return if options[:help]

  parse_encoded

  self.extra = normalize_extra_options(extra_args) unless extra_args.empty?

  remaining_args = args.dup
  arg_messages   = []

  if arguments.empty?
    @arg_settings.each_with_index do |settings, index|
      if index >= args.length
        value = nil
      else
        value = Util::Data.value(args[index])
      end

      if !value.nil? && settings.has_key?(:allowed)
        allowed = settings[:allowed]
        case allowed
        when Class
          if (allowed == Array)
            value          = remaining_args
            remaining_args = []
          end
          unless value.is_a?(allowed)
            arg_messages << CLI.message(settings[:message])
            error = true
          end
        when Array
          unless allowed.include(value)
            arg_messages << CLI.message(settings[:message])
            error = true
          end
        end
      end

      if value.nil?
        if settings.has_key?(:default)
          value = settings[:default]
        else
          error = true
        end
      end

      if !value.nil? && settings.has_key?(:block)
        value = settings[:block].call(value)
        error = true if value.nil?
      end

      break if error

      remaining_args.shift unless remaining_args.empty?
      self.arguments[settings[:name]] = value
    end
  end

  if error
    if ! arg_messages.empty?
      parser.warn(CLI.message('nucleon.core.util.cli.parse.error') + "\n\n" + arg_messages.join("\n") + "\n\n" + parser.help)
    else
      parser.warn(CLI.message('nucleon.core.util.cli.parse.error') + "\n\n" + parser.help)
    end
  else
    self.processed = true
  end

rescue OptionParser::InvalidOption => e
  parser.warn(e.message + "\n\n" + parser.help)
end

#parse_encodedObject




265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/core/util/cli.rb', line 265

def parse_encoded
  if options[:encoded_params]
    encoded_properties = CLI.decode(options[:encoded_params])

    @arg_settings.each do |settings|
      if encoded_properties.has_key?(settings[:name].to_sym)
        self.arguments[settings[:name]] = encoded_properties.delete(settings[:name].to_sym)
      end
    end

    encoded_properties.each do |name, value|
      self.options[name] = value

      if name == :color
        Util::Console.use_colors = value
      end
    end
  end
  options.delete(:encoded_params)
end

#parse_known_args(parser, args) ⇒ Object




288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/core/util/cli.rb', line 288

def parse_known_args(parser, args)
  extra_args = []

  parse_args = lambda do |arg_list|
    begin
      original_list = arg_list.clone

      parser.parse! arg_list
      args = arg_list

    rescue OptionParser::InvalidOption => e
      extra_args += e.args
      while arg_list[0] && arg_list[0][0] != '-'
        extra_args << arg_list.shift
      end
      parse_args.call original_list - extra_args
    end
  end
  parse_args.call args
  [ args, extra_args ]
end

#versionObject




127
128
129
# File 'lib/core/util/cli.rb', line 127

def version
  # Override in executable script
end