cli-ui 1.4.0 → 1.5.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/.rubocop.yml +5 -2
- data/.travis.yml +1 -1
- data/Gemfile +3 -2
- data/Gemfile.lock +22 -18
- data/Rakefile +1 -1
- data/bin/console +3 -3
- data/cli-ui.gemspec +11 -11
- data/lib/cli/ui.rb +19 -14
- data/lib/cli/ui/ansi.rb +7 -9
- data/lib/cli/ui/frame.rb +5 -5
- data/lib/cli/ui/frame/frame_stack.rb +2 -2
- data/lib/cli/ui/frame/frame_style.rb +1 -1
- data/lib/cli/ui/glyph.rb +1 -0
- data/lib/cli/ui/os.rb +8 -4
- data/lib/cli/ui/printer.rb +15 -3
- data/lib/cli/ui/prompt.rb +21 -6
- data/lib/cli/ui/prompt/interactive_options.rb +11 -18
- data/lib/cli/ui/spinner/spin_group.rb +2 -2
- data/lib/cli/ui/stdout_router.rb +1 -1
- data/lib/cli/ui/truncater.rb +1 -1
- data/lib/cli/ui/version.rb +1 -1
- data/lib/cli/ui/wrap.rb +56 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8de8c1fd6c855f812125e71e85dbfc12163dfd504215fab462d56ad5f4d2cc7e
|
4
|
+
data.tar.gz: 404f164084fd9cf85aa382a5d5f93b77b08ea4bc529840ebfe230e1b5ea7c620
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f737c534e372589165a3263854d3a90f024181f632f6ae918fcb7aafea69abad27f50246d35c2957c238447a74871f4705add26d1bf272ad58f4fcc52d31ae6
|
7
|
+
data.tar.gz: 56c449900c817637b97d0e99b05ac01375bbde1458db3f2d5e7122027cdd525e0b8aaf9b9d5290cc2f1fa8cae314efb1365ac46ab277629f5cebf5d113e39b0d
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
-
|
1
|
+
inherit_gem:
|
2
|
+
rubocop-shopify: rubocop-cli.yml
|
3
3
|
|
4
4
|
AllCops:
|
5
5
|
Exclude:
|
@@ -36,3 +36,6 @@ Style/MultilineBlockChain:
|
|
36
36
|
# we prefer rescue to align with the beginning of the line containing begin, not begin itself
|
37
37
|
Layout/RescueEnsureAlignment:
|
38
38
|
Enabled: false
|
39
|
+
|
40
|
+
Style/StringLiterals:
|
41
|
+
EnforcedStyle: single_quotes
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# NOTE: These are development-only dependencies
|
2
|
-
source
|
2
|
+
source 'https://rubygems.org'
|
3
3
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :development, :test do
|
7
7
|
gem 'rubocop'
|
8
|
-
gem '
|
8
|
+
gem 'rubocop-shopify'
|
9
|
+
gem 'byebug', platforms: [:mri]
|
9
10
|
gem 'method_source'
|
10
11
|
end
|
11
12
|
|
data/Gemfile.lock
CHANGED
@@ -1,45 +1,48 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cli-ui (1.
|
4
|
+
cli-ui (1.5.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ansi (1.5.0)
|
10
|
-
ast (2.4.
|
10
|
+
ast (2.4.2)
|
11
11
|
builder (3.2.4)
|
12
12
|
byebug (11.1.3)
|
13
13
|
method_source (1.0.0)
|
14
|
-
minitest (5.14.
|
15
|
-
minitest-reporters (1.4.
|
14
|
+
minitest (5.14.4)
|
15
|
+
minitest-reporters (1.4.3)
|
16
16
|
ansi
|
17
17
|
builder
|
18
18
|
minitest (>= 5.0)
|
19
19
|
ruby-progressbar
|
20
|
-
mocha (1.
|
21
|
-
parallel (1.
|
22
|
-
parser (
|
20
|
+
mocha (1.12.0)
|
21
|
+
parallel (1.20.1)
|
22
|
+
parser (3.0.0.0)
|
23
23
|
ast (~> 2.4.1)
|
24
24
|
rainbow (3.0.0)
|
25
|
-
rake (13.0.
|
26
|
-
regexp_parser (1.
|
27
|
-
rexml (3.2.
|
28
|
-
rubocop (1.1
|
25
|
+
rake (13.0.3)
|
26
|
+
regexp_parser (2.1.1)
|
27
|
+
rexml (3.2.5)
|
28
|
+
rubocop (1.12.1)
|
29
29
|
parallel (~> 1.10)
|
30
|
-
parser (>=
|
30
|
+
parser (>= 3.0.0.0)
|
31
31
|
rainbow (>= 2.2.2, < 4.0)
|
32
|
-
regexp_parser (>= 1.8)
|
32
|
+
regexp_parser (>= 1.8, < 3.0)
|
33
33
|
rexml
|
34
|
-
rubocop-ast (>= 1.0.
|
34
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
35
35
|
ruby-progressbar (~> 1.7)
|
36
|
-
unicode-display_width (>= 1.4.0, <
|
37
|
-
rubocop-ast (1.1
|
36
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
37
|
+
rubocop-ast (1.4.1)
|
38
38
|
parser (>= 2.7.1.5)
|
39
|
-
|
40
|
-
|
39
|
+
rubocop-shopify (2.0.1)
|
40
|
+
rubocop (~> 1.11)
|
41
|
+
ruby-progressbar (1.11.0)
|
42
|
+
unicode-display_width (2.0.0)
|
41
43
|
|
42
44
|
PLATFORMS
|
45
|
+
java
|
43
46
|
ruby
|
44
47
|
|
45
48
|
DEPENDENCIES
|
@@ -51,6 +54,7 @@ DEPENDENCIES
|
|
51
54
|
mocha
|
52
55
|
rake (~> 13.0)
|
53
56
|
rubocop
|
57
|
+
rubocop-shopify
|
54
58
|
|
55
59
|
BUNDLED WITH
|
56
60
|
2.1.0
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'cli/ui'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "cli/ui"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start(__FILE__)
|
data/cli-ui.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require 'cli/ui/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'cli-ui'
|
8
8
|
spec.version = CLI::UI::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Burke Libbey', 'Julian Nadeau', 'Lisa Ugray']
|
10
|
+
spec.email = ['burke.libbey@shopify.com', 'julian.nadeau@shopify.com', 'lisa.ugray@shopify.com']
|
11
11
|
|
12
12
|
spec.summary = 'Terminal UI framework'
|
13
13
|
spec.description = 'Terminal UI framework'
|
14
|
-
spec.homepage =
|
15
|
-
spec.license =
|
14
|
+
spec.homepage = 'https://github.com/shopify/cli-ui'
|
15
|
+
spec.license = 'MIT'
|
16
16
|
|
17
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
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
-
spec.require_paths = [
|
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/lib/cli/ui.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
module CLI
|
2
2
|
module UI
|
3
|
-
autoload :ANSI,
|
4
|
-
autoload :Glyph,
|
5
|
-
autoload :Color,
|
6
|
-
autoload :Frame,
|
7
|
-
autoload :OS,
|
8
|
-
autoload :Printer,
|
9
|
-
autoload :Progress,
|
10
|
-
autoload :Prompt,
|
11
|
-
autoload :Terminal,
|
12
|
-
autoload :Truncater,
|
13
|
-
autoload :Formatter,
|
14
|
-
autoload :Spinner,
|
15
|
-
autoload :Widgets,
|
3
|
+
autoload :ANSI, 'cli/ui/ansi'
|
4
|
+
autoload :Glyph, 'cli/ui/glyph'
|
5
|
+
autoload :Color, 'cli/ui/color'
|
6
|
+
autoload :Frame, 'cli/ui/frame'
|
7
|
+
autoload :OS, 'cli/ui/os'
|
8
|
+
autoload :Printer, 'cli/ui/printer'
|
9
|
+
autoload :Progress, 'cli/ui/progress'
|
10
|
+
autoload :Prompt, 'cli/ui/prompt'
|
11
|
+
autoload :Terminal, 'cli/ui/terminal'
|
12
|
+
autoload :Truncater, 'cli/ui/truncater'
|
13
|
+
autoload :Formatter, 'cli/ui/formatter'
|
14
|
+
autoload :Spinner, 'cli/ui/spinner'
|
15
|
+
autoload :Widgets, 'cli/ui/widgets'
|
16
|
+
autoload :Wrap, 'cli/ui/wrap'
|
16
17
|
|
17
18
|
# Convenience accessor to +CLI::UI::Spinner::SpinGroup+
|
18
19
|
SpinGroup = Spinner::SpinGroup
|
@@ -113,6 +114,10 @@ module CLI
|
|
113
114
|
CLI::UI::Formatter.new(input).format(enable_color: enable_color)
|
114
115
|
end
|
115
116
|
|
117
|
+
def self.wrap(input)
|
118
|
+
CLI::UI::Wrap.new(input).wrap
|
119
|
+
end
|
120
|
+
|
116
121
|
# Convenience Method for +CLI::UI::Printer.puts+
|
117
122
|
#
|
118
123
|
# ==== Attributes
|
@@ -165,7 +170,7 @@ module CLI
|
|
165
170
|
#
|
166
171
|
def self.log_output_to(path)
|
167
172
|
if CLI::UI::StdoutRouter.duplicate_output_to
|
168
|
-
raise
|
173
|
+
raise 'multiple logs not allowed'
|
169
174
|
end
|
170
175
|
CLI::UI::StdoutRouter.duplicate_output_to = File.open(path, 'w')
|
171
176
|
yield
|
data/lib/cli/ui/ansi.rb
CHANGED
@@ -21,6 +21,8 @@ module CLI
|
|
21
21
|
when 0x200d # zero-width joiner
|
22
22
|
zwj = true
|
23
23
|
acc
|
24
|
+
when "\n"
|
25
|
+
acc
|
24
26
|
else
|
25
27
|
acc + 1
|
26
28
|
end
|
@@ -45,7 +47,7 @@ module CLI
|
|
45
47
|
# - +cmd+ - ANSI control sequence Command
|
46
48
|
#
|
47
49
|
def self.control(args, cmd)
|
48
|
-
ESC +
|
50
|
+
ESC + '[' + args + cmd
|
49
51
|
end
|
50
52
|
|
51
53
|
# https://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
@@ -114,13 +116,13 @@ module CLI
|
|
114
116
|
# Show the cursor
|
115
117
|
#
|
116
118
|
def self.show_cursor
|
117
|
-
control('',
|
119
|
+
control('', '?25h')
|
118
120
|
end
|
119
121
|
|
120
122
|
# Hide the cursor
|
121
123
|
#
|
122
124
|
def self.hide_cursor
|
123
|
-
control('',
|
125
|
+
control('', '?25l')
|
124
126
|
end
|
125
127
|
|
126
128
|
# Save the cursor position
|
@@ -138,17 +140,13 @@ module CLI
|
|
138
140
|
# Move to the next line
|
139
141
|
#
|
140
142
|
def self.next_line
|
141
|
-
|
142
|
-
cmd += control('1', 'D') if CLI::UI::OS.current.shift_cursor_on_line_reset?
|
143
|
-
cmd
|
143
|
+
cursor_down + cursor_horizontal_absolute
|
144
144
|
end
|
145
145
|
|
146
146
|
# Move to the previous line
|
147
147
|
#
|
148
148
|
def self.previous_line
|
149
|
-
|
150
|
-
cmd += control('1', 'D') if CLI::UI::OS.current.shift_cursor_on_line_reset?
|
151
|
-
cmd
|
149
|
+
cursor_up + cursor_horizontal_absolute
|
152
150
|
end
|
153
151
|
|
154
152
|
def self.clear_to_end_of_line
|
data/lib/cli/ui/frame.rb
CHANGED
@@ -80,11 +80,11 @@ module CLI
|
|
80
80
|
|
81
81
|
unless block_given?
|
82
82
|
if failure_text
|
83
|
-
raise ArgumentError,
|
83
|
+
raise ArgumentError, 'failure_text is not compatible with blockless invocation'
|
84
84
|
elsif success_text
|
85
|
-
raise ArgumentError,
|
85
|
+
raise ArgumentError, 'success_text is not compatible with blockless invocation'
|
86
86
|
elsif timing
|
87
|
-
raise ArgumentError,
|
87
|
+
raise ArgumentError, 'timing is not compatible with blockless invocation'
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
@@ -147,7 +147,7 @@ module CLI
|
|
147
147
|
#
|
148
148
|
def divider(text, color: nil, frame_style: nil)
|
149
149
|
fs_item = FrameStack.pop
|
150
|
-
raise UnnestedFrameException,
|
150
|
+
raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
|
151
151
|
|
152
152
|
color = CLI::UI.resolve_color(color) || fs_item.color
|
153
153
|
frame_style = CLI::UI.resolve_style(frame_style) || fs_item.frame_style
|
@@ -186,7 +186,7 @@ module CLI
|
|
186
186
|
#
|
187
187
|
def close(text, color: nil, elapsed: nil, frame_style: nil)
|
188
188
|
fs_item = FrameStack.pop
|
189
|
-
raise UnnestedFrameException,
|
189
|
+
raise UnnestedFrameException, 'No frame nesting to unnest' unless fs_item
|
190
190
|
|
191
191
|
color = CLI::UI.resolve_color(color) || fs_item.color
|
192
192
|
frame_style = CLI::UI.resolve_style(frame_style) || fs_item.frame_style
|
@@ -46,11 +46,11 @@ module CLI
|
|
46
46
|
def push(item = nil, color: nil, style: nil)
|
47
47
|
unless item.nil?
|
48
48
|
unless item.is_a?(StackItem)
|
49
|
-
raise ArgumentError,
|
49
|
+
raise ArgumentError, 'item must be a StackItem'
|
50
50
|
end
|
51
51
|
|
52
52
|
unless color.nil? && style.nil?
|
53
|
-
raise ArgumentError,
|
53
|
+
raise ArgumentError, 'Must give one of item or color: and style:'
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -39,7 +39,7 @@ module CLI
|
|
39
39
|
def message
|
40
40
|
keys = FrameStyle.loaded_styles.map(&:inspect).join(',')
|
41
41
|
"invalid frame style: #{@name.inspect}" \
|
42
|
-
|
42
|
+
' -- must be one of CLI::UI::Frame::FrameStyle.loaded_styles ' \
|
43
43
|
"(#{keys})"
|
44
44
|
end
|
45
45
|
end
|
data/lib/cli/ui/glyph.rb
CHANGED
@@ -57,6 +57,7 @@ module CLI
|
|
57
57
|
BUG = new('b', 0x1f41b, '!', Color::WHITE) # Bug emoji (🐛)
|
58
58
|
CHEVRON = new('>', 0xbb, '»', Color::YELLOW) # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK (»)
|
59
59
|
HOURGLASS = new('H', [0x231b, 0xfe0e], 'H', Color::BLUE) # HOURGLASS + VARIATION SELECTOR 15 (⌛︎)
|
60
|
+
WARNING = new('!', [0x26a0, 0xfe0f], '!', Color::YELLOW) # WARNING SIGN + VARIATION SELECTOR 16 (⚠️ )
|
60
61
|
|
61
62
|
# Looks up a glyph by name
|
62
63
|
#
|
data/lib/cli/ui/os.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
1
3
|
module CLI
|
2
4
|
module UI
|
3
5
|
module OS
|
4
6
|
# Determines which OS is currently running the UI, to make it easier to
|
5
7
|
# adapt its behaviour to the features of the OS.
|
6
8
|
def self.current
|
7
|
-
@current_os ||= case
|
9
|
+
@current_os ||= case RbConfig::CONFIG['host_os']
|
8
10
|
when /darwin/
|
9
11
|
Mac
|
10
12
|
when /linux/
|
11
13
|
Linux
|
12
|
-
when /mingw32/
|
13
|
-
Windows
|
14
14
|
else
|
15
|
-
|
15
|
+
if RUBY_PLATFORM !~ /cygwin/ && ENV['OS'] == 'Windows_NT'
|
16
|
+
Windows
|
17
|
+
else
|
18
|
+
raise "Could not determine OS from host_os #{RbConfig::CONFIG["host_os"]}"
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
data/lib/cli/ui/printer.rb
CHANGED
@@ -18,6 +18,7 @@ module CLI
|
|
18
18
|
# * +:encoding+ - Force the output to be in a certain encoding. Defaults to UTF-8.
|
19
19
|
# * +:format+ - Whether to format the string using CLI::UI.fmt. Defaults to true.
|
20
20
|
# * +:graceful+ - Whether to gracefully ignore common I/O errors. Defaults to true.
|
21
|
+
# * +:wrap+ - Whether to wrap text at word boundaries to terminal width. Defaults to true.
|
21
22
|
#
|
22
23
|
# ==== Returns
|
23
24
|
# Returns whether the message was successfully printed,
|
@@ -25,11 +26,22 @@ module CLI
|
|
25
26
|
#
|
26
27
|
# ==== Example
|
27
28
|
#
|
28
|
-
# CLI::UI::Printer.puts('{x} Ouch',
|
29
|
-
#
|
30
|
-
def self.puts(
|
29
|
+
# CLI::UI::Printer.puts('{{x}} Ouch', to: $stderr)
|
30
|
+
#
|
31
|
+
def self.puts(
|
32
|
+
msg,
|
33
|
+
frame_color:
|
34
|
+
nil,
|
35
|
+
to:
|
36
|
+
$stdout,
|
37
|
+
encoding: Encoding::UTF_8,
|
38
|
+
format: true,
|
39
|
+
graceful: true,
|
40
|
+
wrap: true
|
41
|
+
)
|
31
42
|
msg = (+msg).force_encoding(encoding) if encoding
|
32
43
|
msg = CLI::UI.fmt(msg) if format
|
44
|
+
msg = CLI::UI.wrap(msg) if wrap
|
33
45
|
|
34
46
|
if frame_color
|
35
47
|
CLI::UI::Frame.with_frame_color_override(frame_color) { to.puts(msg) }
|
data/lib/cli/ui/prompt.rb
CHANGED
@@ -2,6 +2,21 @@
|
|
2
2
|
require 'cli/ui'
|
3
3
|
require 'readline'
|
4
4
|
|
5
|
+
module Readline
|
6
|
+
unless const_defined?(:FILENAME_COMPLETION_PROC)
|
7
|
+
FILENAME_COMPLETION_PROC = proc do |input|
|
8
|
+
directory = input[-1] == '/' ? input : File.dirname(input)
|
9
|
+
filename = input[-1] == '/' ? '' : File.basename(input)
|
10
|
+
|
11
|
+
(Dir.entries(directory).select do |fp|
|
12
|
+
fp.start_with?(filename)
|
13
|
+
end - (input[-1] == '.' ? [] : ['.', '..'])).map do |fp|
|
14
|
+
File.join(directory, fp).gsub(/\A\.\//, '')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
5
20
|
module CLI
|
6
21
|
module UI
|
7
22
|
module Prompt
|
@@ -191,12 +206,12 @@ module CLI
|
|
191
206
|
|
192
207
|
raise(ArgumentError, 'insufficient options') if options.nil? || options.empty?
|
193
208
|
navigate_text = if CLI::UI::OS.current.supports_arrow_keys?
|
194
|
-
|
209
|
+
'Choose with ↑ ↓ ⏎'
|
195
210
|
else
|
196
211
|
"Navigate up with 'k' and down with 'j', press Enter to select"
|
197
212
|
end
|
198
213
|
|
199
|
-
instructions = (multiple ?
|
214
|
+
instructions = (multiple ? 'Toggle options. ' : '') + navigate_text
|
200
215
|
instructions += ", filter with 'f'" if filter_ui
|
201
216
|
instructions += ", enter option with 'e'" if select_ui && (options.size > 9)
|
202
217
|
puts_question("#{question} {{yellow:(#{instructions})}}")
|
@@ -212,9 +227,9 @@ module CLI
|
|
212
227
|
if multiple
|
213
228
|
resp_text = case resp.size
|
214
229
|
when 0
|
215
|
-
|
230
|
+
'<nothing>'
|
216
231
|
when 1..2
|
217
|
-
resp.join(
|
232
|
+
resp.join(' and ')
|
218
233
|
else
|
219
234
|
"#{resp.size} items"
|
220
235
|
end
|
@@ -251,10 +266,10 @@ module CLI
|
|
251
266
|
def readline(is_file: false)
|
252
267
|
if is_file
|
253
268
|
Readline.completion_proc = Readline::FILENAME_COMPLETION_PROC
|
254
|
-
Readline.completion_append_character =
|
269
|
+
Readline.completion_append_character = ''
|
255
270
|
else
|
256
271
|
Readline.completion_proc = proc { |*| nil }
|
257
|
-
Readline.completion_append_character =
|
272
|
+
Readline.completion_append_character = ' '
|
258
273
|
end
|
259
274
|
|
260
275
|
# because Readline is a C library, CLI::UI's hooks into $stdout don't
|
@@ -5,8 +5,8 @@ module CLI
|
|
5
5
|
module UI
|
6
6
|
module Prompt
|
7
7
|
class InteractiveOptions
|
8
|
-
DONE =
|
9
|
-
CHECKBOX_ICON = { false =>
|
8
|
+
DONE = 'Done'
|
9
|
+
CHECKBOX_ICON = { false => '☐', true => '☑' }
|
10
10
|
|
11
11
|
# Prompts the user with options
|
12
12
|
# Uses an interactive session to allow the user to pick an answer
|
@@ -267,7 +267,7 @@ module CLI
|
|
267
267
|
when 'f', '/' ; start_filter
|
268
268
|
when ('0'..max_digit) ; select_n(char.to_i)
|
269
269
|
when 'y', 'n' ; select_bool(char)
|
270
|
-
when
|
270
|
+
when ' ', "\r", "\n" ; select_current # <enter>
|
271
271
|
end
|
272
272
|
when :filter
|
273
273
|
case char
|
@@ -334,22 +334,15 @@ module CLI
|
|
334
334
|
end
|
335
335
|
|
336
336
|
def read_char
|
337
|
-
|
338
|
-
|
339
|
-
|
337
|
+
if $stdin.tty? && !ENV['TEST']
|
338
|
+
$stdin.getch # raw mode for tty
|
339
|
+
else
|
340
|
+
$stdin.getc
|
340
341
|
end
|
341
342
|
rescue IOError
|
342
343
|
"\e"
|
343
344
|
end
|
344
345
|
|
345
|
-
def raw_tty!
|
346
|
-
if ENV['TEST'] || !$stdin.tty?
|
347
|
-
yield
|
348
|
-
else
|
349
|
-
$stdin.raw { yield }
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
346
|
def presented_options(recalculate: false)
|
354
347
|
return @presented_options unless recalculate
|
355
348
|
|
@@ -411,11 +404,11 @@ module CLI
|
|
411
404
|
end
|
412
405
|
|
413
406
|
def ensure_last_item_is_continuation_marker
|
414
|
-
@presented_options.push([
|
407
|
+
@presented_options.push(['...', nil]) if @presented_options.last.last
|
415
408
|
end
|
416
409
|
|
417
410
|
def ensure_first_item_is_continuation_marker
|
418
|
-
@presented_options.unshift([
|
411
|
+
@presented_options.unshift(['...', nil]) if @presented_options.first.last
|
419
412
|
end
|
420
413
|
|
421
414
|
def max_lines
|
@@ -453,9 +446,9 @@ module CLI
|
|
453
446
|
is_chosen = @multiple && num && @chosen[num - 1] && num != 0
|
454
447
|
|
455
448
|
padding = ' ' * (max_num_length - num.to_s.length)
|
456
|
-
message = " #{num}#{num ?
|
449
|
+
message = " #{num}#{num ? "." : " "}#{padding}"
|
457
450
|
|
458
|
-
format =
|
451
|
+
format = '%s'
|
459
452
|
# If multiple, bold only selected. If not multiple, bold everything
|
460
453
|
format = "{{bold:#{format}}}" if !@multiple || is_chosen
|
461
454
|
format = "{{cyan:#{format}}}" if @multiple && is_chosen && num != @active
|
@@ -246,11 +246,11 @@ module CLI
|
|
246
246
|
end
|
247
247
|
|
248
248
|
CLI::UI::Frame.divider('STDOUT')
|
249
|
-
out =
|
249
|
+
out = '(empty)' if out.nil? || out.strip.empty?
|
250
250
|
puts out
|
251
251
|
|
252
252
|
CLI::UI::Frame.divider('STDERR')
|
253
|
-
err =
|
253
|
+
err = '(empty)' if err.nil? || err.strip.empty?
|
254
254
|
puts err
|
255
255
|
end
|
256
256
|
end
|
data/lib/cli/ui/stdout_router.rb
CHANGED
data/lib/cli/ui/truncater.rb
CHANGED
data/lib/cli/ui/version.rb
CHANGED
data/lib/cli/ui/wrap.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'cli/ui'
|
3
|
+
require 'cli/ui/frame/frame_stack'
|
4
|
+
require 'cli/ui/frame/frame_style'
|
5
|
+
|
6
|
+
module CLI
|
7
|
+
module UI
|
8
|
+
class Wrap
|
9
|
+
def initialize(input)
|
10
|
+
@input = input
|
11
|
+
end
|
12
|
+
|
13
|
+
def wrap
|
14
|
+
max_width = Terminal.width - Frame.prefix_width
|
15
|
+
width = 0
|
16
|
+
final = []
|
17
|
+
# Create an alternation of format codes of parameter lengths 1-20, since + and {1,n} not allowed in lookbehind
|
18
|
+
format_codes = (1..20).map { |n| /\x1b\[[\d;]{#{n}}m/ }.join('|')
|
19
|
+
codes = ''
|
20
|
+
@input.split(/(?=\s|\x1b\[[\d;]+m|\r)|(?<=\s|#{format_codes})/).each do |token|
|
21
|
+
case token
|
22
|
+
when '\x1B[0?m'
|
23
|
+
codes = ''
|
24
|
+
final << token
|
25
|
+
when /\x1b\[[\d;]+m/
|
26
|
+
codes += token # Track in use format codes so that they are resent after frame coloring
|
27
|
+
final << token
|
28
|
+
when "\n"
|
29
|
+
final << "\n#{codes}"
|
30
|
+
width = 0
|
31
|
+
when /\s/
|
32
|
+
token_width = ANSI.printing_width(token)
|
33
|
+
if width + token_width <= max_width
|
34
|
+
final << token
|
35
|
+
width += token_width
|
36
|
+
else
|
37
|
+
final << "\n#{codes}"
|
38
|
+
width = 0
|
39
|
+
end
|
40
|
+
else
|
41
|
+
token_width = ANSI.printing_width(token)
|
42
|
+
if width + token_width <= max_width
|
43
|
+
final << token
|
44
|
+
width += token_width
|
45
|
+
else
|
46
|
+
final << "\n#{codes}"
|
47
|
+
final << token
|
48
|
+
width = token_width
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
final.join
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cli-ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-04-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/cli/ui/widgets.rb
|
90
90
|
- lib/cli/ui/widgets/base.rb
|
91
91
|
- lib/cli/ui/widgets/status.rb
|
92
|
+
- lib/cli/ui/wrap.rb
|
92
93
|
homepage: https://github.com/shopify/cli-ui
|
93
94
|
licenses:
|
94
95
|
- MIT
|