Class: Clin::CommandParser

Inherits:
Object
  • Object
show all
Defined in:
lib/clin/command_parser.rb

Overview

Command parser

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command_cls, argv = ARGV, fallback_help: true) ⇒ CommandParser

Create the command parser

Parameters:

  • command_cls (Class<Clin::Command>)

    Command that must be matched

  • argv (Array<String>) (defaults to: ARGV)

    List of CL arguments

  • fallback_help (Boolean) (defaults to: true)

    If the parse should raise an HelpError or the real error.



12
13
14
15
16
17
18
19
20
21
# File 'lib/clin/command_parser.rb', line 12

def initialize(command_cls, argv = ARGV, fallback_help: true)
  @command = command_cls
  argv = Shellwords.split(argv) if argv.is_a? String
  @argv = argv
  @fallback_help = fallback_help
  @options = {}
  @arguments = {}
  @errors = []
  @skipped_options = []
end

Instance Attribute Details

#errorsObject (readonly)

List of errors that have occurred during the parsing



6
7
8
# File 'lib/clin/command_parser.rb', line 6

def errors
  @errors
end

Instance Method Details

#add_error(err) ⇒ Object



55
56
57
# File 'lib/clin/command_parser.rb', line 55

def add_error(err)
  @errors << err
end

#init_defaultsObject



29
30
31
# File 'lib/clin/command_parser.rb', line 29

def init_defaults
  @options = @command.option_defaults
end

#paramsObject



23
24
25
26
27
# File 'lib/clin/command_parser.rb', line 23

def params
  out = @options.merge(@arguments)
  out[:skipped_options] = @skipped_options if @command.skip_options?
  out
end

#parseObject

Parse the command line.



34
35
36
37
38
39
40
41
42
43
44
# File 'lib/clin/command_parser.rb', line 34

def parse
  argv = @argv.clone
  init_defaults
  parse_options(argv)
  parse_arguments(argv)

  return redispatch(params) if @command.redispatch?
  obj = @command.new(params)
  validate!
  obj
end

#parse_arguments(argv) ⇒ Object

Parse the argument. The options must have been strip out first.



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/clin/command_parser.rb', line 60

def parse_arguments(argv)
  @command.args.each do |arg|
    value, argv = arg.parse(argv)

    @arguments[arg.name.to_sym] = value
  end
  @arguments.delete_if { |_, v| v.nil? }
  @arguments
rescue Clin::ArgumentError => e
  add_error e
end

#parse_options(argv) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/clin/command_parser.rb', line 46

def parse_options(argv)
  parser = Clin::OptionParser.new(@command, argv)
  @options.merge! parser.parse
  @skipped_options = parser.skipped_options
  @errors += parser.errors
  argv.replace(parser.arguments)
  @options
end

#redispatch(params) ⇒ Object

Method called after the argument have been parsed and before creating the command

Parameters:

  • params (Array<String>)

    Parsed params from the command line.



74
75
76
77
78
79
80
81
82
83
# File 'lib/clin/command_parser.rb', line 74

def redispatch(params)
  commands = @command._redispatch_args.last
  commands ||= @command.default_commands
  dispatcher = Clin::CommandDispatcher.new(commands)
  begin
    dispatcher.parse(redispatch_arguments(params))
  rescue Clin::HelpError
    raise Clin::HelpError, @command
  end
end

#redispatch_arguments(params) ⇒ Object

Compute the list of argument to pass to the CommandDispatcher

Parameters:

  • params (Hash)

    Options and Arguments of the CL



87
88
89
90
91
92
93
# File 'lib/clin/command_parser.rb', line 87

def redispatch_arguments(params)
  args, prefix = @command._redispatch_args
  args = args.map { |x| params[x] }.flatten.compact
  args = prefix.split + args unless prefix.nil?
  args += params[:skipped_options] if @command.skip_options?
  args
end

#valid?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/clin/command_parser.rb', line 95

def valid?
  @errors.empty?
end

#validate!Object



99
100
101
102
103
# File 'lib/clin/command_parser.rb', line 99

def validate!
  return if valid?
  fail Clin::HelpError, @command if @fallback_help
  fail @errors.sort_by { |e| e.class.severity }.last
end