bovem 3.0.5 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -3
- data/.rubocop.yml +82 -0
- data/.travis-gemfile +4 -5
- data/.travis.yml +8 -6
- data/CHANGELOG.md +12 -0
- data/Gemfile +9 -8
- data/README.md +1 -1
- data/Rakefile +22 -6
- data/bovem.gemspec +5 -5
- data/doc/Bovem.html +10 -10
- data/doc/Bovem/Application.html +670 -318
- data/doc/Bovem/Command.html +1447 -1125
- data/doc/Bovem/CommandMethods.html +4 -4
- data/doc/Bovem/CommandMethods/Children.html +173 -179
- data/doc/Bovem/CommandMethods/Help.html +9 -9
- data/doc/Bovem/Configuration.html +239 -24
- data/doc/Bovem/Console.html +267 -128
- data/doc/Bovem/ConsoleMethods.html +4 -4
- data/doc/Bovem/ConsoleMethods/Interactions.html +57 -70
- data/doc/Bovem/ConsoleMethods/Interactions/ClassMethods.html +9 -9
- data/doc/Bovem/ConsoleMethods/Logging.html +258 -298
- data/doc/Bovem/ConsoleMethods/Logging/ClassMethods.html +8 -8
- data/doc/Bovem/ConsoleMethods/Output.html +96 -118
- data/doc/Bovem/ConsoleMethods/StyleHandling.html +8 -8
- data/doc/Bovem/ConsoleMethods/StyleHandling/ClassMethods.html +26 -39
- data/doc/Bovem/Errors.html +4 -4
- data/doc/Bovem/Errors/Error.html +4 -4
- data/doc/Bovem/Errors/InvalidConfiguration.html +4 -4
- data/doc/Bovem/Errors/InvalidLogger.html +4 -4
- data/doc/Bovem/I18n.html +175 -0
- data/doc/Bovem/Logger.html +95 -83
- data/doc/Bovem/Option.html +669 -862
- data/doc/Bovem/Parser.html +10 -10
- data/doc/Bovem/ParserMethods.html +4 -4
- data/doc/Bovem/ParserMethods/General.html +4 -4
- data/doc/Bovem/ParserMethods/General/ClassMethods.html +26 -38
- data/doc/Bovem/Shell.html +169 -48
- data/doc/Bovem/ShellMethods.html +4 -4
- data/doc/Bovem/ShellMethods/Directories.html +46 -62
- data/doc/Bovem/ShellMethods/Execute.html +51 -99
- data/doc/Bovem/ShellMethods/General.html +4 -445
- data/doc/Bovem/ShellMethods/Read.html +56 -61
- data/doc/Bovem/ShellMethods/Write.html +22 -242
- data/doc/Bovem/Version.html +6 -6
- data/doc/_index.html +18 -18
- data/doc/class_list.html +6 -2
- data/doc/css/style.css +1 -0
- data/doc/file.README.html +5 -5
- data/doc/file_list.html +5 -1
- data/doc/frames.html +1 -1
- data/doc/index.html +5 -5
- data/doc/js/full_list.js +4 -1
- data/doc/method_list.html +161 -157
- data/doc/top-level-namespace.html +4 -4
- data/lib/bovem.rb +3 -4
- data/lib/bovem/application.rb +47 -39
- data/lib/bovem/command.rb +175 -193
- data/lib/bovem/configuration.rb +28 -29
- data/lib/bovem/console.rb +244 -171
- data/lib/bovem/errors.rb +1 -1
- data/lib/bovem/i18n.rb +18 -0
- data/lib/bovem/logger.rb +26 -26
- data/lib/bovem/option.rb +49 -58
- data/lib/bovem/parser.rb +174 -222
- data/lib/bovem/shell.rb +272 -320
- data/lib/bovem/version.rb +2 -2
- data/locales/en.yml +39 -38
- data/locales/it.yml +39 -38
- data/spec/bovem/application_spec.rb +6 -5
- data/spec/bovem/command_spec.rb +23 -23
- data/spec/bovem/console_spec.rb +101 -102
- data/spec/bovem/i18n_spec.rb +21 -0
- data/spec/bovem/logger_spec.rb +4 -4
- data/spec/bovem/option_spec.rb +43 -43
- data/spec/bovem/parser_spec.rb +13 -13
- data/spec/bovem/shell_spec.rb +106 -115
- data/spec/spec_helper.rb +19 -6
- metadata +14 -13
- data/doc/Bovem/Localizer.html +0 -376
- data/lib/bovem/localizer.rb +0 -27
- data/spec/coverage_helper.rb +0 -20
data/lib/bovem/errors.rb
CHANGED
data/lib/bovem/i18n.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# This file is part of the bovem gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
|
4
|
+
# Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
|
5
|
+
#
|
6
|
+
|
7
|
+
module Bovem
|
8
|
+
# Extension of Lazier::I18n to support method based access.
|
9
|
+
class I18n < ::Lazier::I18n
|
10
|
+
private
|
11
|
+
|
12
|
+
def method_missing(method, *args)
|
13
|
+
rv = send(:t, method)
|
14
|
+
rv = sprintf(rv, *args) if rv.index(/%([\d.]*)[sdf]/) && args.present?
|
15
|
+
rv
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/bovem/logger.rb
CHANGED
@@ -12,6 +12,9 @@ module Bovem
|
|
12
12
|
class Logger < ::Logger
|
13
13
|
attr_reader :device
|
14
14
|
|
15
|
+
# List of valid logger levels.
|
16
|
+
LEVEL_NAMES = {"DEBUG" => :cyan, "INFO" => :green, "WARN" => :yellow, "ERROR" => :red, "FATAL" => :magenta}.freeze
|
17
|
+
|
15
18
|
# Creates a new logger.
|
16
19
|
#
|
17
20
|
# @see http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html
|
@@ -19,7 +22,7 @@ module Bovem
|
|
19
22
|
# @param logdev [String|IO] The log device. This is a filename (String) or IO object (typically STDOUT, STDERR, or an open file).
|
20
23
|
# @param shift_age [Fixnum] Number of old log files to keep, or frequency of rotation (daily, weekly or monthly).
|
21
24
|
# @param shift_size [Fixnum] Maximum logfile size (only applies when shift_age is a number).
|
22
|
-
def initialize(logdev, shift_age = 0, shift_size =
|
25
|
+
def initialize(logdev, shift_age = 0, shift_size = 1_048_576)
|
23
26
|
@device = logdev
|
24
27
|
super(logdev, shift_age, shift_size)
|
25
28
|
end
|
@@ -30,15 +33,13 @@ module Bovem
|
|
30
33
|
# @param level [Fixnum] The minimum severity to log. See http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html for valid levels.
|
31
34
|
# @param formatter [Proc] The formatter to use for logging.
|
32
35
|
# @return [Logger] The new logger.
|
33
|
-
def self.create(file = nil, level
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
raise Bovem::Errors::InvalidLogger
|
41
|
-
end
|
36
|
+
def self.create(file = nil, level: Logger::INFO, formatter: nil)
|
37
|
+
rv = new(get_real_file(file || default_file))
|
38
|
+
rv.level = level.to_integer
|
39
|
+
rv.formatter = formatter || default_formatter
|
40
|
+
rv
|
41
|
+
rescue
|
42
|
+
raise Bovem::Errors::InvalidLogger
|
42
43
|
end
|
43
44
|
|
44
45
|
# Translates a file to standard input or standard output in some special cases.
|
@@ -47,9 +48,9 @@ module Bovem
|
|
47
48
|
# @return [String|IO] The translated file name.
|
48
49
|
def self.get_real_file(file)
|
49
50
|
case file
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
when "STDOUT" then $stdout
|
52
|
+
when "STDERR" then $stderr
|
53
|
+
else file
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
@@ -62,19 +63,18 @@ module Bovem
|
|
62
63
|
# The default formatter for logging.
|
63
64
|
# @return [Proc] The default formatter for logging.
|
64
65
|
def self.default_formatter
|
65
|
-
@default_formatter ||= ::Proc.new
|
66
|
-
color =
|
67
|
-
when "DEBUG" then :cyan
|
68
|
-
when "INFO" then :green
|
69
|
-
when "WARN" then :yellow
|
70
|
-
when "ERROR" then :red
|
71
|
-
when "FATAL" then :magenta
|
72
|
-
else :white
|
73
|
-
end
|
66
|
+
@default_formatter ||= ::Proc.new do |severity, datetime, _, msg|
|
67
|
+
color = LEVEL_NAMES.fetch(severity, :white)
|
74
68
|
|
75
|
-
header = Bovem::Console.replace_markers(
|
76
|
-
|
77
|
-
|
69
|
+
header = Bovem::Console.replace_markers(
|
70
|
+
sprintf(
|
71
|
+
"{mark=bright-#{color}}[%s T+%0.5f] %s:{/mark}", datetime.strftime("%Y/%b/%d %H:%M:%S"),
|
72
|
+
[datetime.to_f - start_time.to_f, 0].max, severity.rjust(5)
|
73
|
+
)
|
74
|
+
)
|
75
|
+
|
76
|
+
sprintf("%s %s\n", header, msg)
|
77
|
+
end
|
78
78
|
end
|
79
79
|
|
80
80
|
# The log time of the first logger. This allows to show a `T+0.1234` information into the log.
|
@@ -83,4 +83,4 @@ module Bovem
|
|
83
83
|
@start_time ||= ::Time.now
|
84
84
|
end
|
85
85
|
end
|
86
|
-
end
|
86
|
+
end
|
data/lib/bovem/option.rb
CHANGED
@@ -10,8 +10,7 @@ module Bovem
|
|
10
10
|
# Values are the default values for that type.
|
11
11
|
#
|
12
12
|
# For any unknown type, the default value is `false`, it means that any unknown type is managed as a Boolean value with no argument.
|
13
|
-
OPTION_TYPES = {String => "", Integer => 0, Fixnum => 0, Bignum => 0, Float => 0.0, Array => []}
|
14
|
-
OPTION_TYPES.default = false
|
13
|
+
OPTION_TYPES = {String => "", Integer => 0, Fixnum => 0, Bignum => 0, Float => 0.0, Array => []}.freeze
|
15
14
|
|
16
15
|
# This class represents an option for a command.
|
17
16
|
#
|
@@ -71,7 +70,7 @@ module Bovem
|
|
71
70
|
#
|
72
71
|
# @param value [String] The short form of this option.
|
73
72
|
def short=(value)
|
74
|
-
value = @name[0, 1]
|
73
|
+
value = @name[0, 1] unless value.present?
|
75
74
|
|
76
75
|
# Clean value
|
77
76
|
final_value = value.to_s.match(/^-{0,2}([a-z0-9])(.*)$/i)[1]
|
@@ -83,7 +82,7 @@ module Bovem
|
|
83
82
|
#
|
84
83
|
# @param value [String] The short form of this option.
|
85
84
|
def long=(value)
|
86
|
-
value = @name
|
85
|
+
value = @name unless value.present?
|
87
86
|
|
88
87
|
# Clean value
|
89
88
|
final_value = value.to_s.match(/^-{0,2}(.+)$/)[1]
|
@@ -96,7 +95,7 @@ module Bovem
|
|
96
95
|
# @param value [String] The validator of this option.
|
97
96
|
def validator=(value)
|
98
97
|
value = nil if value.blank? || (value.is_a?(Regexp) && value.source.blank?)
|
99
|
-
value = value.ensure_array(
|
98
|
+
value = value.ensure_array(no_duplicates: true, compact: true, flatten: true) if !value.nil? && !value.is_a?(Regexp) && !value.is_a?(Proc)
|
100
99
|
@validator = value
|
101
100
|
end
|
102
101
|
|
@@ -123,22 +122,24 @@ module Bovem
|
|
123
122
|
|
124
123
|
# Returns the meta argument for this option.
|
125
124
|
#
|
126
|
-
# @return [String|NilClass] Returns the current meta argument for this option (the default value is the option name uppercased) or `nil`,
|
125
|
+
# @return [String|NilClass] Returns the current meta argument for this option (the default value is the option name uppercased) or `nil`,
|
126
|
+
# if this option doesn't require a meta argument.
|
127
127
|
def meta
|
128
|
-
|
128
|
+
return nil unless requires_argument?
|
129
|
+
@meta.present? ? @meta : @name.upcase
|
129
130
|
end
|
130
131
|
|
131
132
|
# Get the current default value for this option.
|
132
133
|
#
|
133
134
|
# @return [Object] The default value for this option.
|
134
135
|
def default
|
135
|
-
@default || Bovem::OPTION_TYPES[@type]
|
136
|
+
@default || Bovem::OPTION_TYPES[@type] || false
|
136
137
|
end
|
137
138
|
|
138
139
|
# Check if the current option has a default value.
|
139
140
|
#
|
140
141
|
# @return [Boolean] If the current option has a default value.
|
141
|
-
def
|
142
|
+
def default?
|
142
143
|
!@default.nil?
|
143
144
|
end
|
144
145
|
|
@@ -151,7 +152,7 @@ module Bovem
|
|
151
152
|
vs = get_validator_method(@validator)
|
152
153
|
rv = vs ? @validator.send(vs, value) : true
|
153
154
|
|
154
|
-
if rv
|
155
|
+
if rv
|
155
156
|
@value = value
|
156
157
|
@provided = true
|
157
158
|
else # Validation failed
|
@@ -164,10 +165,9 @@ module Bovem
|
|
164
165
|
|
165
166
|
# Executes the action associated to this option.
|
166
167
|
def execute_action
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
168
|
+
return nil unless @action.present?
|
169
|
+
@provided = true
|
170
|
+
@action.call(parent, self)
|
171
171
|
end
|
172
172
|
|
173
173
|
# Checks if this option requires an argument.
|
@@ -187,7 +187,7 @@ module Bovem
|
|
187
187
|
# Check if this command has a help.
|
188
188
|
#
|
189
189
|
# @return [Boolean] `true` if this command has a help, `false` otherwise.
|
190
|
-
def
|
190
|
+
def help?
|
191
191
|
@help.present?
|
192
192
|
end
|
193
193
|
|
@@ -199,56 +199,47 @@ module Bovem
|
|
199
199
|
end
|
200
200
|
|
201
201
|
private
|
202
|
-
# Setups the forms of the this option.
|
203
|
-
#
|
204
|
-
# @param forms [Array] An array of short and long forms for this option. Missing forms will be inferred by the name.
|
205
|
-
def setup_forms(forms)
|
206
|
-
self.short = forms.length > 0 ? forms[0] : @name[0, 1]
|
207
|
-
self.long = forms.length == 2 ? forms[1] : @name
|
208
|
-
end
|
209
202
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
send("#{option}=", value) if respond_to?("#{option}=")
|
216
|
-
end
|
217
|
-
end
|
203
|
+
# :nodoc:
|
204
|
+
def setup_forms(forms)
|
205
|
+
self.short = !forms.empty? ? forms[0] : @name[0, 1]
|
206
|
+
self.long = forms.length == 2 ? forms[1] : @name
|
207
|
+
end
|
218
208
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
@action = action if action.present? && action.respond_to?(:call) && action.try(:arity) == 2
|
209
|
+
# :nodoc:
|
210
|
+
def setup_options(options)
|
211
|
+
(options.is_a?(::Hash) ? options : {}).each_pair do |option, value|
|
212
|
+
send("#{option}=", value) if respond_to?("#{option}=")
|
224
213
|
end
|
214
|
+
end
|
225
215
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
216
|
+
# :nodoc:
|
217
|
+
def setup_action(action)
|
218
|
+
@action = action if action.present? && action.respond_to?(:call) && action.try(:arity) == 2
|
219
|
+
end
|
220
|
+
|
221
|
+
# :nodoc:
|
222
|
+
def handle_set_failure(vs)
|
223
|
+
locale = @parent.i18n
|
231
224
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
225
|
+
message =
|
226
|
+
case vs
|
227
|
+
when "match" then locale.invalid_for_regexp(label, @validator.inspect)
|
228
|
+
when "call" then locale.invalid_for_proc(label)
|
229
|
+
else locale.invalid_value(label, Bovem::Parser.smart_join(@validator.ensure_array, separator: ", ", last_separator: locale.join_separator).html_safe)
|
236
230
|
end
|
237
231
|
|
238
|
-
|
239
|
-
|
232
|
+
raise Bovem::Errors::Error.new(self, :validation_failed, message)
|
233
|
+
end
|
240
234
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
when "Regexp" then "match"
|
249
|
-
when "Proc" then "call"
|
250
|
-
else false
|
251
|
-
end
|
235
|
+
# :nodoc:
|
236
|
+
def get_validator_method(validator)
|
237
|
+
case validator.class.to_s
|
238
|
+
when "Array" then "include?"
|
239
|
+
when "Regexp" then "match"
|
240
|
+
when "Proc" then "call"
|
241
|
+
else false
|
252
242
|
end
|
243
|
+
end
|
253
244
|
end
|
254
|
-
end
|
245
|
+
end
|
data/lib/bovem/parser.rb
CHANGED
@@ -20,11 +20,11 @@ module Bovem
|
|
20
20
|
# @param last_separator [String] The separator to use for the last join.
|
21
21
|
# @param quote [String] If not nil, elements are quoted with that element.
|
22
22
|
# @return [String] The joined array.
|
23
|
-
def smart_join(array, separator
|
23
|
+
def smart_join(array, separator: ", ", last_separator: " and ", quote: "\"")
|
24
24
|
separator = separator.ensure_string
|
25
25
|
last_separator = last_separator.ensure_string
|
26
|
-
array = array.ensure_array {|a| quote.present? ? "#{quote}#{a}#{quote}" : a.ensure_string }
|
27
|
-
|
26
|
+
array = array.ensure_array { |a| quote.present? ? "#{quote}#{a}#{quote}" : a.ensure_string }
|
27
|
+
perform_smart_join(array, last_separator, separator)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Finds a command which corresponds to an argument.
|
@@ -34,18 +34,16 @@ module Bovem
|
|
34
34
|
# @param args [String] The complete list of arguments passed.
|
35
35
|
# @param separator [String] The separator for joined syntax commands.
|
36
36
|
# @return [Hash|NilClass] An hash with `name` and `args` keys if a valid subcommand is found, `nil` otherwise.
|
37
|
-
def find_command(arg, command, args, separator
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
else
|
48
|
-
nil
|
37
|
+
def find_command(arg, command, args: {}, separator: ":")
|
38
|
+
return nil unless command.commands.present?
|
39
|
+
|
40
|
+
arg, args = adjust_command(arg, args, separator)
|
41
|
+
|
42
|
+
matching = match_subcommands(arg, command)
|
43
|
+
if matching.length == 1 # Found a command
|
44
|
+
{name: matching[0], args: args}
|
45
|
+
elsif matching.length > 1 # Ambiguous match
|
46
|
+
raise Bovem::Errors::Error.new(command, :ambiguous_command, command.i18n.ambigous_command(arg, format_alternatives(matching, command)))
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
@@ -59,41 +57,34 @@ module Bovem
|
|
59
57
|
end
|
60
58
|
|
61
59
|
private
|
62
|
-
# Adjusts a command so that it only specify a single command.
|
63
|
-
#
|
64
|
-
# @param arg [String] The string to match.
|
65
|
-
# @param args [String] The complete list of arguments passed.
|
66
|
-
# @param separator [String] The separator for joined syntax commands.
|
67
|
-
# @return [Array] Adjust command and arguments.
|
68
|
-
def adjust_command(arg, args, separator)
|
69
|
-
args = args.ensure_array.dup
|
70
|
-
|
71
|
-
if arg.index(separator) then
|
72
|
-
tokens = arg.split(separator, 2)
|
73
|
-
arg = tokens[0]
|
74
|
-
args.insert(0, tokens[1])
|
75
|
-
end
|
76
|
-
|
77
|
-
[arg, args]
|
78
|
-
end
|
79
60
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# @param command [Command] The command to search subcommand in.
|
84
|
-
# @return [Array] The matching subcommands.
|
85
|
-
def match_subcommands(arg, command)
|
86
|
-
command.commands.keys.select {|c| c =~ /^(#{Regexp.quote(arg)})/ }.compact
|
87
|
-
end
|
61
|
+
# :nodoc:
|
62
|
+
def adjust_command(arg, args, separator)
|
63
|
+
args = args.ensure_array.dup
|
88
64
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
# @return [String] The formatted alternatives.
|
94
|
-
def format_alternatives(matching, command)
|
95
|
-
Bovem::Parser.smart_join(matching, ", ", command.i18n.join_separator).html_safe
|
65
|
+
if arg.index(separator)
|
66
|
+
tokens = arg.split(separator, 2)
|
67
|
+
arg = tokens[0]
|
68
|
+
args.insert(0, tokens[1])
|
96
69
|
end
|
70
|
+
|
71
|
+
[arg, args]
|
72
|
+
end
|
73
|
+
|
74
|
+
# :nodoc:
|
75
|
+
def match_subcommands(arg, command)
|
76
|
+
command.commands.keys.select { |c| c =~ /^(#{Regexp.quote(arg)})/ }.compact
|
77
|
+
end
|
78
|
+
|
79
|
+
# :nodoc:
|
80
|
+
def format_alternatives(matching, command)
|
81
|
+
Bovem::Parser.smart_join(matching, separator: ", ", last_separator: command.i18n.join_separator).html_safe
|
82
|
+
end
|
83
|
+
|
84
|
+
# :nodoc:
|
85
|
+
def perform_smart_join(array, last_separator, separator)
|
86
|
+
array.length < 2 ? (array[0] || "") : (array[0, array.length - 1].join(separator) + last_separator + array[-1])
|
87
|
+
end
|
97
88
|
end
|
98
89
|
end
|
99
90
|
end
|
@@ -114,213 +105,174 @@ module Bovem
|
|
114
105
|
end
|
115
106
|
|
116
107
|
private
|
117
|
-
# Creates a new option parser.
|
118
|
-
#
|
119
|
-
# @param command [Command] The command or application to parse.
|
120
|
-
# @return [OptionParser] The new parser
|
121
|
-
def create_parser(command)
|
122
|
-
forms = {}
|
123
|
-
parser = OptionParser.new do |opts|
|
124
|
-
# Add every option
|
125
|
-
command.options.each_pair do |_, option|
|
126
|
-
check_unique(command, forms, option)
|
127
|
-
setup_option(command, opts, option)
|
128
|
-
end
|
129
|
-
end
|
130
108
|
|
131
|
-
|
109
|
+
# :nodoc:
|
110
|
+
def create_parser(command)
|
111
|
+
forms = {}
|
112
|
+
parser = OptionParser.new do |opts|
|
113
|
+
# Add every option
|
114
|
+
command.options.each_pair do |_, option|
|
115
|
+
check_unique(command, forms, option)
|
116
|
+
setup_option(command, opts, option)
|
117
|
+
end
|
132
118
|
end
|
133
119
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
def perform_parsing(parser, command, args, forms)
|
141
|
-
rv = nil
|
142
|
-
|
143
|
-
begin
|
144
|
-
rv = execute_parsing(parser, command, args)
|
145
|
-
rescue OptionParser::NeedlessArgument, OptionParser::MissingArgument, OptionParser::InvalidOption => oe
|
146
|
-
type = oe.class.to_s.gsub("OptionParser::", "").underscore.to_sym
|
147
|
-
opt = oe.args.first
|
148
|
-
raise Bovem::Errors::Error.new(forms[opt], type, command.i18n.send(type, opt))
|
149
|
-
rescue => e
|
150
|
-
raise e
|
151
|
-
end
|
120
|
+
[forms, parser]
|
121
|
+
end
|
122
|
+
|
123
|
+
# :nodoc:
|
124
|
+
def perform_parsing(parser, command, args, forms)
|
125
|
+
rv = nil
|
152
126
|
|
153
|
-
|
127
|
+
begin
|
128
|
+
rv = execute_parsing(parser, command, args)
|
129
|
+
rescue OptionParser::NeedlessArgument, OptionParser::MissingArgument, OptionParser::InvalidOption => e
|
130
|
+
fail_invalid_option(command, forms, e)
|
131
|
+
rescue => e
|
132
|
+
raise e
|
154
133
|
end
|
155
134
|
|
156
|
-
|
157
|
-
|
158
|
-
# @param parser [OptionParser] The option parser.
|
159
|
-
# @param command [Command] The command or application to parse.
|
160
|
-
# @param args [Array] The arguments to parse.
|
161
|
-
# @return [Command|nil] A command to execute or `nil` if no valid command was found.
|
162
|
-
def execute_parsing(parser, command, args)
|
163
|
-
rv = nil
|
164
|
-
|
165
|
-
if command.options.present? then
|
166
|
-
rv = parse_options(parser, command, args)
|
167
|
-
check_required_options(command)
|
168
|
-
elsif args.present? then
|
169
|
-
rv = find_command_to_execute(command, args)
|
170
|
-
end
|
135
|
+
rv
|
136
|
+
end
|
171
137
|
|
172
|
-
|
173
|
-
|
138
|
+
# :nodoc:
|
139
|
+
def fail_invalid_option(command, forms, oe)
|
140
|
+
type = oe.class.to_s.gsub("OptionParser::", "").underscore.to_sym
|
141
|
+
opt = oe.args.first
|
142
|
+
raise Bovem::Errors::Error.new(forms[opt], type, command.i18n.send(type, opt))
|
143
|
+
end
|
174
144
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
# @param opts [Object] The current set options.
|
179
|
-
# @param option [Option] The option to set.
|
180
|
-
def setup_option(command, opts, option)
|
181
|
-
case option.type.to_s
|
182
|
-
when "String" then parse_string(command, opts, option)
|
183
|
-
when "Integer", "Fixnum", "Bignum" then parse_number(command, opts, option, :is_integer?, :to_integer, command.i18n.invalid_integer(option.label))
|
184
|
-
when "Float" then parse_number(command, opts, option, :is_float?, :to_float, command.i18n.invalid_float(option.label))
|
185
|
-
when "Array" then parse_array(command, opts, option)
|
186
|
-
else option.action.present? ? parse_action(opts, option) : parse_boolean(opts, option)
|
187
|
-
end
|
188
|
-
end
|
145
|
+
# :nodoc:
|
146
|
+
def execute_parsing(parser, command, args)
|
147
|
+
rv = nil
|
189
148
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
def check_unique(command, forms, option)
|
196
|
-
if forms[option.complete_short] || forms[option.complete_long] then
|
197
|
-
raise Bovem::Errors::Error.new(command, :ambiguous_form, command.i18n.conflicting_options(option.label, forms[option.complete_short].label))
|
198
|
-
else
|
199
|
-
forms[option.complete_short] = option.dup
|
200
|
-
forms[option.complete_long] = option.dup
|
201
|
-
end
|
149
|
+
if command.options.present?
|
150
|
+
rv = parse_options(parser, command, args)
|
151
|
+
check_required_options(command)
|
152
|
+
elsif args.present?
|
153
|
+
rv = find_command_to_execute(command, args)
|
202
154
|
end
|
203
155
|
|
204
|
-
|
205
|
-
|
206
|
-
# @param command [Command] The command or application to parse.
|
207
|
-
# @param opts [Object] The current set options.
|
208
|
-
# @param option [Option] The option to set.
|
209
|
-
def parse_option(command, opts, option)
|
210
|
-
opts.on("#{option.complete_short} #{option.meta || command.i18n.help_arg}", "#{option.complete_long} #{option.meta || command.i18n.help_arg}") do |value|
|
211
|
-
yield(value)
|
212
|
-
end
|
213
|
-
end
|
156
|
+
rv
|
157
|
+
end
|
214
158
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
159
|
+
# :nodoc:
|
160
|
+
def setup_option(command, opts, option)
|
161
|
+
case option.type.to_s
|
162
|
+
when "String" then parse_string(command, opts, option)
|
163
|
+
when "Integer", "Fixnum", "Bignum" then setup_int_option(command, option, opts)
|
164
|
+
when "Float" then parse_number(command, opts, option, :float?, :to_float, command.i18n.invalid_float(option.label))
|
165
|
+
when "Array" then parse_array(command, opts, option)
|
166
|
+
else option.action.present? ? parse_action(opts, option) : parse_boolean(opts, option)
|
223
167
|
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# :nodoc:
|
171
|
+
def setup_int_option(command, option, opts)
|
172
|
+
parse_number(command, opts, option, :integer?, :to_integer, command.i18n.invalid_integer(option.label))
|
173
|
+
end
|
224
174
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
175
|
+
# :nodoc:
|
176
|
+
def check_unique(command, forms, option)
|
177
|
+
if forms[option.complete_short] || forms[option.complete_long]
|
178
|
+
fail_non_unique_option(command, forms, option)
|
179
|
+
else
|
180
|
+
forms[option.complete_short] = option.dup
|
181
|
+
forms[option.complete_long] = option.dup
|
232
182
|
end
|
183
|
+
end
|
233
184
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
#
|
242
|
-
|
243
|
-
parse_option(command, opts, option) do |value|
|
244
|
-
raise Bovem::Errors::Error.new(option, :invalid_argument, invalid_message) if !value.send(check_method)
|
245
|
-
option.set(value.send(convert_method))
|
246
|
-
end
|
185
|
+
# :nodoc:
|
186
|
+
def fail_non_unique_option(command, forms, option)
|
187
|
+
raise Bovem::Errors::Error.new(command, :ambiguous_form, command.i18n.conflicting_options(option.label, forms[option.complete_short].label))
|
188
|
+
end
|
189
|
+
|
190
|
+
# :nodoc:
|
191
|
+
def parse_option(command, opts, option)
|
192
|
+
opts.on("#{option.complete_short} #{option.meta || command.i18n.help_arg}", "#{option.complete_long} #{option.meta || command.i18n.help_arg}") do |value|
|
193
|
+
yield(value)
|
247
194
|
end
|
195
|
+
end
|
248
196
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
# @param option [Option] The option to set.
|
254
|
-
def parse_array(command, opts, option)
|
255
|
-
opts.on("#{option.complete_short} #{option.meta || command.i18n.help_arg}", "#{option.complete_long} #{option.meta || command.i18n.help_arg}", Array) do |value|
|
256
|
-
option.set(value.ensure_array)
|
257
|
-
end
|
197
|
+
# :nodoc:
|
198
|
+
def parse_action(opts, option)
|
199
|
+
opts.on("-#{option.short}", "--#{option.long}") do |_|
|
200
|
+
option.execute_action
|
258
201
|
end
|
202
|
+
end
|
259
203
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
204
|
+
# :nodoc:
|
205
|
+
def parse_string(command, opts, option)
|
206
|
+
parse_option(command, opts, option) { |value| option.set(value) }
|
207
|
+
end
|
208
|
+
|
209
|
+
# :nodoc:
|
210
|
+
def parse_number(command, opts, option, check_method, convert_method, invalid_message)
|
211
|
+
parse_option(command, opts, option) do |value|
|
212
|
+
raise Bovem::Errors::Error.new(option, :invalid_argument, invalid_message) unless value.send(check_method)
|
213
|
+
option.set(value.send(convert_method))
|
268
214
|
end
|
215
|
+
end
|
269
216
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
# @param command [Command] The command or application to parse.
|
274
|
-
# @param args [Array] The arguments to parse.
|
275
|
-
# @return [Command|nil] A command to execute or `nil` if no command was found.
|
276
|
-
def parse_options(parser, command, args)
|
277
|
-
rv = nil
|
278
|
-
|
279
|
-
# Parse options
|
280
|
-
parser.order!(args) do |arg|
|
281
|
-
fc = Bovem::Parser.find_command(arg, command, args)
|
282
|
-
|
283
|
-
if fc.present? then
|
284
|
-
rv = fc
|
285
|
-
parser.terminate
|
286
|
-
else
|
287
|
-
command.argument(arg)
|
288
|
-
end
|
289
|
-
end
|
217
|
+
# :nodoc:
|
218
|
+
def parse_array(command, opts, option)
|
219
|
+
meta = option.meta || command.i18n.help_arg
|
290
220
|
|
291
|
-
|
221
|
+
opts.on("#{option.complete_short} #{meta}", "#{option.complete_long} #{meta}", Array) do |value|
|
222
|
+
option.set(value.ensure_array)
|
292
223
|
end
|
224
|
+
end
|
293
225
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
# Check if any required option is missing.
|
299
|
-
command.options.each_pair do |name, option|
|
300
|
-
raise Bovem::Errors::Error.new(option, :missing_option, command.i18n.missing_option(option.label)) if option.required && !option.provided?
|
301
|
-
end
|
226
|
+
# :nodoc:
|
227
|
+
def parse_boolean(opts, option)
|
228
|
+
opts.on("-#{option.short}", "--#{option.long}") do |value|
|
229
|
+
option.set(value.to_boolean)
|
302
230
|
end
|
231
|
+
end
|
303
232
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
# @param args [Array] The arguments to parse.
|
308
|
-
# @return [Command|nil] A command to execute or `nil` if no command was found.
|
309
|
-
def find_command_to_execute(command, args)
|
310
|
-
rv = nil
|
233
|
+
# :nodoc:
|
234
|
+
def parse_options(parser, command, args)
|
235
|
+
rv = nil
|
311
236
|
|
312
|
-
|
313
|
-
|
237
|
+
# Parse options
|
238
|
+
parser.order!(args) do |arg|
|
239
|
+
fc = Bovem::Parser.find_command(arg, command, args: args)
|
314
240
|
|
315
|
-
if fc.present?
|
241
|
+
if fc.present?
|
316
242
|
rv = fc
|
243
|
+
parser.terminate
|
317
244
|
else
|
318
|
-
|
319
|
-
command.argument(arg)
|
320
|
-
end
|
245
|
+
command.argument(arg)
|
321
246
|
end
|
247
|
+
end
|
248
|
+
|
249
|
+
rv
|
250
|
+
end
|
322
251
|
|
323
|
-
|
252
|
+
# :nodoc:
|
253
|
+
def check_required_options(command)
|
254
|
+
# Check if any required option is missing.
|
255
|
+
command.options.each_pair do |_, option|
|
256
|
+
raise Bovem::Errors::Error.new(option, :missing_option, command.i18n.missing_option(option.label)) if option.required && !option.provided?
|
324
257
|
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# :nodoc:
|
261
|
+
def find_command_to_execute(command, args)
|
262
|
+
rv = nil
|
263
|
+
|
264
|
+
# Try to find a command into the first argument
|
265
|
+
fc = Bovem::Parser.find_command(args[0], command, args: args[1, args.length - 1])
|
266
|
+
|
267
|
+
if fc.present?
|
268
|
+
rv = fc
|
269
|
+
else
|
270
|
+
args.each do |arg|
|
271
|
+
command.argument(arg)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
rv
|
276
|
+
end
|
325
277
|
end
|
326
|
-
end
|
278
|
+
end
|