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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8c6abe82a837c62e28cded106185a5ce2d09413637b94fb5bdb6524552648ac
4
- data.tar.gz: 780168b9d23cd55acd5e95e6abcb7b5b0732c694db2feb0f73d5b04ce71dcd63
3
+ metadata.gz: 8de8c1fd6c855f812125e71e85dbfc12163dfd504215fab462d56ad5f4d2cc7e
4
+ data.tar.gz: 404f164084fd9cf85aa382a5d5f93b77b08ea4bc529840ebfe230e1b5ea7c620
5
5
  SHA512:
6
- metadata.gz: cea8f4f738765f77a8474221a9449da3f7bb1cae7610fb5d21dc2ee02f7c03996fc26b661db4eefb1af924ab2b7af0469539040763804c7154353037100fdd0f
7
- data.tar.gz: bfe35b8ded93b0fe857d55836fd0b1aef67b6c5cb036550a152db464e3657607c0fde84621ccfd2541bb477d262b16e3adef0b320a1b037b3664f2141df99404
6
+ metadata.gz: 9f737c534e372589165a3263854d3a90f024181f632f6ae918fcb7aafea69abad27f50246d35c2957c238447a74871f4705add26d1bf272ad58f4fcc52d31ae6
7
+ data.tar.gz: 56c449900c817637b97d0e99b05ac01375bbde1458db3f2d5e7122027cdd525e0b8aaf9b9d5290cc2f1fa8cae314efb1365ac46ab277629f5cebf5d113e39b0d
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
- inherit_from:
2
- - http://shopify.github.io/ruby-style-guide/rubocop.yml
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
@@ -1,7 +1,7 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
3
  - 2.5.8
5
4
  - 2.6.6
6
5
  - 2.7.1
6
+ - jruby-9.2.14.0
7
7
  before_install: gem update --system
data/Gemfile CHANGED
@@ -1,11 +1,12 @@
1
1
  # NOTE: These are development-only dependencies
2
- source "https://rubygems.org"
2
+ source 'https://rubygems.org'
3
3
 
4
4
  gemspec
5
5
 
6
6
  group :development, :test do
7
7
  gem 'rubocop'
8
- gem 'byebug'
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.0)
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.1)
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.2)
15
- minitest-reporters (1.4.2)
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.11.2)
21
- parallel (1.19.2)
22
- parser (2.7.2.0)
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.1)
26
- regexp_parser (1.8.2)
27
- rexml (3.2.4)
28
- rubocop (1.1.0)
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 (>= 2.7.1.5)
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.1)
34
+ rubocop-ast (>= 1.2.0, < 2.0)
35
35
  ruby-progressbar (~> 1.7)
36
- unicode-display_width (>= 1.4.0, < 2.0)
37
- rubocop-ast (1.1.0)
36
+ unicode-display_width (>= 1.4.0, < 3.0)
37
+ rubocop-ast (1.4.1)
38
38
  parser (>= 2.7.1.5)
39
- ruby-progressbar (1.10.1)
40
- unicode-display_width (1.7.0)
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
@@ -7,7 +7,7 @@ require 'bundler/gem_tasks'
7
7
  TEST_ROOT = File.expand_path('../test', __FILE__)
8
8
 
9
9
  Rake::TestTask.new do |t|
10
- t.libs += ["test"]
10
+ t.libs += ['test']
11
11
  t.test_files = FileList[File.join(TEST_ROOT, '**', '*_test.rb')]
12
12
  t.verbose = false
13
13
  t.warning = false
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "cli/ui"
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 "irb"
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("../lib", __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "cli/ui/version"
4
+ require 'cli/ui/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "cli-ui"
7
+ spec.name = 'cli-ui'
8
8
  spec.version = CLI::UI::VERSION
9
- spec.authors = ["Burke Libbey", "Julian Nadeau", "Lisa Ugray"]
10
- spec.email = ["burke.libbey@shopify.com", "julian.nadeau@shopify.com", "lisa.ugray@shopify.com"]
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 = "https://github.com/shopify/cli-ui"
15
- spec.license = "MIT"
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 = "exe"
20
+ spec.bindir = 'exe'
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
22
+ spec.require_paths = ['lib']
23
23
 
24
24
  # spec.add_development_dependency "bundler", "~> 2.0"
25
- spec.add_development_dependency("rake", "~> 13.0")
26
- spec.add_development_dependency("minitest", "~> 5.0")
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, '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'
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 "multiple logs not allowed"
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 + "[" + args + cmd
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('', "?25h")
119
+ control('', '?25h')
118
120
  end
119
121
 
120
122
  # Hide the cursor
121
123
  #
122
124
  def self.hide_cursor
123
- control('', "?25l")
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
- cmd = cursor_down + control('1', 'G')
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
- cmd = cursor_up + control('1', 'G')
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, "failure_text is not compatible with blockless invocation"
83
+ raise ArgumentError, 'failure_text is not compatible with blockless invocation'
84
84
  elsif success_text
85
- raise ArgumentError, "success_text is not compatible with blockless invocation"
85
+ raise ArgumentError, 'success_text is not compatible with blockless invocation'
86
86
  elsif timing
87
- raise ArgumentError, "timing is not compatible with blockless invocation"
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, "No frame nesting to unnest" unless fs_item
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, "No frame nesting to unnest" unless fs_item
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, "item must be a StackItem"
49
+ raise ArgumentError, 'item must be a StackItem'
50
50
  end
51
51
 
52
52
  unless color.nil? && style.nil?
53
- raise ArgumentError, "Must give one of item or color: and style:"
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
- " -- must be one of CLI::UI::Frame::FrameStyle.loaded_styles " \
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 RUBY_PLATFORM
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
- raise "Could not determine OS from platform #{RUBY_PLATFORM}"
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
 
@@ -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', stream: $stderr, color: :red)
29
- #
30
- def self.puts(msg, frame_color: nil, to: $stdout, encoding: Encoding::UTF_8, format: true, graceful: true)
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
- "Choose with ↑ ↓ ⏎"
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 ? "Toggle options. " : "") + navigate_text
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
- "<nothing>"
230
+ '<nothing>'
216
231
  when 1..2
217
- resp.join(" and ")
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 = "Done"
9
- CHECKBOX_ICON = { false => "", true => "" }
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 " ", "\r", "\n" ; select_current # <enter>
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
- raw_tty! do
338
- getc = $stdin.getc
339
- getc ? getc.chr : :timeout
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(["...", nil]) if @presented_options.last.last
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(["...", nil]) if @presented_options.first.last
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 ? '.' : ' '}#{padding}"
449
+ message = " #{num}#{num ? "." : " "}#{padding}"
457
450
 
458
- format = "%s"
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 = "(empty)" if out.nil? || out.strip.empty?
249
+ out = '(empty)' if out.nil? || out.strip.empty?
250
250
  puts out
251
251
 
252
252
  CLI::UI::Frame.divider('STDERR')
253
- err = "(empty)" if err.nil? || err.strip.empty?
253
+ err = '(empty)' if err.nil? || err.strip.empty?
254
254
  puts err
255
255
  end
256
256
  end
@@ -161,7 +161,7 @@ module CLI
161
161
  end
162
162
 
163
163
  require 'securerandom'
164
- id = format("%05d", rand(10**5))
164
+ id = format('%05d', rand(10**5))
165
165
  Thread.current[:cliui_output_id] = {
166
166
  id: id,
167
167
  streams: on_streams,
@@ -83,7 +83,7 @@ module CLI
83
83
  # the end of the string.
84
84
  return text if !truncation_index || width <= printing_width
85
85
 
86
- codepoints[0...truncation_index].pack("U*") + TRUNCATED
86
+ codepoints[0...truncation_index].pack('U*') + TRUNCATED
87
87
  end
88
88
 
89
89
  private
@@ -1,5 +1,5 @@
1
1
  module CLI
2
2
  module UI
3
- VERSION = "1.4.0"
3
+ VERSION = '1.5.0'
4
4
  end
5
5
  end
@@ -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.0
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: 2020-11-02 00:00:00.000000000 Z
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