tty-prompt 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +66 -7
  4. data/examples/key_events.rb +11 -0
  5. data/examples/keypress.rb +3 -5
  6. data/examples/multiline.rb +9 -0
  7. data/examples/pause.rb +7 -0
  8. data/lib/tty/prompt.rb +82 -44
  9. data/lib/tty/prompt/confirm_question.rb +20 -36
  10. data/lib/tty/prompt/enum_list.rb +32 -23
  11. data/lib/tty/prompt/expander.rb +35 -31
  12. data/lib/tty/prompt/keypress.rb +91 -0
  13. data/lib/tty/prompt/list.rb +38 -23
  14. data/lib/tty/prompt/mask_question.rb +4 -7
  15. data/lib/tty/prompt/multi_list.rb +3 -1
  16. data/lib/tty/prompt/multiline.rb +71 -0
  17. data/lib/tty/prompt/question.rb +33 -35
  18. data/lib/tty/prompt/reader.rb +154 -38
  19. data/lib/tty/prompt/reader/codes.rb +4 -4
  20. data/lib/tty/prompt/reader/console.rb +1 -1
  21. data/lib/tty/prompt/reader/history.rb +145 -0
  22. data/lib/tty/prompt/reader/key_event.rb +4 -0
  23. data/lib/tty/prompt/reader/line.rb +162 -0
  24. data/lib/tty/prompt/reader/mode.rb +2 -2
  25. data/lib/tty/prompt/reader/win_console.rb +5 -1
  26. data/lib/tty/prompt/slider.rb +18 -12
  27. data/lib/tty/prompt/timeout.rb +48 -0
  28. data/lib/tty/prompt/version.rb +1 -1
  29. data/spec/unit/ask_spec.rb +15 -0
  30. data/spec/unit/converters/convert_bool_spec.rb +1 -0
  31. data/spec/unit/keypress_spec.rb +35 -6
  32. data/spec/unit/multi_select_spec.rb +18 -0
  33. data/spec/unit/multiline_spec.rb +67 -9
  34. data/spec/unit/question/default_spec.rb +1 -0
  35. data/spec/unit/question/echo_spec.rb +8 -0
  36. data/spec/unit/question/in_spec.rb +13 -0
  37. data/spec/unit/question/required_spec.rb +31 -2
  38. data/spec/unit/question/validate_spec.rb +39 -9
  39. data/spec/unit/reader/history_spec.rb +172 -0
  40. data/spec/unit/reader/key_event_spec.rb +12 -8
  41. data/spec/unit/reader/line_spec.rb +110 -0
  42. data/spec/unit/reader/publish_keypress_event_spec.rb +11 -0
  43. data/spec/unit/reader/read_line_spec.rb +32 -2
  44. data/spec/unit/reader/read_multiline_spec.rb +21 -7
  45. data/spec/unit/select_spec.rb +40 -1
  46. data/spec/unit/yes_no_spec.rb +48 -4
  47. metadata +14 -3
  48. data/lib/tty/prompt/history.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4ff94c2773632a84c5e652c8c725cdc576718ae6
4
- data.tar.gz: 382b630ad1f975325744210cb7a308bfc09175e2
3
+ metadata.gz: 7c73bc3ac5978ca2ec1610fee367e6e04e66c0ec
4
+ data.tar.gz: 3350a73010eb30efd4494799ff5a6e8437115a42
5
5
  SHA512:
6
- metadata.gz: ed722a06def652f9cb1e02fa627fe28ebfdfa0a8bdfa7a36e426b8976d4c0eab287f1e50f2800f2b7c87a185d1b4325d7628409991f6ba9061029976909c2805
7
- data.tar.gz: 5bad4344ba8e132eaf35409329ab8583aa52f2a94a296b5b23eb13cb11c3436e71601c7bd9351ecf17d70b1851d910b2600e4ea8cfea81e08d3de507edbfa43f
6
+ metadata.gz: cd4716769f48d957e8ef5f4167a231d042126ab565267697b3541cd150629c669079275c1cdf66b7d3bba60b02d0b800458d3b84d1f0d0fa26c3c7cce202b709
7
+ data.tar.gz: 003c09c9afe7d9f3e3b6014bc5352150f49a1609827c637342605f34fcbbac59f0a913b6d20f68cad8b698387b720c00f3025ab3a1fa30984b226adaada07f1f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Change log
2
2
 
3
+ ## [v0.12.0] - 2017-03-19
4
+
5
+ ### Added
6
+ * Add Multiline question type
7
+ * Add Keypress question type
8
+ * Add Reader::History for storing buffered lines
9
+ * Add Reader::Line for line abstraction
10
+
11
+ ### Changed
12
+ * Remove :read option from Question
13
+ * Chnage Reader#read_line to handle raw mode for processing special
14
+ characters such as Ctrl+x, navigate through history buffer
15
+ using up/down arrows, allow editing current line by moving left/right
16
+ with arrow keys and inserting content
17
+ * Change Reader#read_multiline to gather multi line input correctly,
18
+ skip empty lines and terminate when Ctrl+d and Ctrl+z are pressed
19
+ * Change Reader::Mode to check if tty is available by Matt Martyn (@MMartyn)
20
+ * Change #keypress prompt to correctly refresh line and accept :keys & :timeout options
21
+
22
+ ### Fixed
23
+ * Fix issue with #select, #multi_selct, #enum_select when choices are
24
+ provided as hash object together with prompt options.
25
+ * Fix issue with default parameter for yes?/no? prompt by Carlos Fonseca (@carlosefonseca)
26
+ * Fix List#help to allow setting help text through DSL
27
+
3
28
  ## [v0.11.0] - 2017-02-26
4
29
 
5
30
  ### Added
data/README.md CHANGED
@@ -56,6 +56,7 @@ Or install it yourself as:
56
56
  * [2.1.7 required](#217-required)
57
57
  * [2.1.8 validate](#218-validate)
58
58
  * [2.2 keypress](#22-keypress)
59
+ * [2.2.1 timeout](#221-timeout)
59
60
  * [2.3 multiline](#23-multiline)
60
61
  * [2.4 mask](#24-mask)
61
62
  * [2.5 yes?/no?](#25-yesno)
@@ -79,6 +80,7 @@ Or install it yourself as:
79
80
  * [3.3 help_color](#33-help_color)
80
81
  * [3.4 interrupt](#34-interrupt)
81
82
  * [3.5 prefix](#35-prefix)
83
+ * [3.6 trakc_history](#36-track_history)
82
84
 
83
85
  ## 1. Usage
84
86
 
@@ -349,21 +351,61 @@ prompt.ask('What is your email?') { |q| q.validate :email }
349
351
 
350
352
  ### 2.2. keypress
351
353
 
352
- In order to ask question with a single character or keypress answer use `keypress`:
354
+ In order to ask question that awaits a single character answer use `keypress` prompt like so:
353
355
 
354
356
  ```ruby
355
- prompt.keypress("Which one do you prefer a, b, c or d ?")
357
+ prompt.keypress("Press key ?")
358
+ # Press key?
359
+ # => a
360
+ ```
361
+
362
+ By default any key is accepted but you can limit keys by using `:keys` option. Any key event names such as `:space` or `:ctrl_k` are valid:
363
+
364
+ ```ruby
365
+ prompt.keypress("Press space or enter to continue, keys: [:space, :return])
366
+ ```
367
+
368
+ #### 2.2.1 timeout
369
+
370
+ Timeout can be set using `:timeout` option to expire prompt and allow the script to continue automatically:
371
+
372
+ ```ruby
373
+ prompt.keypress("Press any key to continue, resumes automatically in 3 seconds ...", timeout: 3)
374
+ ```
375
+
376
+ In addition the `keypress` recognises `:countdown` token when inserted inside the question. It will automatically countdown the time in seconds:
377
+
378
+ ```ruby
379
+ prompt.keypress("Press any key to continue, resumes automatically in :countdown ...", timeout: 3)
356
380
  ```
357
381
 
358
382
  ### 2.3 multiline
359
383
 
360
- Asking for multiline input can be done with `multiline` method.
384
+ Asking for multiline input can be done with `multiline` method. The reading of input will terminate when `Ctrl+d` or `Ctrl+z` is pressed. Empty lines will not be included in the returned array.
361
385
 
362
386
  ```ruby
363
- prompt.multiline("Provide description?")
387
+ prompt.multiline("Description?")
388
+ # Description? (Press CTRL-D or CTRL-Z to finish)
389
+ # I know not all that may be coming,
390
+ # but be it what it will,
391
+ # I'll go to it laughing.
392
+ # => ["I know not all that may be coming,\n", "but be it what it will,\n", "I'll go to it laughing.\n"]
364
393
  ```
365
394
 
366
- The reading of input will terminate when empty line is submitted.
395
+ The `multiline` uses similar options to those supported by `ask` prompt. For example, to provide default description:
396
+
397
+ ```ruby
398
+ prompt.multiline("Description?", default: 'A super sweet prompt.')
399
+ ```
400
+
401
+ or using DSL:
402
+
403
+ ```ruby
404
+ prompt.multiline("Description?") do |q|
405
+ q.default 'A super sweet prompt.'
406
+ q.help 'Press thy ctrl+d to end'
407
+ end
408
+ ```
367
409
 
368
410
  ### 2.4 mask
369
411
 
@@ -377,8 +419,9 @@ prompt.mask('What is your secret?')
377
419
  The masking character can be changed by passing `:mask` option:
378
420
 
379
421
  ```ruby
380
- prompt.mask('What is your secret?', mask: '\u2665')
381
- # => What is your secret? ♥♥♥♥♥
422
+ heart = prompt.decorate(' ', :magenta)
423
+ prompt.mask('What is your secret?', mask: heart)
424
+ # => What is your secret? ❤ ❤ ❤ ❤ ❤
382
425
  ```
383
426
 
384
427
  If you don't wish to show any output use `:echo` option like so:
@@ -387,6 +430,14 @@ If you don't wish to show any output use `:echo` option like so:
387
430
  prompt.mask('What is your secret?', echo: false)
388
431
  ```
389
432
 
433
+ You can also provide validation for your mask to enforce for instance strong passwords:
434
+
435
+ ```ruby
436
+ prompt.mask('What is your secret?', mask: heart) do |q|
437
+ q.validate(/[a-z\ ]{5,15}/)
438
+ end
439
+ ```
440
+
390
441
  ### 2.5 yes?/no?
391
442
 
392
443
  In order to display a query asking for boolean input from user use `yes?` like so:
@@ -1058,6 +1109,14 @@ You can prefix each question asked using the `:prefix` option. This option can b
1058
1109
  prompt = TTY::Prompt.new(prefix: '[?] ')
1059
1110
  ```
1060
1111
 
1112
+ ### 3.6 track_history
1113
+
1114
+ The prompts that accept line input such as `multiline` or `ask` provide history buffer that tracks all the lines entered during `TTY::Prompt.new` interactions. The history buffer provides previoius or next lines when user presses up/down arrows respectively. However, if you wish to disable this behaviour use `:track_history` option like so:
1115
+
1116
+ ```ruby
1117
+ prompt = TTY::Prompt.new(track_history: false)
1118
+ ```
1119
+
1061
1120
  ## Contributing
1062
1121
 
1063
1122
  1. Fork it ( https://github.com/piotrmurach/tty-prompt/fork )
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tty-prompt'
4
+
5
+ prompt = TTY::Prompt::new(interrupt: :exit)
6
+
7
+ prompt.on(:keypress) do |event|
8
+ puts "name: #{event.key.name}, value: #{event.value.dump}"
9
+ end
10
+
11
+ prompt.read_keypress
data/examples/keypress.rb CHANGED
@@ -2,10 +2,8 @@
2
2
 
3
3
  require 'tty-prompt'
4
4
 
5
- prompt = TTY::Prompt::new(interrupt: :exit)
5
+ prompt = TTY::Prompt::new
6
6
 
7
- prompt.on(:keypress) do |event|
8
- puts "name: #{event.key.name}, value: #{event.value.dump}"
9
- end
7
+ answer = prompt.keypress("Press any key to continue")
10
8
 
11
- prompt.read_keypress
9
+ puts "Answer: #{answer}"
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tty-prompt'
4
+
5
+ prompt = TTY::Prompt::new
6
+
7
+ answer = prompt.multiline("Description:")
8
+
9
+ puts "Answer: #{answer.inspect}"
data/examples/pause.rb ADDED
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tty-prompt'
4
+
5
+ prompt = TTY::Prompt::new
6
+
7
+ prompt.keypress("Press space or enter to continue, continuing automatically in :countdown ...", keys: [:space, :return], timeout: 3)
data/lib/tty/prompt.rb CHANGED
@@ -8,8 +8,10 @@ require_relative 'prompt/answers_collector'
8
8
  require_relative 'prompt/confirm_question'
9
9
  require_relative 'prompt/expander'
10
10
  require_relative 'prompt/enum_list'
11
+ require_relative 'prompt/keypress'
11
12
  require_relative 'prompt/list'
12
13
  require_relative 'prompt/multi_list'
14
+ require_relative 'prompt/multiline'
13
15
  require_relative 'prompt/mask_question'
14
16
  require_relative 'prompt/question'
15
17
  require_relative 'prompt/reader'
@@ -87,6 +89,28 @@ module TTY
87
89
 
88
90
  # Initialize a Prompt
89
91
  #
92
+ # @param [Hash] options
93
+ # @option options [IO] :input
94
+ # the input stream
95
+ # @option options [IO] :output
96
+ # the output stream
97
+ # @option options [Hash] :env
98
+ # the environment variables
99
+ # @option options [String] :prefix
100
+ # the prompt prefix, by default empty
101
+ # @option options [Boolean] :enable_color
102
+ # enable color support, true by default
103
+ # @option options [String] :active_color
104
+ # the color used for selected option
105
+ # @option options [String] :help_color
106
+ # the color used for help text
107
+ # @option options [String] :error_color
108
+ # the color used for displaying error messages
109
+ # @option options [Symbol] :interrupt
110
+ # handling of Ctrl+C key out of :signal, :exit, :noop
111
+ # @option options [Boolean] :track_history
112
+ # disable line history tracking, true by default
113
+ #
90
114
  # @api public
91
115
  def initialize(*args)
92
116
  options = Utils.extract_options!(args)
@@ -98,10 +122,29 @@ module TTY
98
122
  @active_color = options.fetch(:active_color) { :green }
99
123
  @help_color = options.fetch(:help_color) { :bright_black }
100
124
  @error_color = options.fetch(:error_color) { :red }
125
+ @interrupt = options.fetch(:interrupt) { :error }
126
+ @track_history = options.fetch(:track_history) { true }
101
127
 
102
128
  @cursor = TTY::Cursor
103
129
  @pastel = Pastel.new(@enabled_color.nil? ? {} : { enabled: @enabled_color })
104
- @reader = Reader.new(@input, @output, interrupt: options[:interrupt], env: @env)
130
+ @reader = Reader.new(@input, @output, interrupt: @interrupt,
131
+ track_history: @track_history, env: @env)
132
+ end
133
+
134
+ # Invoke a question type of prompt
135
+ #
136
+ # @example
137
+ # prompt = TTY::Prompt.new
138
+ # prompt.invoke_question(Question, "Your name? ")
139
+ #
140
+ # @return [String]
141
+ #
142
+ # @api public
143
+ def invoke_question(object, message, *args, &block)
144
+ options = Utils.extract_options!(args)
145
+ options[:messages] = self.class.messages
146
+ question = object.new(self, options)
147
+ question.(message, &block)
105
148
  end
106
149
 
107
150
  # Ask a question.
@@ -122,10 +165,7 @@ module TTY
122
165
  #
123
166
  # @api public
124
167
  def ask(message, *args, &block)
125
- options = Utils.extract_options!(args)
126
- options.merge!({messages: self.class.messages})
127
- question = Question.new(self, options)
128
- question.call(message, &block)
168
+ invoke_question(Question, message, *args, &block)
129
169
  end
130
170
 
131
171
  # Ask a question with a keypress answer
@@ -134,22 +174,47 @@ module TTY
134
174
  #
135
175
  # @api public
136
176
  def keypress(message, *args, &block)
137
- options = Utils.extract_options!(args)
138
- options.merge!(read: :keypress)
139
- args << options
140
- ask(message, *args, &block)
177
+ invoke_question(Keypress, message, *args, &block)
141
178
  end
142
179
 
143
180
  # Ask a question with a multiline answer
144
181
  #
145
- # @see @ask
182
+ # @example
183
+ # prompt.multiline('Description?')
184
+ #
185
+ # @return [Array[String]]
146
186
  #
147
187
  # @api public
148
188
  def multiline(message, *args, &block)
189
+ invoke_question(Multiline, message, *args, &block)
190
+ end
191
+
192
+ # Invoke a list type of prompt
193
+ #
194
+ # @example
195
+ # prompt = TTY::Prompt.new
196
+ # editors = %w(emacs nano vim)
197
+ # prompt.invoke_select(EnumList, "Select editor: ", editors)
198
+ #
199
+ # @return [String]
200
+ #
201
+ # @api public
202
+ def invoke_select(object, question, *args, &block)
149
203
  options = Utils.extract_options!(args)
150
- options.merge!(read: :multiline)
151
- args << options
152
- ask(message, *args, &block)
204
+ choices = if block
205
+ []
206
+ elsif args.empty?
207
+ possible = options.dup
208
+ options = {}
209
+ possible
210
+ elsif args.size == 1 && args[0].is_a?(Hash)
211
+ Utils.extract_options!(args)
212
+ else
213
+ args.flatten
214
+ end
215
+
216
+ list = object.new(self, options)
217
+ list.(question, choices, &block)
153
218
  end
154
219
 
155
220
  # Ask masked question
@@ -162,10 +227,7 @@ module TTY
162
227
  #
163
228
  # @api public
164
229
  def mask(message, *args, &block)
165
- options = Utils.extract_options!(args)
166
- options.merge!({messages: self.class.messages})
167
- question = MaskQuestion.new(self, options)
168
- question.call(message, &block)
230
+ invoke_question(MaskQuestion, message, *args, &block)
169
231
  end
170
232
 
171
233
  # Ask a question with a list of options
@@ -232,30 +294,6 @@ module TTY
232
294
  invoke_select(EnumList, question, *args, &block)
233
295
  end
234
296
 
235
- # Invoke a list type of prompt
236
- #
237
- # @example
238
- # prompt = TTY::Prompt.new
239
- # editors = %w(emacs nano vim)
240
- # prompt.invoke_select(EnumList, "Select editor: ", editors)
241
- #
242
- # @return [String]
243
- #
244
- # @api public
245
- def invoke_select(object, question, *args, &block)
246
- options = Utils.extract_options!(args)
247
- choices = if block
248
- []
249
- elsif args.empty?
250
- options
251
- else
252
- args.flatten
253
- end
254
-
255
- list = object.new(self, options)
256
- list.call(question, choices, &block)
257
- end
258
-
259
297
  # A shortcut method to ask the user positive question and return
260
298
  # true for 'yes' reply, false for 'no'.
261
299
  #
@@ -288,7 +326,7 @@ module TTY
288
326
  #
289
327
  # @api public
290
328
  def no?(message, *args, &block)
291
- defaults = { default: false, type: :no }
329
+ defaults = { default: false }
292
330
  options = Utils.extract_options!(args)
293
331
  options.merge!(defaults.reject { |k, _| options.key?(k) })
294
332
 
@@ -350,7 +388,7 @@ module TTY
350
388
  # @api public
351
389
  def say(message = '', options = {})
352
390
  message = message.to_s
353
- return unless message.length > 0
391
+ return if message.empty?
354
392
 
355
393
  statement = Statement.new(self, options)
356
394
  statement.call(message)
@@ -491,7 +529,7 @@ module TTY
491
529
  enabled_color: enabled_color,
492
530
  help_color: help_color
493
531
  }
494
- "#<#{self.class}: #{attributes.each { |name, val| "@#{name}=#{val}" } }"
532
+ "#<#{self.class}: #{attributes.each { |name, val| "@#{name}=#{val}" }}"
495
533
  end
496
534
  end # Prompt
497
535
  end # TTY
@@ -16,11 +16,9 @@ module TTY
16
16
  # @api public
17
17
  def initialize(prompt, options = {})
18
18
  super
19
-
20
19
  @suffix = options.fetch(:suffix) { UndefinedSetting }
21
20
  @positive = options.fetch(:positive) { UndefinedSetting }
22
21
  @negative = options.fetch(:negative) { UndefinedSetting }
23
- @type = options.fetch(:type) { :yes }
24
22
  end
25
23
 
26
24
  def positive?
@@ -38,21 +36,24 @@ module TTY
38
36
  # Set question suffix
39
37
  #
40
38
  # @api public
41
- def suffix(value)
39
+ def suffix(value = (not_set = true))
40
+ return @negative if not_set
42
41
  @suffix = value
43
42
  end
44
43
 
45
44
  # Set value for matching positive choice
46
45
  #
47
46
  # @api public
48
- def positive(value)
47
+ def positive(value = (not_set = true))
48
+ return @positive if not_set
49
49
  @positive = value
50
50
  end
51
51
 
52
52
  # Set value for matching negative choice
53
53
  #
54
54
  # @api public
55
- def negative(value)
55
+ def negative(value = (not_set = true))
56
+ return @negative if not_set
56
57
  @negative = value
57
58
  end
58
59
 
@@ -66,10 +67,11 @@ module TTY
66
67
 
67
68
  # Render confirmation question
68
69
  #
70
+ # @return [String]
71
+ #
69
72
  # @api private
70
73
  def render_question
71
74
  header = "#{@prefix}#{message} "
72
-
73
75
  if !@done
74
76
  header += @prompt.decorate("(#{@suffix})", @help_color) + ' '
75
77
  else
@@ -77,24 +79,17 @@ module TTY
77
79
  label = answer ? @positive : @negative
78
80
  header += @prompt.decorate(label, @active_color)
79
81
  end
80
- @prompt.print(header)
81
- @prompt.puts if @done
82
-
83
- header.lines.count + (@done ? 1 : 0)
82
+ header << "\n" if @done
83
+ header
84
84
  end
85
85
 
86
86
  protected
87
87
 
88
- # @api private
89
- def is?(type)
90
- @type == type
91
- end
92
-
93
88
  # @api private
94
89
  def setup_defaults
95
90
  return if suffix? && positive?
96
91
 
97
- if suffix? && !positive?
92
+ if suffix? && (!positive? || !negative?)
98
93
  parts = @suffix.split('/')
99
94
  @positive = parts[0]
100
95
  @negative = parts[1]
@@ -104,41 +99,30 @@ module TTY
104
99
  @convert = conversion
105
100
  else
106
101
  create_default_labels
107
- @convert = :bool
102
+ @convert = :bool
108
103
  end
109
104
  end
110
105
 
106
+ # @api private
111
107
  def create_default_labels
112
- if is?(:yes)
113
- @suffix = default? ? 'Y/n' : 'y/N'
114
- @positive = default? ? 'Yes' : 'yes'
115
- @negative = default? ? 'no' : 'No'
116
- else
117
- @suffix = default? ? 'y/N' : 'Y/n'
118
- @positive = default? ? 'Yes' : 'yes'
119
- @negative = default? ? 'No' : 'no'
120
- end
108
+ @suffix = default ? 'Y/n' : 'y/N'
109
+ @positive = default ? 'Yes' : 'yes'
110
+ @negative = default ? 'no' : 'No'
121
111
  end
122
112
 
123
113
  # @api private
124
114
  def create_suffix
125
115
  result = ''
126
- if is?(:yes)
127
- result << "#{default? ? @positive.capitalize : @positive.downcase}"
128
- result << '/'
129
- result << "#{default? ? @negative.downcase : @negative.capitalize}"
130
- else
131
- result << "#{default? ? @positive.downcase : @positive.capitalize}"
132
- result << '/'
133
- result << "#{default? ? @negative.capitalize : @negative.downcase}"
134
- end
116
+ result << "#{default ? positive.capitalize : positive.downcase}"
117
+ result << '/'
118
+ result << "#{default ? negative.downcase : negative.capitalize}"
135
119
  end
136
120
 
137
121
  # Create custom conversion
138
122
  #
139
123
  # @api private
140
124
  def conversion
141
- proc { |input| !input.match(/^#{@positive}|#{@positive[0]}$/i).nil? }
125
+ proc { |input| !input.match(/^#{positive}|#{positive[0]}$/i).nil? }
142
126
  end
143
127
  end # ConfirmQuestion
144
128
  end # Prompt