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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43a4d96ef2927b72add380e17e0dad25b2004659491a5dc4adb36f3c9965c8c9
4
- data.tar.gz: 507780f5ea40771db0ffbc4d0247b9f8f5d08044953dc0c387e92432c42879df
3
+ metadata.gz: 35b9e7b5699cc1a5637d4c00dd95c74047074f1227b0d05f9a9c8b04e1e2cc8b
4
+ data.tar.gz: c8deed23c8e6f0b26d080e15d2830edb5e65d1b5f2f821ccd83db7db27d7aefd
5
5
  SHA512:
6
- metadata.gz: d57c4a7245f5c22b74c762d986b8a80ca331643a3f32f63421f08f412da01e3f6e21c76e0fe1921fa8337ad2cbc168e00bb9f722f3ebfc1fdb7468619169658d
7
- data.tar.gz: 4ab7b06dd787db06af9ca0d70f6d44a26e251707badef5beecdb3bb719a3fc1bebf5357f00df2702589f4ea6960ebc6af83329adadc3e65bd2746e3dbb536fca
6
+ metadata.gz: 5d3e96ec825ca58c0e653613ab84e2ede3e661737f5699571c81aaf9b2cb1252ea802581e5b981a1757d8a5a750ba998c43730c6d2da7d8228b721b06a45640e
7
+ data.tar.gz: e64eeac4c3bf784f8ef3a5e3a61c596e262bd23c4ee05857f76138f82ff2180afb72ccd5c2b7ffedc4e6aa2887b10c76e3a80c33e24ceadd20e71513549b5bf0
@@ -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
- attr_reader :ident
75
+ attr_accessor :ident
76
76
 
77
77
  # Canonical name (String) of the object
78
78
  #
@@ -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 add_version_option
128
- option_token = Token.new(:option, 1, 1, "--version")
129
- brief_token = Token.new(:brief, 1, 1, "Write version number and exit")
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
- end
134
-
135
- def add_help_options
136
- option_token = Token.new(:option, 1, 1, "-h,help")
137
- brief_token = Token.new(:brief, 1, 1, "Write help text and exit")
138
- paragraph_token = Token.new(:text, 1, 1,
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
 
@@ -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.
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.0.18"
2
+ VERSION = "2.0.19"
3
3
  end
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
- def version
101
- return @version if @version
102
- exe = caller.find { |line| line =~ /`<top \(required\)>'$/ }&.sub(/:.*/, "")
103
- file = Dir.glob(File.dirname(exe) + "/../lib/*/version.rb").first
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
- # Add message options (TODO)
109
- attr_accessor :msgopts
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, help: true, version: true, msgopts: false, float: true, exception: false)
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
- @use_version = version ? true : false
129
- @version = @use_version && @version != true ? @version : nil
130
- @msgopts, @float, @exception = msgopts, float, exception
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
- ast.add_version_option if @use_version
143
- ast.add_help_options if @help
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
- if @program.version?
157
- puts version
158
- exit
159
- elsif @program.help?
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
- def self.process(spec, argv, msgopts: false, **opts)
326
- msgopts ||= Messages.is_included?
327
- ShellOpts.process(spec, argv, msgopts: msgopts, **opts)
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
- # The Include module brings the reporting methods into the namespace when
349
- # included
350
- module Messages
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.include(...)
354
- @is_included = true
355
- super
356
- end
441
+ def self.included(...) @is_included = true; super end
357
442
 
358
- def notice(message)
359
- $stderr.puts "#{name}: #{message}" if !quiet?
360
- end
443
+ def notice(message) ::ShellOpts.notice(message) end
444
+ def mesg(message) ::ShellOpts.mesg(message) end
445
+ end
361
446
 
362
- def mesg(message)
363
- $stdout.puts message if !quiet?
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 verb(level = 1, message)
367
- $stdout.puts message if level <= @verbose
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
- def debug(message)
371
- $stdout.puts message if debug?
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