shellopts 2.0.10 → 2.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ext/array.rb +3 -1
- data/lib/shellopts/formatter.rb +34 -51
- data/lib/shellopts/program.rb +16 -3
- data/lib/shellopts/version.rb +1 -1
- data/lib/shellopts.rb +22 -13
- 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: 8dd7a731b489dbf650e15549d9768469ae9d6c47c6dba3ae79f4d956fea069ab
|
4
|
+
data.tar.gz: 4b71aff7ba350d4616a136580857a6acd840141ed0b7463034518dcf4ae4dada
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb5792606dd91f46b95fe786b509fd079697c87fd603c667e49740b365cafafa0cdc7b49a0a86c72cd014f9c2d88cdf74f096422e6099403042d8c34d35044b3
|
7
|
+
data.tar.gz: d7f2637649b474741b70dd9334e25107586fe52eb4e4f9a289453699f334488fed60322a676ad20fcab2f0c993785ccdef89be4397055028e75d79795766b972
|
data/lib/ext/array.rb
CHANGED
@@ -41,7 +41,9 @@ module Ext
|
|
41
41
|
|
42
42
|
module Wrap
|
43
43
|
refine ::Array do
|
44
|
-
# Concatenate
|
44
|
+
# Concatenate array of words into lines that are at most +width+
|
45
|
+
# characters wide. +curr+ is the initial number of characters already
|
46
|
+
# used on the first line
|
45
47
|
def wrap(width, curr = 0)
|
46
48
|
lines = [[]]
|
47
49
|
curr -= 1 # Simplifies conditions below
|
data/lib/shellopts/formatter.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
1
|
require 'terminfo'
|
2
2
|
|
3
|
-
# TODO: Move to ext/indented_io.rb
|
4
|
-
module IndentedIO
|
5
|
-
class IndentedIO
|
6
|
-
def margin() combined_indent.size end
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
3
|
module ShellOpts
|
11
4
|
module Grammar
|
12
5
|
class Node
|
@@ -216,7 +209,10 @@ module ShellOpts
|
|
216
209
|
BRIEF_COL1_MAX_WIDTH = 40
|
217
210
|
|
218
211
|
# Minimum width of second column in brief option and command lists
|
219
|
-
|
212
|
+
BRIEF_COL2_MIN_WIDTH = 30
|
213
|
+
|
214
|
+
# Maximum width of second column in brief option and command lists
|
215
|
+
BRIEF_COL2_MAX_WIDTH = 70
|
220
216
|
|
221
217
|
# Indent to use in help output
|
222
218
|
HELP_INDENT = 4
|
@@ -226,29 +222,21 @@ module ShellOpts
|
|
226
222
|
|
227
223
|
# Usage string in error messages
|
228
224
|
def self.usage(subject)
|
229
|
-
|
230
|
-
@command_prefix =
|
225
|
+
command = Grammar::Command.command(subject)
|
226
|
+
@command_prefix = command.ancestors.map { |node| node.name + " " }.join
|
231
227
|
setup_indent(1) {
|
232
228
|
print lead = "#{USAGE_STRING}: "
|
233
|
-
indent(lead.size, ' ', bol: false) {
|
229
|
+
indent(lead.size, ' ', bol: false) { command.puts_usage }
|
234
230
|
}
|
235
231
|
end
|
236
232
|
|
237
|
-
# # TODO
|
238
|
-
# def self.usage=(usage_lambda)
|
239
|
-
# end
|
240
|
-
|
241
233
|
# When the user gives a -h option
|
242
|
-
def self.brief(
|
243
|
-
command = Grammar::Command.command(
|
234
|
+
def self.brief(subject)
|
235
|
+
command = Grammar::Command.command(subject)
|
244
236
|
@command_prefix = command.ancestors.map { |node| node.name + " " }.join
|
245
237
|
setup_indent(BRIEF_INDENT) { command.puts_brief }
|
246
238
|
end
|
247
239
|
|
248
|
-
# # TODO
|
249
|
-
# def self.brief=(brief_lambda)
|
250
|
-
# end
|
251
|
-
|
252
240
|
# When the user gives a --help option
|
253
241
|
def self.help(subject)
|
254
242
|
subject = Grammar::Command.command(subject)
|
@@ -262,18 +250,6 @@ module ShellOpts
|
|
262
250
|
obj.is_a?(Grammar::Command) ? obj : obj.__grammar__
|
263
251
|
end
|
264
252
|
|
265
|
-
# # TODO
|
266
|
-
# def self.help_w_lambda(program)
|
267
|
-
# if @help_lambda
|
268
|
-
# #
|
269
|
-
# else
|
270
|
-
# program = Grammar::Command.command(program)
|
271
|
-
# setup_indent(HELP_INDENT) { program.puts_descr }
|
272
|
-
# end
|
273
|
-
# end
|
274
|
-
#
|
275
|
-
# def self.help=(help_lambda) @help_lambda end
|
276
|
-
|
277
253
|
def self.puts_columns(widths, fields)
|
278
254
|
l = []
|
279
255
|
first_width, second_width = *widths
|
@@ -284,40 +260,47 @@ module ShellOpts
|
|
284
260
|
puts first
|
285
261
|
indent(first_width + BRIEF_COL_SEP, ' ') { puts second.wrap(second_width) } if second
|
286
262
|
elsif second
|
287
|
-
|
288
|
-
|
263
|
+
indent_size = first_width + BRIEF_COL_SEP
|
264
|
+
printf "%-#{indent_size}s", first
|
265
|
+
indent(indent_size, ' ', bol: false) { puts second.wrap(second_width) }
|
289
266
|
else
|
290
267
|
puts first
|
291
268
|
end
|
292
269
|
end
|
293
270
|
end
|
294
271
|
|
272
|
+
# Returns a tuple of [first-column-width, second-column-width]. +width+ is
|
273
|
+
# the maximum width of the colunms and the BRIEF_COL_SEP separator.
|
274
|
+
# +fields+ is an array of [subject-string, descr-text] tuples where the
|
275
|
+
# descr is an array of words
|
295
276
|
def self.compute_columns(width, fields)
|
296
|
-
first_max =
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
first_width = first_max
|
307
|
-
second_width = width - first_width - BRIEF_COL_SEP
|
277
|
+
first_max =
|
278
|
+
fields.map { |first, _| first.size }.select { |size| size <= BRIEF_COL1_MAX_WIDTH }.max ||
|
279
|
+
BRIEF_COL1_MIN_WIDTH
|
280
|
+
second_max = fields.map { |_, second| second ? second&.map(&:size).sum + second.size - 1 : 0 }.max
|
281
|
+
first_width = [[first_max, BRIEF_COL1_MIN_WIDTH].max, BRIEF_COL1_MAX_WIDTH].min
|
282
|
+
rest = width - first_width - BRIEF_COL_SEP
|
283
|
+
second_min = [BRIEF_COL2_MIN_WIDTH, second_max].min
|
284
|
+
if rest < second_min
|
285
|
+
first_width = [first_max, width - second_min - BRIEF_COL_SEP].max
|
286
|
+
second_width = [width - first_width - BRIEF_COL_SEP, BRIEF_COL2_MIN_WIDTH].max
|
308
287
|
else
|
309
|
-
|
310
|
-
second_width = BRIEF_COL2_MAX_WIDTH
|
288
|
+
second_width = [[rest, BRIEF_COL2_MIN_WIDTH].max, BRIEF_COL2_MAX_WIDTH].min
|
311
289
|
end
|
312
|
-
|
313
290
|
[first_width, second_width]
|
314
291
|
end
|
315
292
|
|
316
293
|
def self.width()
|
317
294
|
@width ||= TermInfo.screen_width - MARGIN_RIGHT
|
295
|
+
@width
|
296
|
+
end
|
297
|
+
|
298
|
+
# Used in rspec
|
299
|
+
def self.width=(width)
|
300
|
+
@width = width
|
318
301
|
end
|
319
302
|
|
320
|
-
def self.rest() width - $stdout.
|
303
|
+
def self.rest() width - $stdout.tab end
|
321
304
|
|
322
305
|
private
|
323
306
|
# TODO Get rid of?
|
data/lib/shellopts/program.rb
CHANGED
@@ -45,12 +45,12 @@ module ShellOpts
|
|
45
45
|
|
46
46
|
# These names can't be used as option or command names
|
47
47
|
RESERVED_OPTION_NAMES = %w(
|
48
|
-
is_a instance_eval instance_exec method_missing singleton_method_added
|
48
|
+
is_a to_h instance_eval instance_exec method_missing singleton_method_added
|
49
49
|
singleton_method_removed singleton_method_undefined
|
50
50
|
)
|
51
51
|
|
52
|
-
# These methods can be overridden by an option or a command (
|
53
|
-
#
|
52
|
+
# These methods can be overridden by an option or a command (this constant
|
53
|
+
# is not used - it is just for informational purposes)
|
54
54
|
OVERRIDEABLE_METHOD_NAMES = %w(
|
55
55
|
subcommand subcommand! supercommand!
|
56
56
|
)
|
@@ -96,6 +96,19 @@ module ShellOpts
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
99
|
+
# Returns a hash of the given options if defined. Returns all options if no
|
100
|
+
# options are given
|
101
|
+
def to_h(*keys)
|
102
|
+
keys = ::Kernel::Array(keys).flatten
|
103
|
+
if keys.empty?
|
104
|
+
@__option_values__
|
105
|
+
else
|
106
|
+
keys.map { |key|
|
107
|
+
@__option_values__.key?(key) ? [key, @__option_values__[key]] : nil
|
108
|
+
}.compact.to_h
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
99
112
|
# Subcommand identifier or nil if not present. #subcommand is often used in
|
100
113
|
# case statement to branch out to code that handles the given subcommand:
|
101
114
|
#
|
data/lib/shellopts/version.rb
CHANGED
data/lib/shellopts.rb
CHANGED
@@ -192,23 +192,23 @@ module ShellOpts
|
|
192
192
|
#
|
193
193
|
# #error is supposed to be used when the user made an error and the usage
|
194
194
|
# is written to help correcting the error
|
195
|
-
#
|
196
195
|
def error(subject = nil, message)
|
197
|
-
saved = $stdout
|
198
|
-
$stdout = $stderr
|
199
196
|
$stderr.puts "#{name}: #{message}"
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
197
|
+
saved = $stdout
|
198
|
+
begin
|
199
|
+
$stdout = $stderr
|
200
|
+
Formatter.usage(grammar)
|
201
|
+
exit 1
|
202
|
+
ensure
|
203
|
+
$stdout = saved
|
204
|
+
end
|
204
205
|
end
|
205
206
|
|
206
207
|
# Write error message to standard error and terminate program with status 1
|
207
208
|
#
|
208
|
-
# #failure
|
209
|
-
#
|
210
|
-
#
|
211
|
-
#
|
209
|
+
# #failure doesn't print the program usage because is supposed to be used
|
210
|
+
# when the user specified the correct arguments but something else went
|
211
|
+
# wrong during processing
|
212
212
|
def failure(message)
|
213
213
|
$stderr.puts "#{name}: #{message}"
|
214
214
|
exit 1
|
@@ -222,7 +222,6 @@ module ShellOpts
|
|
222
222
|
|
223
223
|
# Print help for the given subject or the full documentation if +subject+
|
224
224
|
# is nil. Clears the screen beforehand if :clear is true
|
225
|
-
#
|
226
225
|
def help(subject = nil, clear: true)
|
227
226
|
node = (subject ? @grammar[subject] : @grammar) or
|
228
227
|
raise ArgumentError, "No such command: '#{subject&.sub(".", " ")}'"
|
@@ -333,7 +332,17 @@ module ShellOpts
|
|
333
332
|
def self.instance=(instance) @instance = instance end
|
334
333
|
def self.shellopts() instance end
|
335
334
|
|
336
|
-
|
335
|
+
def self.error(subject = nil, message)
|
336
|
+
instance.error(subject, message) if instance? # Never returns
|
337
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{message}"
|
338
|
+
exit 1
|
339
|
+
end
|
340
|
+
|
341
|
+
def self.failure(message)
|
342
|
+
instance.failure(message) if instance?
|
343
|
+
$stderr.puts "#{File.basename($PROGRAM_NAME)}: #{message}"
|
344
|
+
exit 1
|
345
|
+
end
|
337
346
|
|
338
347
|
# The Include module brings the reporting methods into the namespace when
|
339
348
|
# included
|
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.0.
|
4
|
+
version: 2.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-03
|
11
|
+
date: 2022-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: forward_to
|