cli-ui 2.4.0 → 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 +7 -13
- data/lib/cli/ui/formatter.rb +23 -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 +6 -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 +46 -54
- 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 +3 -3
- data/lib/cli/ui/sorbet_runtime_stub.rb +0 -168
@@ -6,11 +6,9 @@ require 'cli/ui/frame'
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
module Frame
|
9
|
+
# @abstract
|
9
10
|
module FrameStyle
|
10
11
|
include Kernel
|
11
|
-
extend T::Sig
|
12
|
-
extend T::Helpers
|
13
|
-
abstract!
|
14
12
|
|
15
13
|
autoload(:Box, 'cli/ui/frame/frame_style/box')
|
16
14
|
autoload(:Bracket, 'cli/ui/frame/frame_style/bracket')
|
@@ -21,14 +19,12 @@ module CLI
|
|
21
19
|
}
|
22
20
|
|
23
21
|
class << self
|
24
|
-
extend T::Sig
|
25
|
-
|
26
22
|
# Lookup a frame style via its name
|
27
23
|
#
|
28
24
|
# ==== Attributes
|
29
25
|
#
|
30
26
|
# * +symbol+ - frame style name to lookup
|
31
|
-
|
27
|
+
#: ((String | Symbol) name) -> FrameStyle
|
32
28
|
def lookup(name)
|
33
29
|
MAP.fetch(name.to_sym).call
|
34
30
|
rescue KeyError
|
@@ -36,16 +32,22 @@ module CLI
|
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
39
|
-
|
40
|
-
|
35
|
+
# @abstract
|
36
|
+
#: -> Symbol
|
37
|
+
def style_name
|
38
|
+
raise(NotImplementedError)
|
39
|
+
end
|
41
40
|
|
42
41
|
# Returns the character(s) that should be printed at the beginning
|
43
42
|
# of lines inside this frame
|
44
|
-
|
45
|
-
|
43
|
+
# @abstract
|
44
|
+
#: -> String
|
45
|
+
def prefix
|
46
|
+
raise(NotImplementedError)
|
47
|
+
end
|
46
48
|
|
47
49
|
# Returns the printing width of the prefix
|
48
|
-
|
50
|
+
#: -> Integer
|
49
51
|
def prefix_width
|
50
52
|
CLI::UI::ANSI.printing_width(prefix)
|
51
53
|
end
|
@@ -60,8 +62,11 @@ module CLI
|
|
60
62
|
#
|
61
63
|
# * +:color+ - (required) The color of the frame.
|
62
64
|
#
|
63
|
-
|
64
|
-
|
65
|
+
# @abstract
|
66
|
+
#: (String, color: CLI::UI::Color) -> String
|
67
|
+
def start(text, color:)
|
68
|
+
raise(NotImplementedError)
|
69
|
+
end
|
65
70
|
|
66
71
|
# Draws the "Close" line for this frame style
|
67
72
|
#
|
@@ -74,8 +79,11 @@ module CLI
|
|
74
79
|
# * +:color+ - (required) The color of the frame.
|
75
80
|
# * +:right_text+ - Text to print at the right of the line. Defaults to nil
|
76
81
|
#
|
77
|
-
|
78
|
-
|
82
|
+
# @abstract
|
83
|
+
#: (String, color: CLI::UI::Color, ?right_text: String?) -> String
|
84
|
+
def close(text, color:, right_text: nil)
|
85
|
+
raise(NotImplementedError)
|
86
|
+
end
|
79
87
|
|
80
88
|
# Draws a "divider" line for the current frame style
|
81
89
|
#
|
@@ -87,24 +95,25 @@ module CLI
|
|
87
95
|
#
|
88
96
|
# * +:color+ - (required) The color of the frame.
|
89
97
|
#
|
90
|
-
|
91
|
-
|
98
|
+
# @abstract
|
99
|
+
#: (String, color: CLI::UI::Color) -> String
|
100
|
+
def divider(text, color:)
|
101
|
+
raise(NotImplementedError)
|
102
|
+
end
|
92
103
|
|
93
|
-
|
104
|
+
#: (Integer x, String str) -> String
|
94
105
|
def print_at_x(x, str)
|
95
106
|
CLI::UI::ANSI.cursor_horizontal_absolute(1 + x) + str
|
96
107
|
end
|
97
108
|
|
98
109
|
class InvalidFrameStyleName < ArgumentError
|
99
|
-
|
100
|
-
|
101
|
-
sig { params(name: T.any(String, Symbol)).void }
|
110
|
+
#: ((String | Symbol) name) -> void
|
102
111
|
def initialize(name)
|
103
112
|
super
|
104
113
|
@name = name
|
105
114
|
end
|
106
115
|
|
107
|
-
|
116
|
+
#: -> String
|
108
117
|
def message
|
109
118
|
keys = FrameStyle::MAP.keys.map(&:inspect).join(', ')
|
110
119
|
"invalid frame style: #{@name.inspect} " \
|
data/lib/cli/ui/frame.rb
CHANGED
@@ -12,9 +12,7 @@ module CLI
|
|
12
12
|
DEFAULT_FRAME_COLOR = CLI::UI.resolve_color(:cyan)
|
13
13
|
|
14
14
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(FrameStyle) }
|
15
|
+
#: -> FrameStyle
|
18
16
|
def frame_style
|
19
17
|
@frame_style ||= FrameStyle::Box
|
20
18
|
end
|
@@ -27,7 +25,7 @@ module CLI
|
|
27
25
|
#
|
28
26
|
# * +symbol+ or +FrameStyle+ - the default frame style to use for frames
|
29
27
|
#
|
30
|
-
|
28
|
+
#: (frame_stylable frame_style) -> void
|
31
29
|
def frame_style=(frame_style)
|
32
30
|
@frame_style = CLI::UI.resolve_style(frame_style)
|
33
31
|
end
|
@@ -75,18 +73,7 @@ module CLI
|
|
75
73
|
# ┏━━ Open ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
76
74
|
#
|
77
75
|
#
|
78
|
-
|
79
|
-
type_parameters(:T).params(
|
80
|
-
text: String,
|
81
|
-
color: Colorable,
|
82
|
-
failure_text: T.nilable(String),
|
83
|
-
success_text: T.nilable(String),
|
84
|
-
timing: T.any(T::Boolean, Numeric),
|
85
|
-
frame_style: FrameStylable,
|
86
|
-
to: IOLike,
|
87
|
-
block: T.nilable(T.proc.returns(T.type_parameter(:T))),
|
88
|
-
).returns(T.nilable(T.type_parameter(:T)))
|
89
|
-
end
|
76
|
+
#: [T] (String text, ?color: colorable, ?failure_text: String?, ?success_text: String?, ?timing: (Numeric | bool), ?frame_style: frame_stylable, ?to: io_like) ?{ -> T } -> T?
|
90
77
|
def open(
|
91
78
|
text,
|
92
79
|
color: DEFAULT_FRAME_COLOR,
|
@@ -121,7 +108,7 @@ module CLI
|
|
121
108
|
|
122
109
|
closed = false
|
123
110
|
begin
|
124
|
-
success = false
|
111
|
+
success = false #: untyped
|
125
112
|
success = yield
|
126
113
|
rescue
|
127
114
|
closed = true
|
@@ -133,7 +120,8 @@ module CLI
|
|
133
120
|
ensure
|
134
121
|
unless closed
|
135
122
|
t_diff = elapsed(t_start, timing)
|
136
|
-
|
123
|
+
success_bool = success #: as untyped
|
124
|
+
if success_bool != false
|
137
125
|
close(success_text, color: color, elapsed: t_diff, to: to)
|
138
126
|
else
|
139
127
|
close(failure_text, color: :red, elapsed: t_diff, to: to)
|
@@ -169,14 +157,7 @@ module CLI
|
|
169
157
|
#
|
170
158
|
# MUST be inside an open frame or it raises a +UnnestedFrameException+
|
171
159
|
#
|
172
|
-
|
173
|
-
params(
|
174
|
-
text: T.nilable(String),
|
175
|
-
color: T.nilable(Colorable),
|
176
|
-
frame_style: T.nilable(FrameStylable),
|
177
|
-
to: IOLike,
|
178
|
-
).void
|
179
|
-
end
|
160
|
+
#: (String? text, ?color: colorable?, ?frame_style: frame_stylable?, ?to: io_like) -> void
|
180
161
|
def divider(text, color: nil, frame_style: nil, to: $stdout)
|
181
162
|
fs_item = FrameStack.pop
|
182
163
|
raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
|
@@ -218,15 +199,7 @@ module CLI
|
|
218
199
|
#
|
219
200
|
# MUST be inside an open frame or it raises a +UnnestedFrameException+
|
220
201
|
#
|
221
|
-
|
222
|
-
params(
|
223
|
-
text: T.nilable(String),
|
224
|
-
color: T.nilable(Colorable),
|
225
|
-
elapsed: T.nilable(Numeric),
|
226
|
-
frame_style: T.nilable(FrameStylable),
|
227
|
-
to: IOLike,
|
228
|
-
).void
|
229
|
-
end
|
202
|
+
#: (String? text, ?color: colorable?, ?elapsed: Numeric?, ?frame_style: frame_stylable?, ?to: io_like) -> void
|
230
203
|
def close(text, color: nil, elapsed: nil, frame_style: nil, to: $stdout)
|
231
204
|
fs_item = FrameStack.pop
|
232
205
|
raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
|
@@ -247,7 +220,7 @@ module CLI
|
|
247
220
|
#
|
248
221
|
# * +:color+ - The color of the prefix. Defaults to +Thread.current[:cliui_frame_color_override]+
|
249
222
|
#
|
250
|
-
|
223
|
+
#: (?color: colorable?) -> String
|
251
224
|
def prefix(color: Thread.current[:cliui_frame_color_override])
|
252
225
|
(+'').tap do |output|
|
253
226
|
items = FrameStack.items
|
@@ -269,7 +242,7 @@ module CLI
|
|
269
242
|
end
|
270
243
|
|
271
244
|
# The width of a prefix given the number of Frames in the stack
|
272
|
-
|
245
|
+
#: -> Integer
|
273
246
|
def prefix_width
|
274
247
|
w = FrameStack.items.reduce(0) do |width, item|
|
275
248
|
width + item.frame_style.prefix_width
|
@@ -284,11 +257,7 @@ module CLI
|
|
284
257
|
#
|
285
258
|
# * +color+ - The color to override to
|
286
259
|
#
|
287
|
-
|
288
|
-
type_parameters(:T)
|
289
|
-
.params(color: Colorable, block: T.proc.returns(T.type_parameter(:T)))
|
290
|
-
.returns(T.type_parameter(:T))
|
291
|
-
end
|
260
|
+
#: [T] (colorable color) { -> T } -> T
|
292
261
|
def with_frame_color_override(color, &block)
|
293
262
|
prev = Thread.current[:cliui_frame_color_override]
|
294
263
|
Thread.current[:cliui_frame_color_override] = color
|
@@ -303,7 +272,7 @@ module CLI
|
|
303
272
|
# Numeric: return it
|
304
273
|
# false: return nil
|
305
274
|
# true: defaults to Time.new
|
306
|
-
|
275
|
+
#: (Time start, (Numeric | bool) timing) -> Numeric?
|
307
276
|
def elapsed(start, timing)
|
308
277
|
return timing if timing.is_a?(Numeric)
|
309
278
|
return if timing.is_a?(FalseClass)
|
data/lib/cli/ui/glyph.rb
CHANGED
@@ -6,18 +6,14 @@ require 'cli/ui'
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
class Glyph
|
9
|
-
extend T::Sig
|
10
|
-
|
11
9
|
class InvalidGlyphHandle < ArgumentError
|
12
|
-
|
13
|
-
|
14
|
-
sig { params(handle: String).void }
|
10
|
+
#: (String handle) -> void
|
15
11
|
def initialize(handle)
|
16
12
|
super
|
17
13
|
@handle = handle
|
18
14
|
end
|
19
15
|
|
20
|
-
|
16
|
+
#: -> String
|
21
17
|
def message
|
22
18
|
keys = Glyph.available.join(',')
|
23
19
|
"invalid glyph handle: #{@handle} " \
|
@@ -25,13 +21,13 @@ module CLI
|
|
25
21
|
end
|
26
22
|
end
|
27
23
|
|
28
|
-
|
24
|
+
#: String
|
29
25
|
attr_reader :handle, :to_s, :fmt, :char
|
30
26
|
|
31
|
-
|
27
|
+
#: (Integer | Array[Integer])
|
32
28
|
attr_reader :codepoint
|
33
29
|
|
34
|
-
|
30
|
+
#: Color
|
35
31
|
attr_reader :color
|
36
32
|
|
37
33
|
# Creates a new glyph
|
@@ -43,7 +39,7 @@ module CLI
|
|
43
39
|
# * +plain+ - A fallback plain string to be used in case glyphs are disabled
|
44
40
|
# * +color+ - What color to output the glyph. Check +CLI::UI::Color+ for options.
|
45
41
|
#
|
46
|
-
|
42
|
+
#: (String handle, (Integer | Array[Integer]) codepoint, String plain, Color color) -> void
|
47
43
|
def initialize(handle, codepoint, plain, color)
|
48
44
|
@handle = handle
|
49
45
|
@codepoint = codepoint
|
@@ -68,8 +64,6 @@ module CLI
|
|
68
64
|
WARNING = new('!', [0x26a0, 0xfe0f], '!', Color::YELLOW) # WARNING SIGN + VARIATION SELECTOR 16 (⚠️ )
|
69
65
|
|
70
66
|
class << self
|
71
|
-
extend T::Sig
|
72
|
-
|
73
67
|
# Looks up a glyph by name
|
74
68
|
#
|
75
69
|
# ==== Raises
|
@@ -79,7 +73,7 @@ module CLI
|
|
79
73
|
# ==== Returns
|
80
74
|
# Returns a terminal output-capable string
|
81
75
|
#
|
82
|
-
|
76
|
+
#: (String name) -> Glyph
|
83
77
|
def lookup(name)
|
84
78
|
MAP.fetch(name.to_s)
|
85
79
|
rescue KeyError
|
@@ -88,7 +82,7 @@ module CLI
|
|
88
82
|
|
89
83
|
# All available glyphs by name
|
90
84
|
#
|
91
|
-
|
85
|
+
#: -> Array[String]
|
92
86
|
def available
|
93
87
|
MAP.keys
|
94
88
|
end
|
data/lib/cli/ui/os.rb
CHANGED
@@ -6,9 +6,7 @@ require 'rbconfig'
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
class OS
|
9
|
-
|
10
|
-
|
11
|
-
sig { params(emoji: T::Boolean, color_prompt: T::Boolean, arrow_keys: T::Boolean, shift_cursor: T::Boolean).void }
|
9
|
+
#: (?emoji: bool, ?color_prompt: bool, ?arrow_keys: bool, ?shift_cursor: bool) -> void
|
12
10
|
def initialize(emoji: true, color_prompt: true, arrow_keys: true, shift_cursor: false)
|
13
11
|
@emoji = emoji
|
14
12
|
@color_prompt = color_prompt
|
@@ -16,30 +14,28 @@ module CLI
|
|
16
14
|
@shift_cursor = shift_cursor
|
17
15
|
end
|
18
16
|
|
19
|
-
|
17
|
+
#: -> bool
|
20
18
|
def use_emoji?
|
21
19
|
@emoji
|
22
20
|
end
|
23
21
|
|
24
|
-
|
22
|
+
#: -> bool
|
25
23
|
def use_color_prompt?
|
26
24
|
@color_prompt
|
27
25
|
end
|
28
26
|
|
29
|
-
|
27
|
+
#: -> bool
|
30
28
|
def suggest_arrow_keys?
|
31
29
|
@arrow_keys
|
32
30
|
end
|
33
31
|
|
34
|
-
|
32
|
+
#: -> bool
|
35
33
|
def shift_cursor_back_on_horizontal_absolute?
|
36
34
|
@shift_cursor
|
37
35
|
end
|
38
36
|
|
39
37
|
class << self
|
40
|
-
|
41
|
-
|
42
|
-
sig { returns(OS) }
|
38
|
+
#: -> OS
|
43
39
|
def current
|
44
40
|
@current_os ||= case RbConfig::CONFIG['host_os']
|
45
41
|
when /darwin/
|
data/lib/cli/ui/printer.rb
CHANGED
@@ -6,11 +6,7 @@ require 'cli/ui'
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
class Printer
|
9
|
-
extend T::Sig
|
10
|
-
|
11
9
|
class << self
|
12
|
-
extend T::Sig
|
13
|
-
|
14
10
|
# Print a message to a stream with common utilities.
|
15
11
|
# Allows overriding the color, encoding, and target stream.
|
16
12
|
# By default, it formats the string using CLI:UI and rescues common stream errors.
|
@@ -36,17 +32,7 @@ module CLI
|
|
36
32
|
#
|
37
33
|
# CLI::UI::Printer.puts('{{x}} Ouch', to: $stderr)
|
38
34
|
#
|
39
|
-
|
40
|
-
params(
|
41
|
-
msg: String,
|
42
|
-
frame_color: T.nilable(Colorable),
|
43
|
-
to: IOLike,
|
44
|
-
encoding: T.nilable(Encoding),
|
45
|
-
format: T::Boolean,
|
46
|
-
graceful: T::Boolean,
|
47
|
-
wrap: T::Boolean,
|
48
|
-
).returns(T::Boolean)
|
49
|
-
end
|
35
|
+
#: (String msg, ?frame_color: colorable?, ?to: io_like, ?encoding: Encoding?, ?format: bool, ?graceful: bool, ?wrap: bool) -> bool
|
50
36
|
def puts(
|
51
37
|
msg,
|
52
38
|
frame_color: nil,
|
data/lib/cli/ui/progress.rb
CHANGED
@@ -6,16 +6,12 @@ require 'cli/ui'
|
|
6
6
|
module CLI
|
7
7
|
module UI
|
8
8
|
class Progress
|
9
|
-
extend T::Sig
|
10
|
-
|
11
9
|
# A Cyan filled block
|
12
10
|
FILLED_BAR = "\e[46m"
|
13
11
|
# A bright white block
|
14
12
|
UNFILLED_BAR = "\e[1;47m"
|
15
13
|
|
16
14
|
class << self
|
17
|
-
extend T::Sig
|
18
|
-
|
19
15
|
# Add a progress bar to the terminal output
|
20
16
|
#
|
21
17
|
# https://user-images.githubusercontent.com/3074765/33799794-cc4c940e-dd00-11e7-9bdc-90f77ec9167c.gif
|
@@ -42,21 +38,17 @@ module CLI
|
|
42
38
|
# bar.tick(percent: 0.05)
|
43
39
|
# bar.update_title('New title')
|
44
40
|
# end
|
45
|
-
|
46
|
-
type_parameters(:T)
|
47
|
-
.params(
|
48
|
-
title: T.nilable(String),
|
49
|
-
width: Integer,
|
50
|
-
block: T.proc.params(bar: Progress).returns(T.type_parameter(:T)),
|
51
|
-
)
|
52
|
-
.returns(T.type_parameter(:T))
|
53
|
-
end
|
41
|
+
#: [T] (?String? title, ?width: Integer) { (Progress bar) -> T } -> T
|
54
42
|
def progress(title = nil, width: Terminal.width, &block)
|
55
|
-
bar =
|
56
|
-
|
57
|
-
|
43
|
+
bar = nil #: Progress?
|
44
|
+
CLI::UI::ProgressReporter.with_progress(mode: :progress) do |reporter|
|
45
|
+
bar = Progress.new(title, width: width, reporter: reporter)
|
46
|
+
print(CLI::UI::ANSI.hide_cursor)
|
47
|
+
yield(bar)
|
48
|
+
end
|
58
49
|
ensure
|
59
|
-
puts(bar)
|
50
|
+
puts(bar) if bar
|
51
|
+
|
60
52
|
CLI::UI.raw do
|
61
53
|
print(ANSI.show_cursor)
|
62
54
|
end
|
@@ -69,12 +61,14 @@ module CLI
|
|
69
61
|
#
|
70
62
|
# * +:title+ - The title of the progress bar
|
71
63
|
# * +:width+ - The width of the terminal
|
64
|
+
# * +:reporter+ - The progress reporter instance
|
72
65
|
#
|
73
|
-
|
74
|
-
def initialize(title = nil, width: Terminal.width)
|
75
|
-
@percent_done =
|
66
|
+
#: (?String? title, ?width: Integer, ?reporter: ProgressReporter::Reporter?) -> void
|
67
|
+
def initialize(title = nil, width: Terminal.width, reporter: nil)
|
68
|
+
@percent_done = 0 #: Numeric
|
76
69
|
@title = title
|
77
70
|
@max_width = width
|
71
|
+
@reporter = reporter
|
78
72
|
end
|
79
73
|
|
80
74
|
# Set the progress of the bar. Typically used in a +Progress.progress+ block
|
@@ -87,7 +81,7 @@ module CLI
|
|
87
81
|
#
|
88
82
|
# *Note:* The +:percent+ and +:set_percent must be between 0.00 and 1.0
|
89
83
|
#
|
90
|
-
|
84
|
+
#: (?percent: Numeric?, ?set_percent: Numeric?) -> void
|
91
85
|
def tick(percent: nil, set_percent: nil)
|
92
86
|
raise ArgumentError, 'percent and set_percent cannot both be specified' if percent && set_percent
|
93
87
|
|
@@ -95,6 +89,9 @@ module CLI
|
|
95
89
|
@percent_done = set_percent if set_percent
|
96
90
|
@percent_done = [@percent_done, 1.0].min # Make sure we can't go above 1.0
|
97
91
|
|
92
|
+
# Update terminal progress reporter with current percentage
|
93
|
+
@reporter&.set_progress((@percent_done * 100).floor)
|
94
|
+
|
98
95
|
print(self)
|
99
96
|
|
100
97
|
printed_lines = @title ? 2 : 1
|
@@ -107,14 +104,14 @@ module CLI
|
|
107
104
|
#
|
108
105
|
# * +new_title+ - title to change the progress bar to
|
109
106
|
#
|
110
|
-
|
107
|
+
#: (String new_title) -> void
|
111
108
|
def update_title(new_title)
|
112
109
|
@title = new_title
|
113
110
|
end
|
114
111
|
|
115
112
|
# Format the progress bar to be printed to terminal
|
116
113
|
#
|
117
|
-
|
114
|
+
#: -> String
|
118
115
|
def to_s
|
119
116
|
suffix = " #{(@percent_done * 100).floor}%".ljust(5)
|
120
117
|
workable_width = @max_width - Frame.prefix_width - suffix.size
|