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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 812078e64c677a6aff78081e25a04b81be3b3a1fe9496709838e2abb80573b4a
4
- data.tar.gz: 92c14741c409697f543820d656683b9552d4c6c7ce5c29b01a30677a174549c2
3
+ metadata.gz: 8dd7a731b489dbf650e15549d9768469ae9d6c47c6dba3ae79f4d956fea069ab
4
+ data.tar.gz: 4b71aff7ba350d4616a136580857a6acd840141ed0b7463034518dcf4ae4dada
5
5
  SHA512:
6
- metadata.gz: 3b1ac7453a534a50cf250e489688aa82ad1928220a615b9e4f7076c27b588d19a7b355e866f3e3cc789fd2259bb2e5de14ac92e905b7b033528c11be26564356
7
- data.tar.gz: d50433ec49a4bf67fd9947d2028ed81be9c8310e7410d93c691e2cd59ed36ef622937c861ef1f4608e7ef5869804cd0f1a4197abf03fd4c2d96cef4985d5dab4
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 strings into lines that are at most +width+ characters wide
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
@@ -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
- BRIEF_COL2_MAX_WIDTH = 50
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
- subject = Grammar::Command.command(subject)
230
- @command_prefix = subject.ancestors.map { |node| node.name + " " }.join
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) { subject.puts_usage }
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(command)
243
- command = Grammar::Command.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
- printf "%-#{first_width + BRIEF_COL_SEP}s", first
288
- indent(first_width, bol: false) { puts second.wrap(second_width) }
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
- (fields.map { |first, _| first.size } + [BRIEF_COL1_MIN_WIDTH]).max,
298
- BRIEF_COL1_MAX_WIDTH
299
- ].min
300
- second_max = fields.map { |_, second| second ? second&.map(&:size).sum + second.size - 1: 0 }.max
301
-
302
- if first_max + BRIEF_COL_SEP + second_max <= width
303
- first_width = first_max
304
- second_width = second_max
305
- elsif first_max + BRIEF_COL_SEP + BRIEF_COL2_MAX_WIDTH <= width
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
- first_width = [width - BRIEF_COL_SEP - BRIEF_COL2_MAX_WIDTH, BRIEF_COL1_MAX_WIDTH].min
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.margin end
303
+ def self.rest() width - $stdout.tab end
321
304
 
322
305
  private
323
306
  # TODO Get rid of?
@@ -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 (the value is not used -
53
- # this is just for informational purposes)
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
  #
@@ -1,3 +1,3 @@
1
1
  module ShellOpts
2
- VERSION = "2.0.10"
2
+ VERSION = "2.0.13"
3
3
  end
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
- Formatter.usage(grammar)
201
- exit 1
202
- ensure
203
- $stdout = saved
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 is supposed to be used the used specified the correct arguments
209
- # but something went wrong during processing. Since the used didn't cause
210
- # the problem, only the error message is written
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
- forward_self_to :instance, :error, :failure
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.10
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-08 00:00:00.000000000 Z
11
+ date: 2022-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forward_to