shellopts 2.4.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53f85a46df1cf2280e591fbf996781c73e3ddb3dfe88ede023f6ef29f26995a4
4
- data.tar.gz: 0ffb37c5f3843e92676004994600687dec0db89afccd20dea984998692e160a8
3
+ metadata.gz: 93dc09edd7bd318c85134a93f7c45352f4b2e550663c1a80a029d4fcb1d8ab16
4
+ data.tar.gz: c9e0b523c15f372d5dd988d2fd804c01539e90f0ee02ef68d284b4a1340e7c9c
5
5
  SHA512:
6
- metadata.gz: e67de152c69ae86557ec6898e7b0402d4188b8ca57a53128cfd7b3521655e80aadbc6114bcf943101f1a4012216604703dba54ae2a6921019d228b0b343b1837
7
- data.tar.gz: bfe12de981b2504514cd42c81f64511d01fe7948d1d8a563b2f34473d30fa8cd7e5cc22f550e9e81bd3a31ff3da863adbc60dd33ffd9fed53ea69d0bc8907a62
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 | Either a FILE or DIR |
204
+ | PATH | FILE or DIR |
206
205
  | EFILE | An existing file |
207
206
  | EDIR | An existing directory |
208
- | EPATH | Either an EFILE or EDIR |
207
+ | EPATH | EFILE or EDIR |
209
208
  | NFILE | A new file |
210
209
  | NDIR | A new directory |
211
- | NPATH | A new file or directory |
210
+ | NPATH | NFILE or NDIR |
211
+
212
212
 
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:
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
@@ -63,7 +63,8 @@ module ShellOpts
63
63
  def subject # Used in error messages
64
64
  @subject ||=
65
65
  case kind
66
- when :file, :efile, :nfile, :ifile, :ofile; "file"
66
+ when :file, :efile; "regular file"
67
+ when :nfile, :ifile, :ofile; "file"
67
68
  when :dir, :edir, :ndir; "directory"
68
69
  when :path, :epath, :npath; "path"
69
70
  else
@@ -81,19 +82,18 @@ module ShellOpts
81
82
  if literal == '-' && [:ifile, :ofile].include?(kind)
82
83
  true
83
84
 
84
- # 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
85
87
  elsif %w(/dev/stdin /dev/stdout /dev/stderr /dev/null).include?(literal)
86
88
  case kind
87
89
  when :file, :path, :efile, :epath, :nfile, :npath
88
90
  true
89
91
  when :ifile
90
- %w(/dev/stdin /dev/null).include? literal or
91
- set_message "Can't read #{literal}"
92
+ %w(/dev/stdin /dev/null).include? literal or set_message "Can't read #{literal}"
92
93
  when :ofile
93
- %w(/dev/stdout /dev/stderr /dev/null).include?(literal) or
94
- 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}"
95
95
  when :dir, :edir, :ndir
96
- set_message "Expected file, got directory #{literal}"
96
+ set_message "#{literal} is not a directory"
97
97
  else
98
98
  raise ArgumentError, "Unhandled kind: #{kind.inspect}"
99
99
  end
@@ -139,44 +139,47 @@ module ShellOpts
139
139
 
140
140
  protected
141
141
  def match_path(name, literal, kind, method, mode)
142
- # file exists and is the rigth type?
142
+ # file exists and the method returned true
143
143
  if File.send(method, literal)
144
144
  if mode == :new
145
- set_message "#{subject.capitalize} already exists in #{name}: #{literal}"
145
+ set_message "Won't overwrite #{literal}"
146
146
  elsif kind == :path || kind == :epath
147
147
  if File.file?(literal) || File.directory?(literal)
148
148
  true
149
149
  else
150
- set_message "Expected file or directory as #{name} argument: #{literal}"
150
+ set_message "#{literal} is not a file or a directory"
151
151
  end
152
152
  elsif (kind == :ifile || kind == :ofile) && File.directory?(literal)
153
- set_message "File expected, got directory: #{literal}"
153
+ set_message "#{literal} is not a device file"
154
154
  else
155
155
  true
156
156
  end
157
157
 
158
- # file exists but not the right type?
158
+ # file exists but the method returned false
159
159
  elsif File.exist?(literal)
160
160
  if kind == :ifile
161
161
  set_message "Can't read #{literal}"
162
162
  elsif kind == :ofile
163
163
  set_message "Can't write to #{literal}"
164
164
  elsif mode == :new
165
- set_message "#{subject.capitalize} already exists - #{literal}"
165
+ set_message "Won't overwrite #{literal}"
166
166
  else
167
- set_message "Expected #{subject} as #{name} argument: #{literal}"
167
+ set_message "#{literal} is not a #{subject}"
168
168
  end
169
169
 
170
170
  # file does not exist
171
171
  else
172
172
  if [:default, :new].include? mode
173
- if File.exist?(File.dirname(literal)) || kind == :ofile
174
- true
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}"
175
178
  else
176
- set_message "Illegal path in #{name}: #{literal}"
179
+ true
177
180
  end
178
181
  else
179
- set_message "Can't find #{subject} #{literal}"
182
+ set_message "Can't find #{literal}"
180
183
  end
181
184
  end
182
185
  end
@@ -185,7 +188,7 @@ module ShellOpts
185
188
  class EnumArgument < ArgumentType
186
189
  attr_reader :values
187
190
  def initialize(values) @values = values.dup end
188
- def match?(name, literal) value?(literal) or set_message "Illegal value in #{name}: '#{literal}'" end
191
+ def match?(name, literal) value?(literal) or set_message "Illegal value - #{literal}" end
189
192
  def value?(value) @values.include?(value) end
190
193
  end
191
194
  end
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.4.1"
2
+ VERSION = "2.4.2"
3
3
  end
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.1
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-02-10 00:00:00.000000000 Z
11
+ date: 2024-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forward_to