cli-ui 2.3.1 → 2.6.0
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/lib/cli/ui/ansi.rb +23 -27
- data/lib/cli/ui/color.rb +8 -13
- data/lib/cli/ui/formatter.rb +24 -23
- data/lib/cli/ui/frame/frame_stack.rb +9 -21
- data/lib/cli/ui/frame/frame_style/box.rb +11 -10
- data/lib/cli/ui/frame/frame_style/bracket.rb +11 -10
- data/lib/cli/ui/frame/frame_style.rb +31 -22
- data/lib/cli/ui/frame.rb +12 -43
- data/lib/cli/ui/glyph.rb +8 -14
- data/lib/cli/ui/os.rb +9 -10
- data/lib/cli/ui/printer.rb +1 -15
- data/lib/cli/ui/progress.rb +20 -23
- data/lib/cli/ui/progress_reporter.rb +209 -0
- data/lib/cli/ui/prompt/interactive_options.rb +85 -53
- data/lib/cli/ui/prompt/options_handler.rb +4 -6
- data/lib/cli/ui/prompt.rb +22 -45
- data/lib/cli/ui/spinner/async.rb +3 -7
- data/lib/cli/ui/spinner/spin_group.rb +205 -135
- data/lib/cli/ui/spinner.rb +3 -16
- data/lib/cli/ui/stdout_router.rb +38 -55
- data/lib/cli/ui/table.rb +3 -7
- data/lib/cli/ui/terminal.rb +4 -8
- data/lib/cli/ui/truncater.rb +5 -6
- data/lib/cli/ui/version.rb +1 -1
- data/lib/cli/ui/widgets/base.rb +13 -14
- data/lib/cli/ui/widgets/status.rb +10 -10
- data/lib/cli/ui/widgets.rb +7 -15
- data/lib/cli/ui/work_queue.rb +23 -27
- data/lib/cli/ui/wrap.rb +3 -5
- data/lib/cli/ui.rb +42 -97
- metadata +4 -7
- data/lib/cli/ui/sorbet_runtime_stub.rb +0 -169
data/lib/cli/ui/stdout_router.rb
CHANGED
@@ -9,15 +9,13 @@ module CLI
|
|
9
9
|
module UI
|
10
10
|
module StdoutRouter
|
11
11
|
class Writer
|
12
|
-
|
13
|
-
|
14
|
-
sig { params(stream: IOLike, name: Symbol).void }
|
12
|
+
#: (io_like stream, Symbol name) -> void
|
15
13
|
def initialize(stream, name)
|
16
14
|
@stream = stream
|
17
15
|
@name = name
|
18
16
|
end
|
19
17
|
|
20
|
-
|
18
|
+
#: (*Object args) -> Integer
|
21
19
|
def write(*args)
|
22
20
|
strs = args.map do |obj|
|
23
21
|
str = obj.to_s
|
@@ -36,10 +34,12 @@ module CLI
|
|
36
34
|
return 0 if hook.call(strs.join, @name) == false
|
37
35
|
end
|
38
36
|
|
39
|
-
|
37
|
+
stream_args = prepend_id(@stream, strs) #: as untyped
|
38
|
+
ret = @stream.write_without_cli_ui(*stream_args) #: as Integer
|
40
39
|
if (dup = StdoutRouter.duplicate_output_to)
|
41
40
|
begin
|
42
|
-
|
41
|
+
dup_args = prepend_id(dup, strs) #: as untyped
|
42
|
+
dup.write(*dup_args) #: as Integer
|
43
43
|
rescue IOError
|
44
44
|
# Ignore
|
45
45
|
end
|
@@ -49,7 +49,7 @@ module CLI
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
-
|
52
|
+
#: (io_like stream, Array[String] args) -> Array[String]
|
53
53
|
def prepend_id(stream, args)
|
54
54
|
return args unless prepend_id_for_stream(stream)
|
55
55
|
|
@@ -60,7 +60,7 @@ module CLI
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
|
63
|
+
#: (io_like stream) -> bool
|
64
64
|
def prepend_id_for_stream(stream)
|
65
65
|
return false unless Thread.current[:cliui_output_id]
|
66
66
|
return true if Thread.current[:cliui_output_id][:streams].include?(stream)
|
@@ -68,12 +68,12 @@ module CLI
|
|
68
68
|
false
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
#: -> bool
|
72
72
|
def auto_frame_inset?
|
73
73
|
!Thread.current[:no_cliui_frame_inset]
|
74
74
|
end
|
75
75
|
|
76
|
-
|
76
|
+
#: (String str, String prefix) -> String
|
77
77
|
def apply_line_prefix(str, prefix)
|
78
78
|
return '' if str.empty?
|
79
79
|
|
@@ -92,27 +92,23 @@ module CLI
|
|
92
92
|
end
|
93
93
|
|
94
94
|
class Capture
|
95
|
-
extend T::Sig
|
96
|
-
|
97
95
|
@capture_mutex = Mutex.new
|
98
96
|
@stdin_mutex = CLI::UI::ReentrantMutex.new
|
99
97
|
@active_captures = 0
|
100
98
|
@saved_stdin = nil
|
101
99
|
|
102
100
|
class << self
|
103
|
-
|
104
|
-
|
105
|
-
sig { returns(T.nilable(Capture)) }
|
101
|
+
#: -> Capture?
|
106
102
|
def current_capture
|
107
103
|
Thread.current[:cliui_current_capture]
|
108
104
|
end
|
109
105
|
|
110
|
-
|
106
|
+
#: -> Capture
|
111
107
|
def current_capture!
|
112
|
-
|
108
|
+
current_capture #: as !nil
|
113
109
|
end
|
114
110
|
|
115
|
-
|
111
|
+
#: [T] { -> T } -> T
|
116
112
|
def in_alternate_screen(&block)
|
117
113
|
stdin_synchronize do
|
118
114
|
previous_print_captured_output = current_capture&.print_captured_output
|
@@ -139,7 +135,7 @@ module CLI
|
|
139
135
|
end
|
140
136
|
end
|
141
137
|
|
142
|
-
|
138
|
+
#: [T] { -> T } -> T
|
143
139
|
def stdin_synchronize(&block)
|
144
140
|
@stdin_mutex.synchronize do
|
145
141
|
case $stdin
|
@@ -153,7 +149,7 @@ module CLI
|
|
153
149
|
end
|
154
150
|
end
|
155
151
|
|
156
|
-
|
152
|
+
#: [T] { -> T } -> T
|
157
153
|
def with_stdin_masked(&block)
|
158
154
|
@capture_mutex.synchronize do
|
159
155
|
if @active_captures.zero?
|
@@ -179,20 +175,13 @@ module CLI
|
|
179
175
|
|
180
176
|
private
|
181
177
|
|
182
|
-
|
178
|
+
#: -> bool
|
183
179
|
def outermost_uncaptured?
|
184
180
|
@stdin_mutex.count == 1 && $stdin.is_a?(BlockingInput)
|
185
181
|
end
|
186
182
|
end
|
187
183
|
|
188
|
-
|
189
|
-
params(
|
190
|
-
with_frame_inset: T::Boolean,
|
191
|
-
merged_output: T::Boolean,
|
192
|
-
duplicate_output_to: IO,
|
193
|
-
block: T.proc.void,
|
194
|
-
).void
|
195
|
-
end
|
184
|
+
#: (?with_frame_inset: bool, ?merged_output: bool, ?duplicate_output_to: IO) { -> void } -> void
|
196
185
|
def initialize(
|
197
186
|
with_frame_inset: true,
|
198
187
|
merged_output: false,
|
@@ -208,10 +197,10 @@ module CLI
|
|
208
197
|
@err = StringIO.new
|
209
198
|
end
|
210
199
|
|
211
|
-
|
200
|
+
#: bool
|
212
201
|
attr_accessor :print_captured_output
|
213
202
|
|
214
|
-
|
203
|
+
#: -> untyped
|
215
204
|
def run
|
216
205
|
require 'stringio'
|
217
206
|
|
@@ -249,26 +238,24 @@ module CLI
|
|
249
238
|
Thread.current[:cliui_current_capture] = nil
|
250
239
|
end
|
251
240
|
|
252
|
-
|
241
|
+
#: -> String
|
253
242
|
def stdout
|
254
243
|
@out.string
|
255
244
|
end
|
256
245
|
|
257
|
-
|
246
|
+
#: -> String
|
258
247
|
def stderr
|
259
248
|
@err.string
|
260
249
|
end
|
261
250
|
|
262
251
|
class BlockingInput
|
263
|
-
|
264
|
-
|
265
|
-
sig { params(stream: IO).void }
|
252
|
+
#: (IO stream) -> void
|
266
253
|
def initialize(stream)
|
267
254
|
@stream = stream
|
268
255
|
@m = CLI::UI::ReentrantMutex.new
|
269
256
|
end
|
270
257
|
|
271
|
-
|
258
|
+
#: [T] { -> T } -> T
|
272
259
|
def synchronize(&block)
|
273
260
|
@m.synchronize do
|
274
261
|
previous_allowed_to_read = Thread.current[:cliui_allowed_to_read]
|
@@ -317,43 +304,39 @@ module CLI
|
|
317
304
|
end
|
318
305
|
|
319
306
|
class << self
|
320
|
-
extend T::Sig
|
321
|
-
|
322
307
|
WRITE_WITHOUT_CLI_UI = :write_without_cli_ui
|
323
308
|
|
324
309
|
NotEnabled = Class.new(StandardError)
|
325
310
|
|
326
|
-
|
311
|
+
#: io_like?
|
327
312
|
attr_accessor :duplicate_output_to
|
328
313
|
|
329
|
-
|
330
|
-
type_parameters(:T)
|
331
|
-
.params(on_streams: T::Array[IOLike], block: T.proc.params(id: String).returns(T.type_parameter(:T)))
|
332
|
-
.returns(T.type_parameter(:T))
|
333
|
-
end
|
314
|
+
#: [T] (on_streams: Array[io_like]) { (String id) -> T } -> T
|
334
315
|
def with_id(on_streams:, &block)
|
335
316
|
require 'securerandom'
|
336
317
|
id = format('%05d', rand(10**5))
|
337
318
|
Thread.current[:cliui_output_id] = {
|
338
319
|
id: id,
|
339
|
-
streams: on_streams.map
|
320
|
+
streams: on_streams.map do |stream|
|
321
|
+
stream #: as io_like
|
322
|
+
end,
|
340
323
|
}
|
341
324
|
yield(id)
|
342
325
|
ensure
|
343
326
|
Thread.current[:cliui_output_id] = nil
|
344
327
|
end
|
345
328
|
|
346
|
-
|
329
|
+
#: -> Hash[Symbol, (String | io_like)]?
|
347
330
|
def current_id
|
348
331
|
Thread.current[:cliui_output_id]
|
349
332
|
end
|
350
333
|
|
351
|
-
|
334
|
+
#: -> void
|
352
335
|
def assert_enabled!
|
353
336
|
raise NotEnabled unless enabled?
|
354
337
|
end
|
355
338
|
|
356
|
-
|
339
|
+
#: [T] { -> T } -> T
|
357
340
|
def with_enabled(&block)
|
358
341
|
enable
|
359
342
|
yield
|
@@ -362,12 +345,12 @@ module CLI
|
|
362
345
|
end
|
363
346
|
|
364
347
|
# TODO: remove this
|
365
|
-
|
348
|
+
#: -> void
|
366
349
|
def ensure_activated
|
367
350
|
enable unless enabled?
|
368
351
|
end
|
369
352
|
|
370
|
-
|
353
|
+
#: -> bool
|
371
354
|
def enable
|
372
355
|
return false if enabled?($stdout) || enabled?($stderr)
|
373
356
|
|
@@ -376,12 +359,12 @@ module CLI
|
|
376
359
|
true
|
377
360
|
end
|
378
361
|
|
379
|
-
|
362
|
+
#: (?io_like stream) -> bool
|
380
363
|
def enabled?(stream = $stdout)
|
381
364
|
stream.respond_to?(WRITE_WITHOUT_CLI_UI)
|
382
365
|
end
|
383
366
|
|
384
|
-
|
367
|
+
#: -> bool
|
385
368
|
def disable
|
386
369
|
return false unless enabled?($stdout) && enabled?($stderr)
|
387
370
|
|
@@ -392,14 +375,14 @@ module CLI
|
|
392
375
|
|
393
376
|
private
|
394
377
|
|
395
|
-
|
378
|
+
#: (io_like stream) -> void
|
396
379
|
def deactivate(stream)
|
397
380
|
sc = stream.singleton_class
|
398
381
|
sc.send(:remove_method, :write)
|
399
382
|
sc.send(:alias_method, :write, WRITE_WITHOUT_CLI_UI)
|
400
383
|
end
|
401
384
|
|
402
|
-
|
385
|
+
#: (io_like stream, Symbol streamname) -> void
|
403
386
|
def activate(stream, streamname)
|
404
387
|
writer = StdoutRouter::Writer.new(stream, streamname)
|
405
388
|
|
data/lib/cli/ui/table.rb
CHANGED
@@ -3,11 +3,7 @@
|
|
3
3
|
module CLI
|
4
4
|
module UI
|
5
5
|
module Table
|
6
|
-
extend T::Sig
|
7
|
-
|
8
6
|
class << self
|
9
|
-
extend T::Sig
|
10
|
-
|
11
7
|
# Prints a formatted table to the specified output
|
12
8
|
# Automatically pads columns to align based on the longest cell in each column,
|
13
9
|
# ignoring the width of ANSI color codes.
|
@@ -35,7 +31,7 @@ module CLI
|
|
35
31
|
# really_long_cell short
|
36
32
|
# row2 row2
|
37
33
|
#
|
38
|
-
|
34
|
+
#: (Array[Array[String]] table, ?col_spacing: Integer, ?to: io_like) -> void
|
39
35
|
def puts_table(table, col_spacing: 1, to: $stdout)
|
40
36
|
col_sizes = table.transpose.map do |col|
|
41
37
|
col.map { |cell| CLI::UI::ANSI.printing_width(CLI::UI.resolve_text(cell)) }.max
|
@@ -43,7 +39,7 @@ module CLI
|
|
43
39
|
|
44
40
|
table.each do |row|
|
45
41
|
padded_row = row.each_with_index.map do |cell, i|
|
46
|
-
col_size =
|
42
|
+
col_size = col_sizes[i] #: as !nil # guaranteed to be non-nil
|
47
43
|
cell_size = CLI::UI::ANSI.printing_width(CLI::UI.resolve_text(cell))
|
48
44
|
padded_cell = cell + ' ' * (col_size - cell_size)
|
49
45
|
padded_cell
|
@@ -75,7 +71,7 @@ module CLI
|
|
75
71
|
# ["row2", "row2"]
|
76
72
|
# ])
|
77
73
|
#
|
78
|
-
|
74
|
+
#: (Array[Array[String]] table, ?col_spacing: Integer) -> Array[String]
|
79
75
|
def capture_table(table, col_spacing: 1)
|
80
76
|
strio = StringIO.new
|
81
77
|
puts_table(table, col_spacing: col_spacing, to: strio)
|
data/lib/cli/ui/terminal.rb
CHANGED
@@ -7,18 +7,14 @@ require 'io/console'
|
|
7
7
|
module CLI
|
8
8
|
module UI
|
9
9
|
module Terminal
|
10
|
-
extend T::Sig
|
11
|
-
|
12
10
|
DEFAULT_WIDTH = 80
|
13
11
|
DEFAULT_HEIGHT = 24
|
14
12
|
|
15
13
|
class << self
|
16
|
-
extend T::Sig
|
17
|
-
|
18
14
|
# Returns the width of the terminal, if possible
|
19
15
|
# Otherwise will return DEFAULT_WIDTH
|
20
16
|
#
|
21
|
-
|
17
|
+
#: -> Integer
|
22
18
|
def width
|
23
19
|
winsize[1]
|
24
20
|
end
|
@@ -26,12 +22,12 @@ module CLI
|
|
26
22
|
# Returns the width of the terminal, if possible
|
27
23
|
# Otherwise, will return DEFAULT_HEIGHT
|
28
24
|
#
|
29
|
-
|
25
|
+
#: -> Integer
|
30
26
|
def height
|
31
27
|
winsize[0]
|
32
28
|
end
|
33
29
|
|
34
|
-
|
30
|
+
#: -> [Integer, Integer]
|
35
31
|
def winsize
|
36
32
|
@winsize ||= begin
|
37
33
|
winsize = IO.console.winsize
|
@@ -47,7 +43,7 @@ module CLI
|
|
47
43
|
end
|
48
44
|
end
|
49
45
|
|
50
|
-
|
46
|
+
#: -> void
|
51
47
|
def setup_winsize_trap
|
52
48
|
@winsize_trap ||= Signal.trap('WINCH') do
|
53
49
|
@winsize = nil
|
data/lib/cli/ui/truncater.rb
CHANGED
@@ -28,15 +28,13 @@ module CLI
|
|
28
28
|
TRUNCATED = "\x1b[0m…"
|
29
29
|
|
30
30
|
class << self
|
31
|
-
|
32
|
-
|
33
|
-
sig { params(text: String, printing_width: Integer).returns(String) }
|
31
|
+
#: (String text, Integer printing_width) -> String
|
34
32
|
def call(text, printing_width)
|
35
33
|
return text if text.size <= printing_width
|
36
34
|
|
37
35
|
width = 0
|
38
36
|
mode = PARSE_ROOT
|
39
|
-
truncation_index =
|
37
|
+
truncation_index = nil #: Integer?
|
40
38
|
|
41
39
|
codepoints = text.codepoints
|
42
40
|
codepoints.each.with_index do |cp, index|
|
@@ -87,12 +85,13 @@ module CLI
|
|
87
85
|
# the end of the string.
|
88
86
|
return text if !truncation_index || width <= printing_width
|
89
87
|
|
90
|
-
|
88
|
+
slice = codepoints[0...truncation_index] #: as !nil
|
89
|
+
slice.pack('U*') + TRUNCATED
|
91
90
|
end
|
92
91
|
|
93
92
|
private
|
94
93
|
|
95
|
-
|
94
|
+
#: (Integer printable_codepoint) -> Integer
|
96
95
|
def width(printable_codepoint)
|
97
96
|
case printable_codepoint
|
98
97
|
when EMOJI_RANGE
|
data/lib/cli/ui/version.rb
CHANGED
data/lib/cli/ui/widgets/base.rb
CHANGED
@@ -6,21 +6,16 @@ require('cli/ui')
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
module Widgets
|
9
|
+
# @abstract
|
9
10
|
class Base
|
10
|
-
extend T::Sig
|
11
|
-
extend T::Helpers
|
12
|
-
abstract!
|
13
|
-
|
14
11
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { params(argstring: String).returns(String) }
|
12
|
+
#: (String argstring) -> String
|
18
13
|
def call(argstring)
|
19
14
|
new(argstring).render
|
20
15
|
end
|
21
16
|
end
|
22
17
|
|
23
|
-
|
18
|
+
#: (String argstring) -> void
|
24
19
|
def initialize(argstring)
|
25
20
|
pat = self.class.argparse_pattern
|
26
21
|
unless (@match_data = pat.match(argstring))
|
@@ -33,14 +28,18 @@ module CLI
|
|
33
28
|
end
|
34
29
|
|
35
30
|
class << self
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
31
|
+
# @abstract
|
32
|
+
#: -> Regexp
|
33
|
+
def argparse_pattern
|
34
|
+
raise(NotImplementedError)
|
35
|
+
end
|
40
36
|
end
|
41
37
|
|
42
|
-
|
43
|
-
|
38
|
+
# @abstract
|
39
|
+
#: -> String
|
40
|
+
def render
|
41
|
+
raise(NotImplementedError)
|
42
|
+
end
|
44
43
|
end
|
45
44
|
end
|
46
45
|
end
|
@@ -22,15 +22,15 @@ module CLI
|
|
22
22
|
EMPTY_SET = '∅'
|
23
23
|
|
24
24
|
class << self
|
25
|
-
|
26
|
-
|
27
|
-
sig { override.returns(Regexp) }
|
25
|
+
# @override
|
26
|
+
#: -> Regexp
|
28
27
|
def argparse_pattern
|
29
28
|
ARGPARSE_PATTERN
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
|
32
|
+
# @override
|
33
|
+
#: -> String
|
34
34
|
def render
|
35
35
|
if zero?(@succeeded) && zero?(@failed) && zero?(@working) && zero?(@pending)
|
36
36
|
Color::RESET.code + Color::BOLD.code + EMPTY_SET + Color::RESET.code
|
@@ -42,34 +42,34 @@ module CLI
|
|
42
42
|
|
43
43
|
private
|
44
44
|
|
45
|
-
|
45
|
+
#: (String num_str) -> bool
|
46
46
|
def zero?(num_str)
|
47
47
|
num_str == '0'
|
48
48
|
end
|
49
49
|
|
50
|
-
|
50
|
+
#: (String num_str, String rune, Color color) -> String
|
51
51
|
def colorize_if_nonzero(num_str, rune, color)
|
52
52
|
color = Color::GRAY if zero?(num_str)
|
53
53
|
color.code + num_str + rune
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
#: -> String
|
57
57
|
def succeeded_part
|
58
58
|
colorize_if_nonzero(@succeeded, Glyph::CHECK.char, Color::GREEN)
|
59
59
|
end
|
60
60
|
|
61
|
-
|
61
|
+
#: -> String
|
62
62
|
def failed_part
|
63
63
|
colorize_if_nonzero(@failed, Glyph::X.char, Color::RED)
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
#: -> String
|
67
67
|
def working_part
|
68
68
|
rune = zero?(@working) ? SPINNER_STOPPED : Spinner.current_rune
|
69
69
|
colorize_if_nonzero(@working, rune, Color::BLUE)
|
70
70
|
end
|
71
71
|
|
72
|
-
|
72
|
+
#: -> String
|
73
73
|
def pending_part
|
74
74
|
colorize_if_nonzero(@pending, Glyph::HOURGLASS.char, Color::WHITE)
|
75
75
|
end
|
data/lib/cli/ui/widgets.rb
CHANGED
@@ -19,17 +19,13 @@ module CLI
|
|
19
19
|
# CLI::UI::Widgets.register('my-widget') { MyWidget }
|
20
20
|
# puts(CLI::UI.fmt("{{@widget/my-widget:args}}"))
|
21
21
|
module Widgets
|
22
|
-
extend T::Sig
|
23
|
-
|
24
22
|
MAP = {}
|
25
23
|
|
26
24
|
autoload(:Base, 'cli/ui/widgets/base')
|
27
25
|
autoload(:Status, 'cli/ui/widgets/status')
|
28
26
|
|
29
27
|
class << self
|
30
|
-
|
31
|
-
|
32
|
-
sig { params(name: String, cb: T.proc.returns(T.class_of(Widgets::Base))).void }
|
28
|
+
#: (String name) { -> singleton(Widgets::Base) } -> void
|
33
29
|
def register(name, &cb)
|
34
30
|
MAP[name] = cb
|
35
31
|
end
|
@@ -42,7 +38,7 @@ module CLI
|
|
42
38
|
# ==== Returns
|
43
39
|
# A callable widget, to be invoked like `.call(argstring)`
|
44
40
|
#
|
45
|
-
|
41
|
+
#: (String handle) -> singleton(Widgets::Base)
|
46
42
|
def lookup(handle)
|
47
43
|
MAP.fetch(handle).call
|
48
44
|
rescue KeyError, NameError
|
@@ -51,7 +47,7 @@ module CLI
|
|
51
47
|
|
52
48
|
# All available widgets by name
|
53
49
|
#
|
54
|
-
|
50
|
+
#: -> Array[String]
|
55
51
|
def available
|
56
52
|
MAP.keys
|
57
53
|
end
|
@@ -60,15 +56,13 @@ module CLI
|
|
60
56
|
register('status') { Widgets::Status }
|
61
57
|
|
62
58
|
class InvalidWidgetHandle < ArgumentError
|
63
|
-
|
64
|
-
|
65
|
-
sig { params(handle: String).void }
|
59
|
+
#: (String handle) -> void
|
66
60
|
def initialize(handle)
|
67
61
|
super
|
68
62
|
@handle = handle
|
69
63
|
end
|
70
64
|
|
71
|
-
|
65
|
+
#: -> String
|
72
66
|
def message
|
73
67
|
keys = Widgets.available.join(',')
|
74
68
|
"invalid widget handle: #{@handle} " \
|
@@ -77,16 +71,14 @@ module CLI
|
|
77
71
|
end
|
78
72
|
|
79
73
|
class InvalidWidgetArguments < ArgumentError
|
80
|
-
|
81
|
-
|
82
|
-
sig { params(argstring: String, pattern: Regexp).void }
|
74
|
+
#: (String argstring, Regexp pattern) -> void
|
83
75
|
def initialize(argstring, pattern)
|
84
76
|
super(nil)
|
85
77
|
@argstring = argstring
|
86
78
|
@pattern = pattern
|
87
79
|
end
|
88
80
|
|
89
|
-
|
81
|
+
#: -> String
|
90
82
|
def message
|
91
83
|
"invalid widget arguments: #{@argstring} " \
|
92
84
|
"-- must match pattern: #{@pattern.inspect}"
|