shellopts 2.0.0.pre.13 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.ruby-version +1 -1
  4. data/README.md +201 -267
  5. data/TODO +46 -134
  6. data/doc/format.rb +95 -0
  7. data/doc/grammar.txt +27 -0
  8. data/doc/syntax.rb +110 -0
  9. data/doc/syntax.txt +10 -0
  10. data/lib/ext/array.rb +58 -5
  11. data/lib/ext/forward_to.rb +15 -0
  12. data/lib/ext/lcs.rb +34 -0
  13. data/lib/shellopts/analyzer.rb +130 -0
  14. data/lib/shellopts/ansi.rb +8 -0
  15. data/lib/shellopts/args.rb +29 -21
  16. data/lib/shellopts/argument_type.rb +139 -0
  17. data/lib/shellopts/dump.rb +158 -0
  18. data/lib/shellopts/formatter.rb +325 -0
  19. data/lib/shellopts/grammar.rb +375 -0
  20. data/lib/shellopts/interpreter.rb +103 -0
  21. data/lib/shellopts/lexer.rb +175 -0
  22. data/lib/shellopts/parser.rb +269 -82
  23. data/lib/shellopts/program.rb +279 -0
  24. data/lib/shellopts/renderer.rb +227 -0
  25. data/lib/shellopts/stack.rb +7 -0
  26. data/lib/shellopts/token.rb +44 -0
  27. data/lib/shellopts/version.rb +2 -2
  28. data/lib/shellopts.rb +439 -220
  29. data/main +1180 -0
  30. data/shellopts.gemspec +9 -15
  31. metadata +85 -42
  32. data/lib/main.rb +0 -1
  33. data/lib/shellopts/ast/command.rb +0 -41
  34. data/lib/shellopts/ast/node.rb +0 -37
  35. data/lib/shellopts/ast/option.rb +0 -21
  36. data/lib/shellopts/ast/program.rb +0 -14
  37. data/lib/shellopts/compiler.rb +0 -128
  38. data/lib/shellopts/generator.rb +0 -15
  39. data/lib/shellopts/grammar/command.rb +0 -80
  40. data/lib/shellopts/grammar/node.rb +0 -33
  41. data/lib/shellopts/grammar/option.rb +0 -66
  42. data/lib/shellopts/grammar/program.rb +0 -65
  43. data/lib/shellopts/idr.rb +0 -236
  44. data/lib/shellopts/main.rb +0 -10
  45. data/lib/shellopts/option_struct.rb +0 -148
  46. data/lib/shellopts/shellopts.rb +0 -123
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ac8ce6815e283630cb66195b0069a0d1772d8234dd580833e49b38cb0717fe8
4
- data.tar.gz: e6fc6e96d47db9078edad643ce9ee4fabdeaf3450a5ab61fd330b701bfadf244
3
+ metadata.gz: 4f5448df8e0fdd882072ab927e185511b09ebd8b594a9556937fdfd20d41070d
4
+ data.tar.gz: 2743f77e88de6ff10562a2f7d3980b1bfc730d0e024e60e6472da48342a2f153
5
5
  SHA512:
6
- metadata.gz: f77988efda7870d95b7693125e0e4b9753dbbe637cfc126d92559654bd171f17f37698ac7588ce9d3fc0521ba00156b862e763f1ae95190d77d89cc5e500bf5a
7
- data.tar.gz: 98d96929cd577649796e5f699e3c748f7ef3c72cb8ad3dd6036d2e656bae15229a414263a3701a4a027daacb869de2ceb52b1d3095fd1715c064d6befbaedbd0
6
+ metadata.gz: 9e08795c96b4f745a00cb6c38e5ea63beef08ceb640a0427d4bc46ee705189cab188a227a9d1775177d6530596155744d6e8624fa378c87c47f94c36e1adf98b
7
+ data.tar.gz: cb12f16c665fe6fc0e0751ad2328aa7d8e1e48baad9d9d27addb4d88f6a083d780c61ee0b8b57e8218ee829a6e107afa8c076067dfa5d24a973bf353489d7433
data/.gitignore CHANGED
@@ -1,7 +1,6 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /_yardoc/
4
- /doc/
5
4
  /rdoc/
6
5
  /pkg/
7
6
  /spec/reports/
@@ -27,3 +26,5 @@ tt.*
27
26
  s
28
27
  s.*
29
28
 
29
+ # Ignore temporary directory
30
+ /spec/tmpdir/
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.6.6
1
+ ruby-2.7.1
data/README.md CHANGED
@@ -1,345 +1,289 @@
1
1
  # Shellopts
2
2
 
3
- `ShellOpts` is a simple Linux command line parsing libray that covers most modern use
4
- cases incl. sub-commands. Options and commands are specified using a
5
- getopt(1)-like string that is interpreted by the library to process the command
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
- The following program accepts the options -a or --all, --count, --file, and -v
11
- or --verbose. It expects `--count` to have an optional integer argument,
12
- `--file` to have a mandatory argument, and allows `-v` and `--verbose` to be
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
- If there is an error in the command line options, the program will exit with
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
- ## Processing
18
+ opts, args = ShellOpts.process(SPEC, ARGV)
51
19
 
52
- `ShellOpts.process` compiles a usage definition string into a grammar and use
53
- that to parse the command line. If given a block, the block is called with a
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
- ## Usage string
28
+ ShellOpts also allow multi-line definitions with comments that are used as part
29
+ of help messages
82
30
 
83
- A usage string, typically named `USAGE`, is a list of option and command
84
- definitions separated by whitespace. It can span multiple lines. A double
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
- The general [syntax](https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form) is
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
- ```EBNF
91
- options { command options } [ "--" anything ]
41
+ opts, args = ShellOpts.process(SPEC, ARGV)
42
+ ShellOpts::ShellOpts.brief
92
43
  ```
93
44
 
94
- ## Options
45
+ prints
95
46
 
96
- An option is defined by a list of comma-separated names optionally prefixed by a
97
- `+` and/or followed by a `=` and a set of flags. The syntax is
47
+ ```
48
+ Usage
49
+ main --alpha --beta=VAL ARG1 ARG2
98
50
 
99
- ```EBNF
100
- [ "+" ] name-list [ "=" [ "#" | "$" ] [ label ] [ "?" ] ]
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
- #### Flags
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
- There are the following flags:
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
- |Flag|Effect|
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
- #### Repeated options
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
- Options are unique by default and the user will get an error if an option is
118
- used more than once. You can tell the parser to allow several instances of the
119
- same option by prefixing the option names with a `+`. A typical use case is to
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
- verbosity_level = 0
76
+ # Returns true if the option is present and false otherwise
77
+ opts.alpha?()
78
+ opts.beta?()
126
79
 
127
- args = ShellOpts.process(USAGE, ARGV) do |opt, arg|
128
- case opt
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
- #### Option names
84
+ Given the commands "cmd1! cmd2!" the following methods are available:
136
85
 
137
- Option names are a comma-separated list of names. Names can consist of one or more
138
- ASCII letters (a-zA-Z), digits, underscores ('\_') and dashes ('-'). A name
139
- can't start with a dash, though
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
- Names that are one character long are considered 'short options' and are
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
- Examples:
147
- ```
148
- a # -a
149
- all # --all
150
- a,all # -a or --all
151
- r,R,recursive # -r, -R, or --recursive
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
- #### Option argument
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
- An option that takes an an argument is declared with a `=` after the name list.
157
- By default the type of an option is a `String` but a integer argument can be
158
- specified by the `#` flag and a float argument by the `$` flag.
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
- You can label a option value that will be used in help texts and error
161
- messages. A usage string like `file=FILE` will be displayed as `--file=FILE`
162
- and `file=FILE?` like `--file[=FILE]`. If no label is given, `INT` will be used
163
- for integer arguments, `FLOAT` for floating point, and else `ARG`
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
- Arguments are mandatory by default but can be made optional by suffixing a `?`
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
- ## Commands
134
+ ```ruby
135
+ SPEC = "--var=VAR"
136
+ opts, args = ShellOpts.process(SPEC, ARGV)
168
137
 
169
- Sub-commands (like `git clone`) are defined by a name (or a dot-separated list
170
- of names) followed by an exclamation mark. All options following a command are
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
- Examples
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
- #### Command processing
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
- Commands are treated like options but with a value that is an array of options (and
193
- sub-commands) to the command:
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
- ## Parsing
163
+ cmd!
164
+ @ Alternative style of brief comment
213
165
 
214
- Parsing of the command line follows the UNIX traditions for short and long
215
- options. Short options are one letter long and prefixed by a `-`. Short options
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
- Mandatory arguments to short options can be separated by a whitespace (`-f
220
- /path/to/file`) but optional arguments needs to come immediately after the
221
- option: `-f/path/to/file`. Long options also allow a space separator for
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
- Examples
173
+ ```ruby
174
+ SPEC = "-a cmd! -- ARG1 ARG2"
226
175
  ```
227
- f= # -farg or -f arg
228
- f=? # -farg
229
176
 
230
- file= # --file=arg or --file arg
231
- file=? # --file=arg
232
- ```
177
+ ## Options
233
178
 
234
- #### Error handling
179
+ The general syntax for options is
235
180
 
236
- If the command line is invalid, it's a user error and the program exits with
237
- status 1 and prints an error message on STDERR
181
+ ```
182
+ <prefix><optionlist>[=argspec][?]
183
+ ```
238
184
 
239
- If there is an error in the usage string, ShellOpts raises a
240
- `ShellOpts::CompileError`. Note that this exception signals an error by the
241
- application developer and shouldn't be catched. If there is an internal error
242
- in the library, a ShellOpts::InternalError is raised and you should look for a
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
- All ShellOpt exceptions derive from ShellOpt::Error
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
- ShellOpts provides two methods that can be used by the application to
250
- generate error messages in the style of ShellOpts: `ShellOpts.error` and
251
- `ShellOpts.fail`. Both write an error message on STDERR and terminates the
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
- `error` is intended to respond to user errors (like giving a file name that
255
- doesn't exist) and prints a short usage summary to remind the user:
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
- <PROGRAM>: <MESSAGE>
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
- The methods are defined as instance methods on `ShellOpts::ShellOpts` and as
271
- class methods on `ShellOpts`. They can also be included in the global scope by
272
- `include ShellOpts::Utils`
224
+ ## Commands
273
225
 
274
- #### Usage string
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
- The error handling methods prints a prettified version of the usage string
277
- given to `ShellOpts.parse`. The usage string can be overridden by assigning to
278
- `ShellOpts.usage`. A typical use case is when you want to split the usage
279
- description over multiple lines:
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
- ```ruby
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
- Note that this only affects the module-level `ShellOpts.error` method and not
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 implemented like this
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
- USAGE = %{
304
- f,force i I interactive=WHEN? r,R,recusive d,dir
305
- one-file-system no-preserve-root preserve-root
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
- # Remaining arguments are files or directories
340
- files = args
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