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 +4 -4
- data/.gitignore +1 -0
- data/README.md +45 -12
- data/TODO +6 -0
- data/bin/mkdoc +11 -6
- data/lib/shellopts.rb +34 -10
- data/lib/shellopts/compiler.rb +1 -1
- data/lib/shellopts/version.rb +1 -1
- data/shellopts.gemspec +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a081efe12e3a4e2f4b38eab4d2f6776c5dc3c748fb06178a4b42dbbba4e9612
|
4
|
+
data.tar.gz: 27a8d76c4de24c440bd330aa84d2e17014456c927af3c4a12807573df798c01a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f21b1f020dd04219272d5772cf0483b88c108af9991450e2532fcdab5322635a80a1cbac512c284358d10f271c03b4adef65ffb379d3df8a1d6635b9ca9f518
|
7
|
+
data.tar.gz: e88c6c0abcb49a7ba6568aa66c62267a63b92cfb9969387522a52b045fc34d4121cddb4b8c11ffe68d8ed3f13f925391e393e5b4ac292732696de019f7ed4217
|
data/.gitignore
CHANGED
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
`--verbose`
|
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
|
54
|
-
parse the command line. If given a block, the block is called with a
|
55
|
-
pair for each option or command and return a list of the remaining
|
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
|
-
|
3
|
+
set -e
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
14
|
+
# Generate rdoc
|
15
|
+
rdoc --output=rdoc --force-output lib
|
data/lib/shellopts.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
#
|
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
|
-
|
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
|
data/lib/shellopts/compiler.rb
CHANGED
@@ -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.
|
data/lib/shellopts/version.rb
CHANGED
data/shellopts.gemspec
CHANGED
@@ -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", "
|
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.
|
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:
|
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:
|
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:
|
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
|
-
|
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
|