cli-ui 2.2.3 → 2.3.1

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: 140781de33cc19ef1c5bc946a0a887b3707e54475823affad8f5568e98fbc0dd
4
- data.tar.gz: b754caad8da6b0d37ea17d807aef78351518c4f17d511a39decbfb29b0512791
3
+ metadata.gz: 99ed2ae4a35b13db165864297acf7cfc4e636283e51683a7954ca2e2f43ac94c
4
+ data.tar.gz: 30eb1a74cdbd50b95d9c48209c97258261970c9678eb71e089bb894a018bcb0b
5
5
  SHA512:
6
- metadata.gz: 8d841fb206c3de7427c4903aa5bb350241c5fe10bbf39c04cb1980eada288deda4b235bf1d5d99a293ebaa6cd78482dd2f49849d65ddd3e7929d63d2f35894bc
7
- data.tar.gz: 6a99dc71d996abbff3fccdda8ce9ede069a7868ba467d86296bed3575e5726f50f76b65d4d427757f5ddaea211b7926d25045402ae5304e1593ae2fb6bc656fb
6
+ metadata.gz: 219e73a9baa10649b9cd14280ce9fe8d2f18a614006c9b4f5c8c79b3df3da3ef236c00ec290816ab866ff3d67cf058ecf5c88f0034e331a1ab77cdef1df25111
7
+ data.tar.gz: 79de546a04f2ca9fe49246be7df31582cafc791799bbacd868af7fa1e381e42a462685e619a734745500203a25587a7eb6eaee04465b269cee8242ad67334a1b
data/README.md CHANGED
@@ -162,7 +162,7 @@ CLI::UI.frame_style = :box
162
162
  To style an individual frame:
163
163
 
164
164
  ```ruby
165
- CLI::UI.frame('New Style!', frame_style: :bracket) { puts 'It's pretty cool!' }
165
+ CLI::UI.frame('New Style!', frame_style: :bracket) { puts "It's pretty cool!" }
166
166
  ```
167
167
 
168
168
  The default style - `:box` - is what has been used up until now. The other style - `:bracket` - looks like this:
data/lib/cli/ui/ansi.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui'
4
5
 
@@ -45,7 +46,7 @@ module CLI
45
46
  #
46
47
  sig { params(str: String).returns(String) }
47
48
  def strip_codes(str)
48
- str.gsub(/\x1b\[[\d;]+[A-z]|\r/, '')
49
+ str.gsub(/\x1b\[[\d;]+[A-Za-z]|\x1b\][\d;]+.*?\x1b\\|\r/, '')
49
50
  end
50
51
 
51
52
  # Returns an ANSI control sequence
@@ -145,7 +146,7 @@ module CLI
145
146
 
146
147
  sig { returns(Regexp) }
147
148
  def match_alternate_screen
148
- /#{Regexp.escape(control('?1049', ''))}[hl]/
149
+ /#{Regexp.escape(control("?1049", ""))}[hl]/
149
150
  end
150
151
 
151
152
  # Show the cursor
@@ -187,13 +188,34 @@ module CLI
187
188
  #
188
189
  sig { returns(String) }
189
190
  def previous_line
190
- cursor_up + cursor_horizontal_absolute
191
+ previous_lines(1)
192
+ end
193
+
194
+ # Move to the previous n lines
195
+ #
196
+ # ==== Attributes
197
+ #
198
+ # * +n+ - number of lines by which to move the cursor up
199
+ #
200
+ sig { params(n: Integer).returns(String) }
201
+ def previous_lines(n = 1)
202
+ cursor_up(n) + cursor_horizontal_absolute
191
203
  end
192
204
 
193
205
  sig { returns(String) }
194
206
  def clear_to_end_of_line
195
207
  control('', 'K')
196
208
  end
209
+
210
+ sig { returns(String) }
211
+ def insert_line
212
+ insert_lines(1)
213
+ end
214
+
215
+ sig { params(n: Integer).returns(String) }
216
+ def insert_lines(n = 1)
217
+ control(n.to_s, 'L')
218
+ end
197
219
  end
198
220
  end
199
221
  end
data/lib/cli/ui/color.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui'
4
5
 
@@ -42,6 +43,8 @@ module CLI
42
43
 
43
44
  # 240 is very dark gray; 255 is very light gray. 244 is somewhat dark.
44
45
  GRAY = new('38;5;244', :gray)
46
+ # Using color 214 from the 256-color palette for a more distinct orange
47
+ ORANGE = new('38;5;214', :orange)
45
48
 
46
49
  MAP = {
47
50
  red: RED,
@@ -28,6 +28,7 @@ module CLI
28
28
  'bold' => '1',
29
29
  'italic' => '3',
30
30
  'underline' => '4',
31
+ 'strikethrough' => '9',
31
32
  'reset' => '0',
32
33
 
33
34
  # semantic
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CLI
4
5
  module UI
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CLI
4
5
  module UI
@@ -94,7 +95,8 @@ module CLI
94
95
 
95
96
  preamble = +''
96
97
 
97
- preamble << color.code << first << (HORIZONTAL * 2)
98
+ preamble << color.code if CLI::UI.enable_color?
99
+ preamble << first << (HORIZONTAL * 2)
98
100
 
99
101
  unless text.empty?
100
102
  preamble << ' ' << CLI::UI.resolve_text("{{#{color.name}:#{text}}}") << ' '
@@ -128,18 +130,17 @@ module CLI
128
130
 
129
131
  o = +''
130
132
 
131
- # Shopify's CI system supports terminal emulation, but not some of
132
- # the fancier features that we normally use to draw frames
133
- # extra-reliably, so we fall back to a less foolproof strategy. This
134
- # is probably better in general for cases with impoverished terminal
135
- # emulators and no active user.
136
- unless [0, '', nil].include?(ENV['CI'])
133
+ unless CLI::UI.enable_cursor?
137
134
  linewidth = [0, termwidth - (preamble_end + suffix_width + 1)].max
138
135
 
139
- o << color.code << preamble
140
- o << color.code << (HORIZONTAL * linewidth)
141
- o << color.code << suffix
142
- o << CLI::UI::Color::RESET.code << "\n"
136
+ o << color.code if CLI::UI.enable_color?
137
+ o << preamble
138
+ o << color.code if CLI::UI.enable_color?
139
+ o << (HORIZONTAL * linewidth)
140
+ o << color.code if CLI::UI.enable_color?
141
+ o << suffix
142
+ o << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
143
+ o << "\n"
143
144
  return o
144
145
  end
145
146
 
@@ -158,12 +159,12 @@ module CLI
158
159
  # | | | | |
159
160
  # V V V V V
160
161
  # --- Preamble text --------------------- suffix text --
161
- o << color.code
162
+ o << color.code if CLI::UI.enable_color?
162
163
  o << print_at_x(preamble_start, HORIZONTAL * (termwidth - preamble_start)) # draw a full line
163
164
  o << print_at_x(preamble_start, preamble)
164
- o << color.code
165
+ o << color.code if CLI::UI.enable_color?
165
166
  o << print_at_x(suffix_start, suffix)
166
- o << CLI::UI::Color::RESET.code
167
+ o << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
167
168
  o << CLI::UI::ANSI.show_cursor
168
169
  o << "\n"
169
170
 
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CLI
4
5
  module UI
@@ -94,7 +95,8 @@ module CLI
94
95
 
95
96
  preamble = +''
96
97
 
97
- preamble << color.code << first << (HORIZONTAL * 2)
98
+ preamble << color.code if CLI::UI.enable_color?
99
+ preamble << first << (HORIZONTAL * 2)
98
100
 
99
101
  unless text.empty?
100
102
  preamble << ' ' << CLI::UI.resolve_text("{{#{color.name}:#{text}}}") << ' '
@@ -108,15 +110,12 @@ module CLI
108
110
 
109
111
  o = +''
110
112
 
111
- # Shopify's CI system supports terminal emulation, but not some of
112
- # the fancier features that we normally use to draw frames
113
- # extra-reliably, so we fall back to a less foolproof strategy. This
114
- # is probably better in general for cases with impoverished terminal
115
- # emulators and no active user.
116
- unless [0, '', nil].include?(ENV['CI'])
117
- o << color.code << preamble
118
- o << color.code << suffix
119
- o << CLI::UI::Color::RESET.code
113
+ unless CLI::UI.enable_cursor?
114
+ o << color.code if CLI::UI.enable_color?
115
+ o << preamble
116
+ o << color.code if CLI::UI.enable_color?
117
+ o << suffix
118
+ o << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
120
119
  o << "\n"
121
120
 
122
121
  return o
@@ -134,9 +133,11 @@ module CLI
134
133
  # reset to column 1 so that things like ^C don't ruin formatting
135
134
  o << "\r"
136
135
 
137
- o << color.code
138
- o << print_at_x(preamble_start, preamble + color.code + suffix)
139
- o << CLI::UI::Color::RESET.code
136
+ o << color.code if CLI::UI.enable_color?
137
+ o << print_at_x(preamble_start, preamble)
138
+ o << color.code if CLI::UI.enable_color?
139
+ o << suffix
140
+ o << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
140
141
  o << CLI::UI::ANSI.show_cursor
141
142
  o << "\n"
142
143
 
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui/frame'
4
5
 
@@ -106,8 +107,8 @@ module CLI
106
107
  sig { returns(String) }
107
108
  def message
108
109
  keys = FrameStyle::MAP.keys.map(&:inspect).join(', ')
109
- "invalid frame style: #{@name.inspect}" \
110
- ' -- must be one of CLI::UI::Frame::FrameStyle::MAP ' \
110
+ "invalid frame style: #{@name.inspect} " \
111
+ '-- must be one of CLI::UI::Frame::FrameStyle::MAP ' \
111
112
  "(#{keys})"
112
113
  end
113
114
  end
data/lib/cli/ui/frame.rb CHANGED
@@ -1,6 +1,5 @@
1
- # coding: utf-8
2
-
3
1
  # typed: true
2
+ # frozen_string_literal: true
4
3
 
5
4
  require 'cli/ui'
6
5
  require 'cli/ui/frame/frame_stack'
@@ -250,19 +249,21 @@ module CLI
250
249
  #
251
250
  sig { params(color: T.nilable(Colorable)).returns(String) }
252
251
  def prefix(color: Thread.current[:cliui_frame_color_override])
253
- +''.tap do |output|
252
+ (+'').tap do |output|
254
253
  items = FrameStack.items
255
254
 
256
255
  items[0..-2].to_a.each do |item|
257
- output << item.color.code << item.frame_style.prefix
256
+ output << item.color.code if CLI::UI.enable_color?
257
+ output << item.frame_style.prefix
258
+ output << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
258
259
  end
259
260
 
260
261
  if (item = items.last)
261
262
  final_color = color || item.color
262
- output << CLI::UI.resolve_color(final_color).code \
263
- << item.frame_style.prefix \
264
- << ' ' \
265
- << CLI::UI::Color::RESET.code
263
+ output << CLI::UI.resolve_color(final_color).code if CLI::UI.enable_color?
264
+ output << item.frame_style.prefix
265
+ output << CLI::UI::Color::RESET.code if CLI::UI.enable_color?
266
+ output << ' '
266
267
  end
267
268
  end
268
269
  end
data/lib/cli/ui/glyph.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui'
4
5
 
@@ -63,7 +64,7 @@ module CLI
63
64
  X = new('x', 0x2717, 'X', Color::RED) # RED BALLOT X (✗)
64
65
  BUG = new('b', 0x1f41b, '!', Color::WHITE) # Bug emoji (🐛)
65
66
  CHEVRON = new('>', 0xbb, '»', Color::YELLOW) # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK (»)
66
- HOURGLASS = new('H', [0x231b, 0xfe0e], 'H', Color::BLUE) # HOURGLASS + VARIATION SELECTOR 15 (⌛︎)
67
+ HOURGLASS = new('H', 0x29d6, 'H', Color::ORANGE) # HOURGLASS ()
67
68
  WARNING = new('!', [0x26a0, 0xfe0f], '!', Color::YELLOW) # WARNING SIGN + VARIATION SELECTOR 16 (⚠️ )
68
69
 
69
70
  class << self
data/lib/cli/ui/os.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'rbconfig'
4
5
 
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui'
4
5
 
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'cli/ui'
4
5
 
@@ -35,13 +36,23 @@ module CLI
35
36
  # CLI::UI::Progress.progress do |bar|
36
37
  # bar.tick(percent: 0.05)
37
38
  # end
39
+ #
40
+ # Update the title
41
+ # CLI::UI::Progress.progress('Title') do |bar|
42
+ # bar.tick(percent: 0.05)
43
+ # bar.update_title('New title')
44
+ # end
38
45
  sig do
39
46
  type_parameters(:T)
40
- .params(width: Integer, block: T.proc.params(bar: Progress).returns(T.type_parameter(:T)))
47
+ .params(
48
+ title: T.nilable(String),
49
+ width: Integer,
50
+ block: T.proc.params(bar: Progress).returns(T.type_parameter(:T)),
51
+ )
41
52
  .returns(T.type_parameter(:T))
42
53
  end
43
- def progress(width: Terminal.width, &block)
44
- bar = Progress.new(width: width)
54
+ def progress(title = nil, width: Terminal.width, &block)
55
+ bar = Progress.new(title, width: width)
45
56
  print(CLI::UI::ANSI.hide_cursor)
46
57
  yield(bar)
47
58
  ensure
@@ -55,13 +66,14 @@ module CLI
55
66
  # Initialize a progress bar. Typically used in a +Progress.progress+ block
56
67
  #
57
68
  # ==== Options
58
- # One of the follow can be used, but not both together
59
69
  #
70
+ # * +:title+ - The title of the progress bar
60
71
  # * +:width+ - The width of the terminal
61
72
  #
62
- sig { params(width: Integer).void }
63
- def initialize(width: Terminal.width)
73
+ sig { params(title: T.nilable(String), width: Integer).void }
74
+ def initialize(title = nil, width: Terminal.width)
64
75
  @percent_done = T.let(0, Numeric)
76
+ @title = title
65
77
  @max_width = width
66
78
  end
67
79
 
@@ -84,7 +96,20 @@ module CLI
84
96
  @percent_done = [@percent_done, 1.0].min # Make sure we can't go above 1.0
85
97
 
86
98
  print(self)
87
- print(CLI::UI::ANSI.previous_line + "\n")
99
+
100
+ printed_lines = @title ? 2 : 1
101
+ print(CLI::UI::ANSI.previous_lines(printed_lines) + "\n")
102
+ end
103
+
104
+ # Update the progress bar title
105
+ #
106
+ # ==== Attributes
107
+ #
108
+ # * +new_title+ - title to change the progress bar to
109
+ #
110
+ sig { params(new_title: String).void }
111
+ def update_title(new_title)
112
+ @title = new_title
88
113
  end
89
114
 
90
115
  # Format the progress bar to be printed to terminal
@@ -96,11 +121,14 @@ module CLI
96
121
  filled = [(@percent_done * workable_width.to_f).ceil, 0].max
97
122
  unfilled = [workable_width - filled, 0].max
98
123
 
99
- CLI::UI.resolve_text([
124
+ title = CLI::UI.resolve_text(@title, truncate_to: @max_width - Frame.prefix_width) if @title
125
+ bar = CLI::UI.resolve_text([
100
126
  FILLED_BAR + ' ' * filled,
101
127
  UNFILLED_BAR + ' ' * unfilled,
102
128
  CLI::UI::Color::RESET.code + suffix,
103
129
  ].join)
130
+
131
+ [title, bar].compact.join("\n")
104
132
  end
105
133
  end
106
134
  end
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
-
3
2
  # typed: true
3
+ # frozen_string_literal: true
4
4
 
5
5
  require 'io/console'
6
6
 
@@ -59,7 +59,11 @@ module CLI
59
59
  end
60
60
  def initialize(options, multiple: false, default: nil)
61
61
  @options = options
62
- @active = 1
62
+ @active = if default && (i = options.index(default))
63
+ i + 1
64
+ else
65
+ 1
66
+ end
63
67
  @marker = '>'
64
68
  @answer = nil
65
69
  @state = :root
@@ -114,23 +118,20 @@ module CLI
114
118
  # determine how many extra lines would be taken up by them.
115
119
  #
116
120
  # To accomplish this we split the string by new lines and add the
117
- # extra characters to the first line.
118
- # Then we calculate how many lines would be needed to render the string
119
- # based on the terminal width
120
- # 3 = space before the number, the . after the number, the space after the .
121
- # multiple check is for the space for the checkbox, if rendered
122
- # options.count.to_s.size gets us the max size of the number we will display
123
- extra_chars = @marker.length + 3 + @options.count.to_s.size + (@multiple ? 1 : 0)
121
+ # prefix to the first line. We use the options count as the number since
122
+ # it will be the widest number we will display, and we pad the others to
123
+ # align with it. Then we calculate how many lines would be needed to
124
+ # render the string based on the terminal width.
125
+ prefix = "#{@marker} #{@options.count}. #{@multiple ? "☐ " : ""}"
124
126
 
125
127
  @option_lengths = @options.map do |text|
126
128
  next 1 if text.empty?
127
129
 
128
130
  # Find the length of all the lines in this string
129
- non_empty_line_lengths = text.split("\n").reject(&:empty?).map do |line|
131
+ non_empty_line_lengths = "#{prefix}#{text}".split("\n").reject(&:empty?).map do |line|
130
132
  CLI::UI.fmt(line, enable_color: false).length
131
133
  end
132
- # The first line has the marker and number, so we add that so we can take it into account
133
- non_empty_line_lengths[0] += extra_chars
134
+
134
135
  # Finally, we need to calculate how many lines each one will take. We can do that by dividing each one
135
136
  # by the width of the terminal, rounding up to the nearest natural number
136
137
  non_empty_line_lengths.sum { |length| (length.to_f / @terminal_width_at_calculation_time).ceil }
@@ -229,6 +230,12 @@ module CLI
229
230
  end
230
231
  elsif n == 0
231
232
  # Ignore pressing "0" when not in multiple mode
233
+ elsif should_enter_select_mode?(n)
234
+ # When we have more than 9 options, we need to enter select mode
235
+ # to avoid pre-selecting (e.g) 1 when the user wanted 10.
236
+ # This also applies to 2 and 20+ options, 3/30+, etc.
237
+ start_line_select
238
+ @active = n
232
239
  else
233
240
  @active = n
234
241
  @answer = n
@@ -236,6 +243,20 @@ module CLI
236
243
  @redraw = true
237
244
  end
238
245
 
246
+ sig { params(n: Integer).returns(T::Boolean) }
247
+ def should_enter_select_mode?(n)
248
+ # If we have less than 10 options, we don't need to enter select mode
249
+ # and we can just select the option directly. This just keeps the code easier
250
+ # by making the cases simpler to understand
251
+ return false if @options.length <= 9
252
+
253
+ # At this point we have 10+ options so always need to check if we should run.
254
+ # This can be simplified to checking if the length of options is >= to the option selected * 10:
255
+ # n == 1 && options.length >= 10 (1 * 10), n == 2 && options.length >= 20 (2 * 10), etc.
256
+ # which can be further simplified to just:
257
+ @options.length >= (n * 10)
258
+ end
259
+
239
260
  sig { params(char: String).void }
240
261
  def select_bool(char)
241
262
  return unless (@options - ['yes', 'no']).empty?
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CLI
4
5
  module UI
data/lib/cli/ui/prompt.rb CHANGED
@@ -1,23 +1,13 @@
1
1
  # coding: utf-8
2
-
3
2
  # typed: true
3
+ # frozen_string_literal: true
4
4
 
5
5
  require 'cli/ui'
6
- require 'readline'
7
-
8
- module Readline
9
- unless const_defined?(:FILENAME_COMPLETION_PROC)
10
- FILENAME_COMPLETION_PROC = proc do |input|
11
- directory = input[-1] == '/' ? input : File.dirname(input)
12
- filename = input[-1] == '/' ? '' : File.basename(input)
13
-
14
- (Dir.entries(directory).select do |fp|
15
- fp.start_with?(filename)
16
- end - (input[-1] == '.' ? [] : ['.', '..'])).map do |fp|
17
- File.join(directory, fp).gsub(/\A\.\//, '')
18
- end
19
- end
20
- end
6
+ begin
7
+ require 'reline' # For 2.7+
8
+ rescue LoadError
9
+ require 'readline' # For 2.6
10
+ Object.const_set(:Reline, Readline)
21
11
  end
22
12
 
23
13
  module CLI
@@ -137,10 +127,6 @@ module CLI
137
127
  &options_proc
138
128
  )
139
129
  has_options = !!(options || block_given?)
140
- if has_options && default && !multiple
141
- raise(ArgumentError, 'conflicting arguments: default may not be provided with options when not multiple')
142
- end
143
-
144
130
  if has_options && is_file
145
131
  raise(ArgumentError, 'conflicting arguments: is_file is only useful when options are not provided')
146
132
  end
@@ -310,6 +296,8 @@ module CLI
310
296
  instructions += ", filter with 'f'" if filter_ui
311
297
  instructions += ", enter option with 'e'" if select_ui && (options.size > 9)
312
298
 
299
+ resp = T.let([], T.any(String, T::Array[String]))
300
+
313
301
  CLI::UI::StdoutRouter::Capture.in_alternate_screen do
314
302
  puts_question("#{question} " + instructions_color.code + "(#{instructions})" + Color::RESET.code)
315
303
  resp = interactive_prompt(options, multiple: multiple, default: default)
@@ -334,12 +322,12 @@ module CLI
334
322
  resp
335
323
  end
336
324
  puts_question("#{question} (You chose: {{italic:#{resp_text}}})")
325
+ end
337
326
 
338
- if block_given?
339
- T.must(handler).call(resp)
340
- else
341
- resp
342
- end
327
+ if block_given?
328
+ T.must(handler).call(resp)
329
+ else
330
+ resp
343
331
  end
344
332
  end
345
333
 
@@ -375,11 +363,20 @@ module CLI
375
363
  sig { params(is_file: T::Boolean).returns(String) }
376
364
  def readline(is_file: false)
377
365
  if is_file
378
- Readline.completion_proc = Readline::FILENAME_COMPLETION_PROC
379
- Readline.completion_append_character = ''
366
+ Reline.completion_proc = proc do |input|
367
+ directory = input[-1] == '/' ? input : File.dirname(input)
368
+ filename = input[-1] == '/' ? '' : File.basename(input)
369
+
370
+ (Dir.entries(directory).select do |fp|
371
+ fp.start_with?(filename)
372
+ end - (input[-1] == '.' ? [] : ['.', '..'])).map do |fp|
373
+ File.join(directory, fp).gsub(/\A\.\//, '')
374
+ end
375
+ end
376
+ Reline.completion_append_character = ''
380
377
  else
381
- Readline.completion_proc = proc { |*| nil }
382
- Readline.completion_append_character = ' '
378
+ Reline.completion_proc = proc {}
379
+ Reline.completion_append_character = ' '
383
380
  end
384
381
 
385
382
  # because Readline is a C library, CLI::UI's hooks into $stdout don't
@@ -393,7 +390,7 @@ module CLI
393
390
  prompt += CLI::UI::Color::YELLOW.code if CLI::UI::OS.current.use_color_prompt?
394
391
 
395
392
  begin
396
- line = Readline.readline(prompt, true)
393
+ line = Reline.readline(prompt, true)
397
394
  print(CLI::UI::Color::RESET.code)
398
395
  line.to_s.chomp
399
396
  rescue Interrupt
@@ -1,4 +1,5 @@
1
1
  # typed: true
2
+ # frozen_string_literal: true
2
3
 
3
4
  module CLI
4
5
  module UI