shellopts 2.4.0 → 2.4.2
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/README.md +7 -6
- data/TODO +10 -0
- data/lib/shellopts/argument_type.rb +32 -27
- data/lib/shellopts/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 93dc09edd7bd318c85134a93f7c45352f4b2e550663c1a80a029d4fcb1d8ab16
|
|
4
|
+
data.tar.gz: c9e0b523c15f372d5dd988d2fd804c01539e90f0ee02ef68d284b4a1340e7c9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 520132f149801fb6d2bb8e325e38cdb6bf81a01c9d881f88165b02550dfae4a0f95706bcbd558e34b2232015b327c87f779cbf2cdef6d0355640db6e87acaaea
|
|
7
|
+
data.tar.gz: 7a26fe6f1a8501f9a52103224ea4cdfa2d95441e6253af6ecfcb71f09f8f57c84bae7734079fa5ab1c47756f859ac0eaddbac3c350ce1d8a6b845be011ecedc3
|
data/README.md
CHANGED
|
@@ -193,7 +193,6 @@ indicate that the option can be repeated
|
|
|
193
193
|
--gamma=ARG? @ --gamma, takes an optional argument
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
-
|
|
197
196
|
An option argument has a name and a type. The type can be specified as '#'
|
|
198
197
|
(integer), '$' (float), or as a comma-separated list of allowed values. It can
|
|
199
198
|
also be defined by a keyword that expects a file or directory argument:
|
|
@@ -202,15 +201,17 @@ also be defined by a keyword that expects a file or directory argument:
|
|
|
202
201
|
| --------- | ---- |
|
|
203
202
|
| FILE | A file if present or in an existing directory if not |
|
|
204
203
|
| DIR | A directory if present or in an existing directory if not |
|
|
205
|
-
| PATH |
|
|
204
|
+
| PATH | FILE or DIR |
|
|
206
205
|
| EFILE | An existing file |
|
|
207
206
|
| EDIR | An existing directory |
|
|
208
|
-
| EPATH |
|
|
207
|
+
| EPATH | EFILE or EDIR |
|
|
209
208
|
| NFILE | A new file |
|
|
210
209
|
| NDIR | A new directory |
|
|
211
|
-
| NPATH |
|
|
210
|
+
| NPATH | NFILE or NDIR |
|
|
211
|
+
|
|
212
212
|
|
|
213
|
-
By default the option name is inferred from the type but it can be specified
|
|
213
|
+
By default the option name is inferred from the type but it can be specified
|
|
214
|
+
explicitly by separating it from the type with a ':'. Examples:
|
|
214
215
|
|
|
215
216
|
```
|
|
216
217
|
-a=# @ -a takes an integer argument
|
|
@@ -244,7 +245,7 @@ In single-line format, subcommands are specified by prefixing the supercommand's
|
|
|
244
245
|
|
|
245
246
|
## Example
|
|
246
247
|
|
|
247
|
-
The rm(1) command could be specified like this:
|
|
248
|
+
The standard rm(1) command could be specified like this:
|
|
248
249
|
|
|
249
250
|
```ruby
|
|
250
251
|
|
data/TODO
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
|
|
2
|
+
o Remove IFILE and OFILE. Alternatively document them
|
|
3
|
+
o Document special-case file argument '-'
|
|
4
|
+
o Accept both strings and symbols for commands (maybe... ruins the global namespace in #[])
|
|
5
|
+
o ShellOpts#command -> Full path. Eg. ':command.subcommand!'
|
|
6
|
+
ShellOpts#commands -> Array of commands. Eg. [:command!, :subcommand!]
|
|
7
|
+
o Exclude -h, -v, and -q from short description and only include them in the
|
|
8
|
+
detailed option description
|
|
9
|
+
o Output handling: mesg, verb, ... should record eols. error and failure should
|
|
10
|
+
use that to end the current line with a newline if necessary
|
|
11
|
+
o Strings from ShellOpts are frozen. Is that what we want?
|
|
2
12
|
o Assigner methods for options
|
|
3
13
|
o Make opts[] point at the main object
|
|
4
14
|
opts[].subcommand is the direct subcommand of main
|
|
@@ -26,7 +26,7 @@ module ShellOpts
|
|
|
26
26
|
def to_s() name end
|
|
27
27
|
|
|
28
28
|
protected
|
|
29
|
-
# it is important that #set_message return false
|
|
29
|
+
# Note that it is important that #set_message return false
|
|
30
30
|
def set_message(msg)
|
|
31
31
|
@message = msg
|
|
32
32
|
false
|
|
@@ -60,6 +60,18 @@ module ShellOpts
|
|
|
60
60
|
class FileArgument < ArgumentType
|
|
61
61
|
attr_reader :kind
|
|
62
62
|
|
|
63
|
+
def subject # Used in error messages
|
|
64
|
+
@subject ||=
|
|
65
|
+
case kind
|
|
66
|
+
when :file, :efile; "regular file"
|
|
67
|
+
when :nfile, :ifile, :ofile; "file"
|
|
68
|
+
when :dir, :edir, :ndir; "directory"
|
|
69
|
+
when :path, :epath, :npath; "path"
|
|
70
|
+
else
|
|
71
|
+
raise ArgumentError
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
63
75
|
def initialize(kind)
|
|
64
76
|
constrain kind, :file, :dir, :path, :efile, :edir, :epath, :nfile, :ndir, :npath, :ifile, :ofile
|
|
65
77
|
@kind = kind
|
|
@@ -70,19 +82,18 @@ module ShellOpts
|
|
|
70
82
|
if literal == '-' && [:ifile, :ofile].include?(kind)
|
|
71
83
|
true
|
|
72
84
|
|
|
73
|
-
# Special-case standard I/O files
|
|
85
|
+
# Special-case standard I/O files. These files have read-write (rw)
|
|
86
|
+
# filesystem permissions so they need to be handled individually
|
|
74
87
|
elsif %w(/dev/stdin /dev/stdout /dev/stderr /dev/null).include?(literal)
|
|
75
88
|
case kind
|
|
76
89
|
when :file, :path, :efile, :epath, :nfile, :npath
|
|
77
90
|
true
|
|
78
91
|
when :ifile
|
|
79
|
-
%w(/dev/stdin /dev/null).include? literal or
|
|
80
|
-
set_message "Can't read #{literal}"
|
|
92
|
+
%w(/dev/stdin /dev/null).include? literal or set_message "Can't read #{literal}"
|
|
81
93
|
when :ofile
|
|
82
|
-
%w(/dev/stdout /dev/stderr /dev/null).include?(literal) or
|
|
83
|
-
set_message "Can't write to #{literal}"
|
|
94
|
+
%w(/dev/stdout /dev/stderr /dev/null).include?(literal) or set_message "Can't write to #{literal}"
|
|
84
95
|
when :dir, :edir, :ndir
|
|
85
|
-
set_message "
|
|
96
|
+
set_message "#{literal} is not a directory"
|
|
86
97
|
else
|
|
87
98
|
raise ArgumentError, "Unhandled kind: #{kind.inspect}"
|
|
88
99
|
end
|
|
@@ -128,50 +139,44 @@ module ShellOpts
|
|
|
128
139
|
|
|
129
140
|
protected
|
|
130
141
|
def match_path(name, literal, kind, method, mode)
|
|
131
|
-
|
|
132
|
-
case kind
|
|
133
|
-
when :file, :efile, :nfile, :ifile, :ofile; "file"
|
|
134
|
-
when :dir, :edir, :ndir; "directory"
|
|
135
|
-
when :path, :epath, :npath; "path"
|
|
136
|
-
else
|
|
137
|
-
raise ArgumentError
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# file exists and is the rigth type?
|
|
142
|
+
# file exists and the method returned true
|
|
141
143
|
if File.send(method, literal)
|
|
142
144
|
if mode == :new
|
|
143
|
-
set_message "
|
|
145
|
+
set_message "Won't overwrite #{literal}"
|
|
144
146
|
elsif kind == :path || kind == :epath
|
|
145
147
|
if File.file?(literal) || File.directory?(literal)
|
|
146
148
|
true
|
|
147
149
|
else
|
|
148
|
-
set_message "
|
|
150
|
+
set_message "#{literal} is not a file or a directory"
|
|
149
151
|
end
|
|
150
152
|
elsif (kind == :ifile || kind == :ofile) && File.directory?(literal)
|
|
151
|
-
set_message "
|
|
153
|
+
set_message "#{literal} is not a device file"
|
|
152
154
|
else
|
|
153
155
|
true
|
|
154
156
|
end
|
|
155
157
|
|
|
156
|
-
# file exists but
|
|
158
|
+
# file exists but the method returned false
|
|
157
159
|
elsif File.exist?(literal)
|
|
158
160
|
if kind == :ifile
|
|
159
161
|
set_message "Can't read #{literal}"
|
|
160
162
|
elsif kind == :ofile
|
|
161
163
|
set_message "Can't write to #{literal}"
|
|
162
164
|
elsif mode == :new
|
|
163
|
-
set_message "
|
|
165
|
+
set_message "Won't overwrite #{literal}"
|
|
164
166
|
else
|
|
165
|
-
set_message "
|
|
167
|
+
set_message "#{literal} is not a #{subject}"
|
|
166
168
|
end
|
|
167
169
|
|
|
168
170
|
# file does not exist
|
|
169
171
|
else
|
|
170
172
|
if [:default, :new].include? mode
|
|
171
|
-
|
|
172
|
-
|
|
173
|
+
dir = File.dirname(literal)
|
|
174
|
+
if !File.directory?(dir)
|
|
175
|
+
set_message "Illegal path - #{literal}"
|
|
176
|
+
elsif !File.writable?(dir)
|
|
177
|
+
set_message "Can't create #{subject} #{literal}"
|
|
173
178
|
else
|
|
174
|
-
|
|
179
|
+
true
|
|
175
180
|
end
|
|
176
181
|
else
|
|
177
182
|
set_message "Can't find #{literal}"
|
|
@@ -183,7 +188,7 @@ module ShellOpts
|
|
|
183
188
|
class EnumArgument < ArgumentType
|
|
184
189
|
attr_reader :values
|
|
185
190
|
def initialize(values) @values = values.dup end
|
|
186
|
-
def match?(name, literal) value?(literal) or set_message "Illegal value
|
|
191
|
+
def match?(name, literal) value?(literal) or set_message "Illegal value - #{literal}" end
|
|
187
192
|
def value?(value) @values.include?(value) end
|
|
188
193
|
end
|
|
189
194
|
end
|
data/lib/shellopts/version.rb
CHANGED
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: 2.4.
|
|
4
|
+
version: 2.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Claus Rasmussen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-03-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: forward_to
|