cli-ui 1.3.0 → 1.4.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/.dependabot/config.yml +8 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +23 -2
- data/.travis.yml +4 -2
- data/Gemfile.lock +56 -0
- data/README.md +32 -1
- data/Rakefile +1 -1
- data/cli-ui.gemspec +3 -3
- data/dev.yml +1 -1
- data/lib/cli/ui.rb +58 -18
- data/lib/cli/ui/ansi.rb +9 -3
- data/lib/cli/ui/color.rb +9 -8
- data/lib/cli/ui/formatter.rb +13 -13
- data/lib/cli/ui/frame.rb +108 -151
- data/lib/cli/ui/frame/frame_stack.rb +98 -0
- data/lib/cli/ui/frame/frame_style.rb +120 -0
- data/lib/cli/ui/frame/frame_style/box.rb +166 -0
- data/lib/cli/ui/frame/frame_style/bracket.rb +139 -0
- data/lib/cli/ui/glyph.rb +21 -10
- data/lib/cli/ui/os.rb +63 -0
- data/lib/cli/ui/printer.rb +47 -0
- data/lib/cli/ui/progress.rb +9 -7
- data/lib/cli/ui/prompt.rb +50 -16
- data/lib/cli/ui/prompt/interactive_options.rb +63 -44
- data/lib/cli/ui/prompt/options_handler.rb +7 -2
- data/lib/cli/ui/spinner.rb +4 -6
- data/lib/cli/ui/spinner/spin_group.rb +18 -12
- data/lib/cli/ui/stdout_router.rb +12 -7
- data/lib/cli/ui/terminal.rb +26 -16
- data/lib/cli/ui/truncater.rb +3 -3
- data/lib/cli/ui/version.rb +1 -1
- data/lib/cli/ui/widgets.rb +2 -0
- metadata +16 -9
- data/lib/cli/ui/box.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8c6abe82a837c62e28cded106185a5ce2d09413637b94fb5bdb6524552648ac
|
4
|
+
data.tar.gz: 780168b9d23cd55acd5e95e6abcb7b5b0732c694db2feb0f73d5b04ce71dcd63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cea8f4f738765f77a8474221a9449da3f7bb1cae7610fb5d21dc2ee02f7c03996fc26b661db4eefb1af924ab2b7af0469539040763804c7154353037100fdd0f
|
7
|
+
data.tar.gz: bfe35b8ded93b0fe857d55836fd0b1aef67b6c5cb036550a152db464e3657607c0fde84621ccfd2541bb477d262b16e3adef0b320a1b037b3664f2141df99404
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -2,10 +2,19 @@ inherit_from:
|
|
2
2
|
- http://shopify.github.io/ruby-style-guide/rubocop.yml
|
3
3
|
|
4
4
|
AllCops:
|
5
|
-
|
5
|
+
Exclude:
|
6
|
+
- vendor/**/*
|
7
|
+
TargetRubyVersion: 2.5
|
8
|
+
|
9
|
+
Style/FrozenStringLiteralComment:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# This doesn't understand that <<~ doesn't exist in 2.0
|
13
|
+
Layout/HeredocIndentation:
|
14
|
+
Enabled: false
|
6
15
|
|
7
16
|
# This doesn't take into account retrying from an exception
|
8
|
-
Lint/
|
17
|
+
Lint/SuppressedException:
|
9
18
|
Enabled: false
|
10
19
|
|
11
20
|
# allow String.new to create mutable strings
|
@@ -15,3 +24,15 @@ Style/EmptyLiteral:
|
|
15
24
|
# allow the use of globals which makes sense in a CLI app like this
|
16
25
|
Style/GlobalVars:
|
17
26
|
Enabled: false
|
27
|
+
|
28
|
+
# allow using %r{} for regexes
|
29
|
+
Style/RegexpLiteral:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
# allow readable Dev::Util.begin formatting
|
33
|
+
Style/MultilineBlockChain:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
# we prefer rescue to align with the beginning of the line containing begin, not begin itself
|
37
|
+
Layout/RescueEnsureAlignment:
|
38
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cli-ui (1.4.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ansi (1.5.0)
|
10
|
+
ast (2.4.1)
|
11
|
+
builder (3.2.4)
|
12
|
+
byebug (11.1.3)
|
13
|
+
method_source (1.0.0)
|
14
|
+
minitest (5.14.2)
|
15
|
+
minitest-reporters (1.4.2)
|
16
|
+
ansi
|
17
|
+
builder
|
18
|
+
minitest (>= 5.0)
|
19
|
+
ruby-progressbar
|
20
|
+
mocha (1.11.2)
|
21
|
+
parallel (1.19.2)
|
22
|
+
parser (2.7.2.0)
|
23
|
+
ast (~> 2.4.1)
|
24
|
+
rainbow (3.0.0)
|
25
|
+
rake (13.0.1)
|
26
|
+
regexp_parser (1.8.2)
|
27
|
+
rexml (3.2.4)
|
28
|
+
rubocop (1.1.0)
|
29
|
+
parallel (~> 1.10)
|
30
|
+
parser (>= 2.7.1.5)
|
31
|
+
rainbow (>= 2.2.2, < 4.0)
|
32
|
+
regexp_parser (>= 1.8)
|
33
|
+
rexml
|
34
|
+
rubocop-ast (>= 1.0.1)
|
35
|
+
ruby-progressbar (~> 1.7)
|
36
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
37
|
+
rubocop-ast (1.1.0)
|
38
|
+
parser (>= 2.7.1.5)
|
39
|
+
ruby-progressbar (1.10.1)
|
40
|
+
unicode-display_width (1.7.0)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
byebug
|
47
|
+
cli-ui!
|
48
|
+
method_source
|
49
|
+
minitest (>= 5.0.0)
|
50
|
+
minitest-reporters
|
51
|
+
mocha
|
52
|
+
rake (~> 13.0)
|
53
|
+
rubocop
|
54
|
+
|
55
|
+
BUNDLED WITH
|
56
|
+
2.1.0
|
data/README.md
CHANGED
@@ -108,7 +108,7 @@ puts CLI::UI.fmt "{{red:Red}} {{green:Green}}"
|
|
108
108
|
e.g. `{{*}}` => a yellow ⭑
|
109
109
|
|
110
110
|
```ruby
|
111
|
-
puts CLI::UI.fmt "{{*}} {{
|
111
|
+
puts CLI::UI.fmt "{{*}} {{v}} {{?}} {{x}}"
|
112
112
|
```
|
113
113
|
|
114
114
|

|
@@ -144,6 +144,37 @@ end
|
|
144
144
|
|
145
145
|
---
|
146
146
|
|
147
|
+
### Frame Styles
|
148
|
+
|
149
|
+
Modify the appearance of CLI::UI both globally and on an individual frame level.
|
150
|
+
|
151
|
+
To set the default style:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
CLI::UI.frame_style = :box
|
155
|
+
```
|
156
|
+
|
157
|
+
To style an individual frame:
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
CLI::UI.frame('New Style!', frame_style: :bracket) { puts 'It's pretty cool!' }
|
161
|
+
```
|
162
|
+
|
163
|
+
The default style - `:box` - is what has been used up until now. The other style - `:bracket` - looks like this:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
CLI::UI.frame_style = :bracket
|
167
|
+
CLI::UI::StdoutRouter.enable
|
168
|
+
CLI::UI::Frame.open('Frame 1') do
|
169
|
+
CLI::UI::Frame.open('Frame 2') { puts "inside frame 2" }
|
170
|
+
puts "inside frame 1"
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+

|
175
|
+
|
176
|
+
---
|
177
|
+
|
147
178
|
## Example Usage
|
148
179
|
|
149
180
|
The following code makes use of nested-framing, multi-threaded spinners, formatted text, and more.
|
data/Rakefile
CHANGED
data/cli-ui.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = "https://github.com/shopify/cli-ui"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files =
|
17
|
+
spec.files = %x(git ls-files -z).split("\x0").reject do |f|
|
18
18
|
f.match(%r{^(test|spec|features)/})
|
19
19
|
end
|
20
20
|
spec.bindir = "exe"
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
24
|
# spec.add_development_dependency "bundler", "~> 2.0"
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency("rake", "~> 13.0")
|
26
|
+
spec.add_development_dependency("minitest", "~> 5.0")
|
27
27
|
end
|
data/dev.yml
CHANGED
data/lib/cli/ui.rb
CHANGED
@@ -3,8 +3,9 @@ module CLI
|
|
3
3
|
autoload :ANSI, 'cli/ui/ansi'
|
4
4
|
autoload :Glyph, 'cli/ui/glyph'
|
5
5
|
autoload :Color, 'cli/ui/color'
|
6
|
-
autoload :Box, 'cli/ui/box'
|
7
6
|
autoload :Frame, 'cli/ui/frame'
|
7
|
+
autoload :OS, 'cli/ui/os'
|
8
|
+
autoload :Printer, 'cli/ui/printer'
|
8
9
|
autoload :Progress, 'cli/ui/progress'
|
9
10
|
autoload :Prompt, 'cli/ui/prompt'
|
10
11
|
autoload :Terminal, 'cli/ui/terminal'
|
@@ -28,7 +29,7 @@ module CLI
|
|
28
29
|
end
|
29
30
|
|
30
31
|
# Color resolution using +CLI::UI::Color.lookup+
|
31
|
-
# Will lookup using +Color.lookup+
|
32
|
+
# Will lookup using +Color.lookup+ unless it's already a CLI::UI::Color (or nil)
|
32
33
|
#
|
33
34
|
# ==== Attributes
|
34
35
|
#
|
@@ -36,14 +37,29 @@ module CLI
|
|
36
37
|
#
|
37
38
|
def self.resolve_color(input)
|
38
39
|
case input
|
39
|
-
when
|
40
|
-
|
40
|
+
when CLI::UI::Color, nil
|
41
|
+
input
|
41
42
|
else
|
43
|
+
CLI::UI::Color.lookup(input)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Frame style resolution using +CLI::UI::Frame::FrameStyle.lookup+.
|
48
|
+
# Will lookup using +FrameStyle.lookup+ unless it's already a CLI::UI::Frame::FrameStyle(or nil)
|
49
|
+
#
|
50
|
+
# ==== Attributes
|
51
|
+
#
|
52
|
+
# * +input+ - frame style to resolve
|
53
|
+
def self.resolve_style(input)
|
54
|
+
case input
|
55
|
+
when CLI::UI::Frame::FrameStyle, nil
|
42
56
|
input
|
57
|
+
else
|
58
|
+
CLI::UI::Frame::FrameStyle.lookup(input)
|
43
59
|
end
|
44
60
|
end
|
45
61
|
|
46
|
-
#
|
62
|
+
# Convenience Method for +CLI::UI::Prompt.confirm+
|
47
63
|
#
|
48
64
|
# ==== Attributes
|
49
65
|
#
|
@@ -53,18 +69,18 @@ module CLI
|
|
53
69
|
CLI::UI::Prompt.confirm(question, **kwargs)
|
54
70
|
end
|
55
71
|
|
56
|
-
#
|
72
|
+
# Convenience Method for +CLI::UI::Prompt.ask+
|
57
73
|
#
|
58
74
|
# ==== Attributes
|
59
75
|
#
|
60
76
|
# * +question+ - question to ask
|
61
|
-
# * +kwargs+ -
|
77
|
+
# * +kwargs+ - arguments for +Prompt.ask+
|
62
78
|
#
|
63
79
|
def self.ask(question, **kwargs)
|
64
80
|
CLI::UI::Prompt.ask(question, **kwargs)
|
65
81
|
end
|
66
82
|
|
67
|
-
#
|
83
|
+
# Convenience Method to resolve text using +CLI::UI::Formatter.format+
|
68
84
|
# Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
|
69
85
|
#
|
70
86
|
# ==== Attributes
|
@@ -76,10 +92,10 @@ module CLI
|
|
76
92
|
return input if input.nil?
|
77
93
|
formatted = CLI::UI::Formatter.new(input).format
|
78
94
|
return formatted unless truncate_to
|
79
|
-
|
95
|
+
CLI::UI::Truncater.call(formatted, truncate_to)
|
80
96
|
end
|
81
97
|
|
82
|
-
#
|
98
|
+
# Convenience Method to format text using +CLI::UI::Formatter.format+
|
83
99
|
# Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
|
84
100
|
#
|
85
101
|
# https://user-images.githubusercontent.com/3074765/33799827-6d0721a2-dd01-11e7-9ab5-c3d455264afe.png
|
@@ -97,29 +113,40 @@ module CLI
|
|
97
113
|
CLI::UI::Formatter.new(input).format(enable_color: enable_color)
|
98
114
|
end
|
99
115
|
|
100
|
-
#
|
116
|
+
# Convenience Method for +CLI::UI::Printer.puts+
|
117
|
+
#
|
118
|
+
# ==== Attributes
|
119
|
+
#
|
120
|
+
# * +msg+ - Message to print
|
121
|
+
# * +kwargs+ - keyword arguments for +Printer.puts+
|
122
|
+
#
|
123
|
+
def self.puts(msg, **kwargs)
|
124
|
+
CLI::UI::Printer.puts(msg, **kwargs)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Convenience Method for +CLI::UI::Frame.open+
|
101
128
|
#
|
102
129
|
# ==== Attributes
|
103
130
|
#
|
104
131
|
# * +args+ - arguments for +Frame.open+
|
105
132
|
# * +block+ - block for +Frame.open+
|
106
133
|
#
|
107
|
-
def self.frame(*args, &block)
|
108
|
-
CLI::UI::Frame.open(*args, &block)
|
134
|
+
def self.frame(*args, **kwargs, &block)
|
135
|
+
CLI::UI::Frame.open(*args, **kwargs, &block)
|
109
136
|
end
|
110
137
|
|
111
|
-
#
|
138
|
+
# Convenience Method for +CLI::UI::Spinner.spin+
|
112
139
|
#
|
113
140
|
# ==== Attributes
|
114
141
|
#
|
115
142
|
# * +args+ - arguments for +Spinner.open+
|
116
143
|
# * +block+ - block for +Spinner.open+
|
117
144
|
#
|
118
|
-
def self.spinner(*args, &block)
|
119
|
-
CLI::UI::Spinner.spin(*args, &block)
|
145
|
+
def self.spinner(*args, **kwargs, &block)
|
146
|
+
CLI::UI::Spinner.spin(*args, **kwargs, &block)
|
120
147
|
end
|
121
148
|
|
122
|
-
#
|
149
|
+
# Convenience Method to override frame color using +CLI::UI::Frame.with_frame_color+
|
123
150
|
#
|
124
151
|
# ==== Attributes
|
125
152
|
#
|
@@ -143,7 +170,7 @@ module CLI
|
|
143
170
|
CLI::UI::StdoutRouter.duplicate_output_to = File.open(path, 'w')
|
144
171
|
yield
|
145
172
|
ensure
|
146
|
-
if file_descriptor = CLI::UI::StdoutRouter.duplicate_output_to
|
173
|
+
if (file_descriptor = CLI::UI::StdoutRouter.duplicate_output_to)
|
147
174
|
file_descriptor.close
|
148
175
|
CLI::UI::StdoutRouter.duplicate_output_to = nil
|
149
176
|
end
|
@@ -182,6 +209,19 @@ module CLI
|
|
182
209
|
end
|
183
210
|
|
184
211
|
self.enable_color = $stdout.tty?
|
212
|
+
|
213
|
+
# Set the default frame style.
|
214
|
+
# Convenience method for setting the default frame style with +CLI::UI::Frame.frame_style=+
|
215
|
+
#
|
216
|
+
# Raises ArgumentError if +frame_style+ is not valid
|
217
|
+
#
|
218
|
+
# ==== Attributes
|
219
|
+
#
|
220
|
+
# * +symbol+ - the default frame style to use for frames
|
221
|
+
#
|
222
|
+
def self.frame_style=(frame_style)
|
223
|
+
Frame.frame_style = frame_style.to_sym
|
224
|
+
end
|
185
225
|
end
|
186
226
|
end
|
187
227
|
|
data/lib/cli/ui/ansi.rb
CHANGED
@@ -106,7 +106,9 @@ module CLI
|
|
106
106
|
# * +n+ - The column to move to
|
107
107
|
#
|
108
108
|
def self.cursor_horizontal_absolute(n = 1)
|
109
|
-
control(n.to_s, 'G')
|
109
|
+
cmd = control(n.to_s, 'G')
|
110
|
+
cmd += control('1', 'D') if CLI::UI::OS.current.shift_cursor_on_line_reset?
|
111
|
+
cmd
|
110
112
|
end
|
111
113
|
|
112
114
|
# Show the cursor
|
@@ -136,13 +138,17 @@ module CLI
|
|
136
138
|
# Move to the next line
|
137
139
|
#
|
138
140
|
def self.next_line
|
139
|
-
cursor_down + control('1', 'G')
|
141
|
+
cmd = cursor_down + control('1', 'G')
|
142
|
+
cmd += control('1', 'D') if CLI::UI::OS.current.shift_cursor_on_line_reset?
|
143
|
+
cmd
|
140
144
|
end
|
141
145
|
|
142
146
|
# Move to the previous line
|
143
147
|
#
|
144
148
|
def self.previous_line
|
145
|
-
cursor_up + control('1', 'G')
|
149
|
+
cmd = cursor_up + control('1', 'G')
|
150
|
+
cmd += control('1', 'D') if CLI::UI::OS.current.shift_cursor_on_line_reset?
|
151
|
+
cmd
|
146
152
|
end
|
147
153
|
|
148
154
|
def self.clear_to_end_of_line
|
data/lib/cli/ui/color.rb
CHANGED
@@ -35,19 +35,20 @@ module CLI
|
|
35
35
|
GRAY = new('38;5;244', :grey)
|
36
36
|
|
37
37
|
MAP = {
|
38
|
-
red:
|
39
|
-
green:
|
40
|
-
yellow:
|
41
|
-
blue:
|
38
|
+
red: RED,
|
39
|
+
green: GREEN,
|
40
|
+
yellow: YELLOW,
|
41
|
+
blue: BLUE,
|
42
42
|
magenta: MAGENTA,
|
43
|
-
cyan:
|
44
|
-
reset:
|
45
|
-
bold:
|
46
|
-
gray:
|
43
|
+
cyan: CYAN,
|
44
|
+
reset: RESET,
|
45
|
+
bold: BOLD,
|
46
|
+
gray: GRAY,
|
47
47
|
}.freeze
|
48
48
|
|
49
49
|
class InvalidColorName < ArgumentError
|
50
50
|
def initialize(name)
|
51
|
+
super
|
51
52
|
@name = name
|
52
53
|
end
|
53
54
|
|
data/lib/cli/ui/formatter.rb
CHANGED
@@ -12,23 +12,23 @@ module CLI
|
|
12
12
|
#
|
13
13
|
SGR_MAP = {
|
14
14
|
# presentational
|
15
|
-
'red'
|
16
|
-
'green'
|
17
|
-
'yellow'
|
15
|
+
'red' => '31',
|
16
|
+
'green' => '32',
|
17
|
+
'yellow' => '33',
|
18
18
|
# default blue is low-contrast against black in some default terminal color scheme
|
19
|
-
'blue'
|
20
|
-
'magenta'
|
21
|
-
'cyan'
|
22
|
-
'bold'
|
23
|
-
'italic'
|
19
|
+
'blue' => '94', # 9x = high-intensity fg color x
|
20
|
+
'magenta' => '35',
|
21
|
+
'cyan' => '36',
|
22
|
+
'bold' => '1',
|
23
|
+
'italic' => '3',
|
24
24
|
'underline' => '4',
|
25
|
-
'reset'
|
25
|
+
'reset' => '0',
|
26
26
|
|
27
27
|
# semantic
|
28
|
-
'error'
|
28
|
+
'error' => '31', # red
|
29
29
|
'success' => '32', # success
|
30
30
|
'warning' => '33', # yellow
|
31
|
-
'info'
|
31
|
+
'info' => '94', # bright blue
|
32
32
|
'command' => '36', # cyan
|
33
33
|
}.freeze
|
34
34
|
|
@@ -166,10 +166,10 @@ module CLI
|
|
166
166
|
|
167
167
|
def parse_body(sc, stack = [])
|
168
168
|
match = sc.scan(SCAN_BODY)
|
169
|
-
if match
|
169
|
+
if match&.end_with?(BEGIN_EXPR)
|
170
170
|
emit(match[DISCARD_BRACES], stack)
|
171
171
|
parse_expr(sc, stack)
|
172
|
-
elsif match
|
172
|
+
elsif match&.end_with?(END_EXPR)
|
173
173
|
emit(match[DISCARD_BRACES], stack)
|
174
174
|
if stack.pop == LITERAL_BRACES
|
175
175
|
emit('}}', stack)
|