shellopts 2.0.0.pre.14 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.ruby-version +1 -1
- data/README.md +201 -267
- data/TODO +37 -5
- data/doc/format.rb +95 -0
- data/doc/grammar.txt +27 -0
- data/doc/syntax.rb +110 -0
- data/doc/syntax.txt +10 -0
- data/lib/ext/array.rb +62 -0
- data/lib/ext/forward_to.rb +15 -0
- data/lib/ext/lcs.rb +34 -0
- data/lib/shellopts/analyzer.rb +130 -0
- data/lib/shellopts/ansi.rb +8 -0
- data/lib/shellopts/args.rb +29 -21
- data/lib/shellopts/argument_type.rb +139 -0
- data/lib/shellopts/dump.rb +158 -0
- data/lib/shellopts/formatter.rb +292 -92
- data/lib/shellopts/grammar.rb +375 -0
- data/lib/shellopts/interpreter.rb +103 -0
- data/lib/shellopts/lexer.rb +175 -0
- data/lib/shellopts/parser.rb +293 -0
- data/lib/shellopts/program.rb +279 -0
- data/lib/shellopts/renderer.rb +227 -0
- data/lib/shellopts/stack.rb +7 -0
- data/lib/shellopts/token.rb +44 -0
- data/lib/shellopts/version.rb +1 -1
- data/lib/shellopts.rb +360 -3
- data/main +1180 -0
- data/shellopts.gemspec +8 -14
- metadata +86 -41
- data/lib/ext/algorithm.rb +0 -14
- data/lib/ext/ruby_env.rb +0 -8
- data/lib/shellopts/ast/command.rb +0 -112
- data/lib/shellopts/ast/dump.rb +0 -28
- data/lib/shellopts/ast/option.rb +0 -15
- data/lib/shellopts/ast/parser.rb +0 -106
- data/lib/shellopts/constants.rb +0 -88
- data/lib/shellopts/exceptions.rb +0 -21
- data/lib/shellopts/grammar/analyzer.rb +0 -76
- data/lib/shellopts/grammar/command.rb +0 -87
- data/lib/shellopts/grammar/dump.rb +0 -56
- data/lib/shellopts/grammar/lexer.rb +0 -56
- data/lib/shellopts/grammar/option.rb +0 -55
- data/lib/shellopts/grammar/parser.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 013afe67b6f86e17d37bfbd1b18f3b4b7e7e5026d3249900326b23d1ed75ed95
|
4
|
+
data.tar.gz: 7ccfcca5ef44d9958e3f03ea23ea211893357ff32c7c5e5fdc4953ec61548306
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a50d291b69952d04bc054ea09cf292f6df414a4d6e1df69ac47cb3d2489626301c7eba4f66edd268f1c486463d6c37a1fd0b3cd431060c7100da980272c2b9e
|
7
|
+
data.tar.gz: 0bd422a52a4b11f69ade0d744df2a0bf8db6a05d67e282bfadb6a1a72af6f1ebe21ec0dd24b8ce663379d9e69db643036606e2fc1e502995e24f2f7b5c8bdea3
|
data/.gitignore
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.7.1
|
data/README.md
CHANGED
@@ -1,345 +1,289 @@
|
|
1
1
|
# Shellopts
|
2
2
|
|
3
|
-
`ShellOpts` is a
|
4
|
-
|
5
|
-
|
6
|
-
line
|
3
|
+
`ShellOpts` is a command line processing library. It supports short
|
4
|
+
and long options and subcommands, and has built-in help and error messages
|
5
|
+
|
7
6
|
|
8
7
|
## Usage
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
repeated:
|
9
|
+
ShellOpts use a string to specify legal options and documentation. The
|
10
|
+
following program accepts the options --alpha and --beta with an argument. -a
|
11
|
+
and -b are option aliases:
|
14
12
|
|
15
13
|
```ruby
|
16
|
-
|
17
|
-
# Define options
|
18
|
-
USAGE = "a,all count=#? file= +v,verbose -- FILE..."
|
19
|
-
|
20
|
-
# Define default values
|
21
|
-
all = false
|
22
|
-
count = nil
|
23
|
-
file = nil
|
24
|
-
verbosity_level = 0
|
25
|
-
|
26
|
-
# Process command line and return remaining non-option arguments
|
27
|
-
args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
|
28
|
-
case opt
|
29
|
-
when '-a', '--all'; all = true
|
30
|
-
when '--count'; count = arg || 42
|
31
|
-
when '--file'; file = arg # never nil
|
32
|
-
when '-v, '--verbose'; verbosity_level += 1
|
33
|
-
else
|
34
|
-
fail "Internal Error: Unmatched option: '#{opt}'"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Process remaining command line arguments
|
39
|
-
args.each { |arg| ... }
|
40
|
-
```
|
41
|
-
|
42
|
-
Note that the `else` clause catches legal but unhandled options; it is not an
|
43
|
-
user error. It typically happens because of a missing or misspelled option name
|
44
|
-
in the `when` clauses
|
14
|
+
require 'shellopts'
|
45
15
|
|
46
|
-
|
47
|
-
status 1 and print an error message and a short usage description on standard
|
48
|
-
error
|
16
|
+
SPEC = "-a,alpha -b,beta=VAL -- ARG1 ARG2"
|
49
17
|
|
50
|
-
|
18
|
+
opts, args = ShellOpts.process(SPEC, ARGV)
|
51
19
|
|
52
|
-
|
53
|
-
|
54
|
-
name/value pair for each option or command and return a list of the remaining
|
55
|
-
non-option arguments
|
20
|
+
alpha = opts.alpha? # True if -a or --alpha are present
|
21
|
+
beta = opts.beta # The value of the -b or --beta option
|
56
22
|
|
57
|
-
```ruby
|
58
|
-
args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
|
59
|
-
case opt
|
60
|
-
when ...
|
61
|
-
end
|
62
|
-
end
|
63
23
|
```
|
64
24
|
|
65
|
-
This calls the block for each option in the same order as on the command line
|
66
|
-
and return the remaining non-option args. It also sets up the `ShellOpts.error` and
|
67
|
-
`ShellOpts.fail` methods. Please note that you need to call `ShellOpts.reset`
|
68
|
-
if you want to process another command line
|
69
|
-
|
70
|
-
If `ShellOpts.process` is called without a block it returns a
|
71
|
-
`ShellOpts::ShellOpts` object. It can be used to process more than one command
|
72
|
-
line at a time and to inspect the grammar and AST
|
73
|
-
|
74
25
|
```ruby
|
75
|
-
shellopts = ShellOpts.process(USAGE, ARGV) # Returns a ShellOpts::ShellOpts object
|
76
|
-
shellopts.each { |opt, arg| ... } # Access options
|
77
|
-
args = shellopts.args # Access remaining arguments
|
78
|
-
shellopts.error "Something went wrong" # Emit an error message and exit
|
79
26
|
```
|
80
27
|
|
81
|
-
|
28
|
+
ShellOpts also allow multi-line definitions with comments that are used as part
|
29
|
+
of help messages
|
82
30
|
|
83
|
-
|
84
|
-
|
85
|
-
dash (`--`) marks the end of the definition, anything after that is not
|
86
|
-
interpreted but copied verbatim in error messages
|
31
|
+
```ruby
|
32
|
+
require 'shellopts'
|
87
33
|
|
88
|
-
|
34
|
+
SPEC = %(
|
35
|
+
-a,alpha @ Brief comment for -a and --alpha options
|
36
|
+
-b,beta=VAL
|
37
|
+
@ Alternative style of brief comment
|
38
|
+
-- ARG1 ARG2
|
39
|
+
)
|
89
40
|
|
90
|
-
|
91
|
-
|
41
|
+
opts, args = ShellOpts.process(SPEC, ARGV)
|
42
|
+
ShellOpts::ShellOpts.brief
|
92
43
|
```
|
93
44
|
|
94
|
-
|
45
|
+
prints
|
95
46
|
|
96
|
-
|
97
|
-
|
47
|
+
```
|
48
|
+
Usage
|
49
|
+
main --alpha --beta=VAL ARG1 ARG2
|
98
50
|
|
99
|
-
|
100
|
-
|
51
|
+
Options
|
52
|
+
-a, --alpha Brief comment for -a and --alpha options
|
53
|
+
-b, --beta=VAL Alternative style of brief comment
|
101
54
|
```
|
102
55
|
|
103
|
-
|
56
|
+
There is also a `ShellOpts.help` method that prints a more detailed
|
57
|
+
documentation, and a `ShellOpts.usage` method that prints a compact usage
|
58
|
+
string
|
104
59
|
|
105
|
-
|
60
|
+
If there is an error in the command line options, the program will exit with
|
61
|
+
status 1 and print an error message and usage on standard error. If there is
|
62
|
+
an error in the specification, a message to the developer with the origin of
|
63
|
+
the error is printed on standard error
|
106
64
|
|
107
|
-
|
108
|
-
|---|---|
|
109
|
-
|+|Repeated option (prefix)|
|
110
|
-
|=|Argument. Mandatory unless `?` is also used|
|
111
|
-
|#|Integer argument|
|
112
|
-
|$|Floating point argument|
|
113
|
-
|?|Optional argument|
|
65
|
+
## Processing
|
114
66
|
|
115
|
-
|
67
|
+
`ShellOpts.process` creates a `ShellOpts::ShellOpts` object and use it to
|
68
|
+
compile the specification and process the command line. It returns a tuple of a
|
69
|
+
Program object and an array of the remaining arguments
|
116
70
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
let the user repeat a 'verbose' option to increase verbosity: `+v,verbose`
|
121
|
-
allows `-vvv` or `--verbose --verbose --verbose`. `ShellOpts::process` yields
|
122
|
-
an entry for each usage so should handle repeated options like this
|
71
|
+
The Program object has accessor methods for each defined option and sub-command
|
72
|
+
to check presence and return an optional argument. Given the options "--alpha
|
73
|
+
--beta=ARG" then the following accessor methods are available:
|
123
74
|
|
124
75
|
```ruby
|
125
|
-
|
76
|
+
# Returns true if the option is present and false otherwise
|
77
|
+
opts.alpha?()
|
78
|
+
opts.beta?()
|
126
79
|
|
127
|
-
|
128
|
-
|
129
|
-
when '-v', '--verbose'; verbosity_level += 1
|
130
|
-
# other options
|
131
|
-
end
|
132
|
-
end
|
80
|
+
# Returns the argument of the beta option or nil if missing
|
81
|
+
opts.beta()
|
133
82
|
```
|
134
83
|
|
135
|
-
|
84
|
+
Given the commands "cmd1! cmd2!" the following methods are available:
|
136
85
|
|
137
|
-
|
138
|
-
|
139
|
-
|
86
|
+
```ruby
|
87
|
+
# Returns the sub-command object or nil if not present
|
88
|
+
opts.cmd1!
|
89
|
+
opts.cmd2!
|
90
|
+
|
91
|
+
opts.subcommand! # Returns the sub-command object or nil if not present
|
92
|
+
opts.subcommand # Returns the sub-command's identifier (eg. :cmd1!)
|
93
|
+
```
|
140
94
|
|
141
|
-
|
142
|
-
prefixed with a single dash on the command line (eg. '-a'). Names with two or
|
143
|
-
more characters are 'long options' and are used with two dashes (eg. '--all').
|
144
|
-
Note that short and long names handles arguments differently
|
95
|
+
It is used like this
|
145
96
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
97
|
+
```ruby
|
98
|
+
case opts.subcommand
|
99
|
+
when :cmd1
|
100
|
+
# opts.cmd1 is defined here
|
101
|
+
when :cmd2
|
102
|
+
# opts.cmd2 is defined here
|
103
|
+
end
|
104
|
+
end
|
152
105
|
```
|
153
106
|
|
154
|
-
|
107
|
+
Sub-commands have options and even sub-sub-commands of their own. They can be
|
108
|
+
nested to any depth (which is not recommended, btw.)
|
155
109
|
|
156
|
-
|
157
|
-
|
158
|
-
|
110
|
+
The module methods `::usage`, `::brief`, and `::help` prints documentation with
|
111
|
+
increasing detail. `::usage` lists the options and commands without any comments,
|
112
|
+
`::brief` includes source text that starts with a '@', and `::help` the full
|
113
|
+
documentation in a man-page like format. Example
|
159
114
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
115
|
+
```ruby
|
116
|
+
SPEC = "-h --help"
|
117
|
+
opts, args = ShellOpts.process(SPEC, ARGV)
|
118
|
+
|
119
|
+
if opts.h?
|
120
|
+
ShellOpts.brief
|
121
|
+
exit
|
122
|
+
elsif opts.help?
|
123
|
+
ShellOpts.help
|
124
|
+
exit
|
125
|
+
end
|
126
|
+
```
|
164
127
|
|
165
|
-
|
128
|
+
The module methods `::error` and `::failure` are used to report errors in a common
|
129
|
+
format and then terminate the program with status 1. `::error` is used to report
|
130
|
+
errors that the user can correct and prints a usage description as a reminder.
|
131
|
+
`::failure` is used to report errors within the program so the usage descriptionn
|
132
|
+
is not printed:
|
166
133
|
|
167
|
-
|
134
|
+
```ruby
|
135
|
+
SPEC = "--var=VAR"
|
136
|
+
opts, args = ShellOpts.process(SPEC, ARGV)
|
168
137
|
|
169
|
-
|
170
|
-
|
171
|
-
local to that command. It is not possible to 'reset' this behaviour so global
|
172
|
-
options should always come before the first command. Nested commands are
|
173
|
-
specified using a dot-separated "path" to the nested sub-command
|
138
|
+
# --var is a mandatory 'option'
|
139
|
+
opts.var? or error "Missing --var 'option'"
|
174
140
|
|
175
|
-
|
176
|
-
|
177
|
-
g,global clone! t,template=
|
178
|
-
g,global clone! t,template= clone.list! v,verbose
|
141
|
+
# later during processing
|
142
|
+
condition or failure "Memory overflow"
|
179
143
|
```
|
180
144
|
|
181
|
-
The last example could be called like `program -g clone list -v`. You may split
|
182
|
-
the usage string to improve readability:
|
183
145
|
|
184
|
-
|
185
|
-
g,global
|
186
|
-
clone! t,template=
|
187
|
-
clone.list! v,verbose
|
188
|
-
```
|
146
|
+
## Specification
|
189
147
|
|
190
|
-
|
148
|
+
The specification is possibly multi-line string, typically named `SPEC`, that
|
149
|
+
is a mix of option or command definitions and related documentation.
|
150
|
+
Indentation is used to nest the elements and '@' is used to tag an option or
|
151
|
+
command with a brief description
|
191
152
|
|
192
|
-
|
193
|
-
|
153
|
+
The specifiction is parsed line-by-line: Lines matching and initial '-', or
|
154
|
+
'--' are considered option definitions and lines starting with a word
|
155
|
+
immediately followed by an exclamation mark is a command definition (like 'cmd!
|
156
|
+
...'). Text following a '@' (except in paragraphs) is a brief comment, the rest
|
157
|
+
is paragraphs
|
194
158
|
|
195
|
-
```ruby
|
196
|
-
USAGE = "a cmd! b c"
|
197
|
-
|
198
|
-
args = ShellOpts.process(USAGE, ARGV) { |opt, arg|
|
199
|
-
case opt
|
200
|
-
when '-a'; # Handle -a
|
201
|
-
when 'cmd'
|
202
|
-
arg.each { |opt, arg|
|
203
|
-
case opt
|
204
|
-
when '-b'; # Handle -b
|
205
|
-
when '-c'; # Handle -c
|
206
|
-
end
|
207
|
-
}
|
208
|
-
end
|
209
|
-
}
|
210
159
|
```
|
160
|
+
-a,alpha @ Brief comment for -a and --alpha options
|
161
|
+
Longer description of the option that is used by `::help`
|
211
162
|
|
212
|
-
|
163
|
+
cmd!
|
164
|
+
@ Alternative style of brief comment
|
213
165
|
|
214
|
-
|
215
|
-
|
216
|
-
can be grouped so that `-abc` is the same as `-a -b -c`. Long options are
|
217
|
-
prefixed with a `--` and can't be grouped
|
166
|
+
Longer description of the command
|
167
|
+
```
|
218
168
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
mandatory arguments but use `=` to separate the option from optional arguments:
|
223
|
-
`--file=/path/to/file`
|
169
|
+
Text starting with '--' follow by a blank character is a free-text description
|
170
|
+
of the command-line arguments. It is not parsed but used in documentation and
|
171
|
+
error messages:
|
224
172
|
|
225
|
-
|
173
|
+
```ruby
|
174
|
+
SPEC = "-a cmd! -- ARG1 ARG2"
|
226
175
|
```
|
227
|
-
f= # -farg or -f arg
|
228
|
-
f=? # -farg
|
229
176
|
|
230
|
-
|
231
|
-
file=? # --file=arg
|
232
|
-
```
|
177
|
+
## Options
|
233
178
|
|
234
|
-
|
179
|
+
The general syntax for options is
|
235
180
|
|
236
|
-
|
237
|
-
|
181
|
+
```
|
182
|
+
<prefix><optionlist>[=argspec][?]
|
183
|
+
```
|
238
184
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
newer version of `ShellOpts` or file a bug-report
|
185
|
+
The option list is a comma-separated list of option names. It is prefixed with
|
186
|
+
a '-' if the option list starts with a short option name and '--' if the option
|
187
|
+
list starts with a long name. '-' and '--' can be replaced with '+' or '++' to
|
188
|
+
indicate that the option can be repeated
|
244
189
|
|
245
|
-
|
190
|
+
```
|
191
|
+
-a,alpha @ -a and --alpha
|
192
|
+
++beta @ --beta, can be repeated
|
193
|
+
--gamma=ARG? @ --gamma, takes an optional argument
|
194
|
+
```
|
246
195
|
|
247
|
-
#### Error handling methods
|
248
196
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
program with status 1.
|
197
|
+
An option argument has a name and a type. The type can be specified as '#'
|
198
|
+
(integer), '$' (float), or as a comma-separated list of allowed values. It can
|
199
|
+
also be defined by a keyword that expects a file or directory argument:
|
253
200
|
|
254
|
-
|
255
|
-
|
201
|
+
| Keyword | Type |
|
202
|
+
| --------- | ---- |
|
203
|
+
| FILE | A file if present or in an existing directory if not |
|
204
|
+
| DIR | A directory if present or in an existing directory if not |
|
205
|
+
| PATH | Either a FILE or DIR |
|
206
|
+
| EFILE | An existing file |
|
207
|
+
| EDIR | An existing directory |
|
208
|
+
| EPATH | Either an EFILE or EDIR |
|
209
|
+
| NFILE | A new file |
|
210
|
+
| NDIR | A new directory |
|
211
|
+
| NPATH | A new file or directory |
|
256
212
|
|
257
|
-
|
258
|
-
<PROGRAM>: <MESSAGE>
|
259
|
-
Usage: <PROGRAM> <USAGE>
|
260
|
-
```
|
261
|
-
The usage string is a prettyfied version of the usage definition given to
|
262
|
-
ShellOpts
|
213
|
+
By default the option name is inferred from the type but it can be specified explicitly by separating it from the type with a ':'. Examples:
|
263
214
|
|
264
|
-
`fail` is used to report that something is wrong with the assumptions about the
|
265
|
-
system (eg. disk full) and omits the usage summary
|
266
215
|
```
|
267
|
-
|
216
|
+
-a=# @ -a takes an integer argument
|
217
|
+
-b=MONEY:$ @ -b takes a float argument. Is shown as '-b=MONEY' in messages
|
218
|
+
-c=red,blue,green @ -c takes one of the listed words
|
219
|
+
-d=FILE @ Fails if file exists and is not a file
|
220
|
+
-d=EDIR @ Fails if directory doesn't exist or is not a directory
|
221
|
+
-d=INPUT:EFILE @ Takes and existing file. Shown as '-d=INPUT' in messages
|
268
222
|
```
|
269
223
|
|
270
|
-
|
271
|
-
class methods on `ShellOpts`. They can also be included in the global scope by
|
272
|
-
`include ShellOpts::Utils`
|
224
|
+
## Commands
|
273
225
|
|
274
|
-
|
226
|
+
Commands are specified as lines starting with the name of the command
|
227
|
+
immediately followed by a '!' like `cmd!`. Commands can have options and even
|
228
|
+
subcommands of their own, in the multi-line format they're indented under the
|
229
|
+
command line like this
|
275
230
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
231
|
+
```
|
232
|
+
-a @ Program level option
|
233
|
+
cmd!
|
234
|
+
-b @ Command level option
|
235
|
+
subcmd!
|
236
|
+
-c @ Sub-command level option
|
237
|
+
```
|
280
238
|
|
281
|
-
|
239
|
+
In single-line format, subcommands are specified by prefixing the supercommand's name:
|
282
240
|
|
283
|
-
USAGE="long-and-complex-usage-string"
|
284
|
-
ShellOpts.usage = <<~EOD
|
285
|
-
usage explanation
|
286
|
-
split over
|
287
|
-
multiple lines
|
288
|
-
EOD
|
289
241
|
```
|
290
|
-
|
291
|
-
|
292
|
-
object-level `ShellOpts::ShellOpts#error` method. This is considered a bug and
|
293
|
-
will fixed at some point
|
242
|
+
-a cmd! -b cmd.subcmd! -c
|
243
|
+
```
|
294
244
|
|
295
245
|
## Example
|
296
246
|
|
297
|
-
The rm(1) command could be
|
247
|
+
The rm(1) command could be specified like this:
|
248
|
+
|
298
249
|
```ruby
|
299
250
|
|
300
251
|
require 'shellopts'
|
301
252
|
|
302
253
|
# Define options
|
303
|
-
|
304
|
-
f,force
|
305
|
-
|
306
|
-
v,verbose help version
|
307
|
-
}
|
308
|
-
|
309
|
-
# Define defaults
|
310
|
-
force = false
|
311
|
-
prompt = false
|
312
|
-
prompt_once = false
|
313
|
-
interactive = false
|
314
|
-
interactive_when = nil
|
315
|
-
recursive = false
|
316
|
-
remove_empty_dirs = false
|
317
|
-
one_file_system = false
|
318
|
-
preserve_root = true
|
319
|
-
verbose = false
|
320
|
-
|
321
|
-
# Process command line
|
322
|
-
args = ShellOpts.process(USAGE, ARGV) { |opt, arg|
|
323
|
-
case opt
|
324
|
-
when '-f', '--force'; force = true
|
325
|
-
when '-i'; prompt = true
|
326
|
-
when '-I'; prompt_once = true
|
327
|
-
when '--interactive'; interactive = true; interactive_when = arg
|
328
|
-
when '-r', '-R', '--recursive'; recursive = true
|
329
|
-
when '-d', '--dir'; remove_empty_dirs = true
|
330
|
-
when '--one-file-system'; one_file_system = true
|
331
|
-
when '--preserve-root'; preserve_root = true
|
332
|
-
when '--no-preserve-root'; preserve_root = false
|
333
|
-
when '--verbose'; verbose = true
|
334
|
-
when '--help'; print_help; exit
|
335
|
-
when '--version'; puts VERSION; exit
|
336
|
-
end
|
337
|
-
end
|
254
|
+
SPEC = %(
|
255
|
+
-f,force @ ignore nonexisten files and arguments, never prompt
|
256
|
+
-i @ prompt before every removal
|
338
257
|
|
339
|
-
|
340
|
-
|
341
|
-
|
258
|
+
-I
|
259
|
+
@ prompt once
|
260
|
+
|
261
|
+
prompt once before removing more than three files, or when removing
|
262
|
+
recursively; less intrusive than -i, while still giving protection
|
263
|
+
against most mistakes
|
264
|
+
|
265
|
+
--interactive=WHEN:never,once,always
|
266
|
+
@ prompt according to WHEN
|
342
267
|
|
268
|
+
prompt according to WHEN: never, once (-I), or always (-i); without WHEN, prompt always
|
269
|
+
|
270
|
+
--one-file-system
|
271
|
+
@ stay on fuile system
|
272
|
+
|
273
|
+
when removing a hierarchy recursively, skip any directory that is on a file system different from
|
274
|
+
that of the corresponding command line argument
|
275
|
+
|
276
|
+
--no-preserve-root @ do not treat '/' specially
|
277
|
+
--preserve-root @ do not remove '/' (default)
|
278
|
+
-r,R,recursive @ remove directories and their contents recursively
|
279
|
+
-d,dir @ remove empty directories
|
280
|
+
-v,verbose @ explain what is being done
|
281
|
+
--help @ display this help and exit
|
282
|
+
--version @ output version information and exit
|
283
|
+
|
284
|
+
-- FILE...
|
285
|
+
)
|
286
|
+
```
|
343
287
|
|
344
288
|
## See also
|
345
289
|
|
@@ -378,16 +322,6 @@ release a new version, update the version number in `version.rb`, and then run
|
|
378
322
|
git commits and tags, and push the `.gem` file to
|
379
323
|
[rubygems.org](https://rubygems.org).
|
380
324
|
|
381
|
-
## Implementation
|
382
|
-
|
383
|
-
FIXME
|
384
|
-
# ShellOpts is a library for parsing command line options and commands. It
|
385
|
-
# consists of the interface module {ShellOpts}, the implementation class
|
386
|
-
# {ShellOpts::ShellOpts} and the representation classes
|
387
|
-
# {ShellOpts::OptionsHash} and {ShellOpts::OptionsStruct}.
|
388
|
-
# {ShellOpts::Messenger} is used for error messages
|
389
|
-
|
390
|
-
|
391
325
|
## Contributing
|
392
326
|
|
393
327
|
Bug reports and pull requests are welcome on GitHub at
|
data/TODO
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
-
|
2
|
-
o '
|
3
|
-
o
|
4
|
-
o
|
5
|
-
|
1
|
+
|
2
|
+
o Ignore all text after ' # ' (doesn't conflict with option flag)
|
3
|
+
o Command aliases
|
4
|
+
o Add user-defined setions
|
5
|
+
o Add a SOURCE section with link to git repo
|
6
|
+
o Bullet-lists
|
7
|
+
o Allow a USAGE section (and NAME)
|
8
|
+
o Find source in code an adjust line number in error messages
|
9
|
+
o Rename line and char to lineno and charno
|
10
|
+
o Client-defined argument types
|
11
|
+
o Rename Expr -> ?
|
12
|
+
o Find clean(er) procedural object model
|
13
|
+
o Allow assignment to options (this makes practical stuff easier)
|
6
14
|
o Special handling of --help arguments so that '--help command' is possible
|
7
15
|
o Support for paging of help:
|
8
16
|
begin
|
@@ -14,3 +22,27 @@ o Support for paging of help:
|
|
14
22
|
file.close
|
15
23
|
end
|
16
24
|
|
25
|
+
+ Bold text output
|
26
|
+
+ Recursive format of commands
|
27
|
+
+ Rename Compiler -> Interpreter
|
28
|
+
|
29
|
+
|
30
|
+
OLD
|
31
|
+
|
32
|
+
o Fix that it is near unsable when the user doesn't do 'include ShellOpts'
|
33
|
+
o Subcommands can be parsed as well:
|
34
|
+
opts, args = Shellopts.process(OPTIONS, ARGV)
|
35
|
+
...
|
36
|
+
opts, command = opts.process
|
37
|
+
case command
|
38
|
+
when ...
|
39
|
+
end
|
40
|
+
o 'help' should list commands in declaration order
|
41
|
+
o 'help' should use all levels by default
|
42
|
+
o 'help' should always include top-level options (try setting levels: 10 and
|
43
|
+
see top-level options are gone
|
44
|
+
o A ShellOpts#shift command that makes it possible for Array#expect to emit
|
45
|
+
relevant error messages
|
46
|
+
|
47
|
+
+ Somehow escape comments where a line starts with an option name
|
48
|
+
+ Parse and check enumeration arguments ('--debug=tokens|ast|idr|...')
|