cli-ui 2.4.0 → 2.7.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 +29 -28
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a1c6da3c7bdbea0fb1cc70677acac4182c40196cf65b69127c40804bed532d4
|
|
4
|
+
data.tar.gz: 6ba1a30edf06fdb24d53869a70ba505f492a4ea70792fe5bfd0a3cddc2ca4b50
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a514afedeb744836daa7f3df1d20960c0b80fd47483d6f9f5407443c58cca58313363cface002ac7b2dafe6846b53c10507739dd9f72256f0a8742735b165b3e
|
|
7
|
+
data.tar.gz: a8e467997d9b5309787c7bcb4c30bf4d025c4aa968179938c1a673c712ccecceb37f06edfc70daaca4232f9def8f72e102808aed4f2ccfd4da7e245b87f382eb
|
data/lib/cli/ui/ansi.rb
CHANGED
|
@@ -6,21 +6,22 @@ require 'cli/ui'
|
|
|
6
6
|
module CLI
|
|
7
7
|
module UI
|
|
8
8
|
module ANSI
|
|
9
|
-
extend T::Sig
|
|
10
|
-
|
|
11
9
|
ESC = "\x1b"
|
|
10
|
+
# https://ghostty.org/docs/vt/concepts/sequences#csi-sequences
|
|
11
|
+
CSI_SEQUENCE = /\x1b\[[\d;:]+[\x20-\x2f]*?[\x40-\x7e]/
|
|
12
|
+
# https://ghostty.org/docs/vt/concepts/sequences#osc-sequences
|
|
13
|
+
# OSC sequences can be terminated with either ST (\x1b\x5c) or BEL (\x07)
|
|
14
|
+
OSC_SEQUENCE = /\x1b\][^\x07\x1b]*?(?:\x07|\x1b\x5c)/
|
|
12
15
|
|
|
13
16
|
class << self
|
|
14
|
-
extend T::Sig
|
|
15
|
-
|
|
16
17
|
# ANSI escape sequences (like \x1b[31m) have zero width.
|
|
17
18
|
# when calculating the padding width, we must exclude them.
|
|
18
19
|
# This also implements a basic version of utf8 character width calculation like
|
|
19
20
|
# we could get for real from something like utf8proc.
|
|
20
21
|
#
|
|
21
|
-
|
|
22
|
+
#: (String str) -> Integer
|
|
22
23
|
def printing_width(str)
|
|
23
|
-
zwj =
|
|
24
|
+
zwj = false #: bool
|
|
24
25
|
strip_codes(str).codepoints.reduce(0) do |acc, cp|
|
|
25
26
|
if zwj
|
|
26
27
|
zwj = false
|
|
@@ -44,9 +45,9 @@ module CLI
|
|
|
44
45
|
#
|
|
45
46
|
# - +str+ - The string from which to strip codes
|
|
46
47
|
#
|
|
47
|
-
|
|
48
|
+
#: (String str) -> String
|
|
48
49
|
def strip_codes(str)
|
|
49
|
-
str.gsub(/\
|
|
50
|
+
str.gsub(Regexp.union(CSI_SEQUENCE, OSC_SEQUENCE, /\r/), '')
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
# Returns an ANSI control sequence
|
|
@@ -56,13 +57,13 @@ module CLI
|
|
|
56
57
|
# - +args+ - Argument to pass to the ANSI control sequence
|
|
57
58
|
# - +cmd+ - ANSI control sequence Command
|
|
58
59
|
#
|
|
59
|
-
|
|
60
|
+
#: (String args, String cmd) -> String
|
|
60
61
|
def control(args, cmd)
|
|
61
62
|
ESC + '[' + args + cmd
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
# https://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
65
|
-
|
|
66
|
+
#: (String params) -> String
|
|
66
67
|
def sgr(params)
|
|
67
68
|
control(params, 'm')
|
|
68
69
|
end
|
|
@@ -75,7 +76,7 @@ module CLI
|
|
|
75
76
|
#
|
|
76
77
|
# * +n+ - number of lines by which to move the cursor up
|
|
77
78
|
#
|
|
78
|
-
|
|
79
|
+
#: (?Integer n) -> String
|
|
79
80
|
def cursor_up(n = 1)
|
|
80
81
|
return '' if n.zero?
|
|
81
82
|
|
|
@@ -88,7 +89,7 @@ module CLI
|
|
|
88
89
|
#
|
|
89
90
|
# * +n+ - number of lines by which to move the cursor down
|
|
90
91
|
#
|
|
91
|
-
|
|
92
|
+
#: (?Integer n) -> String
|
|
92
93
|
def cursor_down(n = 1)
|
|
93
94
|
return '' if n.zero?
|
|
94
95
|
|
|
@@ -101,7 +102,7 @@ module CLI
|
|
|
101
102
|
#
|
|
102
103
|
# * +n+ - number of columns by which to move the cursor forward
|
|
103
104
|
#
|
|
104
|
-
|
|
105
|
+
#: (?Integer n) -> String
|
|
105
106
|
def cursor_forward(n = 1)
|
|
106
107
|
return '' if n.zero?
|
|
107
108
|
|
|
@@ -114,7 +115,7 @@ module CLI
|
|
|
114
115
|
#
|
|
115
116
|
# * +n+ - number of columns by which to move the cursor back
|
|
116
117
|
#
|
|
117
|
-
|
|
118
|
+
#: (?Integer n) -> String
|
|
118
119
|
def cursor_back(n = 1)
|
|
119
120
|
return '' if n.zero?
|
|
120
121
|
|
|
@@ -127,66 +128,66 @@ module CLI
|
|
|
127
128
|
#
|
|
128
129
|
# * +n+ - The column to move to
|
|
129
130
|
#
|
|
130
|
-
|
|
131
|
+
#: (?Integer n) -> String
|
|
131
132
|
def cursor_horizontal_absolute(n = 1)
|
|
132
133
|
cmd = control(n.to_s, 'G')
|
|
133
134
|
cmd += cursor_back if CLI::UI::OS.current.shift_cursor_back_on_horizontal_absolute?
|
|
134
135
|
cmd
|
|
135
136
|
end
|
|
136
137
|
|
|
137
|
-
|
|
138
|
+
#: -> String
|
|
138
139
|
def enter_alternate_screen
|
|
139
140
|
control('?1049', 'h')
|
|
140
141
|
end
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
#: -> String
|
|
143
144
|
def exit_alternate_screen
|
|
144
145
|
control('?1049', 'l')
|
|
145
146
|
end
|
|
146
147
|
|
|
147
|
-
|
|
148
|
+
#: -> Regexp
|
|
148
149
|
def match_alternate_screen
|
|
149
150
|
/#{Regexp.escape(control("?1049", ""))}[hl]/
|
|
150
151
|
end
|
|
151
152
|
|
|
152
153
|
# Show the cursor
|
|
153
154
|
#
|
|
154
|
-
|
|
155
|
+
#: -> String
|
|
155
156
|
def show_cursor
|
|
156
157
|
control('', '?25h')
|
|
157
158
|
end
|
|
158
159
|
|
|
159
160
|
# Hide the cursor
|
|
160
161
|
#
|
|
161
|
-
|
|
162
|
+
#: -> String
|
|
162
163
|
def hide_cursor
|
|
163
164
|
control('', '?25l')
|
|
164
165
|
end
|
|
165
166
|
|
|
166
167
|
# Save the cursor position
|
|
167
168
|
#
|
|
168
|
-
|
|
169
|
+
#: -> String
|
|
169
170
|
def cursor_save
|
|
170
171
|
control('', 's')
|
|
171
172
|
end
|
|
172
173
|
|
|
173
174
|
# Restore the saved cursor position
|
|
174
175
|
#
|
|
175
|
-
|
|
176
|
+
#: -> String
|
|
176
177
|
def cursor_restore
|
|
177
178
|
control('', 'u')
|
|
178
179
|
end
|
|
179
180
|
|
|
180
181
|
# Move to the next line
|
|
181
182
|
#
|
|
182
|
-
|
|
183
|
+
#: -> String
|
|
183
184
|
def next_line
|
|
184
185
|
cursor_down + cursor_horizontal_absolute
|
|
185
186
|
end
|
|
186
187
|
|
|
187
188
|
# Move to the previous line
|
|
188
189
|
#
|
|
189
|
-
|
|
190
|
+
#: -> String
|
|
190
191
|
def previous_line
|
|
191
192
|
previous_lines(1)
|
|
192
193
|
end
|
|
@@ -197,22 +198,22 @@ module CLI
|
|
|
197
198
|
#
|
|
198
199
|
# * +n+ - number of lines by which to move the cursor up
|
|
199
200
|
#
|
|
200
|
-
|
|
201
|
+
#: (?Integer n) -> String
|
|
201
202
|
def previous_lines(n = 1)
|
|
202
203
|
cursor_up(n) + cursor_horizontal_absolute
|
|
203
204
|
end
|
|
204
205
|
|
|
205
|
-
|
|
206
|
+
#: -> String
|
|
206
207
|
def clear_to_end_of_line
|
|
207
208
|
control('', 'K')
|
|
208
209
|
end
|
|
209
210
|
|
|
210
|
-
|
|
211
|
+
#: -> String
|
|
211
212
|
def insert_line
|
|
212
213
|
insert_lines(1)
|
|
213
214
|
end
|
|
214
215
|
|
|
215
|
-
|
|
216
|
+
#: (?Integer n) -> String
|
|
216
217
|
def insert_lines(n = 1)
|
|
217
218
|
control(n.to_s, 'L')
|
|
218
219
|
end
|
data/lib/cli/ui/color.rb
CHANGED
|
@@ -6,12 +6,10 @@ require 'cli/ui'
|
|
|
6
6
|
module CLI
|
|
7
7
|
module UI
|
|
8
8
|
class Color
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sig { returns(String) }
|
|
9
|
+
#: String
|
|
12
10
|
attr_reader :sgr, :code
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
#: Symbol
|
|
15
13
|
attr_reader :name
|
|
16
14
|
|
|
17
15
|
# Creates a new color mapping
|
|
@@ -23,7 +21,7 @@ module CLI
|
|
|
23
21
|
# * +sgr+ - The color signature
|
|
24
22
|
# * +name+ - The name of the color
|
|
25
23
|
#
|
|
26
|
-
|
|
24
|
+
#: (String sgr, Symbol name) -> void
|
|
27
25
|
def initialize(sgr, name)
|
|
28
26
|
@sgr = sgr
|
|
29
27
|
@code = CLI::UI::ANSI.sgr(sgr)
|
|
@@ -60,15 +58,13 @@ module CLI
|
|
|
60
58
|
}.freeze
|
|
61
59
|
|
|
62
60
|
class InvalidColorName < ArgumentError
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
sig { params(name: Symbol).void }
|
|
61
|
+
#: (Symbol name) -> void
|
|
66
62
|
def initialize(name)
|
|
67
63
|
super
|
|
68
64
|
@name = name
|
|
69
65
|
end
|
|
70
66
|
|
|
71
|
-
|
|
67
|
+
#: -> String
|
|
72
68
|
def message
|
|
73
69
|
keys = Color.available.map(&:inspect).join(',')
|
|
74
70
|
"invalid color: #{@name.inspect} " \
|
|
@@ -77,8 +73,6 @@ module CLI
|
|
|
77
73
|
end
|
|
78
74
|
|
|
79
75
|
class << self
|
|
80
|
-
extend T::Sig
|
|
81
|
-
|
|
82
76
|
# Looks up a color code by name
|
|
83
77
|
#
|
|
84
78
|
# ==== Raises
|
|
@@ -88,7 +82,7 @@ module CLI
|
|
|
88
82
|
# ==== Returns
|
|
89
83
|
# Returns a color code
|
|
90
84
|
#
|
|
91
|
-
|
|
85
|
+
#: ((Symbol | String) name) -> Color
|
|
92
86
|
def lookup(name)
|
|
93
87
|
MAP.fetch(name.to_sym)
|
|
94
88
|
rescue KeyError
|
|
@@ -97,7 +91,7 @@ module CLI
|
|
|
97
91
|
|
|
98
92
|
# All available colors by name
|
|
99
93
|
#
|
|
100
|
-
|
|
94
|
+
#: -> Array[Symbol]
|
|
101
95
|
def available
|
|
102
96
|
MAP.keys
|
|
103
97
|
end
|
data/lib/cli/ui/formatter.rb
CHANGED
|
@@ -7,8 +7,6 @@ require('strscan')
|
|
|
7
7
|
module CLI
|
|
8
8
|
module UI
|
|
9
9
|
class Formatter
|
|
10
|
-
extend T::Sig
|
|
11
|
-
|
|
12
10
|
# Available mappings of formattings
|
|
13
11
|
# To use any of them, you can use {{<key>:<string>}}
|
|
14
12
|
# There are presentational (colours and formatters)
|
|
@@ -59,18 +57,16 @@ module CLI
|
|
|
59
57
|
|
|
60
58
|
LITERAL_BRACES = Class.new
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
#: type stack = Array[String | LITERAL_BRACES]
|
|
63
61
|
|
|
64
62
|
class FormatError < StandardError
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sig { returns(String) }
|
|
63
|
+
#: String
|
|
68
64
|
attr_accessor :input
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
#: Integer
|
|
71
67
|
attr_accessor :index
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
#: (String message, String input, Integer index) -> void
|
|
74
70
|
def initialize(message, input, index)
|
|
75
71
|
super(message)
|
|
76
72
|
@input = input
|
|
@@ -84,10 +80,10 @@ module CLI
|
|
|
84
80
|
#
|
|
85
81
|
# * +text+ - the text to format
|
|
86
82
|
#
|
|
87
|
-
|
|
83
|
+
#: (String text) -> void
|
|
88
84
|
def initialize(text)
|
|
89
85
|
@text = text
|
|
90
|
-
@nodes =
|
|
86
|
+
@nodes = [] #: Array[[String, stack]]
|
|
91
87
|
end
|
|
92
88
|
|
|
93
89
|
# Format the text using a map.
|
|
@@ -100,11 +96,11 @@ module CLI
|
|
|
100
96
|
#
|
|
101
97
|
# * +:enable_color+ - enable color output? Default is true unless output is redirected
|
|
102
98
|
#
|
|
103
|
-
|
|
99
|
+
#: (?Hash[String, String] sgr_map, ?enable_color: bool) -> String
|
|
104
100
|
def format(sgr_map = SGR_MAP, enable_color: CLI::UI.enable_color?)
|
|
105
101
|
@nodes.replace([])
|
|
106
102
|
stack = parse_body(StringScanner.new(@text))
|
|
107
|
-
prev_fmt =
|
|
103
|
+
prev_fmt = nil #: stack?
|
|
108
104
|
content = @nodes.each_with_object(+'') do |(text, fmt), str|
|
|
109
105
|
if prev_fmt != fmt && enable_color
|
|
110
106
|
text = apply_format(text, fmt, sgr_map)
|
|
@@ -118,7 +114,8 @@ module CLI
|
|
|
118
114
|
return content unless enable_color
|
|
119
115
|
return content if stack == prev_fmt
|
|
120
116
|
|
|
121
|
-
|
|
117
|
+
last_node = @nodes.last #: as !nil
|
|
118
|
+
unless stack.empty? && (@nodes.empty? || last_node[1].empty?)
|
|
122
119
|
content << apply_format('', stack, sgr_map)
|
|
123
120
|
end
|
|
124
121
|
content
|
|
@@ -126,7 +123,7 @@ module CLI
|
|
|
126
123
|
|
|
127
124
|
private
|
|
128
125
|
|
|
129
|
-
|
|
126
|
+
#: (String text, stack fmt, Hash[String, String] sgr_map) -> String
|
|
130
127
|
def apply_format(text, fmt, sgr_map)
|
|
131
128
|
sgr = fmt.each_with_object(+'0') do |name, str|
|
|
132
129
|
next if name.is_a?(LITERAL_BRACES)
|
|
@@ -144,10 +141,10 @@ module CLI
|
|
|
144
141
|
CLI::UI::ANSI.sgr(sgr) + text
|
|
145
142
|
end
|
|
146
143
|
|
|
147
|
-
|
|
144
|
+
#: (StringScanner sc, stack stack) -> stack
|
|
148
145
|
def parse_expr(sc, stack)
|
|
149
146
|
if (match = sc.scan(SCAN_GLYPH))
|
|
150
|
-
glyph_handle =
|
|
147
|
+
glyph_handle = match[0] #: as !nil
|
|
151
148
|
begin
|
|
152
149
|
glyph = Glyph.lookup(glyph_handle)
|
|
153
150
|
emit(glyph.char, [glyph.color.name.to_s])
|
|
@@ -160,11 +157,12 @@ module CLI
|
|
|
160
157
|
)
|
|
161
158
|
end
|
|
162
159
|
elsif (match = sc.scan(SCAN_WIDGET))
|
|
163
|
-
match_data =
|
|
164
|
-
widget_handle =
|
|
160
|
+
match_data = SCAN_WIDGET.match(match) #: as !nil # Regexp.last_match doesn't work here
|
|
161
|
+
widget_handle = match_data['handle'] #: as !nil
|
|
165
162
|
begin
|
|
166
163
|
widget = Widgets.lookup(widget_handle)
|
|
167
|
-
|
|
164
|
+
args = match_data['args'] #: as !nil
|
|
165
|
+
emit(widget.call(args), stack)
|
|
168
166
|
rescue Widgets::InvalidWidgetHandle
|
|
169
167
|
index = sc.pos - 2 # rewind past '}}'
|
|
170
168
|
raise(FormatError.new(
|
|
@@ -188,14 +186,16 @@ module CLI
|
|
|
188
186
|
stack
|
|
189
187
|
end
|
|
190
188
|
|
|
191
|
-
|
|
189
|
+
#: (StringScanner sc, ?stack stack) -> stack
|
|
192
190
|
def parse_body(sc, stack = [])
|
|
193
191
|
match = sc.scan(SCAN_BODY)
|
|
194
192
|
if match&.end_with?(BEGIN_EXPR)
|
|
195
|
-
|
|
193
|
+
text = match[DISCARD_BRACES] #: as !nil
|
|
194
|
+
emit(text, stack)
|
|
196
195
|
parse_expr(sc, stack)
|
|
197
196
|
elsif match&.end_with?(END_EXPR)
|
|
198
|
-
|
|
197
|
+
text = match[DISCARD_BRACES] #: as !nil
|
|
198
|
+
emit(text, stack)
|
|
199
199
|
if stack.pop.is_a?(LITERAL_BRACES)
|
|
200
200
|
emit('}}', stack)
|
|
201
201
|
end
|
|
@@ -208,7 +208,7 @@ module CLI
|
|
|
208
208
|
stack
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
|
|
211
|
+
#: (String text, stack stack) -> void
|
|
212
212
|
def emit(text, stack)
|
|
213
213
|
return if text.empty?
|
|
214
214
|
|
|
@@ -6,18 +6,13 @@ module CLI
|
|
|
6
6
|
module Frame
|
|
7
7
|
module FrameStack
|
|
8
8
|
class StackItem
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sig { returns(CLI::UI::Color) }
|
|
9
|
+
#: CLI::UI::Color
|
|
12
10
|
attr_reader :color
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
#: CLI::UI::Frame::FrameStyle
|
|
15
13
|
attr_reader :frame_style
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
params(color_name: CLI::UI::Colorable, style_name: FrameStylable)
|
|
19
|
-
.void
|
|
20
|
-
end
|
|
15
|
+
#: (CLI::UI::colorable color_name, frame_stylable style_name) -> void
|
|
21
16
|
def initialize(color_name, style_name)
|
|
22
17
|
@color = CLI::UI.resolve_color(color_name)
|
|
23
18
|
@frame_style = CLI::UI.resolve_style(style_name)
|
|
@@ -25,10 +20,8 @@ module CLI
|
|
|
25
20
|
end
|
|
26
21
|
|
|
27
22
|
class << self
|
|
28
|
-
extend T::Sig
|
|
29
|
-
|
|
30
23
|
# Fetch all items off the frame stack
|
|
31
|
-
|
|
24
|
+
#: -> Array[StackItem]
|
|
32
25
|
def items
|
|
33
26
|
Thread.current[:cliui_frame_stack] ||= []
|
|
34
27
|
end
|
|
@@ -51,24 +44,19 @@ module CLI
|
|
|
51
44
|
# If both an item and a color/style pair are given, raises an +ArgumentError+
|
|
52
45
|
# If the given item is not a +StackItem+, raises an +ArgumentError+
|
|
53
46
|
#
|
|
54
|
-
|
|
55
|
-
params(
|
|
56
|
-
item: T.nilable(StackItem),
|
|
57
|
-
color: T.nilable(CLI::UI::Color),
|
|
58
|
-
style: T.nilable(CLI::UI::Frame::FrameStyle),
|
|
59
|
-
)
|
|
60
|
-
.void
|
|
61
|
-
end
|
|
47
|
+
#: (?StackItem? item, ?color: CLI::UI::Color?, ?style: CLI::UI::Frame::FrameStyle?) -> void
|
|
62
48
|
def push(item = nil, color: nil, style: nil)
|
|
63
49
|
if color.nil? != style.nil? || item.nil? == color.nil?
|
|
64
50
|
raise ArgumentError, 'Must give one of item or color: and style:'
|
|
65
51
|
end
|
|
66
52
|
|
|
67
|
-
|
|
53
|
+
c = color #: as !nil
|
|
54
|
+
s = style #: as !nil
|
|
55
|
+
items.push(item || StackItem.new(c, s))
|
|
68
56
|
end
|
|
69
57
|
|
|
70
58
|
# Removes and returns the last stack item off the stack
|
|
71
|
-
|
|
59
|
+
#: -> StackItem?
|
|
72
60
|
def pop
|
|
73
61
|
items.pop
|
|
74
62
|
end
|
|
@@ -15,14 +15,14 @@ module CLI
|
|
|
15
15
|
BOTTOM_LEFT = '┗'
|
|
16
16
|
|
|
17
17
|
class << self
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
sig { override.returns(Symbol) }
|
|
18
|
+
# @override
|
|
19
|
+
#: -> Symbol
|
|
21
20
|
def style_name
|
|
22
21
|
:box
|
|
23
22
|
end
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
# @override
|
|
25
|
+
#: -> String
|
|
26
26
|
def prefix
|
|
27
27
|
VERTICAL
|
|
28
28
|
end
|
|
@@ -41,7 +41,8 @@ module CLI
|
|
|
41
41
|
#
|
|
42
42
|
# ┏━━ Open ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
43
43
|
#
|
|
44
|
-
|
|
44
|
+
# @override
|
|
45
|
+
#: (String text, color: CLI::UI::Color) -> String
|
|
45
46
|
def start(text, color:)
|
|
46
47
|
edge(text, color: color, first: TOP_LEFT)
|
|
47
48
|
end
|
|
@@ -60,7 +61,8 @@ module CLI
|
|
|
60
61
|
#
|
|
61
62
|
# ┣━━ Divider ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
62
63
|
#
|
|
63
|
-
|
|
64
|
+
# @override
|
|
65
|
+
#: (String text, color: CLI::UI::Color) -> String
|
|
64
66
|
def divider(text, color:)
|
|
65
67
|
edge(text, color: color, first: DIVIDER)
|
|
66
68
|
end
|
|
@@ -80,16 +82,15 @@ module CLI
|
|
|
80
82
|
#
|
|
81
83
|
# ┗━━ Close ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
82
84
|
#
|
|
83
|
-
|
|
85
|
+
# @override
|
|
86
|
+
#: (String text, color: CLI::UI::Color, ?right_text: String?) -> String
|
|
84
87
|
def close(text, color:, right_text: nil)
|
|
85
88
|
edge(text, color: color, right_text: right_text, first: BOTTOM_LEFT)
|
|
86
89
|
end
|
|
87
90
|
|
|
88
91
|
private
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
params(text: String, color: CLI::UI::Color, first: String, right_text: T.nilable(String)).returns(String)
|
|
92
|
-
end
|
|
93
|
+
#: (String text, color: CLI::UI::Color, first: String, ?right_text: String?) -> String
|
|
93
94
|
def edge(text, color:, first:, right_text: nil)
|
|
94
95
|
color = CLI::UI.resolve_color(color)
|
|
95
96
|
|
|
@@ -15,14 +15,14 @@ module CLI
|
|
|
15
15
|
BOTTOM_LEFT = '┗'
|
|
16
16
|
|
|
17
17
|
class << self
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
sig { override.returns(Symbol) }
|
|
18
|
+
# @override
|
|
19
|
+
#: -> Symbol
|
|
21
20
|
def style_name
|
|
22
21
|
:bracket
|
|
23
22
|
end
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
# @override
|
|
25
|
+
#: -> String
|
|
26
26
|
def prefix
|
|
27
27
|
VERTICAL
|
|
28
28
|
end
|
|
@@ -41,7 +41,8 @@ module CLI
|
|
|
41
41
|
#
|
|
42
42
|
# ┏━━ Open
|
|
43
43
|
#
|
|
44
|
-
|
|
44
|
+
# @override
|
|
45
|
+
#: (String text, color: CLI::UI::Color) -> String
|
|
45
46
|
def start(text, color:)
|
|
46
47
|
edge(text, color: color, first: TOP_LEFT)
|
|
47
48
|
end
|
|
@@ -60,7 +61,8 @@ module CLI
|
|
|
60
61
|
#
|
|
61
62
|
# ┣━━ Divider
|
|
62
63
|
#
|
|
63
|
-
|
|
64
|
+
# @override
|
|
65
|
+
#: (String text, color: CLI::UI::Color) -> String
|
|
64
66
|
def divider(text, color:)
|
|
65
67
|
edge(text, color: color, first: DIVIDER)
|
|
66
68
|
end
|
|
@@ -80,16 +82,15 @@ module CLI
|
|
|
80
82
|
#
|
|
81
83
|
# ┗━━ Close
|
|
82
84
|
#
|
|
83
|
-
|
|
85
|
+
# @override
|
|
86
|
+
#: (String text, color: CLI::UI::Color, ?right_text: String?) -> String
|
|
84
87
|
def close(text, color:, right_text: nil)
|
|
85
88
|
edge(text, color: color, right_text: right_text, first: BOTTOM_LEFT)
|
|
86
89
|
end
|
|
87
90
|
|
|
88
91
|
private
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
params(text: String, color: CLI::UI::Color, first: String, right_text: T.nilable(String)).returns(String)
|
|
92
|
-
end
|
|
93
|
+
#: (String text, color: CLI::UI::Color, first: String, ?right_text: String?) -> String
|
|
93
94
|
def edge(text, color:, first:, right_text: nil)
|
|
94
95
|
color = CLI::UI.resolve_color(color)
|
|
95
96
|
|