shellopts 0.9.2 → 0.9.7

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: 710c9651cae2494969fe031b4d8a91bbcebd123c8d395b512bec5b193c50e6ea
4
- data.tar.gz: e2a4901ea784ec6331ccd65ef4df58daf04aba44c0c395f736da27eee14f8f12
3
+ metadata.gz: 4a081efe12e3a4e2f4b38eab4d2f6776c5dc3c748fb06178a4b42dbbba4e9612
4
+ data.tar.gz: 27a8d76c4de24c440bd330aa84d2e17014456c927af3c4a12807573df798c01a
5
5
  SHA512:
6
- metadata.gz: ad85e178173ba17e7cfc0b452cc1bcdd50e7c17374885b8aecddd4495e04a5492c14bdecfdd13445738e63c8bfa2434c3f0957ab1e7d803dc18ba42722726761
7
- data.tar.gz: be53d32e0fdcbcf4caee01762e5bb5d6b8452ffeaf6ae7f65e9746cf7a222aa65ab38ca8dd4db8de91c6f0507e4fc9df88d30c286e29a83d994d020bae4759a1
6
+ metadata.gz: 4f21b1f020dd04219272d5772cf0483b88c108af9991450e2532fcdab5322635a80a1cbac512c284358d10f271c03b4adef65ffb379d3df8a1d6635b9ca9f518
7
+ data.tar.gz: e88c6c0abcb49a7ba6568aa66c62267a63b92cfb9969387522a52b045fc34d4121cddb4b8c11ffe68d8ed3f13f925391e393e5b4ac292732696de019f7ed4217
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  /.yardoc
3
3
  /_yardoc/
4
4
  /doc/
5
+ /rdoc/
5
6
  /pkg/
6
7
  /spec/reports/
7
8
  /tmp/
data/README.md CHANGED
@@ -1,20 +1,20 @@
1
1
  # Shellopts
2
2
 
3
- `ShellOpts` is a simple command line parsing libray that covers most modern use
3
+ `ShellOpts` is a simple Linux command line parsing libray that covers most modern use
4
4
  cases incl. sub-commands. Options and commands are specified using a
5
5
  getopt(1)-like string that is interpreted by the library to process the command
6
6
  line
7
7
 
8
8
  ## Usage
9
9
 
10
- The following program accepts `-a` and `--all` that are aliases
11
- for the same option, `--count` that may be given an integer argument but
12
- defaults to 42, `--file` that has a mandatory argument, and `-v` and
13
- `--verbose` that can be repeated to increase the verbosity level
10
+ Program that accepts the options -a or --all, --count, --file, and -v or
11
+ --verbose. The usage definition expects `--count` to have an optional integer
12
+ argument, `--file` to have a mandatory argument, and allows `-v` and
13
+ `--verbose` to be repeated:
14
14
 
15
- ```ruby
16
- require 'shellopts'
17
15
 
16
+ ```ruby
17
+
18
18
  # Define options
19
19
  USAGE = "a,all count=#? file= +v,verbose -- FILE..."
20
20
 
@@ -36,7 +36,7 @@ args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
36
36
  end
37
37
  end
38
38
 
39
- # Process remaining arguments
39
+ # Process remaining command line arguments
40
40
  args.each { |arg| ... }
41
41
  ```
42
42
 
@@ -50,10 +50,10 @@ error
50
50
 
51
51
  ## Processing
52
52
 
53
- `ShellOpts.process` compiles a usage definition string into a grammar and use that to
54
- parse the command line. If given a block, the block is called with a name/value
55
- pair for each option or command and return a list of the remaining non-option
56
- arguments
53
+ `ShellOpts.process` compiles a usage definition string into a grammar and use
54
+ that to parse the command line. If given a block, the block is called with a
55
+ name/value pair for each option or command and return a list of the remaining
56
+ non-option arguments
57
57
 
58
58
  ```ruby
59
59
  args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
@@ -101,6 +101,18 @@ An option is defined by a list of comma-separated names optionally prefixed by a
101
101
  [ "+" ] name-list [ "=" [ "#" | "$" ] [ label ] [ "?" ] ]
102
102
  ```
103
103
 
104
+ #### Flags
105
+
106
+ There are the following flags:
107
+
108
+ |Flag|Effect|
109
+ |---|---|
110
+ |+|Repeated option (prefix)|
111
+ |=|Argument. Mandatory unless `?` is also used|
112
+ |#|Integer argument|
113
+ |$|Floating point argument|
114
+ |?|Optional argument|
115
+
104
116
  #### Repeated options
105
117
 
106
118
  Options are unique by default and the user will get an error if an option is
@@ -260,6 +272,27 @@ The methods are defined as instance methods on `ShellOpts::ShellOpts` and as
260
272
  class methods on `ShellOpts`. They can also be included in the global scope by
261
273
  `include ShellOpts::Utils`
262
274
 
275
+ #### Usage string
276
+
277
+ The error handling methods prints a prettified version of the usage string
278
+ given to `ShellOpts.parse`. The usage string can be overridden by assigning to
279
+ `ShellOpts.usage`. A typical use case is when you want to split the usage
280
+ description over multiple lines:
281
+
282
+ ```ruby
283
+
284
+ USAGE="long-and-complex-usage-string"
285
+ ShellOpts.usage = <<~EOD
286
+ usage explanation
287
+ split over
288
+ multiple lines
289
+ EOD
290
+ ```
291
+
292
+ Note that this only affects the module-level `ShellOpts.error` method and not
293
+ object-level `ShellOpts::ShellOpts#error` method. This is considered a bug and
294
+ will fixed at some point
295
+
263
296
  ## Example
264
297
 
265
298
  The rm(1) command could be implemented like this
data/TODO CHANGED
@@ -1,5 +1,10 @@
1
1
 
2
2
  TODO
3
+ o Check on return value from #process block to see if all options was handled:
4
+ case opt
5
+ when '-v'; verbose = true # Return value 'true' is ok
6
+ # Unhandled option means return value is nil
7
+ end
3
8
  o Consolidate some of the 3 variations of #error and #fail
4
9
  o Add a option flag for solitary options (--help)
5
10
  o Make a #to_yaml
@@ -55,6 +60,7 @@ LATER
55
60
  o Escape of separator in lists
56
61
  o Handle output of subcommand usage like "cmd1 cmd1.cmd2 cmd2"
57
62
  o Command-specific arguments: clone! o,opt ++ ARG1 ARG2...
63
+ o Hostname and email as basic types
58
64
 
59
65
  ON TO_H BRANCH
60
66
  ShellOpts.process(usage, argv) { |opt,val| ... } => args
data/bin/mkdoc CHANGED
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/bash
2
2
 
3
- LINK='<link rel="stylesheet" type="text/css" href="stylesheet.css">'
3
+ set -e
4
4
 
5
- {
6
- echo $LINK
7
- pandoc README.md
8
- } >index.html
5
+ # Generate github-like page
6
+ (
7
+ cd doc
8
+ {
9
+ echo '<link rel="stylesheet" type="text/css" href="stylesheet.css">'
10
+ pandoc ../README.md
11
+ } >index.html
12
+ )
9
13
 
10
- rdoc lib
14
+ # Generate rdoc
15
+ rdoc --output=rdoc --force-output lib
@@ -2,6 +2,7 @@ require "shellopts/version"
2
2
 
3
3
  require 'shellopts/compiler.rb'
4
4
  require 'shellopts/parser.rb'
5
+ require 'shellopts/utils.rb'
5
6
 
6
7
  # ShellOpts is a library for parsing command line options and sub-commands. The
7
8
  # library API consists of the methods {ShellOpts.process}, {ShellOpts.error},
@@ -11,6 +12,18 @@ require 'shellopts/parser.rb'
11
12
  # name of the program
12
13
  #
13
14
  module ShellOpts
15
+ # Return the hidden +ShellOpts::ShellOpts+ object (see .process)
16
+ def self.shellopts()
17
+ @shellopts
18
+ end
19
+
20
+ # Prettified usage string used by #error and #fail. Default is +usage+ of
21
+ # the current +ShellOpts::ShellOpts+ object
22
+ def self.usage() @usage || @shellopts&.usage end
23
+
24
+ # Set the usage string
25
+ def self.usage=(usage) @usage = usage end
26
+
14
27
  # Process command line options and arguments. #process takes a usage string
15
28
  # defining the options and the array of command line arguments to be parsed
16
29
  # as arguments
@@ -71,14 +84,16 @@ module ShellOpts
71
84
  # #process saves a hidden {ShellOpts::ShellOpts} class variable used by the
72
85
  # class methods #error and #fail. Call #reset to clear the global object if
73
86
  # you really need to parse more than one command line. Alternatively you can
74
- # create +ShellOpts::ShellOpts+ objects yourself and use the object methods
75
- # #error and #fail instead:
87
+ # create +ShellOpts::ShellOpts+ objects yourself and also use the object methods
88
+ # #error and #fail:
76
89
  #
77
90
  # shellopts = ShellOpts::ShellOpts.new(USAGE, ARGS)
78
91
  # shellopts.each { |name, value| ... }
79
92
  # shellopts.args.each { |arg| ... }
80
93
  # shellopts.error("Something went wrong")
81
94
  #
95
+ # Use #shellopts to get the hidden +ShellOpts::ShellOpts+ object
96
+ #
82
97
  def self.process(usage, argv, program_name: PROGRAM, &block)
83
98
  if !block_given?
84
99
  ShellOpts.new(usage, argv, program_name: program_name)
@@ -94,15 +109,20 @@ module ShellOpts
94
109
  # another command line
95
110
  def self.reset()
96
111
  @shellopts = nil
112
+ @usage = nil
97
113
  end
98
114
 
99
115
  # Print error message and usage string and exit with status 1. It use the
100
116
  # current ShellOpts object if defined. This method should be called in
101
117
  # response to user-errors (eg. specifying an illegal option)
118
+ #
119
+ # If there is no current ShellOpts object +error+ will look for USAGE to make
120
+ # it possible to use +error+ before the command line is processed and also as
121
+ # a stand-alone error reporting method
102
122
  def self.error(*msgs)
103
123
  program = @shellopts&.program_name || PROGRAM
104
- usage = @shellopts&.usage || (defined?(USAGE) && USAGE ? Grammar.compile(PROGRAM, USAGE).usage : nil)
105
- emit_and_exit(program, usage, *msgs)
124
+ usage_string = usage || (defined?(USAGE) && USAGE ? Grammar.compile(PROGRAM, USAGE).usage : nil)
125
+ emit_and_exit(program, @usage.nil?, usage_string, *msgs)
106
126
  end
107
127
 
108
128
  # Print error message and exit with status 1. It use the current ShellOpts
@@ -110,7 +130,7 @@ module ShellOpts
110
130
  # user-errors but system errors (like disk full)
111
131
  def self.fail(*msgs)
112
132
  program = @shellopts&.program_name || PROGRAM
113
- emit_and_exit(program, nil, *msgs)
133
+ emit_and_exit(program, false, nil, *msgs)
114
134
  end
115
135
 
116
136
  # The compilation object
@@ -118,7 +138,7 @@ module ShellOpts
118
138
  # Name of program
119
139
  attr_reader :program_name
120
140
 
121
- # Usage string. Shorthand for +grammar.usage+
141
+ # Prettified usage string used by #error and #fail. Shorthand for +grammar.usage+
122
142
  def usage() @grammar.usage end
123
143
 
124
144
  # The grammar compiled from the usage string. If #ast is defined, it's
@@ -171,13 +191,13 @@ module ShellOpts
171
191
  # should be called in response to user-errors (eg. specifying an illegal
172
192
  # option)
173
193
  def error(*msgs)
174
- ::ShellOpts.emit_and_exit(program_name, usage, msgs)
194
+ ::ShellOpts.emit_and_exit(program_name, true, usage, msgs)
175
195
  end
176
196
 
177
197
  # Print error message and exit with status 1. This method should not be
178
198
  # called in response to user-errors but system errors (like disk full)
179
199
  def fail(*msgs)
180
- ::ShellOpts.emit_and_exit(program_name, nil, msgs)
200
+ ::ShellOpts.emit_and_exit(program_name, false, nil, msgs)
181
201
  end
182
202
  end
183
203
 
@@ -198,9 +218,13 @@ module ShellOpts
198
218
  private
199
219
  @shellopts = nil
200
220
 
201
- def self.emit_and_exit(program, usage, *msgs)
221
+ def self.emit_and_exit(program, use_usage, usage, *msgs)
202
222
  $stderr.puts "#{program}: #{msgs.join}"
203
- $stderr.puts "Usage: #{program} #{usage}" if usage
223
+ if use_usage
224
+ $stderr.puts "Usage: #{program} #{usage}" if usage
225
+ else
226
+ $stderr.puts usage if usage
227
+ end
204
228
  exit 1
205
229
  end
206
230
  end
@@ -27,7 +27,7 @@ module ShellOpts
27
27
 
28
28
  # Initialize a Compiler object. source is the option definition string
29
29
  def initialize(program_name, source)
30
- @program_name, @tokens = program_name, source.split(/\s+/)
30
+ @program_name, @tokens = program_name, source.split(/\s+/).reject(&:empty?)
31
31
 
32
32
  # @commands_by_path is an hash from command-path to Command or Program
33
33
  # object. The top level Program object has nil as its path.
@@ -1,3 +1,3 @@
1
1
  module Shellopts
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.7"
3
3
  end
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.require_paths = ["lib"]
34
34
 
35
35
  spec.add_development_dependency "bundler", "~> 1.16"
36
- spec.add_development_dependency "rake", "~> 10.0"
36
+ spec.add_development_dependency "rake", ">= 12.3.3"
37
37
  spec.add_development_dependency "rspec", "~> 3.0"
38
38
  spec.add_development_dependency "indented_io"
39
39
  spec.add_development_dependency "simplecov"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shellopts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-27 00:00:00.000000000 Z
11
+ date: 2020-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -103,6 +103,7 @@ files:
103
103
  - bin/console
104
104
  - bin/mkdoc
105
105
  - bin/setup
106
+ - doc/stylesheet.css
106
107
  - lib/ext/array.rb
107
108
  - lib/shellopts.rb
108
109
  - lib/shellopts/ast/command.rb
@@ -137,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
137
138
  - !ruby/object:Gem::Version
138
139
  version: '0'
139
140
  requirements: []
140
- rubyforge_project:
141
- rubygems_version: 2.7.6
141
+ rubygems_version: 3.0.8
142
142
  signing_key:
143
143
  specification_version: 4
144
144
  summary: Parse command line options and arguments