shellopts 2.0.19 → 2.0.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35b9e7b5699cc1a5637d4c00dd95c74047074f1227b0d05f9a9c8b04e1e2cc8b
4
- data.tar.gz: c8deed23c8e6f0b26d080e15d2830edb5e65d1b5f2f821ccd83db7db27d7aefd
3
+ metadata.gz: d3f9f19d62ccf36d5de39421163eb70e7aa8ae621cee13381d48ce68e7ab593d
4
+ data.tar.gz: 13351ee8dceceea7c5da573de7c5bd257aa2efd1c4690be760f6ebe1445ca8c9
5
5
  SHA512:
6
- metadata.gz: 5d3e96ec825ca58c0e653613ab84e2ede3e661737f5699571c81aaf9b2cb1252ea802581e5b981a1757d8a5a750ba998c43730c6d2da7d8228b721b06a45640e
7
- data.tar.gz: e64eeac4c3bf784f8ef3a5e3a61c596e262bd23c4ee05857f76138f82ff2180afb72ccd5c2b7ffedc4e6aa2887b10c76e3a80c33e24ceadd20e71513549b5bf0
6
+ metadata.gz: 4afd636e92e1ff74b45c77399d4dbaba6afaccd441ee528800a727ed5e4db802d481d8dcaaddcd46bdbcd7c28f3b121b35e42b63e44f02d006c557eafda29692
7
+ data.tar.gz: 7c12cd6d9f0dede5c7931cf82b8e1ff32d4de738c2d3dd42fb5c2f65740ed0804078eb65ca0b951ce28a1095fd9b43289df01501275a5f9c178a965e569aa054
data/TODO CHANGED
@@ -1,3 +1,19 @@
1
+
2
+ o Make opts[] point at the main object
3
+ opts[].subcommand is the direct subcommand of main
4
+ o Make opts be the aggrated set of options in a subcommand
5
+ opts.subcommand is the concatenated path of subcommands
6
+ o Make opts[:some_command] be the set of options for that subcommand (already done)
7
+ o Sub-command options can overshadow options of outer commands but it is an
8
+ error to access them using opts. Use opts[] or opts[:some_command] instead
9
+
10
+ o Add a default argument to extract:
11
+ def extract(range, *defaults)
12
+ end
13
+
14
+ extract(3..4, 'dbo')
15
+
16
+ o More strict parsing of option and command lines
1
17
  o --option can't be escaped if on the start of a block line?
2
18
  o Use require_relative
3
19
  o In the following list is a command with a mandatory sub-command
@@ -30,8 +30,8 @@ module ShellOpts
30
30
  class Command
31
31
  using Ext::Array::Wrap
32
32
 
33
- def puts_usage(bol: false)
34
- width = [Formatter.rest, Formatter::USAGE_MAX_WIDTH].min
33
+ def puts_usage(bol: false, max_width: Formatter::USAGE_MAX_WIDTH)
34
+ width = [Formatter.rest, max_width].min
35
35
  if descrs.size == 0
36
36
  print (lead = Formatter.command_prefix || "")
37
37
  indent(lead.size, ' ', bol: bol && lead == "") {
@@ -41,7 +41,7 @@ module ShellOpts
41
41
  lead = Formatter.command_prefix || ""
42
42
  descrs.each { |descr|
43
43
  print lead
44
- puts render(:single, width, args: [descr.text])
44
+ puts render(:multi, width, args: descr.text.split(' '))
45
45
  }
46
46
  end
47
47
  end
@@ -58,7 +58,7 @@ module ShellOpts
58
58
  end
59
59
 
60
60
  puts "Usage"
61
- indent { puts_usage(bol: true) }
61
+ indent { puts_usage(bol: true, max_width: Formatter::HELP_MAX_WIDTH) }
62
62
 
63
63
  if options.any?
64
64
  puts
@@ -112,14 +112,13 @@ module ShellOpts
112
112
  puts
113
113
 
114
114
  puts Ansi.bold "USAGE"
115
- indent { puts_usage(bol: true) }
115
+ indent { puts_usage(bol: true, max_width: Formatter::HELP_MAX_WIDTH) }
116
116
 
117
117
  section = {
118
118
  Paragraph => "DESCRIPTION",
119
119
  OptionGroup => "OPTION",
120
120
  Command => "COMMAND"
121
121
  }
122
-
123
122
  seen_sections = {}
124
123
  newline = false # True if a newline should be printed before child
125
124
  indent {
@@ -173,7 +172,10 @@ module ShellOpts
173
172
  end
174
173
 
175
174
  module WrappedNode
176
- def puts_descr(width = Formatter.rest) puts lines(width) end
175
+ def puts_descr
176
+ width = [Formatter.rest, Formatter::HELP_MAX_WIDTH].min
177
+ puts lines(width)
178
+ end
177
179
  end
178
180
 
179
181
  class Code
@@ -217,6 +219,9 @@ module ShellOpts
217
219
  # Indent to use in help output
218
220
  HELP_INDENT = 4
219
221
 
222
+ # Max. width of help text (not including indent)
223
+ HELP_MAX_WIDTH = 85
224
+
220
225
  # Command prefix when subject is a sub-command
221
226
  def self.command_prefix() @command_prefix end
222
227
 
@@ -84,19 +84,27 @@ module ShellOpts
84
84
  }
85
85
  end
86
86
 
87
- # Returns a hash of the given options if defined. Returns all options if no
88
- # options are given
87
+ # Returns a hash from option ident to value
88
+ #
89
+ # The value depends on the option type: If it is not repeatable, the value
90
+ # is the argument or nil if not present (or allowed). If the option is
91
+ # repeatable and has an argument, the value is an array of the arguments,
92
+ # if it doesn't have an argument, the value is the number of occurrences
93
+ #
89
94
  def to_h(*keys)
90
95
  keys = ::Kernel::Array(keys).flatten
91
- if keys.empty?
92
- self.to_h(@__grammar__.options.map(&:ident))
93
- else
94
- keys.map { |key|
95
- self.__send__("#{key}?".to_sym) ? [key, self.__send__(key)] : nil
96
- }.compact.to_h
97
- end
96
+ __option_values__.select { |key,_| keys.empty? || keys.include?(key) }
98
97
  end
99
98
 
99
+ # Like #to_h but present options without arguments have a true value
100
+ #
101
+ def to_h?(*keys)
102
+ keys = ::Kernel::Array(keys).flatten
103
+ keys = keys.empty? ? __option_values__.keys : keys
104
+ keys.filter_map { |key| __option_values__.key?(key) && [key, self.__send__(key)] }.to_h
105
+ end
106
+
107
+
100
108
  # Subcommand identifier or nil if not present. #subcommand is often used in
101
109
  # case statement to branch out to code that handles the given subcommand:
102
110
  #
@@ -15,9 +15,9 @@ require 'terminfo'
15
15
  #
16
16
  # Command rendering
17
17
  # cmd --all --beta [cmd1|cmd2] ARG1 ARG2 # Single-line formats (:single)
18
- # cmd --all --beta [cmd1|cmd2] ARGS...
18
+ # cmd --all --beta [cmd1|cmd2] ARGS... # Not used
19
19
  # cmd -a -b [cmd1|cmd2] ARG1 ARG2
20
- # cmd -a -b [cmd1|cmd2] ARGS...
20
+ # cmd -a -b [cmd1|cmd2] ARGS... # Not used
21
21
  #
22
22
  # cmd -a -b [cmd1|cmd2] ARG1 ARG2 # One line for each argument description (:enum)
23
23
  # cmd -a -b [cmd1|cmd2] ARG3 ARG4 # (used in the USAGE section)
@@ -108,7 +108,7 @@ module ShellOpts
108
108
  def get_args(args: nil)
109
109
  case descrs.size
110
110
  when 0; []
111
- when 1; [descrs.first.text]
111
+ when 1; descrs.first.text.split(' ')
112
112
  else [DESCRS_ABBR]
113
113
  end
114
114
  end
@@ -120,6 +120,7 @@ module ShellOpts
120
120
  end
121
121
 
122
122
  # Force one line. Compact options, commands, arguments if needed
123
+ #
123
124
  def render_single(width, args: nil)
124
125
  long_options = options.map { |option| option.render(:long) }
125
126
  short_options = options.map { |option| option.render(:short) }
@@ -164,32 +165,30 @@ module ShellOpts
164
165
  def render_multi(width, args: nil)
165
166
  long_options = options.map { |option| option.render(:long) }
166
167
  short_options = options.map { |option| option.render(:short) }
167
- short_commands = commands.empty? ? [] : ["[#{commands.map(&:name).join("|")}]"]
168
- compact_commands = [COMMANDS_ABBR]
168
+ compact_options = options.empty? ? [] : [OPTIONS_ABBR]
169
+
170
+ # Only compact commands if they can't fit on one line
171
+ if commands.empty?
172
+ use_commands = []
173
+ else
174
+ short_command = "[#{commands.map(&:name).join("|")}]"
175
+ use_commands = [short_command.size > width ? COMMANDS_ABBR : short_command]
176
+ end
169
177
 
170
178
  args ||= get_args
171
179
 
172
180
  # On one line
173
- words = [name] + long_options + short_commands + args
181
+ words = [name] + long_options + use_commands + args
174
182
  return [words.join(" ")] if pass?(words, width)
175
- words = [name] + short_options + short_commands + args
183
+ words = [name] + short_options + use_commands + args
184
+ return [words.join(" ")] if pass?(words, width)
185
+ words = [name] + compact_options + use_commands + args
176
186
  return [words.join(" ")] if pass?(words, width)
177
187
 
178
188
  # On multiple lines
179
189
  lead = name + " "
180
- options = long_options.wrap(width - lead.size)
181
- options = [lead + options[0]] + indent_lines(lead.size, options[1..-1])
182
-
183
- begin
184
- words = short_commands + args
185
- break if pass?(words, width)
186
- words = compact_commands + args
187
- break if pass?(words, width)
188
- words = compact_commands + [DESCRS_ABBR]
189
- end while false
190
-
191
- cmdargs = words.empty? ? [] : [words.join(" ")]
192
- options + indent_lines(lead.size, cmdargs)
190
+ words = (long_options + use_commands + args).wrap(width - lead.size)
191
+ lines = [lead + words[0]] + indent_lines(lead.size, words[1..-1])
193
192
  end
194
193
 
195
194
  protected
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.0.19"
2
+ VERSION = "2.0.22"
3
3
  end
data/lib/shellopts.rb CHANGED
@@ -382,7 +382,6 @@ module ShellOpts
382
382
  end
383
383
  end
384
384
 
385
-
386
385
  def self.process(spec, argv, quiet: nil, verbose: nil, debug: nil, **opts)
387
386
  constrain quiet, String, true, false, nil
388
387
  quiet = quiet.nil? ? Message.is_included? || Verbose.is_included? : quiet
@@ -410,8 +409,7 @@ module ShellOpts
410
409
  end
411
410
 
412
411
  def self.notice(message)
413
- $stderr.puts "#{instance.program.__grammar__.name}: #{message}" \
414
- if !instance.quiet || !instance.program.quiet?
412
+ $stderr.puts message if !instance.quiet || !instance.program.quiet?
415
413
  end
416
414
 
417
415
  def self.mesg(message)
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.19
4
+ version: 2.0.22
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-04-16 00:00:00.000000000 Z
11
+ date: 2022-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forward_to