gli_aziz_light 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +17 -0
- data/CONTRIBUTING.md +23 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +201 -0
- data/ObjectModel.graffle +1191 -0
- data/README.rdoc +109 -0
- data/Rakefile +126 -0
- data/bin/gli +59 -0
- data/bin/report_on_rake_results +10 -0
- data/bin/test_all_rubies.sh +6 -0
- data/features/gli_executable.feature +90 -0
- data/features/gli_init.feature +232 -0
- data/features/step_definitions/gli_executable_steps.rb +18 -0
- data/features/step_definitions/gli_init_steps.rb +11 -0
- data/features/step_definitions/todo_steps.rb +88 -0
- data/features/support/env.rb +53 -0
- data/features/todo.feature +413 -0
- data/features/todo_legacy.feature +128 -0
- data/gli.cheat +95 -0
- data/gli.gemspec +34 -0
- data/gli.rdoc +73 -0
- data/lib/gli.rb +35 -0
- data/lib/gli/app.rb +286 -0
- data/lib/gli/app_support.rb +341 -0
- data/lib/gli/command.rb +171 -0
- data/lib/gli/command_finder.rb +41 -0
- data/lib/gli/command_line_option.rb +34 -0
- data/lib/gli/command_line_token.rb +63 -0
- data/lib/gli/command_support.rb +181 -0
- data/lib/gli/commands/compound_command.rb +42 -0
- data/lib/gli/commands/doc.rb +231 -0
- data/lib/gli/commands/help.rb +95 -0
- data/lib/gli/commands/help_modules/arg_name_formatter.rb +20 -0
- data/lib/gli/commands/help_modules/command_finder.rb +60 -0
- data/lib/gli/commands/help_modules/command_help_format.rb +156 -0
- data/lib/gli/commands/help_modules/global_help_format.rb +70 -0
- data/lib/gli/commands/help_modules/help_completion_format.rb +31 -0
- data/lib/gli/commands/help_modules/list_formatter.rb +23 -0
- data/lib/gli/commands/help_modules/one_line_wrapper.rb +18 -0
- data/lib/gli/commands/help_modules/options_formatter.rb +49 -0
- data/lib/gli/commands/help_modules/text_wrapper.rb +53 -0
- data/lib/gli/commands/help_modules/tty_only_wrapper.rb +23 -0
- data/lib/gli/commands/help_modules/verbatim_wrapper.rb +16 -0
- data/lib/gli/commands/initconfig.rb +74 -0
- data/lib/gli/commands/rdoc_document_listener.rb +116 -0
- data/lib/gli/commands/scaffold.rb +401 -0
- data/lib/gli/dsl.rb +226 -0
- data/lib/gli/exceptions.rb +71 -0
- data/lib/gli/flag.rb +68 -0
- data/lib/gli/gli_option_block_parser.rb +84 -0
- data/lib/gli/gli_option_parser.rb +156 -0
- data/lib/gli/option_parser_factory.rb +81 -0
- data/lib/gli/option_parsing_result.rb +21 -0
- data/lib/gli/options.rb +23 -0
- data/lib/gli/switch.rb +35 -0
- data/lib/gli/terminal.rb +101 -0
- data/lib/gli/version.rb +5 -0
- data/test/apps/README.md +2 -0
- data/test/apps/todo/Gemfile +2 -0
- data/test/apps/todo/README.rdoc +6 -0
- data/test/apps/todo/Rakefile +23 -0
- data/test/apps/todo/bin/todo +63 -0
- data/test/apps/todo/lib/todo/commands/create.rb +24 -0
- data/test/apps/todo/lib/todo/commands/list.rb +63 -0
- data/test/apps/todo/lib/todo/commands/ls.rb +47 -0
- data/test/apps/todo/lib/todo/commands/make.rb +52 -0
- data/test/apps/todo/lib/todo/version.rb +3 -0
- data/test/apps/todo/test/tc_nothing.rb +14 -0
- data/test/apps/todo/todo.gemspec +23 -0
- data/test/apps/todo/todo.rdoc +5 -0
- data/test/apps/todo_legacy/Gemfile +2 -0
- data/test/apps/todo_legacy/README.rdoc +6 -0
- data/test/apps/todo_legacy/Rakefile +23 -0
- data/test/apps/todo_legacy/bin/todo +61 -0
- data/test/apps/todo_legacy/lib/todo/commands/create.rb +24 -0
- data/test/apps/todo_legacy/lib/todo/commands/list.rb +63 -0
- data/test/apps/todo_legacy/lib/todo/commands/ls.rb +47 -0
- data/test/apps/todo_legacy/lib/todo/version.rb +3 -0
- data/test/apps/todo_legacy/test/tc_nothing.rb +14 -0
- data/test/apps/todo_legacy/todo.gemspec +23 -0
- data/test/apps/todo_legacy/todo.rdoc +5 -0
- data/test/apps/todo_plugins/commands/third.rb +1 -0
- data/test/config.yaml +10 -0
- data/test/fake_std_out.rb +30 -0
- data/test/init_simplecov.rb +8 -0
- data/test/option_test_helper.rb +13 -0
- data/test/tc_command.rb +508 -0
- data/test/tc_compound_command.rb +22 -0
- data/test/tc_doc.rb +325 -0
- data/test/tc_flag.rb +62 -0
- data/test/tc_gli.rb +773 -0
- data/test/tc_help.rb +387 -0
- data/test/tc_options.rb +43 -0
- data/test/tc_subcommand_parsing.rb +104 -0
- data/test/tc_subcommands.rb +260 -0
- data/test/tc_switch.rb +55 -0
- data/test/tc_terminal.rb +100 -0
- data/test/tc_verbatim_wrapper.rb +36 -0
- data/test/test_helper.rb +20 -0
- metadata +330 -0
data/lib/gli/dsl.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
module GLI
|
2
|
+
# The primary DSL for GLI. This represents the methods shared between your top-level app and
|
3
|
+
# the commands. See GLI::Command for additional methods that apply only to command objects.
|
4
|
+
module DSL
|
5
|
+
# Describe the next switch, flag, or command. This should be a
|
6
|
+
# short, one-line description
|
7
|
+
#
|
8
|
+
# +description+:: A String of the short descripiton of the switch, flag, or command following
|
9
|
+
def desc(description); @next_desc = description; end
|
10
|
+
alias :d :desc
|
11
|
+
|
12
|
+
# Provide a longer, more detailed description. This
|
13
|
+
# will be reformatted and wrapped to fit in the terminal's columns
|
14
|
+
#
|
15
|
+
# +long_desc+:: A String that is s longer description of the switch, flag, or command following.
|
16
|
+
def long_desc(long_desc); @next_long_desc = long_desc; end
|
17
|
+
|
18
|
+
# Describe the argument name of the next flag. It's important to keep
|
19
|
+
# this VERY short and, ideally, without any spaces (see Example).
|
20
|
+
#
|
21
|
+
# +name+:: A String that *briefly* describes the argument given to the following command or flag.
|
22
|
+
# +options+:: Symbol or array of symbols to annotate this argument. This doesn't affect parsing, just
|
23
|
+
# the help output. Values recognized are:
|
24
|
+
# +:optional+:: indicates this argument is optional; will format it with square brackets
|
25
|
+
# +:multiple+:: indicates multiple values are accepted; will format appropriately
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# desc 'Set the filename'
|
29
|
+
# arg_name 'file_name'
|
30
|
+
# flag [:f,:filename]
|
31
|
+
#
|
32
|
+
# Produces:
|
33
|
+
# -f, --filename=file_name Set the filename
|
34
|
+
def arg_name(name,options=[])
|
35
|
+
@next_arg_name = name
|
36
|
+
@next_arg_options = options
|
37
|
+
end
|
38
|
+
|
39
|
+
# set the default value of the next flag or switch
|
40
|
+
#
|
41
|
+
# +val+:: The default value to be used for the following flag if the user doesn't specify one
|
42
|
+
# and, when using a config file, the config also doesn't specify one. For a switch, this is
|
43
|
+
# the value to be used if the switch isn't specified on the command-line. Note that if you
|
44
|
+
# set a switch to have a default of true, using the switch on the command-line has no effect.
|
45
|
+
# To disable a switch where the default is true, use the <tt>--no-</tt> form.
|
46
|
+
def default_value(val); @next_default_value = val; end
|
47
|
+
|
48
|
+
# Create a flag, which is a switch that takes an argument
|
49
|
+
#
|
50
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names
|
51
|
+
# and aliases for this flag. The last element can be a hash of options:
|
52
|
+
# +:desc+:: the description, instead of using #desc
|
53
|
+
# +:long_desc+:: the long_description, instead of using #long_desc
|
54
|
+
# +:default_value+:: the default value, instead of using #default_value
|
55
|
+
# +:arg_name+:: the arg name, instead of using #arg_name
|
56
|
+
# +:must_match+:: A regexp that the flag's value must match
|
57
|
+
# +:type+:: A Class (or object you passed to GLI::App#accept) to trigger type coversion
|
58
|
+
#
|
59
|
+
# Example:
|
60
|
+
#
|
61
|
+
# desc 'Set the filename'
|
62
|
+
# flag [:f,:filename,'file-name']
|
63
|
+
#
|
64
|
+
# flag :ipaddress, :desc => "IP Address", :must_match => /\d+\.\d+\.\d+\.\d+/
|
65
|
+
#
|
66
|
+
# flag :names, :desc => "list of names", :type => Array
|
67
|
+
#
|
68
|
+
# Produces:
|
69
|
+
#
|
70
|
+
# -f, --filename, --file-name=arg Set the filename
|
71
|
+
def flag(*names)
|
72
|
+
options = extract_options(names)
|
73
|
+
names = [names].flatten
|
74
|
+
|
75
|
+
verify_unused(names)
|
76
|
+
flag = Flag.new(names,options)
|
77
|
+
flags[flag.name] = flag
|
78
|
+
|
79
|
+
clear_nexts
|
80
|
+
flags_declaration_order << flag
|
81
|
+
flag
|
82
|
+
end
|
83
|
+
alias :f :flag
|
84
|
+
|
85
|
+
# Create a switch, which is a command line flag that takes no arguments (thus, it _switches_ something on)
|
86
|
+
#
|
87
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names
|
88
|
+
# and aliases for this switch. The last element can be a hash of options:
|
89
|
+
# +:desc+:: the description, instead of using #desc
|
90
|
+
# +:long_desc+:: the long_description, instead of using #long_desc
|
91
|
+
# +:default_value+:: if the switch is omitted, use this as the default value. By default, switches default to off, or +false+
|
92
|
+
# +:negatable+:: if true, this switch will get a negatable form (e.g. <tt>--[no-]switch</tt>, false it will not. Default is true
|
93
|
+
def switch(*names)
|
94
|
+
options = extract_options(names)
|
95
|
+
names = [names].flatten
|
96
|
+
|
97
|
+
verify_unused(names)
|
98
|
+
switch = Switch.new(names,options)
|
99
|
+
switches[switch.name] = switch
|
100
|
+
|
101
|
+
clear_nexts
|
102
|
+
switches_declaration_order << switch
|
103
|
+
switch
|
104
|
+
end
|
105
|
+
alias :s :switch
|
106
|
+
|
107
|
+
def clear_nexts # :nodoc:
|
108
|
+
@next_desc = nil
|
109
|
+
@next_arg_name = nil
|
110
|
+
@next_arg_options = nil
|
111
|
+
@next_default_value = nil
|
112
|
+
@next_long_desc = nil
|
113
|
+
end
|
114
|
+
|
115
|
+
# Define a new command. This can be done in a few ways, but the most common method is
|
116
|
+
# to pass a symbol (or Array of symbols) representing the command name (or names) and a block.
|
117
|
+
# The block will be given an instance of the Command that was created.
|
118
|
+
# You then may call methods on this object to define aspects of that Command.
|
119
|
+
#
|
120
|
+
# Alternatively, you can call this with a one element Hash, where the key is the symbol representing the name
|
121
|
+
# of the command, and the value being an Array of symbols representing the commands to call in order, as a
|
122
|
+
# chained or compound command. Note that these commands must exist already, and that only those command-specific
|
123
|
+
# options defined in *this* command will be parsed and passed to the chained commands. This might not be what you expect
|
124
|
+
#
|
125
|
+
# +names+:: a String or Symbol, or an Array of String or Symbol that represent all the different names and aliases
|
126
|
+
# for this command *or* a Hash, as described above.
|
127
|
+
#
|
128
|
+
# ==Examples
|
129
|
+
#
|
130
|
+
# # Make a command named list
|
131
|
+
# command :list do |c|
|
132
|
+
# c.action do |global_options,options,args|
|
133
|
+
# # your command code
|
134
|
+
# end
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# # Make a command named list, callable by ls as well
|
138
|
+
# command [:list,:ls] do |c|
|
139
|
+
# c.action do |global_options,options,args|
|
140
|
+
# # your command code
|
141
|
+
# end
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# # Make a command named all, that calls list and list_contexts
|
145
|
+
# command :all => [ :list, :list_contexts ]
|
146
|
+
#
|
147
|
+
# # Make a command named all, aliased as :a:, that calls list and list_contexts
|
148
|
+
# command [:all,:a] => [ :list, :list_contexts ]
|
149
|
+
#
|
150
|
+
def command(*names)
|
151
|
+
command_options = {
|
152
|
+
:description => @next_desc,
|
153
|
+
:arguments_name => @next_arg_name,
|
154
|
+
:arguments_options => @next_arg_options,
|
155
|
+
:long_desc => @next_long_desc,
|
156
|
+
:skips_pre => @skips_pre,
|
157
|
+
:skips_post => @skips_post,
|
158
|
+
:skips_around => @skips_around,
|
159
|
+
}
|
160
|
+
@commands_declaration_order ||= []
|
161
|
+
if names.first.kind_of? Hash
|
162
|
+
command = GLI::Commands::CompoundCommand.new(self,
|
163
|
+
names.first,
|
164
|
+
command_options)
|
165
|
+
command.parent = self
|
166
|
+
commands[command.name] = command
|
167
|
+
@commands_declaration_order << command
|
168
|
+
else
|
169
|
+
new_command = Command.new(command_options.merge(:names => [names].flatten))
|
170
|
+
command = commands[new_command.name]
|
171
|
+
if command.nil?
|
172
|
+
command = new_command
|
173
|
+
command.parent = self
|
174
|
+
commands[command.name] = command
|
175
|
+
@commands_declaration_order << command
|
176
|
+
end
|
177
|
+
yield command
|
178
|
+
end
|
179
|
+
clear_nexts
|
180
|
+
end
|
181
|
+
alias :c :command
|
182
|
+
|
183
|
+
def flags_declaration_order # :nodoc:
|
184
|
+
@flags_declaration_order ||= []
|
185
|
+
end
|
186
|
+
|
187
|
+
def switches_declaration_order # :nodoc:
|
188
|
+
@switches_declaration_order ||= []
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
private
|
193
|
+
# Checks that the names passed in have not been used in another flag or option
|
194
|
+
def verify_unused(names) # :nodoc:
|
195
|
+
names.each do |name|
|
196
|
+
verify_unused_in_option(name,flags,"flag")
|
197
|
+
verify_unused_in_option(name,switches,"switch")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def verify_unused_in_option(name,option_like,type) # :nodoc:
|
202
|
+
return if name.to_s == 'help'
|
203
|
+
raise ArgumentError.new("#{name} has already been specified as a #{type} #{context_description}") if option_like[name]
|
204
|
+
option_like.each do |one_option_name,one_option|
|
205
|
+
if one_option.aliases
|
206
|
+
if one_option.aliases.include? name
|
207
|
+
raise ArgumentError.new("#{name} has already been specified as an alias of #{type} #{one_option_name} #{context_description}")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Extract the options hash out of the argument to flag/switch and
|
214
|
+
# set the values if using classic style
|
215
|
+
def extract_options(names)
|
216
|
+
options = {}
|
217
|
+
options = names.pop if names.last.kind_of? Hash
|
218
|
+
options = { :desc => @next_desc,
|
219
|
+
:long_desc => @next_long_desc,
|
220
|
+
:default_value => @next_default_value,
|
221
|
+
:arg_name => @next_arg_name}.merge(options)
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module GLI
|
2
|
+
# Mixed into all exceptions that GLI handles; you can use this to catch
|
3
|
+
# anything that came from GLI intentionally. You can also mix this into non-GLI
|
4
|
+
# exceptions to get GLI's exit behavior.
|
5
|
+
module StandardException
|
6
|
+
def exit_code; 1; end
|
7
|
+
end
|
8
|
+
# Indicates that the command line invocation was bad
|
9
|
+
class BadCommandLine < StandardError
|
10
|
+
include StandardException
|
11
|
+
def exit_code; 64; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class PreconditionFailed < StandardError
|
15
|
+
include StandardException
|
16
|
+
def exit_code; 65; end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Indicates the bad command line was an unknown command
|
20
|
+
class UnknownCommand < BadCommandLine
|
21
|
+
end
|
22
|
+
|
23
|
+
# The command issued partially matches more than one command
|
24
|
+
class AmbiguousCommand < BadCommandLine
|
25
|
+
end
|
26
|
+
|
27
|
+
# Indicates the bad command line was an unknown global argument
|
28
|
+
class UnknownGlobalArgument < BadCommandLine
|
29
|
+
end
|
30
|
+
|
31
|
+
class CommandException < BadCommandLine
|
32
|
+
# The command for which the argument was unknown
|
33
|
+
attr_reader :command_in_context
|
34
|
+
# +message+:: the error message to show the user
|
35
|
+
# +command+:: the command we were using to parse command-specific options
|
36
|
+
def initialize(message,command_in_context,exit_code=nil)
|
37
|
+
super(message)
|
38
|
+
@command_in_context = command_in_context
|
39
|
+
@exit_code = exit_code
|
40
|
+
end
|
41
|
+
|
42
|
+
def exit_code
|
43
|
+
@exit_code || super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Indicates the bad command line was an unknown command argument
|
48
|
+
class UnknownCommandArgument < CommandException
|
49
|
+
end
|
50
|
+
|
51
|
+
# Raise this if you want to use an exit status that isn't the default
|
52
|
+
# provided by GLI. Note that GLI::App#exit_now! might be a bit more to your liking.
|
53
|
+
#
|
54
|
+
# Example:
|
55
|
+
#
|
56
|
+
# raise CustomExit.new("Not connected to DB",-5) unless connected?
|
57
|
+
# raise CustomExit.new("Bad SQL",-6) unless valid_sql?(args[0])
|
58
|
+
#
|
59
|
+
class CustomExit < StandardError
|
60
|
+
include StandardException
|
61
|
+
attr_reader :exit_code #:nodoc:
|
62
|
+
# Create a custom exit exception
|
63
|
+
#
|
64
|
+
# +message+:: String containing error message to show the user
|
65
|
+
# +exit_code+:: the exit code to use (as an Int), overridding GLI's default
|
66
|
+
def initialize(message,exit_code)
|
67
|
+
super(message)
|
68
|
+
@exit_code = exit_code
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/gli/flag.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'gli/command_line_option.rb'
|
2
|
+
|
3
|
+
module GLI
|
4
|
+
# Defines a flag, which is to say a switch that takes an argument
|
5
|
+
class Flag < CommandLineOption # :nodoc:
|
6
|
+
|
7
|
+
# Regexp that is used to see if the flag's argument matches
|
8
|
+
attr_reader :must_match
|
9
|
+
|
10
|
+
# Type to which we want to cast the values
|
11
|
+
attr_reader :type
|
12
|
+
|
13
|
+
# Name of the argument that user configured
|
14
|
+
attr_reader :argument_name
|
15
|
+
|
16
|
+
# Creates a new option
|
17
|
+
#
|
18
|
+
# names:: Array of symbols or strings representing the names of this switch
|
19
|
+
# options:: hash of options:
|
20
|
+
# :desc:: the short description
|
21
|
+
# :long_desc:: the long description
|
22
|
+
# :default_value:: the default value of this option
|
23
|
+
# :arg_name:: the name of the flag's argument, default is "arg"
|
24
|
+
# :must_match:: a regexp that the flag's value must match
|
25
|
+
# :type:: a class to convert the value to
|
26
|
+
# :mask:: if true, the default value of this flag will not be output in the help.
|
27
|
+
# This is useful for password flags where you might not want to show it
|
28
|
+
# on the command-line.
|
29
|
+
def initialize(names,options)
|
30
|
+
super(names,options)
|
31
|
+
@argument_name = options[:arg_name] || "arg"
|
32
|
+
@default_value = options[:default_value]
|
33
|
+
@must_match = options[:must_match]
|
34
|
+
@type = options[:type]
|
35
|
+
@mask = options[:mask]
|
36
|
+
end
|
37
|
+
|
38
|
+
def safe_default_value
|
39
|
+
if @mask
|
40
|
+
"********"
|
41
|
+
else
|
42
|
+
default_value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def arguments_for_option_parser
|
47
|
+
args = all_forms_a.map { |name| "#{name} VAL" }
|
48
|
+
args << @must_match if @must_match
|
49
|
+
args << @type if @type
|
50
|
+
args
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a string of all possible forms
|
54
|
+
# of this flag. Mostly intended for printing
|
55
|
+
# to the user.
|
56
|
+
def all_forms(joiner=', ')
|
57
|
+
forms = all_forms_a
|
58
|
+
string = forms.join(joiner)
|
59
|
+
if forms[-1] =~ /^\-\-/
|
60
|
+
string += '='
|
61
|
+
else
|
62
|
+
string += ' '
|
63
|
+
end
|
64
|
+
string += @argument_name
|
65
|
+
return string
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module GLI
|
2
|
+
# An "option block" is a set of parseable options, starting from the beginning of
|
3
|
+
# the argument list, stopping with the first unknown command-line element.
|
4
|
+
# This class handles parsing that block
|
5
|
+
class GLIOptionBlockParser
|
6
|
+
|
7
|
+
# Create the parser using the given +OptionParser+ instance and exception handling
|
8
|
+
# strategy.
|
9
|
+
#
|
10
|
+
# option_parser_factory:: An +OptionParserFactory+ instance, configured to parse wherever you are on the command line
|
11
|
+
# exception_klass_or_block:: means of handling exceptions from +OptionParser+. One of:
|
12
|
+
# an exception class:: will be raised on errors with a message
|
13
|
+
# lambda/block:: will be called with a single argument - the error message.
|
14
|
+
def initialize(option_parser_factory,exception_klass_or_block)
|
15
|
+
@option_parser_factory = option_parser_factory
|
16
|
+
@extra_error_context = nil
|
17
|
+
@exception_handler = if exception_klass_or_block.kind_of?(Class)
|
18
|
+
lambda { |message,extra_error_context|
|
19
|
+
raise exception_klass_or_block,message
|
20
|
+
}
|
21
|
+
else
|
22
|
+
exception_klass_or_block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Parse the given argument list, returning the unparsed arguments and options hash of parsed arguments.
|
27
|
+
# Exceptions from +OptionParser+ are given to the handler configured in the constructor
|
28
|
+
#
|
29
|
+
# args:: argument list. This will be mutated
|
30
|
+
#
|
31
|
+
# Returns unparsed args
|
32
|
+
def parse!(args)
|
33
|
+
do_parse(args)
|
34
|
+
rescue OptionParser::InvalidOption => ex
|
35
|
+
@exception_handler.call("Unknown option #{ex.args.join(' ')}",@extra_error_context)
|
36
|
+
rescue OptionParser::InvalidArgument => ex
|
37
|
+
@exception_handler.call("#{ex.reason}: #{ex.args.join(' ')}",@extra_error_context)
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def do_parse(args)
|
43
|
+
first_non_option = nil
|
44
|
+
@option_parser_factory.option_parser.order!(args) do |non_option|
|
45
|
+
first_non_option = non_option
|
46
|
+
break
|
47
|
+
end
|
48
|
+
args.unshift(first_non_option)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class CommandOptionBlockParser < GLIOptionBlockParser
|
53
|
+
|
54
|
+
def command=(command_being_parsed)
|
55
|
+
@extra_error_context = command_being_parsed
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def break_on_non_option?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
def do_parse(args)
|
65
|
+
unknown_options = []
|
66
|
+
@option_parser_factory.option_parser.order!(args) do |non_option|
|
67
|
+
unknown_options << non_option
|
68
|
+
break if break_on_non_option?
|
69
|
+
end
|
70
|
+
unknown_options.reverse.each do |unknown_option|
|
71
|
+
args.unshift(unknown_option)
|
72
|
+
end
|
73
|
+
args
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class LegacyCommandOptionBlockParser < CommandOptionBlockParser
|
78
|
+
|
79
|
+
protected
|
80
|
+
def break_on_non_option?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|