cli-ui 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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