tty-prompt 0.18.1 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -0
  3. data/README.md +598 -256
  4. data/lib/tty-prompt.rb +1 -2
  5. data/lib/tty/prompt.rb +192 -144
  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 +9 -10
  9. data/lib/tty/prompt/choices.rb +30 -12
  10. data/lib/tty/prompt/confirm_question.rb +42 -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 +81 -26
  16. data/lib/tty/prompt/errors.rb +31 -0
  17. data/lib/tty/prompt/evaluator.rb +2 -2
  18. data/lib/tty/prompt/expander.rb +45 -15
  19. data/lib/tty/prompt/keypress.rb +33 -36
  20. data/lib/tty/prompt/list.rb +198 -63
  21. data/lib/tty/prompt/mask_question.rb +11 -8
  22. data/lib/tty/prompt/multi_list.rb +131 -28
  23. data/lib/tty/prompt/multiline.rb +9 -7
  24. data/lib/tty/prompt/paginator.rb +38 -26
  25. data/lib/tty/prompt/question.rb +92 -37
  26. data/lib/tty/prompt/question/checks.rb +20 -2
  27. data/lib/tty/prompt/question/modifier.rb +4 -2
  28. data/lib/tty/prompt/question/validation.rb +3 -3
  29. data/lib/tty/prompt/selected_choices.rb +77 -0
  30. data/lib/tty/prompt/slider.rb +125 -30
  31. data/lib/tty/prompt/statement.rb +3 -3
  32. data/lib/tty/prompt/suggestion.rb +7 -6
  33. data/lib/tty/prompt/symbols.rb +58 -34
  34. data/lib/tty/prompt/test.rb +36 -0
  35. data/lib/tty/prompt/timer.rb +75 -0
  36. data/lib/tty/prompt/utils.rb +1 -3
  37. data/lib/tty/prompt/version.rb +1 -1
  38. metadata +29 -227
  39. data/Rakefile +0 -8
  40. data/examples/ask.rb +0 -7
  41. data/examples/ask_valid.rb +0 -12
  42. data/examples/collect.rb +0 -21
  43. data/examples/echo.rb +0 -11
  44. data/examples/enum_select.rb +0 -7
  45. data/examples/enum_select_disabled.rb +0 -16
  46. data/examples/enum_select_paged.rb +0 -9
  47. data/examples/enum_select_wrapped.rb +0 -15
  48. data/examples/expand.rb +0 -29
  49. data/examples/in.rb +0 -9
  50. data/examples/inputs.rb +0 -10
  51. data/examples/key_events.rb +0 -15
  52. data/examples/keypress.rb +0 -9
  53. data/examples/mask.rb +0 -13
  54. data/examples/multi_select.rb +0 -8
  55. data/examples/multi_select_disabled.rb +0 -17
  56. data/examples/multi_select_paged.rb +0 -9
  57. data/examples/multi_select_wrapped.rb +0 -15
  58. data/examples/multiline.rb +0 -9
  59. data/examples/pause.rb +0 -9
  60. data/examples/select.rb +0 -24
  61. data/examples/select_disabled.rb +0 -18
  62. data/examples/select_enum.rb +0 -8
  63. data/examples/select_filtered.rb +0 -11
  64. data/examples/select_paginated.rb +0 -11
  65. data/examples/select_wrapped.rb +0 -15
  66. data/examples/slider.rb +0 -6
  67. data/examples/validation.rb +0 -9
  68. data/examples/yes_no.rb +0 -7
  69. data/lib/tty/prompt/messages.rb +0 -49
  70. data/lib/tty/prompt/timeout.rb +0 -78
  71. data/lib/tty/test_prompt.rb +0 -20
  72. data/spec/spec_helper.rb +0 -45
  73. data/spec/unit/ask_spec.rb +0 -132
  74. data/spec/unit/choice/eql_spec.rb +0 -22
  75. data/spec/unit/choice/from_spec.rb +0 -96
  76. data/spec/unit/choices/add_spec.rb +0 -12
  77. data/spec/unit/choices/each_spec.rb +0 -13
  78. data/spec/unit/choices/find_by_spec.rb +0 -10
  79. data/spec/unit/choices/new_spec.rb +0 -10
  80. data/spec/unit/choices/pluck_spec.rb +0 -9
  81. data/spec/unit/collect_spec.rb +0 -96
  82. data/spec/unit/converters/convert_bool_spec.rb +0 -58
  83. data/spec/unit/converters/convert_char_spec.rb +0 -11
  84. data/spec/unit/converters/convert_custom_spec.rb +0 -14
  85. data/spec/unit/converters/convert_date_spec.rb +0 -34
  86. data/spec/unit/converters/convert_file_spec.rb +0 -18
  87. data/spec/unit/converters/convert_number_spec.rb +0 -39
  88. data/spec/unit/converters/convert_path_spec.rb +0 -15
  89. data/spec/unit/converters/convert_range_spec.rb +0 -22
  90. data/spec/unit/converters/convert_regex_spec.rb +0 -12
  91. data/spec/unit/converters/convert_string_spec.rb +0 -21
  92. data/spec/unit/converters/on_error_spec.rb +0 -9
  93. data/spec/unit/distance/distance_spec.rb +0 -73
  94. data/spec/unit/enum_paginator_spec.rb +0 -75
  95. data/spec/unit/enum_select_spec.rb +0 -446
  96. data/spec/unit/error_spec.rb +0 -20
  97. data/spec/unit/evaluator_spec.rb +0 -67
  98. data/spec/unit/expand_spec.rb +0 -198
  99. data/spec/unit/keypress_spec.rb +0 -72
  100. data/spec/unit/mask_spec.rb +0 -132
  101. data/spec/unit/multi_select_spec.rb +0 -511
  102. data/spec/unit/multiline_spec.rb +0 -77
  103. data/spec/unit/new_spec.rb +0 -20
  104. data/spec/unit/ok_spec.rb +0 -10
  105. data/spec/unit/paginator_spec.rb +0 -73
  106. data/spec/unit/question/checks_spec.rb +0 -97
  107. data/spec/unit/question/default_spec.rb +0 -31
  108. data/spec/unit/question/echo_spec.rb +0 -38
  109. data/spec/unit/question/in_spec.rb +0 -115
  110. data/spec/unit/question/initialize_spec.rb +0 -12
  111. data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
  112. data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
  113. data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
  114. data/spec/unit/question/modify_spec.rb +0 -41
  115. data/spec/unit/question/required_spec.rb +0 -92
  116. data/spec/unit/question/validate_spec.rb +0 -115
  117. data/spec/unit/question/validation/call_spec.rb +0 -31
  118. data/spec/unit/question/validation/coerce_spec.rb +0 -30
  119. data/spec/unit/result_spec.rb +0 -40
  120. data/spec/unit/say_spec.rb +0 -67
  121. data/spec/unit/select_spec.rb +0 -660
  122. data/spec/unit/slider_spec.rb +0 -100
  123. data/spec/unit/statement/initialize_spec.rb +0 -15
  124. data/spec/unit/subscribe_spec.rb +0 -22
  125. data/spec/unit/suggest_spec.rb +0 -28
  126. data/spec/unit/warn_spec.rb +0 -21
  127. data/spec/unit/yes_no_spec.rb +0 -251
  128. data/tasks/console.rake +0 -11
  129. data/tasks/coverage.rake +0 -11
  130. data/tasks/spec.rake +0 -29
  131. 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,18 +387,21 @@ 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)
391
+ # prompt.slider("What size?", [ 'xs', 's', 'm', 'l', 'xl' ])
371
392
  #
372
393
  # @param [String] question
373
394
  # the question to ask
374
395
  #
396
+ # @param [Array] choices
397
+ # the choices to display
398
+ #
375
399
  # @return [String]
376
400
  #
377
401
  # @api public
378
- def slider(question, *args, &block)
379
- options = Utils.extract_options!(args)
380
- slider = Slider.new(self, options)
381
- slider.call(question, &block)
402
+ def slider(question, choices = nil, **options, &block)
403
+ slider = Slider.new(self, **options)
404
+ slider.call(question, choices, &block)
382
405
  end
383
406
 
384
407
  # Print statement out. If the supplied message ends with a space or
@@ -392,11 +415,11 @@ module TTY
392
415
  # @return [String]
393
416
  #
394
417
  # @api public
395
- def say(message = '', options = {})
418
+ def say(message = "", **options)
396
419
  message = message.to_s
397
420
  return if message.empty?
398
421
 
399
- statement = Statement.new(self, options)
422
+ statement = Statement.new(self, **options)
400
423
  statement.call(message)
401
424
  end
402
425
 
@@ -411,9 +434,9 @@ module TTY
411
434
  # @return [Array] messages
412
435
  #
413
436
  # @api public
414
- def ok(*args)
415
- options = Utils.extract_options!(args)
416
- args.each { |message| say message, options.merge(color: :green) }
437
+ def ok(*args, **options)
438
+ opts = { color: :green }.merge(options)
439
+ args.each { |message| say(message, **opts) }
417
440
  end
418
441
 
419
442
  # Print statement(s) out in yellow color.
@@ -427,9 +450,9 @@ module TTY
427
450
  # @return [Array] messages
428
451
  #
429
452
  # @api public
430
- def warn(*args)
431
- options = Utils.extract_options!(args)
432
- args.each { |message| say message, options.merge(color: :yellow) }
453
+ def warn(*args, **options)
454
+ opts = { color: :yellow }.merge(options)
455
+ args.each { |message| say(message, **opts) }
433
456
  end
434
457
 
435
458
  # Print statement(s) out in red color.
@@ -443,16 +466,38 @@ module TTY
443
466
  # @return [Array] messages
444
467
  #
445
468
  # @api public
446
- def error(*args)
447
- options = Utils.extract_options!(args)
448
- args.each { |message| say message, options.merge(color: :red) }
469
+ def error(*args, **options)
470
+ opts = { color: :red }.merge(options)
471
+ args.each { |message| say(message, **opts) }
472
+ end
473
+
474
+ # Print debug information in terminal top right corner
475
+ #
476
+ # @example
477
+ # prompt.debug "info1", "info2"
478
+ #
479
+ # @param [Array] messages
480
+ #
481
+ # @retrun [nil]
482
+ #
483
+ # @api public
484
+ def debug(*messages)
485
+ longest = messages.max_by(&:length).size
486
+ width = TTY::Screen.width - longest
487
+ print cursor.save
488
+ messages.reverse_each do |msg|
489
+ print cursor.column(width) + cursor.up + cursor.clear_line_after
490
+ print msg
491
+ end
492
+ ensure
493
+ print cursor.restore
449
494
  end
450
495
 
451
496
  # Takes the string provided by the user and compare it with other possible
452
497
  # matches to suggest an unambigous string
453
498
  #
454
499
  # @example
455
- # prompt.suggest('sta', ['status', 'stage', 'commit', 'branch'])
500
+ # prompt.suggest("sta", ["status", "stage", "commit", "branch"])
456
501
  # # => "status, stage"
457
502
  #
458
503
  # @param [String] message
@@ -470,8 +515,8 @@ module TTY
470
515
  # @return [String]
471
516
  #
472
517
  # @api public
473
- def suggest(message, possibilities, options = {})
474
- suggestion = Suggestion.new(options)
518
+ def suggest(message, possibilities, **options)
519
+ suggestion = Suggestion.new(**options)
475
520
  say(suggestion.suggest(message, possibilities))
476
521
  end
477
522
 
@@ -479,15 +524,15 @@ module TTY
479
524
  #
480
525
  # @example
481
526
  # prompt.collect do
482
- # key(:name).ask('Name?')
527
+ # key(:name).ask("Name?")
483
528
  # end
484
529
  #
485
530
  # @return [Hash]
486
531
  # the collection of answers
487
532
  #
488
533
  # @api public
489
- def collect(options = {}, &block)
490
- collector = AnswersCollector.new(self, options)
534
+ def collect(**options, &block)
535
+ collector = AnswersCollector.new(self, **options)
491
536
  collector.call(&block)
492
537
  end
493
538
 
@@ -521,21 +566,24 @@ module TTY
521
566
  $stderr
522
567
  end
523
568
 
524
- # Inspect class name and public attributes
569
+ # Inspect this instance public attributes
570
+ #
525
571
  # @return [String]
526
572
  #
527
573
  # @api public
528
574
  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}" }}"
575
+ attributes = [
576
+ :prefix,
577
+ :quiet,
578
+ :enabled_color,
579
+ :active_color,
580
+ :error_color,
581
+ :help_color,
582
+ :input,
583
+ :output,
584
+ ]
585
+ name = self.class.name
586
+ "#<#{name}#{attributes.map { |attr| " #{attr}=#{send(attr).inspect}" }.join}>"
539
587
  end
540
588
  end # Prompt
541
589
  end # TTY