shellopts 2.0.18 → 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/shellopts/grammar.rb +1 -1
- data/lib/shellopts/parser.rb +10 -15
- data/lib/shellopts/program.rb +12 -0
- data/lib/shellopts/version.rb +1 -1
- data/lib/shellopts.rb +135 -45
- data/main +15 -1185
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35b9e7b5699cc1a5637d4c00dd95c74047074f1227b0d05f9a9c8b04e1e2cc8b
|
4
|
+
data.tar.gz: c8deed23c8e6f0b26d080e15d2830edb5e65d1b5f2f821ccd83db7db27d7aefd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d3e96ec825ca58c0e653613ab84e2ede3e661737f5699571c81aaf9b2cb1252ea802581e5b981a1757d8a5a750ba998c43730c6d2da7d8228b721b06a45640e
|
7
|
+
data.tar.gz: e64eeac4c3bf784f8ef3a5e3a61c596e262bd23c4ee05857f76138f82ff2180afb72ccd5c2b7ffedc4e6aa2887b10c76e3a80c33e24ceadd20e71513549b5bf0
|
data/lib/shellopts/grammar.rb
CHANGED
@@ -72,7 +72,7 @@ module ShellOpts
|
|
72
72
|
# Note that the analyzer fails with an an error if both --with-separator
|
73
73
|
# and --with_separator are used because they would both map to
|
74
74
|
# :with_separator
|
75
|
-
|
75
|
+
attr_accessor :ident
|
76
76
|
|
77
77
|
# Canonical name (String) of the object
|
78
78
|
#
|
data/lib/shellopts/parser.rb
CHANGED
@@ -23,7 +23,7 @@ module ShellOpts
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class Option
|
26
|
-
SHORT_NAME_RE = /[a-zA-Z0-9]/
|
26
|
+
SHORT_NAME_RE = /[a-zA-Z0-9?]/
|
27
27
|
LONG_NAME_RE = /[a-zA-Z0-9][a-zA-Z0-9_-]*/
|
28
28
|
NAME_RE = /(?:#{SHORT_NAME_RE}|#{LONG_NAME_RE})(?:,#{LONG_NAME_RE})*/
|
29
29
|
|
@@ -124,23 +124,18 @@ module ShellOpts
|
|
124
124
|
super(nil, token)
|
125
125
|
end
|
126
126
|
|
127
|
-
def
|
128
|
-
option_token = Token.new(:option, 1, 1,
|
129
|
-
brief_token = Token.new(:brief, 1, 1,
|
127
|
+
def inject_option(decl, brief, paragraph = nil, &block)
|
128
|
+
option_token = Token.new(:option, 1, 1, decl)
|
129
|
+
brief_token = Token.new(:brief, 1, 1, brief)
|
130
130
|
group = OptionGroup.new(self, option_token)
|
131
131
|
option = Option.parse(group, option_token)
|
132
132
|
brief = Brief.parse(group, brief_token)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
"-h prints a brief help text, --help prints a longer man-style description of the command")
|
140
|
-
group = OptionGroup.new(self, option_token)
|
141
|
-
option = Option.parse(group, option_token)
|
142
|
-
brief = Brief.parse(group, brief_token)
|
143
|
-
paragraph = Paragraph.parse(group, paragraph_token)
|
133
|
+
paragraph ||= yield(option) if block_given?
|
134
|
+
if paragraph
|
135
|
+
paragraph_token = Token.new(:text, 1, 1, paragraph)
|
136
|
+
paragraph = Paragraph.parse(group, paragraph_token)
|
137
|
+
end
|
138
|
+
option
|
144
139
|
end
|
145
140
|
end
|
146
141
|
|
data/lib/shellopts/program.rb
CHANGED
@@ -297,6 +297,18 @@ module ShellOpts
|
|
297
297
|
|
298
298
|
# The top-level command
|
299
299
|
class Program < Command
|
300
|
+
# Accessors for standard options values that are not affected if the option
|
301
|
+
# is renamed
|
302
|
+
attr_accessor :__quiet__
|
303
|
+
attr_accessor :__verbose__
|
304
|
+
attr_accessor :__debug__
|
305
|
+
|
306
|
+
def initialize
|
307
|
+
super
|
308
|
+
@__quiet__ = false
|
309
|
+
@__verbose__ = 0
|
310
|
+
@__debug__ = false
|
311
|
+
end
|
300
312
|
end
|
301
313
|
|
302
314
|
# Option models an option as given by the user on the subcommand line.
|
data/lib/shellopts/version.rb
CHANGED
data/lib/shellopts.rb
CHANGED
@@ -96,17 +96,20 @@ module ShellOpts
|
|
96
96
|
# Automatically add a -h and a --help option if true
|
97
97
|
attr_reader :help
|
98
98
|
|
99
|
-
# Version of client program. If not nil a --version option is added to the program
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
@version = IO.read(file).sub(/^.*VERSION\s*=\s*"(.*?)".*$/m, '\1') or
|
105
|
-
raise ArgumentError, "ShellOpts needs an explicit version"
|
106
|
-
end
|
99
|
+
# Version of client program. If not nil, a --version option is added to the program
|
100
|
+
attr_reader :version
|
101
|
+
|
102
|
+
# Automatically add a -q and a --quiet option if true
|
103
|
+
attr_reader :quiet
|
107
104
|
|
108
|
-
#
|
109
|
-
|
105
|
+
# Automatically add a -v and a --verbose option if true
|
106
|
+
attr_reader :verbose
|
107
|
+
|
108
|
+
# Automatically add a --debug option if true
|
109
|
+
attr_reader :debug
|
110
|
+
|
111
|
+
# Version number (this is usually detected dynamically)
|
112
|
+
attr_reader :version_number
|
110
113
|
|
111
114
|
# Floating options
|
112
115
|
attr_accessor :float
|
@@ -122,12 +125,33 @@ module ShellOpts
|
|
122
125
|
attr_reader :tokens
|
123
126
|
alias_method :ast, :grammar
|
124
127
|
|
125
|
-
def initialize(name: nil,
|
128
|
+
def initialize(name: nil,
|
129
|
+
# Options
|
130
|
+
help: true,
|
131
|
+
version: true,
|
132
|
+
quiet: nil,
|
133
|
+
verbose: nil,
|
134
|
+
debug: nil,
|
135
|
+
|
136
|
+
# Version number (usually detected)
|
137
|
+
version_number: nil,
|
138
|
+
|
139
|
+
# Floating options
|
140
|
+
float: true,
|
141
|
+
|
142
|
+
# Let exceptions through
|
143
|
+
exceptions: false
|
144
|
+
)
|
145
|
+
|
126
146
|
@name = name || File.basename($PROGRAM_NAME)
|
127
147
|
@help = help
|
128
|
-
@
|
129
|
-
@
|
130
|
-
@
|
148
|
+
@version = version || (version.nil? && !version_number.nil?)
|
149
|
+
@quiet = quiet
|
150
|
+
@verbose = verbose
|
151
|
+
@debug = debug
|
152
|
+
@version_number = version_number || find_version_number
|
153
|
+
@float = float
|
154
|
+
@exception = exception
|
131
155
|
end
|
132
156
|
|
133
157
|
# Compile source and return grammar object. Also sets #spec and #grammar.
|
@@ -139,8 +163,31 @@ module ShellOpts
|
|
139
163
|
@file = find_caller_file
|
140
164
|
@tokens = Lexer.lex(name, @spec, @oneline)
|
141
165
|
ast = Parser.parse(tokens)
|
142
|
-
|
143
|
-
|
166
|
+
|
167
|
+
help_spec = (@help == true ? "-h,help" : @help)
|
168
|
+
version_spec = (@version == true ? "--version" : @version)
|
169
|
+
quiet_spec = (@quiet == true ? "-q,quiet" : @quiet)
|
170
|
+
verbose_spec = (@verbose == true ? "+v,verbose" : @verbose)
|
171
|
+
debug_spec = (@debug == true ? "--debug" : @debug)
|
172
|
+
|
173
|
+
@quiet_option =
|
174
|
+
ast.inject_option(quiet_spec, "Quiet", "Do not write anything to standard output") if @quiet
|
175
|
+
@verbose_option =
|
176
|
+
ast.inject_option(verbose_spec, "Increase verbosity", "Write verbose output") if @verbose
|
177
|
+
@debug_option =
|
178
|
+
ast.inject_option(debug_spec, "Write debug information") if @debug
|
179
|
+
@help_option =
|
180
|
+
ast.inject_option(help_spec, "Write short or long help") { |option|
|
181
|
+
short_option = option.short_names.first
|
182
|
+
long_option = option.long_names.first
|
183
|
+
[
|
184
|
+
short_option && "#{short_option} prints a brief help text",
|
185
|
+
long_option && "#{long_option} prints a longer man-style description of the command"
|
186
|
+
].compact.join(", ")
|
187
|
+
} if @help
|
188
|
+
@version_option =
|
189
|
+
ast.inject_option(version_spec, "Write version number and exit") if @version
|
190
|
+
|
144
191
|
@grammar = Analyzer.analyze(ast)
|
145
192
|
}
|
146
193
|
self
|
@@ -153,16 +200,22 @@ module ShellOpts
|
|
153
200
|
handle_exceptions {
|
154
201
|
@argv = argv.dup
|
155
202
|
@program, @args = Interpreter.interpret(grammar, argv, float: float, exception: exception)
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
if @program[:help].name == "-h"
|
161
|
-
ShellOpts.brief
|
162
|
-
else
|
203
|
+
|
204
|
+
# Process standard options (that may have been renamed)
|
205
|
+
if @program.__send__(:"#{@help_option.ident}?")
|
206
|
+
if @program[:help].name =~ /^--/
|
163
207
|
ShellOpts.help
|
208
|
+
else
|
209
|
+
ShellOpts.brief
|
164
210
|
end
|
165
211
|
exit
|
212
|
+
elsif @program.__send__(:"#{@version_option.ident}?")
|
213
|
+
puts version_number
|
214
|
+
exit
|
215
|
+
else
|
216
|
+
@program.__quiet__ = @program.__send__(:"#{@quiet_option.ident}?") if @quiet
|
217
|
+
@program.__verbose__ = @program.__send__(:"#{@verbose_option.ident}") if @verbose
|
218
|
+
@program.__debug__ = @program.__send__(:"#{@debug_option.ident}?") if @debug
|
166
219
|
end
|
167
220
|
}
|
168
221
|
self
|
@@ -235,6 +288,13 @@ module ShellOpts
|
|
235
288
|
def self.help(subject = nil) ::ShellOpts.instance.help(subject) end
|
236
289
|
|
237
290
|
private
|
291
|
+
def find_version_number
|
292
|
+
exe = caller.find { |line| line =~ /`<top \(required\)>'$/ }&.sub(/:.*/, "") or return nil
|
293
|
+
file = Dir.glob(File.dirname(exe) + "/../lib/*/version.rb").first or return nil
|
294
|
+
IO.read(file).sub(/^.*VERSION\s*=\s*"(.*?)".*$/m, '\1') or
|
295
|
+
raise ArgumentError, "ShellOpts needs an explicit version"
|
296
|
+
end
|
297
|
+
|
238
298
|
def handle_exceptions(&block)
|
239
299
|
return yield if exception
|
240
300
|
begin
|
@@ -322,9 +382,13 @@ module ShellOpts
|
|
322
382
|
end
|
323
383
|
end
|
324
384
|
|
325
|
-
|
326
|
-
|
327
|
-
|
385
|
+
|
386
|
+
def self.process(spec, argv, quiet: nil, verbose: nil, debug: nil, **opts)
|
387
|
+
constrain quiet, String, true, false, nil
|
388
|
+
quiet = quiet.nil? ? Message.is_included? || Verbose.is_included? : quiet
|
389
|
+
verbose = verbose.nil? ? ::ShellOpts::Verbose.is_included? : verbose
|
390
|
+
debug = debug.nil? ? Debug.is_included? : debug
|
391
|
+
ShellOpts.process(spec, argv, quiet: quiet, verbose: verbose, debug: debug, **opts)
|
328
392
|
end
|
329
393
|
|
330
394
|
@instance = nil
|
@@ -345,31 +409,57 @@ module ShellOpts
|
|
345
409
|
exit 1
|
346
410
|
end
|
347
411
|
|
348
|
-
|
349
|
-
|
350
|
-
|
412
|
+
def self.notice(message)
|
413
|
+
$stderr.puts "#{instance.program.__grammar__.name}: #{message}" \
|
414
|
+
if !instance.quiet || !instance.program.quiet?
|
415
|
+
end
|
416
|
+
|
417
|
+
def self.mesg(message)
|
418
|
+
$stdout.puts message if !instance.quiet || !instance.program.__quiet__
|
419
|
+
end
|
420
|
+
|
421
|
+
def self.verb(level = 1, message)
|
422
|
+
$stdout.puts message if instance.verbose && level <= instance.program.__verbose__
|
423
|
+
end
|
424
|
+
|
425
|
+
def self.debug(message)
|
426
|
+
$stdout.puts message if instance.debug && instance.program.__debug__
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.quiet_flag
|
430
|
+
end
|
431
|
+
|
432
|
+
def self.verbose_flag
|
433
|
+
end
|
434
|
+
|
435
|
+
def self.debug_flag
|
436
|
+
end
|
437
|
+
|
438
|
+
module Message
|
351
439
|
@is_included = false
|
352
440
|
def self.is_included?() @is_included end
|
353
|
-
def self.
|
354
|
-
@is_included = true
|
355
|
-
super
|
356
|
-
end
|
441
|
+
def self.included(...) @is_included = true; super end
|
357
442
|
|
358
|
-
def notice(message)
|
359
|
-
|
360
|
-
|
443
|
+
def notice(message) ::ShellOpts.notice(message) end
|
444
|
+
def mesg(message) ::ShellOpts.mesg(message) end
|
445
|
+
end
|
361
446
|
|
362
|
-
|
363
|
-
|
364
|
-
end
|
447
|
+
module Verbose
|
448
|
+
@is_included = false
|
449
|
+
def self.is_included?() @is_included end
|
450
|
+
def self.included(...) @is_included = true; super end
|
365
451
|
|
366
|
-
def
|
367
|
-
|
368
|
-
end
|
452
|
+
def notice(message) ::ShellOpts.notice(message) end
|
453
|
+
def mesg(message) ::ShellOpts.mesg(message) end
|
454
|
+
def verb(level = 1, message) ::ShellOpts.verb(level, message) end
|
455
|
+
end
|
369
456
|
|
370
|
-
|
371
|
-
|
372
|
-
end
|
457
|
+
module Debug
|
458
|
+
@is_included = false
|
459
|
+
def self.is_included?() @is_included end
|
460
|
+
def self.included(...) @is_included = true; super end
|
461
|
+
|
462
|
+
def debug(message) ::ShellOpts.debug(message) end
|
373
463
|
end
|
374
464
|
|
375
465
|
module ErrorHandling
|