highline 2.0.0.pre.develop.4 → 2.0.0.pre.develop.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fe7f4a2acbc139058d22c6e720cf45f3d8807278
4
- data.tar.gz: 4a2e208bb898d2498f5911efaa695095341cb43c
3
+ metadata.gz: 13e2a946fd059cbf2c25bff77dc7e70b299fccab
4
+ data.tar.gz: c35a2236e1ce0d83cac30b9e2464abf4f61fc421
5
5
  SHA512:
6
- metadata.gz: 3f276ad26eb858d757254770be10c6a007b0c4032078ef7f750b677499ed19c43315b0518d802480fd3cb9b8f2804286bdfd255ea647a85f5209be312dd8ab90
7
- data.tar.gz: ab6323e8a8a16a5912328700cb207ca9009a60f05772102bf643db3ca8dd4b21dc7a527d79aad8113cbb32f2d6a1ed66297220d3faf86c3ca43d8befa85a8034
6
+ metadata.gz: dadda880956f0ecb41ffca76a81cb89cd26fc63e3dea10f54bc7753d7af95e7f04a7185b0a1caab7a2b0ea31cc0cb932fb25971094252925af9cd52759176a4f
7
+ data.tar.gz: 54aa4ee03370b217bb9dacb8e94ba129f70cab24513297fe24f863a99b635ba45992091d5dea60c08ee94f5d77138329d9385f6ff01808336bdf8ac1d859d219
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ doc
2
2
  pkg
3
3
  .DS_Store
4
4
  coverage
5
+ Gemfile.lock
@@ -2,6 +2,16 @@
2
2
 
3
3
  Below is a complete listing of changes for each revision of HighLine.
4
4
 
5
+ ### 2.0.0-develop.6 / 2016-02-01
6
+ * PR #184 - Menu improvements, bug fixes, and more tests by Geoff Lee (@matrinox)
7
+ * Add third arg to menu that overides the choice displayed to the user
8
+ * FIX: autocomplete prompt does not include menu choices after the first
9
+ * Add specs to cover the new features and the bug fix
10
+ * PR #183 - Fix menu example in README.md by Fabien Foerster (@fabienfoerster)
11
+
12
+ ### 2.0.0-develop.5 / 2015-12-27
13
+ * Fix #180 with PR #181 - Make it possible to overwrite the menu prompt shown on errors.
14
+
5
15
  ### 2.0.0-develop.4 / 2015-12-14
6
16
  This versions makes the code documentation 100% 'A' grade on inch.
7
17
  We have used inch and http://inch-ci.org to guide the priorities
data/README.md CHANGED
@@ -72,8 +72,8 @@ cli.say("This should be <%= color('bold', BOLD) %>!")
72
72
 
73
73
  cli.choose do |menu|
74
74
  menu.prompt = "Please choose your favorite programming language? "
75
- menu.choice(:ruby) { say("Good choice!") }
76
- menu.choices(:python, :perl) { say("Not from around here, are you?") }
75
+ menu.choice(:ruby) { cli.say("Good choice!") }
76
+ menu.choices(:python, :perl) { cli.say("Not from around here, are you?") }
77
77
  end
78
78
  ```
79
79
 
@@ -251,11 +251,18 @@ class HighLine
251
251
  menu.answer_type = menu.shell ? shell_style_lambda(menu) : menu.options
252
252
 
253
253
  selected = ask(menu)
254
+ return unless selected
254
255
 
255
256
  if menu.shell
256
- menu.select(self, *selected)
257
+ selection, details = selected
257
258
  else
258
- menu.select(self, selected)
259
+ selection = selected
260
+ end
261
+
262
+ if menu.gather
263
+ menu.gather_selected(self, selection, details)
264
+ else
265
+ menu.select(self, selection, details)
259
266
  end
260
267
  end
261
268
 
@@ -485,7 +492,7 @@ class HighLine
485
492
  # of the question.
486
493
  #
487
494
  def explain_error(error, question)
488
- say(question.responses[error]) if error
495
+ say(question.final_responses[error]) if error
489
496
  say(question.ask_on_error_msg)
490
497
  end
491
498
 
@@ -154,20 +154,45 @@ class HighLine
154
154
  # cli.choose do |menu|
155
155
  # menu.shell = true
156
156
  #
157
- # menu.choice(:load, "Load a file.")
158
- # menu.choice(:save, "Save data in file.")
159
- # menu.choice(:quit, "Exit program.")
157
+ # menu.choice(:load, text: 'Load a file', help: "Load a file using your favourite editor.")
158
+ # menu.choice(:save, help: "Save data in file.")
159
+ # menu.choice(:quit, help: "Exit program.")
160
160
  #
161
161
  # menu.help("rules", "The rules of this system are as follows...")
162
162
  # end
163
163
 
164
- def choice( name, help = nil, &action )
165
- @items << [name, action]
166
-
167
- @help[name.to_s.downcase] = help if help
164
+ def choice( name, help = nil, text = nil, &action )
165
+ item = MenuItem.new(name, text: text, help: help, action: action)
166
+ @items << item
167
+ @help.merge!(item.item_help)
168
168
  update_responses # rebuild responses based on our settings
169
169
  end
170
170
 
171
+ #
172
+ # This method helps reduce the namespaces in the original call, which would look
173
+ # like this: HighLine::Menu::MenuItem.new(...)
174
+ # With #build_item, it looks like this: menu.build_item(...)
175
+ # @param *args splat args, the same args you would pass to an initialization of
176
+ # HighLine::Menu::MenuItem
177
+ # @return [HighLine::Menu::MenuItem] the menu item
178
+
179
+ def build_item(*args)
180
+ MenuItem.new(*args)
181
+ end
182
+
183
+ #
184
+ # Adds an item directly to the menu. If you want more configuraiton or options,
185
+ # use this method
186
+ #
187
+ # @param item [Menu::MenuItem] item containing choice fields and more
188
+ # @return [void]
189
+
190
+ def add_item(item)
191
+ @items << item
192
+ @help.merge!(item.item_help)
193
+ update_responses
194
+ end
195
+
171
196
  #
172
197
  # A shortcut for multiple calls to the sister method {#choice}. <b>Be
173
198
  # warned:</b> An _action_ set here will apply to *all* provided
@@ -177,6 +202,10 @@ class HighLine
177
202
  # @param action (see #choice)
178
203
  # @return [void]
179
204
  # @example (see HighLine::Menu#initialize)
205
+ #
206
+ # choice has more options available to you, like longer text or help (and
207
+ # of course, individual actions)
208
+ #
180
209
  def choices( *names, &action )
181
210
  names.each { |n| choice(n, &action) }
182
211
  end
@@ -189,9 +218,9 @@ class HighLine
189
218
  # @return (see #choice)
190
219
 
191
220
  def hidden( name, help = nil, &action )
192
- @hidden_items << [name, action]
193
-
194
- @help[name.to_s.downcase] = help if help
221
+ item = MenuItem.new(name, text: name, help: help, action: action)
222
+ @hidden_items << item
223
+ @help.merge!(item.item_help)
195
224
  end
196
225
 
197
226
  #
@@ -302,27 +331,29 @@ class HighLine
302
331
  #
303
332
  def options( )
304
333
  # add in any hidden menu commands
305
- @items.concat(@hidden_items)
306
-
307
- by_index = if @index == :letter
308
- l_index = "`"
309
- @items.map { "#{l_index.succ!}" }
310
- else
311
- (1 .. @items.size).collect { |s| String(s) }
312
- end
313
- by_name = @items.collect { |c| c.first }
334
+ items = all_items
314
335
 
315
336
  case @select_by
316
337
  when :index then
317
- by_index
338
+ map_items_by_index(items, @index)
318
339
  when :name
319
- by_name
340
+ items.map(&:name)
341
+ else
342
+ map_items_by_index(items, @index) + items.map(&:name)
343
+ end
344
+ end
345
+
346
+ def map_items_by_index(items, index = nil)
347
+ if index == :letter
348
+ l_index = "`"
349
+ items.map { "#{l_index.succ!}" }
320
350
  else
321
- by_index + by_name
351
+ (1 .. items.size).map(&:to_s)
322
352
  end
323
- ensure
324
- # make sure the hidden items are removed, before we return
325
- @items.slice!(@items.size - @hidden_items.size, @hidden_items.size)
353
+ end
354
+
355
+ def all_items
356
+ @items + @hidden_items
326
357
  end
327
358
 
328
359
  #
@@ -337,44 +368,83 @@ class HighLine
337
368
  # else it returns the action return value.
338
369
  def select( highline_context, selection, details = nil )
339
370
  # add in any hidden menu commands
340
- @items.concat(@hidden_items)
371
+ items = all_items
341
372
 
342
373
  # Find the selected action.
343
- name, action = if selection =~ /^\d+$/ # is a number?
344
- get_item_by_number(selection)
345
- else
346
- get_item_by_letter(selection)
347
- end
374
+ selected_item = find_item_from_selection(items, selection)
348
375
 
349
376
  # Run or return it.
350
- if action
351
- @highline = highline_context
352
- if @shell
353
- result = action.call(name, details)
354
- else
355
- result = action.call(name)
356
- end
357
- @nil_on_handled ? nil : result
377
+ @highline = highline_context
378
+ value_for_selected_item(selected_item, details)
379
+ end
380
+
381
+ def find_item_from_selection(items, selection)
382
+ if selection =~ /^\d+$/ # is a number?
383
+ get_item_by_number(items, selection)
358
384
  else
359
- name
385
+ get_item_by_letter(items, selection)
360
386
  end
361
- ensure
362
- # make sure the hidden items are removed, before we return
363
- @items.slice!(@items.size - @hidden_items.size, @hidden_items.size)
364
387
  end
365
388
 
366
389
  # Returns the menu item referenced by its index
367
390
  # @param selection [Integer] menu item's index.
368
- def get_item_by_number(selection)
369
- @items[selection.to_i - 1]
391
+ def get_item_by_number(items, selection)
392
+ items[selection.to_i - 1]
370
393
  end
371
394
 
372
395
  # Returns the menu item referenced by its title/header/name.
373
396
  # @param selection [String] menu's title/header/name
374
- def get_item_by_letter(selection)
397
+ def get_item_by_letter(items, selection)
398
+ item = items.find { |i| i.name == selection }
399
+ return item if item
375
400
  l_index = "`" # character before the letter "a"
376
- index = @items.map { "#{l_index.succ!}" }.index(selection)
377
- @items.find { |c| c.first == selection } or @items[index]
401
+ index = items.map { "#{l_index.succ!}" }.index(selection)
402
+ items[index]
403
+ end
404
+
405
+ def value_for_selected_item(item, details)
406
+ if item.action
407
+ if @shell
408
+ result = item.action.call(item.name, details)
409
+ else
410
+ result = item.action.call(item.name)
411
+ end
412
+ @nil_on_handled ? nil : result
413
+ else
414
+ item.name
415
+ end
416
+ end
417
+
418
+ def gather_selected(highline_context, selections, details = nil)
419
+ @highline = highline_context
420
+ # add in any hidden menu commands
421
+ items = all_items
422
+
423
+ if selections.is_a?(Array)
424
+ value_for_array_selections(items, selections, details)
425
+ elsif selections.is_a?(Hash)
426
+ value_for_hash_selections(items, selections, details)
427
+ else
428
+ fail ArgumentError, 'selections must be either Array or Hash'
429
+ end
430
+ end
431
+
432
+ def value_for_array_selections(items, selections, details)
433
+ # Find the selected items and return values
434
+ selected_items = selections.map do |selection|
435
+ find_item_from_selection(items, selection)
436
+ end
437
+ selected_items.map do |selected_item|
438
+ value_for_selected_item(selected_item, details)
439
+ end
440
+ end
441
+
442
+ def value_for_hash_selections(items, selections, details)
443
+ # Find the selected items and return in hash form
444
+ selections.each_with_object({}) do |(key, selection), memo|
445
+ selected_item = find_item_from_selection(items, selection)
446
+ memo[key] = value_for_selected_item(selected_item, details)
447
+ end
378
448
  end
379
449
 
380
450
  #
@@ -385,14 +455,14 @@ class HighLine
385
455
  def to_ary( )
386
456
  case @index
387
457
  when :number
388
- @items.map { |c| "#{@items.index(c) + 1}#{@index_suffix}#{c.first}" }
458
+ @items.map { |i| "#{@items.index(i) + 1}#{@index_suffix}#{i.text}" }
389
459
  when :letter
390
460
  l_index = "`"
391
- @items.map { |c| "#{l_index.succ!}#{@index_suffix}#{c.first}" }
461
+ @items.map { |i| "#{l_index.succ!}#{@index_suffix}#{i.text}" }
392
462
  when :none
393
- @items.map { |c| "#{c.first}" }
463
+ @items.map { |i| "#{i.text}" }
394
464
  else
395
- @items.map { |c| "#{index}#{@index_suffix}#{c.first}" }
465
+ @items.map { |i| "#{index}#{@index_suffix}#{i.text}" }
396
466
  end
397
467
  end
398
468
 
@@ -425,12 +495,32 @@ class HighLine
425
495
  # This method will update the intelligent responses to account for
426
496
  # Menu specific differences. Calls the superclass' (Question's)
427
497
  # build_responses method, overriding its default arguments to specify
428
- # 'options' will be used to populate choice lists, and that
429
- # the newly built hash will predominate over the preexisting hash
430
- # for any keys that are the same.
498
+ # 'options' will be used to populate choice lists.
431
499
  #
432
- def update_responses( )
433
- build_responses(options, true)
500
+ def update_responses
501
+ build_responses(options)
502
+ end
503
+
504
+ class MenuItem
505
+ attr_reader :name, :text, :help, :action
506
+
507
+ #
508
+ # @param name [String] The name that is matched against the user input
509
+ # @param text: [String] The text that displays for that choice (defaults to name)
510
+ # @param help: [String] help, see above (not sure how it works)
511
+ # @param action: [Block] a block that gets called when choice is selected
512
+ #
513
+ def initialize(name, attributes)
514
+ @name = name
515
+ @text = attributes[:text] || @name
516
+ @help = attributes[:help]
517
+ @action = attributes[:action]
518
+ end
519
+
520
+ def item_help
521
+ return {} unless help
522
+ { name.to_s.downcase => help }
523
+ end
434
524
  end
435
525
  end
436
526
  end
@@ -61,7 +61,8 @@ class HighLine
61
61
  @first_answer = nil
62
62
  @directory = Pathname.new(File.expand_path(File.dirname($0)))
63
63
  @glob = "*"
64
- @responses = Hash.new
64
+ @user_responses = Hash.new
65
+ @internal_responses = default_responses_hash
65
66
  @overwrite = false
66
67
 
67
68
  # allow block to override settings
@@ -214,7 +215,9 @@ class HighLine
214
215
  # <tt>:not_valid</tt>:: The error message shown when
215
216
  # validation checks fail.
216
217
  #
217
- attr_reader :responses
218
+ def responses
219
+ @user_responses
220
+ end
218
221
  #
219
222
  # When set to +true+ the question is asked, but output does not progress to
220
223
  # the next line. The Cursor is moved back to the beginning of the question
@@ -242,16 +245,21 @@ class HighLine
242
245
  # @return [Hash] responses Hash winner (new and old merge).
243
246
  # @param message_source [Class] Array or String for example.
244
247
  # Same as {#answer_type}.
245
- # @param new_hash_wins [Boolean] merge precedence (new vs. old).
246
248
 
247
- def build_responses(message_source = answer_type, new_hash_wins = false)
249
+ def build_responses(message_source = answer_type)
248
250
  append_default if [::String, Symbol].include? default.class
249
251
 
250
- old_hash = responses
251
-
252
252
  new_hash = build_responses_new_hash(message_source)
253
+ # Update our internal responses with the new hash
254
+ # generated from the message source
255
+ @internal_responses = @internal_responses.merge(new_hash)
256
+ end
253
257
 
254
- @responses = new_hash_wins ? old_hash.merge(new_hash) : new_hash.merge(old_hash)
258
+ def default_responses_hash
259
+ {
260
+ :ask_on_error => "? ",
261
+ :mismatch => "Your entries didn't match."
262
+ }
255
263
  end
256
264
 
257
265
  # When updating the responses hash, it generates the new one.
@@ -260,17 +268,21 @@ class HighLine
260
268
  def build_responses_new_hash(message_source)
261
269
  { :ambiguous_completion => "Ambiguous choice. Please choose one of " +
262
270
  choice_error_str(message_source) + '.',
263
- :ask_on_error => "? ",
264
271
  :invalid_type => "You must enter a valid #{message_source}.",
265
272
  :no_completion => "You must choose one of " +
266
273
  choice_error_str(message_source) + '.',
267
274
  :not_in_range => "Your answer isn't within the expected range " +
268
275
  "(#{expected_range}).",
269
- :mismatch => "Your entries didn't match.",
270
276
  :not_valid => "Your answer isn't valid (must match " +
271
277
  "#{validate.inspect})." }
272
278
  end
273
279
 
280
+ # This is the actual responses hash that gets used in determining output
281
+ # Notice that we give @user_responses precedence over the responses
282
+ # generated internally via build_response
283
+ def final_responses
284
+ @internal_responses.merge(@user_responses)
285
+ end
274
286
 
275
287
  #
276
288
  # Returns the provided _answer_string_ after changing character case by
@@ -531,10 +543,10 @@ class HighLine
531
543
  # @return [self] if :ask_on_error on responses Hash is set to :question
532
544
  # @return [String] if :ask_on_error on responses Hash is set to something else
533
545
  def ask_on_error_msg
534
- if responses[:ask_on_error] == :question
546
+ if final_responses[:ask_on_error] == :question
535
547
  self
536
- elsif responses[:ask_on_error]
537
- responses[:ask_on_error]
548
+ elsif final_responses[:ask_on_error]
549
+ final_responses[:ask_on_error]
538
550
  end
539
551
  end
540
552
 
@@ -105,13 +105,11 @@ class HighLine
105
105
  # with keys provided by the Hash on {Question#gather}
106
106
  # @return [Hash]
107
107
  def gather_hash
108
- answers = {}
109
-
110
- question.gather.keys.sort.each do |key|
108
+ sorted_keys = question.gather.keys.sort_by(&:to_s)
109
+ sorted_keys.each_with_object({}) do |key, answers|
111
110
  @highline.key = key
112
111
  answers[key] = ask_once
113
112
  end
114
- answers
115
113
  end
116
114
 
117
115
 
@@ -119,7 +117,7 @@ class HighLine
119
117
 
120
118
  ## Delegate to Highline
121
119
  def explain_error(error)
122
- @highline.say(question.responses[error]) if error
120
+ @highline.say(question.final_responses[error]) if error
123
121
  @highline.say(question.ask_on_error_msg)
124
122
  end
125
123
 
@@ -133,15 +131,18 @@ class HighLine
133
131
  end
134
132
 
135
133
  def answer_matches_regex(answer)
136
- (question.gather.is_a?(::String) && answer.to_s == question.gather) ||
137
- (question.gather.is_a?(Regexp) && answer.to_s =~ question.gather)
134
+ if question.gather.is_a?(::String) || question.gather.is_a?(Symbol)
135
+ answer.to_s == question.gather.to_s
136
+ else question.gather.is_a?(Regexp)
137
+ answer.to_s =~ question.gather
138
+ end
138
139
  end
139
140
 
140
141
  def gather_answers_based_on_type
141
142
  case question.gather
142
143
  when Integer
143
144
  gather_integer
144
- when ::String, Regexp
145
+ when ::String, Symbol, Regexp
145
146
  gather_regexp
146
147
  when Hash
147
148
  gather_hash
@@ -2,5 +2,5 @@
2
2
 
3
3
  class HighLine
4
4
  # The version of the installed library.
5
- VERSION = "2.0.0-develop.4".freeze
5
+ VERSION = "2.0.0-develop.6".freeze
6
6
  end
@@ -37,21 +37,21 @@ class TestMenu < Minitest::Test
37
37
 
38
38
  @terminal.choose do |menu|
39
39
  # Default: menu.flow = :rows
40
-
41
- menu.choice "Sample1"
42
- menu.choice "Sample2"
43
- menu.choice "Sample3"
40
+
41
+ menu.choice "Sample1"
42
+ menu.choice "Sample2"
43
+ menu.choice "Sample3"
44
44
  end
45
45
  assert_equal("1. Sample1\n2. Sample2\n3. Sample3\n? ", @output.string)
46
46
 
47
47
  @output.truncate(@output.rewind)
48
48
  @input.rewind
49
-
49
+
50
50
  @terminal.choose do |menu|
51
51
  menu.flow = :columns_across
52
-
53
- menu.choice "Sample1"
54
- menu.choice "Sample2"
52
+
53
+ menu.choice "Sample1"
54
+ menu.choice "Sample2"
55
55
  menu.choice "Sample3"
56
56
  end
57
57
  assert_equal("1. Sample1 2. Sample2 3. Sample3\n? ", @output.string)
@@ -63,13 +63,13 @@ class TestMenu < Minitest::Test
63
63
  menu.flow = :inline
64
64
  menu.index = :none
65
65
 
66
- menu.choice "Sample1"
67
- menu.choice "Sample2"
68
- menu.choice "Sample3"
66
+ menu.choice "Sample1"
67
+ menu.choice "Sample2"
68
+ menu.choice "Sample3"
69
69
  end
70
70
  assert_equal("Sample1, Sample2 or Sample3? ", @output.string)
71
71
  end
72
-
72
+
73
73
  def test_unicode_flow
74
74
  @input << "1\n"
75
75
  @input.rewind
@@ -81,6 +81,76 @@ class TestMenu < Minitest::Test
81
81
  assert_equal("1. Unicode right single quotation mark: ’\n? ".encode(@output.external_encoding, { :undef => :replace }), @output.string)
82
82
  end
83
83
 
84
+ def test_text_override_index_selects_name
85
+ @input << "1\n"
86
+ @input.rewind
87
+
88
+ selected = @terminal.choose do |menu|
89
+ menu.choice("Sample1", nil, "Sample2")
90
+ menu.choice("Sample2", nil, "Sample1")
91
+ end
92
+ assert_equal(selected, "Sample1")
93
+ assert_equal("1. Sample2\n" +
94
+ "2. Sample1\n" +
95
+ "? ", @output.string)
96
+ end
97
+
98
+ def test_text_override_selections_matches_name
99
+ @input << "Sample2\n"
100
+ @input.rewind
101
+
102
+ selected = @terminal.choose do |menu|
103
+ menu.choice("Sample1", nil, "Sample2")
104
+ menu.choice("Sample2", nil, "Sample1")
105
+ end
106
+ assert_equal(selected, "Sample2")
107
+ assert_equal("1. Sample2\n" +
108
+ "2. Sample1\n" +
109
+ "? ", @output.string)
110
+ end
111
+
112
+ def test_menu_add_item_index_selects_name
113
+ @input << "1\n"
114
+ @input.rewind
115
+
116
+ selected = @terminal.choose do |menu|
117
+ menu.add_item(HighLine::Menu::MenuItem.new("Sample1", text: "Sample2"))
118
+ menu.add_item(HighLine::Menu::MenuItem.new("Sample2", text: "Sample1"))
119
+ end
120
+ assert_equal(selected, "Sample1")
121
+ assert_equal("1. Sample2\n" +
122
+ "2. Sample1\n" +
123
+ "? ", @output.string)
124
+ end
125
+
126
+ def test_menu_add_item_selections_matches_name
127
+ @input << "Sample2\n"
128
+ @input.rewind
129
+
130
+ selected = @terminal.choose do |menu|
131
+ menu.add_item(HighLine::Menu::MenuItem.new("Sample1", text: "Sample2"))
132
+ menu.add_item(HighLine::Menu::MenuItem.new("Sample2", text: "Sample1"))
133
+ end
134
+ assert_equal(selected, "Sample2")
135
+ assert_equal("1. Sample2\n" +
136
+ "2. Sample1\n" +
137
+ "? ", @output.string)
138
+ end
139
+
140
+ def test_menu_build_item
141
+ @input << "Sample2\n"
142
+ @input.rewind
143
+
144
+ selected = @terminal.choose do |menu|
145
+ menu.add_item(menu.build_item("Sample1", text: "Sample2"))
146
+ menu.add_item(menu.build_item("Sample2", text: "Sample1"))
147
+ end
148
+ assert_equal(selected, "Sample2")
149
+ assert_equal("1. Sample2\n" +
150
+ "2. Sample1\n" +
151
+ "? ", @output.string)
152
+ end
153
+
84
154
  def test_help
85
155
  @input << "help\nhelp load\nhelp rules\nhelp missing\n"
86
156
  @input.rewind
@@ -92,7 +162,7 @@ class TestMenu < Minitest::Test
92
162
  menu.choice(:load, "Load a file.")
93
163
  menu.choice(:save, "Save data in file.")
94
164
  menu.choice(:quit, "Exit program.")
95
-
165
+
96
166
  menu.help("rules", "The rules of this system are as follows...")
97
167
  end
98
168
  end
@@ -102,15 +172,15 @@ class TestMenu < Minitest::Test
102
172
  "specific topic enter:\n" +
103
173
  "\thelp [TOPIC]\n" +
104
174
  "Try asking for help on any of the following:\n" +
105
- "\nload quit rules save \n" +
175
+ "\nload quit rules save \n" +
106
176
  "1. load\n2. save\n3. quit\n4. help\n? " +
107
- "= load\n\n" +
177
+ "= load\n\n" +
108
178
  "Load a file.\n" +
109
179
  "1. load\n2. save\n3. quit\n4. help\n? " +
110
180
  "= rules\n\n" +
111
181
  "The rules of this system are as follows...\n" +
112
182
  "1. load\n2. save\n3. quit\n4. help\n? " +
113
- "= missing\n\n" +
183
+ "= missing\n\n" +
114
184
  "There's no help for that topic.\n", @output.string )
115
185
  end
116
186
 
@@ -120,22 +190,22 @@ class TestMenu < Minitest::Test
120
190
 
121
191
  @terminal.choose do |menu|
122
192
  # Default: menu.index = :number
123
-
124
- menu.choice "Sample1"
125
- menu.choice "Sample2"
126
- menu.choice "Sample3"
193
+
194
+ menu.choice "Sample1"
195
+ menu.choice "Sample2"
196
+ menu.choice "Sample3"
127
197
  end
128
198
  assert_equal("1. Sample1\n2. Sample2\n3. Sample3\n? ", @output.string)
129
199
 
130
200
  @output.truncate(@output.rewind)
131
201
  @input.rewind
132
-
202
+
133
203
  @terminal.choose do |menu|
134
204
  menu.index = :letter
135
205
  menu.index_suffix = ") "
136
-
137
- menu.choice "Sample1"
138
- menu.choice "Sample2"
206
+
207
+ menu.choice "Sample1"
208
+ menu.choice "Sample2"
139
209
  menu.choice "Sample3"
140
210
  end
141
211
  assert_equal("a) Sample1\nb) Sample2\nc) Sample3\n? ", @output.string)
@@ -146,15 +216,15 @@ class TestMenu < Minitest::Test
146
216
  @terminal.choose do |menu|
147
217
  menu.index = :none
148
218
 
149
- menu.choice "Sample1"
150
- menu.choice "Sample2"
151
- menu.choice "Sample3"
219
+ menu.choice "Sample1"
220
+ menu.choice "Sample2"
221
+ menu.choice "Sample3"
152
222
  end
153
223
  assert_equal("Sample1\nSample2\nSample3\n? ", @output.string)
154
224
 
155
225
  @output.truncate(@output.rewind)
156
226
  @input.rewind
157
-
227
+
158
228
  @terminal.choose do |menu|
159
229
  menu.index = "*"
160
230
 
@@ -164,11 +234,11 @@ class TestMenu < Minitest::Test
164
234
  end
165
235
  assert_equal("* Sample1\n* Sample2\n* Sample3\n? ", @output.string)
166
236
  end
167
-
237
+
168
238
  def test_layouts
169
239
  @input << "save\n"
170
240
  @input.rewind
171
-
241
+
172
242
  @terminal.choose(:load, :save, :quit) # Default: layout = :list
173
243
  assert_equal("1. load\n2. save\n3. quit\n? ", @output.string)
174
244
 
@@ -178,7 +248,7 @@ class TestMenu < Minitest::Test
178
248
  @terminal.choose(:load, :save, :quit) do |menu|
179
249
  menu.header = "File Menu"
180
250
  end
181
- assert_equal( "File Menu:\n" +
251
+ assert_equal( "File Menu:\n" +
182
252
  "1. load\n2. save\n3. quit\n? ", @output.string )
183
253
 
184
254
  @input.rewind
@@ -189,7 +259,7 @@ class TestMenu < Minitest::Test
189
259
  menu.header = "File Menu"
190
260
  menu.prompt = "Operation? "
191
261
  end
192
- assert_equal( "File Menu: Operation? " +
262
+ assert_equal( "File Menu: Operation? " +
193
263
  "(load, save or quit) ", @output.string )
194
264
 
195
265
  @input.rewind
@@ -208,7 +278,7 @@ class TestMenu < Minitest::Test
208
278
  end
209
279
  assert_equal("1. load\n2. save\n3. quit\nFile Menu: ", @output.string)
210
280
  end
211
-
281
+
212
282
  def test_list_option
213
283
  @input << "l\n"
214
284
  @input.rewind
@@ -252,18 +322,18 @@ class TestMenu < Minitest::Test
252
322
  end
253
323
  assert_equal("Sample2", output)
254
324
  end
255
-
325
+
256
326
  def test_passed_command
257
327
  @input << "q\n"
258
328
  @input.rewind
259
-
329
+
260
330
  selected = nil
261
331
  @terminal.choose do |menu|
262
332
  menu.choices(:load, :save, :quit) { |command| selected = command }
263
333
  end
264
334
  assert_equal(:quit, selected)
265
335
  end
266
-
336
+
267
337
  def test_question_options
268
338
  @input << "save\n"
269
339
  @input.rewind
@@ -286,19 +356,19 @@ class TestMenu < Minitest::Test
286
356
  def test_select_by
287
357
  @input << "Sample1\n2\n"
288
358
  @input.rewind
289
-
359
+
290
360
  selected = @terminal.choose do |menu|
291
361
  menu.choice "Sample1"
292
362
  menu.choice "Sample2"
293
363
  menu.choice "Sample3"
294
364
  end
295
365
  assert_equal("Sample1", selected)
296
-
366
+
297
367
  @input.rewind
298
368
 
299
369
  selected = @terminal.choose do |menu|
300
370
  menu.select_by = :index
301
-
371
+
302
372
  menu.choice "Sample1"
303
373
  menu.choice "Sample2"
304
374
  menu.choice "Sample3"
@@ -309,7 +379,7 @@ class TestMenu < Minitest::Test
309
379
 
310
380
  selected = @terminal.choose do |menu|
311
381
  menu.select_by = :name
312
-
382
+
313
383
  menu.choice "Sample1"
314
384
  menu.choice "Sample2"
315
385
  menu.choice "Sample3"
@@ -320,7 +390,7 @@ class TestMenu < Minitest::Test
320
390
  def test_hidden
321
391
  @input << "Hidden\n4\n"
322
392
  @input.rewind
323
-
393
+
324
394
  selected = @terminal.choose do |menu|
325
395
  menu.choice "Sample1"
326
396
  menu.choice "Sample2"
@@ -329,12 +399,12 @@ class TestMenu < Minitest::Test
329
399
  end
330
400
  assert_equal("Hidden!", selected)
331
401
  assert_equal("1. Sample1\n2. Sample2\n3. Sample3\n? ", @output.string)
332
-
402
+
333
403
  @input.rewind
334
404
 
335
405
  selected = @terminal.choose do |menu|
336
406
  menu.select_by = :index
337
-
407
+
338
408
  menu.choice "Sample1"
339
409
  menu.choice "Sample2"
340
410
  menu.choice "Sample3"
@@ -346,7 +416,7 @@ class TestMenu < Minitest::Test
346
416
 
347
417
  selected = @terminal.choose do |menu|
348
418
  menu.select_by = :name
349
-
419
+
350
420
  menu.choice "Sample1"
351
421
  menu.choice "Sample2"
352
422
  menu.choice "Sample3"
@@ -360,8 +430,8 @@ class TestMenu < Minitest::Test
360
430
  def test_select_by_letter
361
431
  @input << "b\n"
362
432
  @input.rewind
363
-
364
- selected = @terminal.choose do |menu|
433
+
434
+ selected = @terminal.choose do |menu|
365
435
  menu.index = :letter
366
436
  menu.choice :save
367
437
  menu.choice :load
@@ -369,7 +439,7 @@ class TestMenu < Minitest::Test
369
439
  end
370
440
  assert_equal(:load, selected)
371
441
  end
372
-
442
+
373
443
  def test_shell
374
444
  @input << "save --some-option my_file.txt\n"
375
445
  @input.rewind
@@ -381,7 +451,7 @@ class TestMenu < Minitest::Test
381
451
  menu.choice(:save) do |command, details|
382
452
  selected = command
383
453
  options = details
384
-
454
+
385
455
  "Saved!"
386
456
  end
387
457
  menu.shell = true
@@ -402,9 +472,9 @@ class TestMenu < Minitest::Test
402
472
  def test_symbols
403
473
  @input << "3\n"
404
474
  @input.rewind
405
-
475
+
406
476
  selected = @terminal.choose do |menu|
407
- menu.choices(:save, :load, :quit)
477
+ menu.choices(:save, :load, :quit)
408
478
  end
409
479
  assert_equal(:quit, selected)
410
480
  end
@@ -414,13 +484,12 @@ class TestMenu < Minitest::Test
414
484
  # Will page twice, so start with two new lines
415
485
  @input << "\n\n3\n"
416
486
  @input.rewind
417
-
418
- # Sadly this goes into an infinite loop without the fix to page_print
419
- selected = @terminal.choose(* 1..10)
487
+
488
+ # Sadly this goes into an infinite loop without the fix to page_print
489
+ selected = @terminal.choose(* 1..10)
420
490
  assert_equal(selected, 3)
421
491
  end
422
492
 
423
-
424
493
  def test_cancel_paging
425
494
  # Tests that paging can be cancelled halfway through
426
495
  @terminal.page_at = 5
@@ -434,9 +503,152 @@ class TestMenu < Minitest::Test
434
503
  # Make sure paging message appeared
435
504
  assert( @output.string.index('press enter/return to continue or q to stop'),
436
505
  "Paging message did not appear." )
437
-
506
+
438
507
  # Make sure it only appeared once
439
508
  assert( @output.string !~ /q to stop.*q to stop/m,
440
509
  "Paging message appeared more than once." )
441
510
  end
511
+
512
+ def test_autocomplete_prompt
513
+ @input << "lisp\nRuby\n"
514
+ @input.rewind
515
+
516
+ answer = @terminal.choose do |menu|
517
+ menu.choice(:Perl)
518
+ menu.choice(:Python)
519
+ menu.choice(:Ruby)
520
+ menu.prompt = "What is your favorite programming language? "
521
+ end
522
+ languages = [:Perl, :Python, :Ruby]
523
+ assert_equal("1. Perl\n" +
524
+ "2. Python\n" +
525
+ "3. Ruby\n" +
526
+ "What is your favorite programming language? " +
527
+ "You must choose one of [1, 2, 3, Perl, Python, Ruby].\n" +
528
+ "? ", @output.string )
529
+ end
530
+
531
+ # Issue #180 - https://github.com/JEG2/highline/issues/180
532
+ def test_menu_prompt
533
+ @input << "2\n1\n"
534
+ @input.rewind
535
+
536
+ selected = @terminal.choose do |menu|
537
+ menu.responses[:ask_on_error] = "> "
538
+ menu.prompt = "> "
539
+ menu.choice :exit, "Exit cube editor"
540
+ end
541
+
542
+ prompt = "> "
543
+ first_asking = "1. exit\n"
544
+ error_message = "You must choose one of [1, exit].\n"
545
+ complete_interaction = first_asking + prompt + error_message + prompt # Same prompt when repeating question
546
+
547
+ assert_equal complete_interaction, @output.string
548
+ end
549
+
550
+ def test_menu_gather_integer
551
+ @input << "Sample1\nlast\n"
552
+ @input.rewind
553
+
554
+ selected = @terminal.choose do |menu|
555
+ menu.gather = 2
556
+ menu.choice "Sample1"
557
+ menu.choice "Sample2"
558
+ menu.choice "last"
559
+ end
560
+ assert_equal(["Sample1", "last"], selected)
561
+
562
+ assert_equal("1. Sample1\n" +
563
+ "2. Sample2\n" +
564
+ "3. last\n" +
565
+ "? 1. Sample1\n" +
566
+ "2. Sample2\n" +
567
+ "3. last\n" +
568
+ "? ", @output.string)
569
+ end
570
+
571
+ def test_menu_gather_string
572
+ @input << "Sample1\nlast\n"
573
+ @input.rewind
574
+
575
+ selected = @terminal.choose do |menu|
576
+ menu.gather = :last
577
+ menu.choice "Sample1"
578
+ menu.choice "Sample2"
579
+ menu.choice :last
580
+ end
581
+ assert_equal(["Sample1"], selected)
582
+
583
+ assert_equal("1. Sample1\n" +
584
+ "2. Sample2\n" +
585
+ "3. last\n" +
586
+ "? 1. Sample1\n" +
587
+ "2. Sample2\n" +
588
+ "3. last\n" +
589
+ "? ", @output.string)
590
+ end
591
+
592
+ def test_menu_gather_symbol
593
+ @input << "Sample1\nlast\n"
594
+ @input.rewind
595
+
596
+ selected = @terminal.choose do |menu|
597
+ menu.gather = "last"
598
+ menu.choice "Sample1"
599
+ menu.choice "Sample2"
600
+ menu.choice "last"
601
+ end
602
+ assert_equal(["Sample1"], selected)
603
+
604
+ assert_equal("1. Sample1\n" +
605
+ "2. Sample2\n" +
606
+ "3. last\n" +
607
+ "? 1. Sample1\n" +
608
+ "2. Sample2\n" +
609
+ "3. last\n" +
610
+ "? ", @output.string)
611
+ end
612
+
613
+ def test_menu_gather_regexp
614
+ @input << "Sample1\nlast\n"
615
+ @input.rewind
616
+
617
+ selected = @terminal.choose do |menu|
618
+ menu.gather = /la/
619
+ menu.choice "Sample1"
620
+ menu.choice "Sample2"
621
+ menu.choice "last"
622
+ end
623
+ assert_equal(["Sample1"], selected)
624
+
625
+ assert_equal("1. Sample1\n" +
626
+ "2. Sample2\n" +
627
+ "3. last\n" +
628
+ "? 1. Sample1\n" +
629
+ "2. Sample2\n" +
630
+ "3. last\n" +
631
+ "? ", @output.string)
632
+ end
633
+
634
+ def test_menu_gather_hash
635
+ @input << "Sample1\n3\n"
636
+ @input.rewind
637
+
638
+ selected = @terminal.choose do |menu|
639
+ menu.gather = { "First" => true, second: true }
640
+ menu.choice "Sample1"
641
+ menu.choice "Sample2"
642
+ menu.choice "last"
643
+ end
644
+ assert_equal({ "First" => "Sample1", second: "last" }, selected)
645
+
646
+ assert_equal("1. Sample1\n" +
647
+ "2. Sample2\n" +
648
+ "3. last\n" +
649
+ "? 1. Sample1\n" +
650
+ "2. Sample2\n" +
651
+ "3. last\n" +
652
+ "? ", @output.string)
653
+ end
442
654
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: highline
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.develop.4
4
+ version: 2.0.0.pre.develop.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Edward Gray II
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-14 00:00:00.000000000 Z
11
+ date: 2016-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: code_statistics