tty-prompt 0.18.0 → 0.22.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.
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