cli-ui 1.2.1 → 1.2.2

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: 37c3f9d8f4c1cd9dcf6d86319d35b947d2b99ae0dc0f1b975397d77f555f1f57
4
- data.tar.gz: d7b3eee8bba21a191746ecf244c428f8c702e1c2fbfb41242740d38a9d317dab
3
+ metadata.gz: 7c658a2195a92d5e4ccf05fc1359eef09d25b5a01e0110c6ab84190d4a10c922
4
+ data.tar.gz: 4745f15513a91abef5cce3e3523d26de38d60336dbdf723601402fe8bd4b2635
5
5
  SHA512:
6
- metadata.gz: e35d9d93f31d2bacbd1623d63937f99deecc928e7ef97ebe0b5c4f6199b37952d9d7dad97cfe004ce7cc03296776f7767ccf08336dcbc261eb63f097450211cc
7
- data.tar.gz: a184a3dc46bfe4074bbfb8571253e00bc016ac40734ea2ab13baeabe526cfa3194855d3ca69424fd1b069157c7ec4ee7fc76debbdca71ecaa48fc145446039a8
6
+ metadata.gz: 609b7cab1cde15280659813f6b283c419c76b744a9089dcded708c3cf08113b7118150fd5e6642f8e41709f8b481ad0a51927d48ac294432ce108209faefccce
7
+ data.tar.gz: feb06db36c85af0d83c2407bf6ebb06ee1c65ea8ec38b7b80b09bbeaac0a25220a7fe2707993bee950916cd203e31d219b6db6adf132b08e9027be8e00df846a
data/README.md CHANGED
@@ -34,7 +34,7 @@ To handle content flow (see example below)
34
34
  CLI::UI::StdoutRouter.enable
35
35
  CLI::UI::Frame.open('Frame 1') do
36
36
  CLI::UI::Frame.open('Frame 2') { puts "inside frame 2" }
37
- puts "inside frame 1"
37
+ puts "inside frame 1"
38
38
  end
39
39
  ```
40
40
 
@@ -43,7 +43,10 @@ end
43
43
  ---
44
44
 
45
45
  ### Interactive Prompts
46
- Prompt user with options and ask them to choose. Can answer using arrow keys, numbers, or vim bindings (or y/n for yes/no questions)
46
+ Prompt user with options and ask them to choose. Can answer using arrow keys, vim bindings (`j`/`k`), or numbers (or y/n for yes/no questions).
47
+
48
+ For large numbers of options, using `e`, `:`, or `G` will toggle "line select" mode which allows numbers greater than 9 to be typed and
49
+ `f` or `/` will allow the user to filter options using a free-form text input.
47
50
 
48
51
  ```ruby
49
52
  CLI::UI.ask('What language/framework do you use?', options: %w(rails go ruby python))
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.15"
24
+ # spec.add_development_dependency "bundler", "~> 2.0"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency "minitest", "~> 5.0"
27
27
  end
@@ -48,8 +48,8 @@ module CLI
48
48
  #
49
49
  # * +question+ - question to confirm
50
50
  #
51
- def self.confirm(question)
52
- CLI::UI::Prompt.confirm(question)
51
+ def self.confirm(question, **kwargs)
52
+ CLI::UI::Prompt.confirm(question, **kwargs)
53
53
  end
54
54
 
55
55
  # Conviencence Method for +CLI::UI::Prompt.ask+
@@ -72,7 +72,7 @@ module CLI
72
72
  # Format the progress bar to be printed to terminal
73
73
  #
74
74
  def to_s
75
- suffix = " #{(@percent_done * 100).round(2)}%"
75
+ suffix = " #{(@percent_done * 100).floor}%".ljust(5)
76
76
  workable_width = @max_width - Frame.prefix_width - suffix.size
77
77
  filled = [(@percent_done * workable_width.to_f).ceil, 0].max
78
78
  unfilled = [workable_width - filled, 0].max
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require 'cli/ui'
2
3
  require 'readline'
3
4
 
@@ -30,11 +31,15 @@ module CLI
30
31
  # * +:default+ - The default answer to the question (e.g. they just press enter and don't input anything)
31
32
  # * +:is_file+ - Tells the input to use file auto-completion (tab completion)
32
33
  # * +:allow_empty+ - Allows the answer to be empty
34
+ # * +:multiple+ - Allow multiple options to be selected
35
+ # * +:filter_ui+ - Enable option filtering (default: true)
36
+ # * +:select_ui+ - Enable long-form option selection (default: true)
33
37
  #
34
38
  # Note:
35
39
  # * +:options+ or providing a +Block+ conflicts with +:default+ and +:is_file+, you cannot set options with either of these keywords
36
40
  # * +:default+ conflicts with +:allow_empty:, you cannot set these together
37
41
  # * +:options+ conflicts with providing a +Block+ , you may only set one
42
+ # * +:multiple+ can only be used with +:options+ or a +Block+; it is ignored, otherwise.
38
43
  #
39
44
  # ==== Block (optional)
40
45
  #
@@ -71,13 +76,13 @@ module CLI
71
76
  # handler.option('python') { |selection| selection }
72
77
  # end
73
78
  #
74
- def ask(question, options: nil, default: nil, is_file: nil, allow_empty: true, multiple: false, &options_proc)
79
+ def ask(question, options: nil, default: nil, is_file: nil, allow_empty: true, multiple: false, filter_ui: true, select_ui: true, &options_proc)
75
80
  if ((options || block_given?) && (default || is_file))
76
81
  raise(ArgumentError, 'conflicting arguments: options provided with default or is_file')
77
82
  end
78
83
 
79
84
  if options || block_given?
80
- ask_interactive(question, options, multiple: multiple, &options_proc)
85
+ ask_interactive(question, options, multiple: multiple, filter_ui: filter_ui, select_ui: select_ui, &options_proc)
81
86
  else
82
87
  ask_free_form(question, default, is_file, allow_empty)
83
88
  end
@@ -91,8 +96,10 @@ module CLI
91
96
  # Confirmation question
92
97
  # CLI::UI::Prompt.confirm('Is the sky blue?')
93
98
  #
94
- def confirm(question)
95
- ask_interactive(question, %w(yes no)) == 'yes'
99
+ # CLI::UI::Prompt.confirm('Do a dangerous thing?', default: false)
100
+ #
101
+ def confirm(question, default: true)
102
+ ask_interactive(question, default ? %w(yes no) : %w(no yes), filter_ui: false) == 'yes'
96
103
  end
97
104
 
98
105
  private
@@ -121,7 +128,7 @@ module CLI
121
128
  end
122
129
  end
123
130
 
124
- def ask_interactive(question, options = nil, multiple: false)
131
+ def ask_interactive(question, options = nil, multiple: false, filter_ui: true, select_ui: true)
125
132
  raise(ArgumentError, 'conflicting arguments: options and block given') if options && block_given?
126
133
 
127
134
  options ||= if block_given?
@@ -132,6 +139,8 @@ module CLI
132
139
 
133
140
  raise(ArgumentError, 'insufficient options') if options.nil? || options.size < 2
134
141
  instructions = (multiple ? "Toggle options. " : "") + "Choose with ↑ ↓ ⏎"
142
+ instructions += ", filter with 'f'" if filter_ui
143
+ instructions += ", enter option with 'e'" if select_ui and options.size > 9
135
144
  puts_question("#{question} {{yellow:(#{instructions})}}")
136
145
  resp = interactive_prompt(options, multiple: multiple)
137
146
 
@@ -195,10 +204,11 @@ module CLI
195
204
  # thread to manage output, but the current strategy feels like a
196
205
  # better tradeoff.
197
206
  prefix = CLI::UI.with_frame_color(:blue) { CLI::UI::Frame.prefix }
198
- prompt = prefix + CLI::UI.fmt('{{blue:> }}{{yellow:')
207
+ prompt = prefix + CLI::UI.fmt('{{blue:> }}') + CLI::UI::Color::YELLOW.code
199
208
 
200
209
  begin
201
210
  line = Readline.readline(prompt, true)
211
+ print CLI::UI::Color::RESET.code
202
212
  line.to_s.chomp
203
213
  rescue Interrupt
204
214
  CLI::UI.raw { STDERR.puts('^C' + CLI::UI::Color::RESET.code) }
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require 'io/console'
2
3
 
3
4
  module CLI
@@ -10,6 +11,9 @@ module CLI
10
11
  # Prompts the user with options
11
12
  # Uses an interactive session to allow the user to pick an answer
12
13
  # Can use arrows, y/n, numbers (1/2), and vim bindings to control
14
+ # For more than 9 options, hitting 'e', ':', or 'G' will enter select
15
+ # mode allowing the user to type in longer numbers
16
+ # Pressing 'f' or '/' will allow the user to filter the results
13
17
  #
14
18
  # https://user-images.githubusercontent.com/3074765/33797984-0ebb5e64-dcdf-11e7-9e7e-7204f279cece.gif
15
19
  #
@@ -42,16 +46,22 @@ module CLI
42
46
  @answer = nil
43
47
  @state = :root
44
48
  @multiple = multiple
49
+ # Indicate that an extra line (the "metadata" line) is present and
50
+ # the terminal output should be drawn over when processing user input
51
+ @displaying_metadata = false
52
+ @filter = ''
45
53
  # 0-indexed array representing if selected
46
54
  # @options[0] is selected if @chosen[0]
47
55
  @chosen = Array.new(@options.size) { false } if multiple
48
56
  @redraw = true
57
+ @presented_options = []
49
58
  end
50
59
 
51
60
  # Calls the +InteractiveOptions+ and asks the question
52
61
  # Usually used from +self.call+
53
62
  #
54
63
  def call
64
+ calculate_option_line_lengths
55
65
  CLI::UI.raw { print(ANSI.hide_cursor) }
56
66
  while @answer.nil?
57
67
  render_options
@@ -59,6 +69,7 @@ module CLI
59
69
  reset_position
60
70
  end
61
71
  clear_output
72
+
62
73
  @answer
63
74
  ensure
64
75
  CLI::UI.raw do
@@ -68,46 +79,96 @@ module CLI
68
79
 
69
80
  private
70
81
 
71
- def reset_position
82
+ def calculate_option_line_lengths
83
+ @terminal_width_at_calculation_time = CLI::UI::Terminal.width
84
+ # options will be an array of questions but each option can be multi-line
85
+ # so to get the # of lines, you need to join then split
86
+
87
+ # since lines may be longer than the terminal is wide, we need to
88
+ # determine how many extra lines would be taken up by them
89
+ max_width = (@terminal_width_at_calculation_time -
90
+ @options.count.to_s.size - # Width of the displayed number
91
+ 5 - # Extra characters added during rendering
92
+ (@multiple ? 1 : 0) # Space for the checkbox, if rendered
93
+ ).to_f
94
+
95
+ @option_lengths = @options.map do |text|
96
+ width = 1 if text.empty?
97
+ width ||= text
98
+ .split("\n")
99
+ .reject(&:empty?)
100
+ .map { |l| (l.length / max_width).ceil }
101
+ .reduce(&:+)
102
+
103
+ width
104
+ end
105
+ end
106
+
107
+ def reset_position(number_of_lines=num_lines)
72
108
  # This will put us back at the beginning of the options
73
109
  # When we redraw the options, they will be overwritten
74
110
  CLI::UI.raw do
75
- num_lines.times { print(ANSI.previous_line) }
111
+ number_of_lines.times { print(ANSI.previous_line) }
76
112
  end
77
113
  end
78
114
 
79
- def clear_output
115
+ def clear_output(number_of_lines=num_lines)
80
116
  CLI::UI.raw do
81
117
  # Write over all lines with whitespace
82
- num_lines.times { puts(' ' * CLI::UI::Terminal.width) }
118
+ number_of_lines.times { puts(' ' * CLI::UI::Terminal.width) }
83
119
  end
84
- reset_position
120
+ reset_position number_of_lines
121
+
122
+ # Update if metadata is being displayed
123
+ # This must be done _after_ the output is cleared or it won't draw over
124
+ # the entire output
125
+ @displaying_metadata = display_metadata?
126
+ end
127
+
128
+ # Don't use this in place of +@displaying_metadata+, this updates too
129
+ # quickly to be useful when drawing to the screen.
130
+ def display_metadata?
131
+ filtering? or selecting? or has_filter?
85
132
  end
86
133
 
87
134
  def num_lines
88
- options = presented_options.map(&:first)
89
- # @options will be an array of questions but each option can be multi-line
90
- # so to get the # of lines, you need to join then split
135
+ calculate_option_line_lengths if terminal_width_changed?
91
136
 
92
- # empty_option_count is needed since empty option titles are omitted
93
- # from the line count when reject(&:empty?) is called
137
+ option_length = presented_options.reduce(0) do |total_length, (_, option_number)|
138
+ # Handle continuation markers and "Done" option when multiple is true
139
+ next total_length + 1 if option_number.nil? or option_number.zero?
140
+ total_length + @option_lengths[option_number - 1]
141
+ end
142
+
143
+ option_length + (@displaying_metadata ? 1 : 0)
144
+ end
94
145
 
95
- empty_option_count = options.count(&:empty?)
96
- joined_options = options.join("\n")
97
- joined_options.split("\n").reject(&:empty?).size + empty_option_count
146
+ def terminal_width_changed?
147
+ @terminal_width_at_calculation_time != CLI::UI::Terminal.width
98
148
  end
99
149
 
100
150
  ESC = "\e"
151
+ BACKSPACE = "\u007F"
152
+ CTRL_C = "\u0003"
153
+ CTRL_D = "\u0004"
101
154
 
102
155
  def up
103
- min_pos = @multiple ? 0 : 1
104
- @active = @active - 1 >= min_pos ? @active - 1 : @options.length
156
+ active_index = @filtered_options.index { |_,num| num == @active } || 0
157
+
158
+ previous_visible = @filtered_options[active_index - 1]
159
+ previous_visible ||= @filtered_options.last
160
+
161
+ @active = previous_visible ? previous_visible.last : -1
105
162
  @redraw = true
106
163
  end
107
164
 
108
165
  def down
109
- min_pos = @multiple ? 0 : 1
110
- @active = @active + 1 <= @options.length ? @active + 1 : min_pos
166
+ active_index = @filtered_options.index { |_,num| num == @active } || 0
167
+
168
+ next_visible = @filtered_options[active_index + 1]
169
+ next_visible ||= @filtered_options.first
170
+
171
+ @active = next_visible ? next_visible.last : -1
111
172
  @redraw = true
112
173
  end
113
174
 
@@ -141,7 +202,36 @@ module CLI
141
202
  @redraw = true
142
203
  end
143
204
 
205
+ def build_selection(char)
206
+ @active = (@active.to_s + char).to_i
207
+ @redraw = true
208
+ end
209
+
210
+ def chop_selection
211
+ @active = @active.to_s.chop.to_i
212
+ @redraw = true
213
+ end
214
+
215
+ def update_search(char)
216
+ @redraw = true
217
+
218
+ # Control+D or Backspace on empty search closes search
219
+ if char == CTRL_D or (@filter.empty? and char == BACKSPACE)
220
+ @filter = ''
221
+ @state = :root
222
+ return
223
+ end
224
+
225
+ if char == BACKSPACE
226
+ @filter.chop!
227
+ else
228
+ @filter += char
229
+ end
230
+ end
231
+
144
232
  def select_current
233
+ # Prevent selection of invisible options
234
+ return unless presented_options.any? { |_,num| num == @active }
145
235
  select_n(@active)
146
236
  end
147
237
 
@@ -153,29 +243,49 @@ module CLI
153
243
  # rubocop:disable Style/WhenThen,Layout/SpaceBeforeSemicolon
154
244
  def wait_for_user_input
155
245
  char = read_char
246
+ @last_char = char
247
+
248
+ case char
249
+ when :timeout ; raise Interrupt # Timeout, use interrupt to simulate
250
+ when CTRL_C ; raise Interrupt
251
+ end
252
+
156
253
  case @state
157
254
  when :root
158
255
  case char
159
- when :timeout ; raise Interrupt # Timeout, use interrupt to simulate
160
256
  when ESC ; @state = :esc
161
257
  when 'k' ; up
162
258
  when 'j' ; down
163
- when '0' ; select_n(char.to_i)
164
- when ('1'..@options.size.to_s) ; select_n(char.to_i)
259
+ when 'e', ':', 'G' ; start_line_select
260
+ when 'f', '/' ; start_filter
261
+ when ('0'..@options.size.to_s) ; select_n(char.to_i)
165
262
  when 'y', 'n' ; select_bool(char)
166
263
  when " ", "\r", "\n" ; select_current # <enter>
167
- when "\u0003" ; raise Interrupt # Ctrl-c
264
+ end
265
+ when :filter
266
+ case char
267
+ when ESC ; @state = :esc
268
+ when "\r", "\n" ; select_current
269
+ else ; update_search(char)
270
+ end
271
+ when :line_select
272
+ case char
273
+ when ESC ; @state = :esc
274
+ when 'k' ; up ; @state = :root
275
+ when 'j' ; down ; @state = :root
276
+ when 'e',':','G','q' ; stop_line_select
277
+ when '0'..'9' ; build_selection(char)
278
+ when BACKSPACE ; chop_selection # Pop last input on backspace
279
+ when ' ', "\r", "\n" ; select_current
168
280
  end
169
281
  when :esc
170
282
  case char
171
- when :timeout ; raise Interrupt # Timeout, use interrupt to simulate
172
283
  when '[' ; @state = :esc_bracket
173
284
  else ; raise Interrupt # unhandled escape sequence.
174
285
  end
175
286
  when :esc_bracket
176
- @state = :root
287
+ @state = has_filter? ? :filter : :root
177
288
  case char
178
- when :timeout ; raise Interrupt # Timeout, use interrupt to simulate
179
289
  when 'A' ; up
180
290
  when 'B' ; down
181
291
  else ; raise Interrupt # unhandled escape sequence.
@@ -184,6 +294,35 @@ module CLI
184
294
  end
185
295
  # rubocop:enable Style/WhenThen,Layout/SpaceBeforeSemicolon
186
296
 
297
+ def selecting?
298
+ @state == :line_select
299
+ end
300
+
301
+ def filtering?
302
+ @state == :filter
303
+ end
304
+
305
+ def has_filter?
306
+ !@filter.empty?
307
+ end
308
+
309
+ def start_filter
310
+ @state = :filter
311
+ @redraw = true
312
+ end
313
+
314
+ def start_line_select
315
+ @state = :line_select
316
+ @active = 0
317
+ @redraw = true
318
+ end
319
+
320
+ def stop_line_select
321
+ @state = :root
322
+ @active = 1 if @active.zero?
323
+ @redraw = true
324
+ end
325
+
187
326
  def read_char
188
327
  raw_tty! do
189
328
  getc = $stdin.getc
@@ -205,9 +344,18 @@ module CLI
205
344
  return @presented_options unless recalculate
206
345
 
207
346
  @presented_options = @options.zip(1..Float::INFINITY)
347
+ if has_filter?
348
+ @presented_options.select! { |option,_| option.downcase.include?(@filter.downcase) }
349
+ end
350
+
351
+ # Used for selection purposes
352
+ @filtered_options = @presented_options.dup
353
+
208
354
  @presented_options.unshift([DONE, 0]) if @multiple
209
355
 
210
- while num_lines > max_options
356
+ ensure_visible_is_active if has_filter?
357
+
358
+ while num_lines > max_lines
211
359
  # try to keep the selection centered in the window:
212
360
  if distance_from_selection_to_end > distance_from_start_to_selection
213
361
  # selection is closer to top than bottom, so trim a row from the bottom
@@ -223,14 +371,22 @@ module CLI
223
371
  @presented_options
224
372
  end
225
373
 
374
+ def ensure_visible_is_active
375
+ unless presented_options.any? { |_, num| num == @active }
376
+ @active = presented_options.first&.last.to_i
377
+ end
378
+ end
379
+
226
380
  def distance_from_selection_to_end
227
- last_visible_option_number = @presented_options[-1].last || @presented_options[-2].last
228
- last_visible_option_number - @active
381
+ @presented_options.count - index_of_active_option
229
382
  end
230
383
 
231
384
  def distance_from_start_to_selection
232
- first_visible_option_number = @presented_options[0].last || @presented_options[1].last
233
- @active - first_visible_option_number
385
+ index_of_active_option
386
+ end
387
+
388
+ def index_of_active_option
389
+ @presented_options.index { |_,num| num == @active }.to_i
234
390
  end
235
391
 
236
392
  def ensure_last_item_is_continuation_marker
@@ -241,14 +397,38 @@ module CLI
241
397
  @presented_options.unshift(["...", nil]) if @presented_options.first.last
242
398
  end
243
399
 
244
- def max_options
245
- @max_options ||= CLI::UI::Terminal.height - 2 # Keeps a one line question visible
400
+ def max_lines
401
+ CLI::UI::Terminal.height - (@displaying_metadata ? 3 : 2) # Keeps a one line question visible
246
402
  end
247
403
 
248
404
  def render_options
405
+ previously_displayed_lines = num_lines
406
+
407
+ @displaying_metadata = display_metadata?
408
+
409
+ options = presented_options(recalculate: true)
410
+
411
+ clear_output(previously_displayed_lines) if previously_displayed_lines > num_lines
412
+
249
413
  max_num_length = (@options.size + 1).to_s.length
250
414
 
251
- presented_options(recalculate: true).each do |choice, num|
415
+ metadata_text = if selecting?
416
+ select_text = @active
417
+ select_text = '{{info:e, q, or up/down anytime to exit}}' if @active == 0
418
+ "Select: #{select_text}"
419
+ elsif filtering? or has_filter?
420
+ filter_text = @filter
421
+ filter_text = '{{info:Ctrl-D anytime or Backspace now to exit}}' if @filter.empty?
422
+ "Filter: #{filter_text}"
423
+ end
424
+
425
+ if metadata_text
426
+ CLI::UI.with_frame_color(:blue) do
427
+ puts CLI::UI.fmt(" {{green:#{metadata_text}}}#{ANSI.clear_to_end_of_line}")
428
+ end
429
+ end
430
+
431
+ options.each do |choice, num|
252
432
  is_chosen = @multiple && num && @chosen[num - 1]
253
433
 
254
434
  padding = ' ' * (max_num_length - num.to_s.length)
@@ -261,19 +441,29 @@ module CLI
261
441
  format = " #{format}"
262
442
 
263
443
  message += sprintf(format, CHECKBOX_ICON[is_chosen]) if @multiple && num && num > 0
264
- message += choice.split("\n").map { |l| sprintf(format, l) }.join("\n")
444
+ message += format_choice(format, choice)
265
445
 
266
446
  if num == @active
267
- message = message.split("\n").map.with_index do |l, idx|
268
- idx == 0 ? "{{blue:> #{l.strip}}}" : "{{blue:>#{l.strip}}}"
269
- end.join("\n")
447
+
448
+ color = (filtering? or selecting?) ? 'green' : 'blue'
449
+ message = message.split("\n").map { |l| "{{#{color}:> #{l.strip}}}" }.join("\n")
270
450
  end
271
451
 
272
452
  CLI::UI.with_frame_color(:blue) do
273
- puts CLI::UI.fmt(message) + CLI::UI::ANSI.clear_to_end_of_line
453
+ puts CLI::UI.fmt(message)
274
454
  end
275
455
  end
276
456
  end
457
+
458
+ def format_choice(format, choice)
459
+ eol = CLI::UI::ANSI.clear_to_end_of_line
460
+ lines = choice.split("\n")
461
+
462
+ return eol if lines.empty? # Handle blank options
463
+
464
+ lines.map! { |l| sprintf(format, l) + eol }
465
+ lines.join("\n")
466
+ end
277
467
  end
278
468
  end
279
469
  end
@@ -197,7 +197,13 @@ module CLI
197
197
  sleep(PERIOD)
198
198
  end
199
199
 
200
- debrief if @auto_debrief
200
+ if @auto_debrief
201
+ debrief
202
+ else
203
+ @m.synchronize do
204
+ @tasks.all?(&:success)
205
+ end
206
+ end
201
207
  end
202
208
 
203
209
  # Debriefs failed tasks is +auto_debrief+ is true
@@ -1,5 +1,5 @@
1
1
  module CLI
2
2
  module UI
3
- VERSION = "1.2.1"
3
+ VERSION = "1.2.2"
4
4
  end
5
5
  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.2.1
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Burke Libbey
@@ -10,22 +10,8 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2018-11-06 00:00:00.000000000 Z
13
+ date: 2019-02-27 00:00:00.000000000 Z
14
14
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: bundler
17
- requirement: !ruby/object:Gem::Requirement
18
- requirements:
19
- - - "~>"
20
- - !ruby/object:Gem::Version
21
- version: '1.15'
22
- type: :development
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- requirements:
26
- - - "~>"
27
- - !ruby/object:Gem::Version
28
- version: '1.15'
29
15
  - !ruby/object:Gem::Dependency
30
16
  name: rake
31
17
  requirement: !ruby/object:Gem::Requirement
@@ -110,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
96
  - !ruby/object:Gem::Version
111
97
  version: '0'
112
98
  requirements: []
113
- rubyforge_project:
114
- rubygems_version: 2.7.6
99
+ rubygems_version: 3.0.2
115
100
  signing_key:
116
101
  specification_version: 4
117
102
  summary: Terminal UI framework