tty-prompt 0.18.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/README.md +549 -248
  4. data/lib/tty-prompt.rb +1 -2
  5. data/lib/tty/prompt.rb +187 -143
  6. data/lib/tty/prompt/answers_collector.rb +5 -5
  7. data/lib/tty/prompt/{enum_paginator.rb → block_paginator.rb} +20 -19
  8. data/lib/tty/prompt/choice.rb +5 -7
  9. data/lib/tty/prompt/choices.rb +29 -11
  10. data/lib/tty/prompt/confirm_question.rb +38 -16
  11. data/lib/tty/prompt/const.rb +17 -0
  12. data/lib/tty/prompt/converter_dsl.rb +6 -7
  13. data/lib/tty/prompt/converter_registry.rb +31 -26
  14. data/lib/tty/prompt/converters.rb +139 -32
  15. data/lib/tty/prompt/enum_list.rb +57 -27
  16. data/lib/tty/prompt/errors.rb +31 -0
  17. data/lib/tty/prompt/evaluator.rb +1 -1
  18. data/lib/tty/prompt/expander.rb +39 -13
  19. data/lib/tty/prompt/keypress.rb +31 -36
  20. data/lib/tty/prompt/list.rb +175 -65
  21. data/lib/tty/prompt/mask_question.rb +4 -5
  22. data/lib/tty/prompt/multi_list.rb +124 -33
  23. data/lib/tty/prompt/multiline.rb +7 -6
  24. data/lib/tty/prompt/paginator.rb +38 -26
  25. data/lib/tty/prompt/question.rb +83 -34
  26. data/lib/tty/prompt/question/checks.rb +18 -0
  27. data/lib/tty/prompt/question/validation.rb +3 -3
  28. data/lib/tty/prompt/selected_choices.rb +76 -0
  29. data/lib/tty/prompt/slider.rb +83 -16
  30. data/lib/tty/prompt/statement.rb +3 -3
  31. data/lib/tty/prompt/suggestion.rb +6 -6
  32. data/lib/tty/prompt/symbols.rb +58 -34
  33. data/lib/tty/prompt/test.rb +36 -0
  34. data/lib/tty/prompt/timer.rb +75 -0
  35. data/lib/tty/prompt/utils.rb +1 -3
  36. data/lib/tty/prompt/version.rb +1 -1
  37. metadata +29 -227
  38. data/Rakefile +0 -8
  39. data/examples/ask.rb +0 -7
  40. data/examples/ask_valid.rb +0 -12
  41. data/examples/collect.rb +0 -21
  42. data/examples/echo.rb +0 -11
  43. data/examples/enum_select.rb +0 -7
  44. data/examples/enum_select_disabled.rb +0 -16
  45. data/examples/enum_select_paged.rb +0 -9
  46. data/examples/enum_select_wrapped.rb +0 -15
  47. data/examples/expand.rb +0 -29
  48. data/examples/in.rb +0 -9
  49. data/examples/inputs.rb +0 -10
  50. data/examples/key_events.rb +0 -15
  51. data/examples/keypress.rb +0 -9
  52. data/examples/mask.rb +0 -13
  53. data/examples/multi_select.rb +0 -8
  54. data/examples/multi_select_disabled.rb +0 -17
  55. data/examples/multi_select_paged.rb +0 -9
  56. data/examples/multi_select_wrapped.rb +0 -15
  57. data/examples/multiline.rb +0 -9
  58. data/examples/pause.rb +0 -9
  59. data/examples/select.rb +0 -20
  60. data/examples/select_disabled.rb +0 -18
  61. data/examples/select_enum.rb +0 -8
  62. data/examples/select_filtered.rb +0 -11
  63. data/examples/select_paginated.rb +0 -11
  64. data/examples/select_wrapped.rb +0 -15
  65. data/examples/slider.rb +0 -6
  66. data/examples/validation.rb +0 -9
  67. data/examples/yes_no.rb +0 -7
  68. data/lib/tty/prompt/messages.rb +0 -49
  69. data/lib/tty/prompt/timeout.rb +0 -78
  70. data/lib/tty/test_prompt.rb +0 -20
  71. data/spec/spec_helper.rb +0 -45
  72. data/spec/unit/ask_spec.rb +0 -132
  73. data/spec/unit/choice/eql_spec.rb +0 -22
  74. data/spec/unit/choice/from_spec.rb +0 -96
  75. data/spec/unit/choices/add_spec.rb +0 -12
  76. data/spec/unit/choices/each_spec.rb +0 -13
  77. data/spec/unit/choices/find_by_spec.rb +0 -10
  78. data/spec/unit/choices/new_spec.rb +0 -10
  79. data/spec/unit/choices/pluck_spec.rb +0 -9
  80. data/spec/unit/collect_spec.rb +0 -96
  81. data/spec/unit/converters/convert_bool_spec.rb +0 -58
  82. data/spec/unit/converters/convert_char_spec.rb +0 -11
  83. data/spec/unit/converters/convert_custom_spec.rb +0 -14
  84. data/spec/unit/converters/convert_date_spec.rb +0 -34
  85. data/spec/unit/converters/convert_file_spec.rb +0 -18
  86. data/spec/unit/converters/convert_number_spec.rb +0 -39
  87. data/spec/unit/converters/convert_path_spec.rb +0 -15
  88. data/spec/unit/converters/convert_range_spec.rb +0 -22
  89. data/spec/unit/converters/convert_regex_spec.rb +0 -12
  90. data/spec/unit/converters/convert_string_spec.rb +0 -21
  91. data/spec/unit/converters/on_error_spec.rb +0 -9
  92. data/spec/unit/distance/distance_spec.rb +0 -73
  93. data/spec/unit/enum_paginator_spec.rb +0 -75
  94. data/spec/unit/enum_select_spec.rb +0 -446
  95. data/spec/unit/error_spec.rb +0 -20
  96. data/spec/unit/evaluator_spec.rb +0 -67
  97. data/spec/unit/expand_spec.rb +0 -198
  98. data/spec/unit/keypress_spec.rb +0 -72
  99. data/spec/unit/mask_spec.rb +0 -132
  100. data/spec/unit/multi_select_spec.rb +0 -495
  101. data/spec/unit/multiline_spec.rb +0 -77
  102. data/spec/unit/new_spec.rb +0 -20
  103. data/spec/unit/ok_spec.rb +0 -10
  104. data/spec/unit/paginator_spec.rb +0 -73
  105. data/spec/unit/question/checks_spec.rb +0 -97
  106. data/spec/unit/question/default_spec.rb +0 -31
  107. data/spec/unit/question/echo_spec.rb +0 -38
  108. data/spec/unit/question/in_spec.rb +0 -115
  109. data/spec/unit/question/initialize_spec.rb +0 -12
  110. data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
  111. data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
  112. data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
  113. data/spec/unit/question/modify_spec.rb +0 -41
  114. data/spec/unit/question/required_spec.rb +0 -92
  115. data/spec/unit/question/validate_spec.rb +0 -115
  116. data/spec/unit/question/validation/call_spec.rb +0 -31
  117. data/spec/unit/question/validation/coerce_spec.rb +0 -30
  118. data/spec/unit/result_spec.rb +0 -40
  119. data/spec/unit/say_spec.rb +0 -67
  120. data/spec/unit/select_spec.rb +0 -643
  121. data/spec/unit/slider_spec.rb +0 -100
  122. data/spec/unit/statement/initialize_spec.rb +0 -15
  123. data/spec/unit/subscribe_spec.rb +0 -22
  124. data/spec/unit/suggest_spec.rb +0 -28
  125. data/spec/unit/warn_spec.rb +0 -21
  126. data/spec/unit/yes_no_spec.rb +0 -251
  127. data/tasks/console.rake +0 -11
  128. data/tasks/coverage.rake +0 -11
  129. data/tasks/spec.rake +0 -29
  130. data/tty-prompt.gemspec +0 -33
@@ -1,2 +1 @@
1
- require_relative 'tty/prompt'
2
- require_relative 'tty/test_prompt'
1
+ require_relative "tty/prompt"
@@ -1,49 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'pastel'
5
- require 'tty-cursor'
6
- require 'tty-reader'
7
-
8
- require_relative 'prompt/answers_collector'
9
- require_relative 'prompt/confirm_question'
10
- require_relative 'prompt/expander'
11
- require_relative 'prompt/enum_list'
12
- require_relative 'prompt/keypress'
13
- require_relative 'prompt/list'
14
- require_relative 'prompt/multi_list'
15
- require_relative 'prompt/multiline'
16
- require_relative 'prompt/mask_question'
17
- require_relative 'prompt/question'
18
- require_relative 'prompt/slider'
19
- require_relative 'prompt/statement'
20
- require_relative 'prompt/suggestion'
21
- require_relative 'prompt/utils'
22
- require_relative 'prompt/version'
3
+ require "forwardable"
4
+ require "pastel"
5
+ require "tty-cursor"
6
+ require "tty-reader"
7
+ require "tty-screen"
8
+
9
+ require_relative "prompt/answers_collector"
10
+ require_relative "prompt/confirm_question"
11
+ require_relative "prompt/errors"
12
+ require_relative "prompt/expander"
13
+ require_relative "prompt/enum_list"
14
+ require_relative "prompt/keypress"
15
+ require_relative "prompt/list"
16
+ require_relative "prompt/multi_list"
17
+ require_relative "prompt/multiline"
18
+ require_relative "prompt/mask_question"
19
+ require_relative "prompt/question"
20
+ require_relative "prompt/slider"
21
+ require_relative "prompt/statement"
22
+ require_relative "prompt/suggestion"
23
+ require_relative "prompt/symbols"
24
+ require_relative "prompt/utils"
25
+ require_relative "prompt/version"
23
26
 
24
27
  module TTY
25
28
  # A main entry for asking prompt questions.
26
29
  class Prompt
27
30
  extend Forwardable
28
31
 
29
- # Raised when wrong parameter is used to configure prompt
30
- ConfigurationError = Class.new(StandardError)
31
-
32
- # Raised when type conversion cannot be performed
33
- ConversionError = Class.new(StandardError)
34
-
35
- # Raised when the passed in validation argument is of wrong type
36
- ValidationCoercion = Class.new(TypeError)
37
-
38
- # Raised when the required argument is not supplied
39
- ArgumentRequired = Class.new(ArgumentError)
40
-
41
- # Raised when the argument validation fails
42
- ArgumentValidation = Class.new(ArgumentError)
43
-
44
- # Raised when the argument is not expected
45
- InvalidArgument = Class.new(ArgumentError)
46
-
47
32
  # @api private
48
33
  attr_reader :input
49
34
 
@@ -69,12 +54,27 @@ module TTY
69
54
  # @api private
70
55
  attr_reader :active_color, :help_color, :error_color, :enabled_color
71
56
 
72
- def_delegators :@pastel, :decorate, :strip
57
+ # Quiet mode
58
+ #
59
+ # @api private
60
+ attr_reader :quiet
61
+
62
+ # The collection of display symbols
63
+ #
64
+ # @example
65
+ # prompt = TTY::Prompt.new(symbols: {marker: ">"})
66
+ #
67
+ # @return [Hash]
68
+ #
69
+ # @api private
70
+ attr_reader :symbols
71
+
72
+ def_delegators :@pastel, :strip
73
73
 
74
74
  def_delegators :@cursor, :clear_lines, :clear_line,
75
75
  :show, :hide
76
76
 
77
- def_delegators :@reader, :read_char, :read_line, :read_keypress,
77
+ def_delegators :@reader, :read_char, :read_keypress, :read_line,
78
78
  :read_multiline, :on, :subscribe, :unsubscribe, :trigger,
79
79
  :count_screen_lines
80
80
 
@@ -82,61 +82,90 @@ module TTY
82
82
 
83
83
  def self.messages
84
84
  {
85
- range?: 'Value %{value} must be within the range %{in}',
86
- valid?: 'Your answer is invalid (must match %{valid})',
87
- required?: 'Value must be provided'
85
+ range?: "Value %{value} must be within the range %{in}",
86
+ valid?: "Your answer is invalid (must match %{valid})",
87
+ required?: "Value must be provided",
88
+ convert?: "Cannot convert `%{value}` to '%{type}' type"
88
89
  }
89
90
  end
90
91
 
91
92
  # Initialize a Prompt
92
93
  #
93
- # @param [Hash] options
94
- # @option options [IO] :input
94
+ # @param [IO] :input
95
95
  # the input stream
96
- # @option options [IO] :output
96
+ # @param [IO] :output
97
97
  # the output stream
98
- # @option options [Hash] :env
98
+ # @param [Hash] :env
99
99
  # the environment variables
100
- # @option options [String] :prefix
100
+ # @param [Hash] :symbols
101
+ # the symbols displayed in prompts such as :marker, :cross
102
+ # @param options [Boolean] :quiet
103
+ # enable quiet mode, don't re-echo the question
104
+ # @param [String] :prefix
101
105
  # the prompt prefix, by default empty
102
- # @option options [Boolean] :enable_color
106
+ # @param [Symbol] :interrupt
107
+ # handling of Ctrl+C key out of :signal, :exit, :noop
108
+ # @param [Boolean] :track_history
109
+ # disable line history tracking, true by default
110
+ # @param [Boolean] :enable_color
103
111
  # enable color support, true by default
104
- # @option options [String] :active_color
112
+ # @param [String,Proc] :active_color
105
113
  # the color used for selected option
106
- # @option options [String] :help_color
114
+ # @param [String,Proc] :help_color
107
115
  # the color used for help text
108
- # @option options [String] :error_color
116
+ # @param [String] :error_color
109
117
  # the color used for displaying error messages
110
- # @option options [Symbol] :interrupt
111
- # handling of Ctrl+C key out of :signal, :exit, :noop
112
- # @option options [Boolean] :track_history
113
- # disable line history tracking, true by default
114
118
  #
115
119
  # @api public
116
- def initialize(*args)
117
- options = Utils.extract_options!(args)
118
- @input = options.fetch(:input) { $stdin }
119
- @output = options.fetch(:output) { $stdout }
120
- @env = options.fetch(:env) { ENV }
121
- @prefix = options.fetch(:prefix) { '' }
122
- @enabled_color = options[:enable_color]
123
- @active_color = options.fetch(:active_color) { :green }
124
- @help_color = options.fetch(:help_color) { :bright_black }
125
- @error_color = options.fetch(:error_color) { :red }
126
- @interrupt = options.fetch(:interrupt) { :error }
127
- @track_history = options.fetch(:track_history) { true }
120
+ def initialize(input: $stdin, output: $stdout, env: ENV, symbols: {},
121
+ prefix: "", interrupt: :error, track_history: true,
122
+ quiet: false, enable_color: nil, active_color: :green,
123
+ help_color: :bright_black, error_color: :red)
124
+ @input = input
125
+ @output = output
126
+ @env = env
127
+ @prefix = prefix
128
+ @enabled_color = enable_color
129
+ @active_color = active_color
130
+ @help_color = help_color
131
+ @error_color = error_color
132
+ @interrupt = interrupt
133
+ @track_history = track_history
134
+ @symbols = Symbols.symbols.merge(symbols)
135
+ @quiet = quiet
128
136
 
129
137
  @cursor = TTY::Cursor
130
- @pastel = Pastel.new(@enabled_color.nil? ? {} : { enabled: @enabled_color })
138
+ @pastel = enabled_color.nil? ? Pastel.new : Pastel.new(enabled: enabled_color)
131
139
  @reader = TTY::Reader.new(
132
- input: @input,
133
- output: @output,
134
- interrupt: @interrupt,
135
- track_history: @track_history,
136
- env: @env
140
+ input: input,
141
+ output: output,
142
+ interrupt: interrupt,
143
+ track_history: track_history,
144
+ env: env
137
145
  )
138
146
  end
139
147
 
148
+ # Decorate a string with colors
149
+ #
150
+ # @param [String] :string
151
+ # the string to color
152
+ # @param [Array<Proc|Symbol>] :colors
153
+ # collection of color symbols or callable object
154
+ #
155
+ # @api public
156
+ def decorate(string, *colors)
157
+ if Utils.blank?(string) || @enabled_color == false || colors.empty?
158
+ return string
159
+ end
160
+
161
+ coloring = colors.first
162
+ if coloring.respond_to?(:call)
163
+ coloring.call(string)
164
+ else
165
+ @pastel.decorate(string, *colors)
166
+ end
167
+ end
168
+
140
169
  # Invoke a question type of prompt
141
170
  #
142
171
  # @example
@@ -146,10 +175,9 @@ module TTY
146
175
  # @return [String]
147
176
  #
148
177
  # @api public
149
- def invoke_question(object, message, *args, &block)
150
- options = Utils.extract_options!(args)
178
+ def invoke_question(object, message, **options, &block)
151
179
  options[:messages] = self.class.messages
152
- question = object.new(self, options)
180
+ question = object.new(self, **options)
153
181
  question.(message, &block)
154
182
  end
155
183
 
@@ -170,8 +198,8 @@ module TTY
170
198
  # @return [TTY::Prompt::Question]
171
199
  #
172
200
  # @api public
173
- def ask(message, *args, &block)
174
- invoke_question(Question, message, *args, &block)
201
+ def ask(message = "", **options, &block)
202
+ invoke_question(Question, message, **options, &block)
175
203
  end
176
204
 
177
205
  # Ask a question with a keypress answer
@@ -179,20 +207,20 @@ module TTY
179
207
  # @see #ask
180
208
  #
181
209
  # @api public
182
- def keypress(message, *args, &block)
183
- invoke_question(Keypress, message, *args, &block)
210
+ def keypress(message = "", **options, &block)
211
+ invoke_question(Keypress, message, **options, &block)
184
212
  end
185
213
 
186
214
  # Ask a question with a multiline answer
187
215
  #
188
216
  # @example
189
- # prompt.multiline('Description?')
217
+ # prompt.multiline("Description?")
190
218
  #
191
219
  # @return [Array[String]]
192
220
  #
193
221
  # @api public
194
- def multiline(message, *args, &block)
195
- invoke_question(Multiline, message, *args, &block)
222
+ def multiline(message = "", **options, &block)
223
+ invoke_question(Multiline, message, **options, &block)
196
224
  end
197
225
 
198
226
  # Invoke a list type of prompt
@@ -207,9 +235,7 @@ module TTY
207
235
  # @api public
208
236
  def invoke_select(object, question, *args, &block)
209
237
  options = Utils.extract_options!(args)
210
- choices = if block
211
- []
212
- elsif args.empty?
238
+ choices = if args.empty? && !block
213
239
  possible = options.dup
214
240
  options = {}
215
241
  possible
@@ -219,7 +245,7 @@ module TTY
219
245
  args.flatten
220
246
  end
221
247
 
222
- list = object.new(self, options)
248
+ list = object.new(self, **options)
223
249
  list.(question, choices, &block)
224
250
  end
225
251
 
@@ -232,8 +258,8 @@ module TTY
232
258
  # @return [TTY::Prompt::MaskQuestion]
233
259
  #
234
260
  # @api public
235
- def mask(message, *args, &block)
236
- invoke_question(MaskQuestion, message, *args, &block)
261
+ def mask(message = "", **options, &block)
262
+ invoke_question(MaskQuestion, message, **options, &block)
237
263
  end
238
264
 
239
265
  # Ask a question with a list of options
@@ -301,42 +327,36 @@ module TTY
301
327
  end
302
328
 
303
329
  # A shortcut method to ask the user positive question and return
304
- # true for 'yes' reply, false for 'no'.
330
+ # true for "yes" reply, false for "no".
305
331
  #
306
332
  # @example
307
333
  # prompt = TTY::Prompt.new
308
- # prompt.yes?('Are you human?')
334
+ # prompt.yes?("Are you human?")
309
335
  # # => Are you human? (Y/n)
310
336
  #
311
337
  # @return [Boolean]
312
338
  #
313
339
  # @api public
314
- def yes?(message, *args, &block)
315
- defaults = { default: true }
316
- options = Utils.extract_options!(args)
317
- options.merge!(defaults.reject { |k, _| options.key?(k) })
318
-
319
- question = ConfirmQuestion.new(self, options)
340
+ def yes?(message, **options, &block)
341
+ opts = { default: true }.merge(options)
342
+ question = ConfirmQuestion.new(self, **opts)
320
343
  question.call(message, &block)
321
344
  end
322
345
 
323
346
  # A shortcut method to ask the user negative question and return
324
- # true for 'no' reply.
347
+ # true for "no" reply.
325
348
  #
326
349
  # @example
327
350
  # prompt = TTY::Prompt.new
328
- # prompt.no?('Are you alien?') # => true
351
+ # prompt.no?("Are you alien?") # => true
329
352
  # # => Are you human? (y/N)
330
353
  #
331
354
  # @return [Boolean]
332
355
  #
333
356
  # @api public
334
- def no?(message, *args, &block)
335
- defaults = { default: false }
336
- options = Utils.extract_options!(args)
337
- options.merge!(defaults.reject { |k, _| options.key?(k) })
338
-
339
- question = ConfirmQuestion.new(self, options)
357
+ def no?(message, **options, &block)
358
+ opts = { default: false }.merge(options)
359
+ question = ConfirmQuestion.new(self, **opts)
340
360
  !question.call(message, &block)
341
361
  end
342
362
 
@@ -345,15 +365,15 @@ module TTY
345
365
  # @example
346
366
  # prompt = TTY::Prompt.new
347
367
  # choices = [{
348
- # key: 'Y',
349
- # name: 'Overwrite',
368
+ # key: "Y",
369
+ # name: "Overwrite",
350
370
  # value: :yes
351
371
  # }, {
352
- # key: 'n',
353
- # name: 'Skip',
372
+ # key: "n",
373
+ # name: "Skip",
354
374
  # value: :no
355
375
  # }]
356
- # prompt.expand('Overwirte Gemfile?', choices)
376
+ # prompt.expand("Overwirte Gemfile?", choices)
357
377
  #
358
378
  # @return [Object]
359
379
  # the user specified value
@@ -367,7 +387,7 @@ module TTY
367
387
  #
368
388
  # @example
369
389
  # prompt = TTY::Prompt.new
370
- # prompt.slider('What size?', min: 32, max: 54, step: 2)
390
+ # prompt.slider("What size?", min: 32, max: 54, step: 2)
371
391
  #
372
392
  # @param [String] question
373
393
  # the question to ask
@@ -375,9 +395,8 @@ module TTY
375
395
  # @return [String]
376
396
  #
377
397
  # @api public
378
- def slider(question, *args, &block)
379
- options = Utils.extract_options!(args)
380
- slider = Slider.new(self, options)
398
+ def slider(question, **options, &block)
399
+ slider = Slider.new(self, **options)
381
400
  slider.call(question, &block)
382
401
  end
383
402
 
@@ -392,11 +411,11 @@ module TTY
392
411
  # @return [String]
393
412
  #
394
413
  # @api public
395
- def say(message = '', options = {})
414
+ def say(message = "", **options)
396
415
  message = message.to_s
397
416
  return if message.empty?
398
417
 
399
- statement = Statement.new(self, options)
418
+ statement = Statement.new(self, **options)
400
419
  statement.call(message)
401
420
  end
402
421
 
@@ -411,9 +430,9 @@ module TTY
411
430
  # @return [Array] messages
412
431
  #
413
432
  # @api public
414
- def ok(*args)
415
- options = Utils.extract_options!(args)
416
- args.each { |message| say message, options.merge(color: :green) }
433
+ def ok(*args, **options)
434
+ opts = { color: :green }.merge(options)
435
+ args.each { |message| say(message, **opts) }
417
436
  end
418
437
 
419
438
  # Print statement(s) out in yellow color.
@@ -427,9 +446,9 @@ module TTY
427
446
  # @return [Array] messages
428
447
  #
429
448
  # @api public
430
- def warn(*args)
431
- options = Utils.extract_options!(args)
432
- args.each { |message| say message, options.merge(color: :yellow) }
449
+ def warn(*args, **options)
450
+ opts = { color: :yellow }.merge(options)
451
+ args.each { |message| say(message, **opts) }
433
452
  end
434
453
 
435
454
  # Print statement(s) out in red color.
@@ -443,16 +462,38 @@ module TTY
443
462
  # @return [Array] messages
444
463
  #
445
464
  # @api public
446
- def error(*args)
447
- options = Utils.extract_options!(args)
448
- args.each { |message| say message, options.merge(color: :red) }
465
+ def error(*args, **options)
466
+ opts = { color: :red }.merge(options)
467
+ args.each { |message| say(message, **opts) }
468
+ end
469
+
470
+ # Print debug information in terminal top right corner
471
+ #
472
+ # @example
473
+ # prompt.debug "info1", "info2"
474
+ #
475
+ # @param [Array] messages
476
+ #
477
+ # @retrun [nil]
478
+ #
479
+ # @api public
480
+ def debug(*messages)
481
+ longest = messages.max_by(&:length).size
482
+ width = TTY::Screen.width - longest
483
+ print cursor.save
484
+ messages.reverse_each do |msg|
485
+ print cursor.column(width) + cursor.up + cursor.clear_line_after
486
+ print msg
487
+ end
488
+ ensure
489
+ print cursor.restore
449
490
  end
450
491
 
451
492
  # Takes the string provided by the user and compare it with other possible
452
493
  # matches to suggest an unambigous string
453
494
  #
454
495
  # @example
455
- # prompt.suggest('sta', ['status', 'stage', 'commit', 'branch'])
496
+ # prompt.suggest("sta", ["status", "stage", "commit", "branch"])
456
497
  # # => "status, stage"
457
498
  #
458
499
  # @param [String] message
@@ -470,8 +511,8 @@ module TTY
470
511
  # @return [String]
471
512
  #
472
513
  # @api public
473
- def suggest(message, possibilities, options = {})
474
- suggestion = Suggestion.new(options)
514
+ def suggest(message, possibilities, **options)
515
+ suggestion = Suggestion.new(**options)
475
516
  say(suggestion.suggest(message, possibilities))
476
517
  end
477
518
 
@@ -479,15 +520,15 @@ module TTY
479
520
  #
480
521
  # @example
481
522
  # prompt.collect do
482
- # key(:name).ask('Name?')
523
+ # key(:name).ask("Name?")
483
524
  # end
484
525
  #
485
526
  # @return [Hash]
486
527
  # the collection of answers
487
528
  #
488
529
  # @api public
489
- def collect(options = {}, &block)
490
- collector = AnswersCollector.new(self, options)
530
+ def collect(**options, &block)
531
+ collector = AnswersCollector.new(self, **options)
491
532
  collector.call(&block)
492
533
  end
493
534
 
@@ -521,21 +562,24 @@ module TTY
521
562
  $stderr
522
563
  end
523
564
 
524
- # Inspect class name and public attributes
565
+ # Inspect this instance public attributes
566
+ #
525
567
  # @return [String]
526
568
  #
527
569
  # @api public
528
570
  def inspect
529
- attributes = {
530
- input: input,
531
- output: output,
532
- prefix: prefix,
533
- active_color: active_color,
534
- error_color: error_color,
535
- enabled_color: enabled_color,
536
- help_color: help_color
537
- }
538
- "#<#{self.class}: #{attributes.each { |name, val| "@#{name}=#{val}" }}"
571
+ attributes = [
572
+ :prefix,
573
+ :quiet,
574
+ :enabled_color,
575
+ :active_color,
576
+ :error_color,
577
+ :help_color,
578
+ :input,
579
+ :output,
580
+ ]
581
+ name = self.class.name
582
+ "#<#{name}#{attributes.map { |attr| " #{attr}=#{send(attr).inspect}" }.join}>"
539
583
  end
540
584
  end # Prompt
541
585
  end # TTY