tty-prompt 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +29 -4
  4. data/lib/tty/prompt.rb +3 -3
  5. data/lib/tty/prompt/multi_list.rb +33 -10
  6. data/lib/tty/prompt/version.rb +1 -1
  7. metadata +11 -175
  8. data/Rakefile +0 -8
  9. data/examples/ask.rb +0 -7
  10. data/examples/ask_blank.rb +0 -9
  11. data/examples/ask_multiline.rb +0 -7
  12. data/examples/ask_valid.rb +0 -12
  13. data/examples/collect.rb +0 -21
  14. data/examples/echo.rb +0 -11
  15. data/examples/enum_select.rb +0 -7
  16. data/examples/enum_select_disabled.rb +0 -16
  17. data/examples/enum_select_paged.rb +0 -9
  18. data/examples/enum_select_wrapped.rb +0 -15
  19. data/examples/expand.rb +0 -29
  20. data/examples/expand_auto.rb +0 -29
  21. data/examples/in.rb +0 -9
  22. data/examples/inputs.rb +0 -10
  23. data/examples/key_events.rb +0 -15
  24. data/examples/keypress.rb +0 -9
  25. data/examples/mask.rb +0 -13
  26. data/examples/multi_select.rb +0 -8
  27. data/examples/multi_select_disabled.rb +0 -17
  28. data/examples/multi_select_disabled_paged.rb +0 -22
  29. data/examples/multi_select_paged.rb +0 -9
  30. data/examples/multi_select_wrapped.rb +0 -15
  31. data/examples/multiline.rb +0 -9
  32. data/examples/pause.rb +0 -9
  33. data/examples/select.rb +0 -24
  34. data/examples/select_disabled.rb +0 -18
  35. data/examples/select_disabled_paged.rb +0 -22
  36. data/examples/select_enum.rb +0 -8
  37. data/examples/select_filtered.rb +0 -11
  38. data/examples/select_paginated.rb +0 -11
  39. data/examples/select_wrapped.rb +0 -15
  40. data/examples/slider.rb +0 -6
  41. data/examples/validation.rb +0 -9
  42. data/examples/yes_no.rb +0 -7
  43. data/spec/spec_helper.rb +0 -61
  44. data/spec/unit/ask_spec.rb +0 -173
  45. data/spec/unit/block_paginator_spec.rb +0 -84
  46. data/spec/unit/choice/eql_spec.rb +0 -22
  47. data/spec/unit/choice/from_spec.rb +0 -130
  48. data/spec/unit/choices/add_spec.rb +0 -12
  49. data/spec/unit/choices/each_spec.rb +0 -13
  50. data/spec/unit/choices/find_by_spec.rb +0 -10
  51. data/spec/unit/choices/new_spec.rb +0 -10
  52. data/spec/unit/choices/pluck_spec.rb +0 -9
  53. data/spec/unit/collect_spec.rb +0 -96
  54. data/spec/unit/converters/convert_bool_spec.rb +0 -58
  55. data/spec/unit/converters/convert_char_spec.rb +0 -11
  56. data/spec/unit/converters/convert_custom_spec.rb +0 -14
  57. data/spec/unit/converters/convert_date_spec.rb +0 -34
  58. data/spec/unit/converters/convert_file_spec.rb +0 -18
  59. data/spec/unit/converters/convert_number_spec.rb +0 -39
  60. data/spec/unit/converters/convert_path_spec.rb +0 -15
  61. data/spec/unit/converters/convert_range_spec.rb +0 -22
  62. data/spec/unit/converters/convert_regex_spec.rb +0 -12
  63. data/spec/unit/converters/convert_string_spec.rb +0 -21
  64. data/spec/unit/converters/on_error_spec.rb +0 -9
  65. data/spec/unit/distance/distance_spec.rb +0 -73
  66. data/spec/unit/enum_select_spec.rb +0 -518
  67. data/spec/unit/error_spec.rb +0 -20
  68. data/spec/unit/evaluator_spec.rb +0 -67
  69. data/spec/unit/expand_spec.rb +0 -290
  70. data/spec/unit/keypress_spec.rb +0 -66
  71. data/spec/unit/mask_spec.rb +0 -140
  72. data/spec/unit/multi_select_spec.rb +0 -741
  73. data/spec/unit/multiline_spec.rb +0 -77
  74. data/spec/unit/new_spec.rb +0 -20
  75. data/spec/unit/ok_spec.rb +0 -10
  76. data/spec/unit/paginator_spec.rb +0 -92
  77. data/spec/unit/question/checks_spec.rb +0 -97
  78. data/spec/unit/question/default_spec.rb +0 -31
  79. data/spec/unit/question/echo_spec.rb +0 -38
  80. data/spec/unit/question/in_spec.rb +0 -115
  81. data/spec/unit/question/initialize_spec.rb +0 -12
  82. data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
  83. data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
  84. data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
  85. data/spec/unit/question/modify_spec.rb +0 -41
  86. data/spec/unit/question/required_spec.rb +0 -92
  87. data/spec/unit/question/validate_spec.rb +0 -115
  88. data/spec/unit/question/validation/call_spec.rb +0 -31
  89. data/spec/unit/question/validation/coerce_spec.rb +0 -30
  90. data/spec/unit/result_spec.rb +0 -40
  91. data/spec/unit/say_spec.rb +0 -67
  92. data/spec/unit/select_spec.rb +0 -942
  93. data/spec/unit/slider_spec.rb +0 -142
  94. data/spec/unit/statement/initialize_spec.rb +0 -15
  95. data/spec/unit/subscribe_spec.rb +0 -22
  96. data/spec/unit/suggest_spec.rb +0 -28
  97. data/spec/unit/timer_spec.rb +0 -29
  98. data/spec/unit/warn_spec.rb +0 -21
  99. data/spec/unit/yes_no_spec.rb +0 -285
  100. data/tasks/console.rake +0 -11
  101. data/tasks/coverage.rake +0 -11
  102. data/tasks/spec.rake +0 -29
  103. data/tty-prompt.gemspec +0 -40
@@ -1,741 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Prompt do
4
- let(:symbols) { TTY::Prompt::Symbols.symbols }
5
- let(:up_down) { "#{symbols[:arrow_up]}/#{symbols[:arrow_down]}" }
6
- let(:left_right) { "#{symbols[:arrow_left]}/#{symbols[:arrow_right]}"}
7
-
8
- def output_helper(prompt, choices, active, selected, options = {})
9
- raise ":init requires :hint" if options[:init] && options[:hint].nil?
10
- hint = options[:hint]
11
- init = options.fetch(:init, false)
12
- enum = options[:enum]
13
-
14
- out = []
15
- out << "\e[?25l" if init
16
- out << prompt << " "
17
- out << "(max. #{options[:max]}) " if options[:max]
18
- out << selected.join(', ')
19
- out << " " if init && !selected.empty?
20
- out << "\e[90m" if init
21
- out << (init ? "(#{hint})\e[0m" : " (#{hint})") if hint
22
- out << "\n"
23
- out << choices.map.with_index do |choice, i|
24
- name = choice.is_a?(Hash) ? choice[:name] : choice
25
- disabled = choice.is_a?(Hash) ? choice[:disabled] : false
26
- num = (i + 1).to_s + enum if enum
27
-
28
- prefix = name == active ? "#{symbols[:marker]} " : " "
29
- prefix += if disabled
30
- "\e[31m#{symbols[:cross]}\e[0m #{num}#{name} #{disabled}"
31
- elsif selected.include?(name)
32
- "\e[32m#{symbols[:radio_on]}\e[0m #{num}#{name}"
33
- else
34
- "#{symbols[:radio_off]} #{num}#{name}"
35
- end
36
- prefix
37
- end.join("\n")
38
- out << "\e[2K\e[1G\e[1A" * choices.count
39
- out << "\e[2K\e[1G"
40
- out.join
41
- end
42
-
43
- def exit_message(prompt, choices)
44
- "#{prompt} \e[32m#{choices.join(', ')}\e[0m\n\e[?25h"
45
- end
46
-
47
- # Ensure a wide prompt on CI
48
- before { allow(TTY::Screen).to receive(:width).and_return(200) }
49
-
50
- it "selects nothing when return pressed immediately" do
51
- prompt = TTY::TestPrompt.new
52
- choices = %i(vodka beer wine whisky bourbon)
53
- prompt.input << "\r"
54
- prompt.input.rewind
55
-
56
- expect(prompt.multi_select("Select drinks?", choices)). to eq([])
57
-
58
- expected_output = [
59
- "\e[?25lSelect drinks? \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
60
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
61
- " #{symbols[:radio_off]} beer\n",
62
- " #{symbols[:radio_off]} wine\n",
63
- " #{symbols[:radio_off]} whisky\n",
64
- " #{symbols[:radio_off]} bourbon",
65
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
66
- "Select drinks? \n\e[?25h"
67
- ].join
68
- expect(prompt.output.string).to eq(expected_output)
69
- end
70
-
71
- it "selects item when space pressed" do
72
- prompt = TTY::TestPrompt.new
73
- choices = %w(vodka beer wine whisky bourbon)
74
- prompt.input << " \r"
75
- prompt.input.rewind
76
- expect(prompt.multi_select("Select drinks?", choices)). to eq(['vodka'])
77
-
78
- expected_output = [
79
- "\e[?25lSelect drinks? \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
80
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
81
- " #{symbols[:radio_off]} beer\n",
82
- " #{symbols[:radio_off]} wine\n",
83
- " #{symbols[:radio_off]} whisky\n",
84
- " #{symbols[:radio_off]} bourbon",
85
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
86
- "Select drinks? vodka\n",
87
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
88
- " #{symbols[:radio_off]} beer\n",
89
- " #{symbols[:radio_off]} wine\n",
90
- " #{symbols[:radio_off]} whisky\n",
91
- " #{symbols[:radio_off]} bourbon",
92
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
93
- "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
94
- ].join
95
- expect(prompt.output.string).to eq(expected_output)
96
- end
97
-
98
- it "selects item when space pressed but doesn't echo item if echo: false" do
99
- prompt = TTY::TestPrompt.new
100
- choices = %w(vodka beer wine whisky bourbon)
101
- prompt.input << " \r"
102
- prompt.input.rewind
103
- expect(prompt.multi_select("Select drinks?", choices, echo: false)). to eq(['vodka'])
104
-
105
- expected_output = [
106
- "\e[?25lSelect drinks? \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
107
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
108
- " #{symbols[:radio_off]} beer\n",
109
- " #{symbols[:radio_off]} wine\n",
110
- " #{symbols[:radio_off]} whisky\n",
111
- " #{symbols[:radio_off]} bourbon",
112
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
113
- "Select drinks? \n",
114
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
115
- " #{symbols[:radio_off]} beer\n",
116
- " #{symbols[:radio_off]} wine\n",
117
- " #{symbols[:radio_off]} whisky\n",
118
- " #{symbols[:radio_off]} bourbon",
119
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
120
- "Select drinks? \n\e[?25h"
121
- ].join
122
- expect(prompt.output.string).to eq(expected_output)
123
- end
124
-
125
- it "sets choice custom values" do
126
- prompt = TTY::TestPrompt.new
127
- choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
128
- prompt.input << " \r"
129
- prompt.input.rewind
130
- expect(prompt.multi_select("Select drinks?", choices)).to eq([1])
131
- expected_output = [
132
- "\e[?25lSelect drinks? \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
133
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
134
- " #{symbols[:radio_off]} beer\n",
135
- " #{symbols[:radio_off]} wine\n",
136
- " #{symbols[:radio_off]} whisky\n",
137
- " #{symbols[:radio_off]} bourbon",
138
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
139
- "Select drinks? vodka\n",
140
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
141
- " #{symbols[:radio_off]} beer\n",
142
- " #{symbols[:radio_off]} wine\n",
143
- " #{symbols[:radio_off]} whisky\n",
144
- " #{symbols[:radio_off]} bourbon",
145
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
146
- "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
147
- ].join
148
- expect(prompt.output.string).to eq(expected_output)
149
- end
150
-
151
- it "sets choice name and value through DSL" do
152
- prompt = TTY::TestPrompt.new
153
- prompt.input << " \r"
154
- prompt.input.rewind
155
- value = prompt.multi_select("Select drinks?") do |menu|
156
- menu.symbols marker: '>', radio_off: '-', radio_on: '='
157
- menu.enum ')'
158
-
159
- menu.choice :vodka, {score: 1}
160
- menu.choice :beer, 2
161
- menu.choice :wine, 3
162
- menu.choices whisky: 4, bourbon: 5
163
- end
164
- expect(value).to eq([{score: 1}])
165
- expect(prompt.output.string).to eq([
166
- "\e[?25lSelect drinks? \e[90m(Use #{up_down} arrow or number (1-5) keys, press Space to select and Enter to finish)\e[0m\n",
167
- "> - 1) vodka\n",
168
- " - 2) beer\n",
169
- " - 3) wine\n",
170
- " - 4) whisky\n",
171
- " - 5) bourbon",
172
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
173
- "Select drinks? vodka\n",
174
- "> \e[32m=\e[0m 1) vodka\n",
175
- " - 2) beer\n",
176
- " - 3) wine\n",
177
- " - 4) whisky\n",
178
- " - 5) bourbon",
179
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
180
- "Select drinks? \e[32mvodka\e[0m\n\e[?25h"
181
- ].join)
182
- end
183
-
184
- it "sets default options through DSL syntax" do
185
- prompt = TTY::TestPrompt.new
186
- prompt.input << "\r"
187
- prompt.input.rewind
188
- value = prompt.multi_select("Select drinks?") do |menu|
189
- menu.default 2, 5
190
-
191
- menu.choice :vodka, {score: 10}
192
- menu.choice :beer, {score: 20}
193
- menu.choice :wine, {score: 30}
194
- menu.choice :whisky, {score: 40}
195
- menu.choice :bourbon, {score: 50}
196
- end
197
- expect(value).to match_array([{score: 20}, {score: 50}])
198
- expect(prompt.output.string).to eq([
199
- "\e[?25lSelect drinks? beer, bourbon \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
200
- " #{symbols[:radio_off]} vodka\n",
201
- " \e[32m#{symbols[:radio_on]}\e[0m beer\n",
202
- " #{symbols[:radio_off]} wine\n",
203
- " #{symbols[:radio_off]} whisky\n",
204
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m bourbon",
205
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
206
- "Select drinks? \e[32mbeer, bourbon\e[0m\n\e[?25h",
207
- ].join)
208
- end
209
-
210
- it "sets default options through hash syntax" do
211
- prompt = TTY::TestPrompt.new
212
- prompt.input << "\r"
213
- prompt.input.rewind
214
- value = prompt.multi_select("Select drinks?", default: [2, 5]) do |menu|
215
- menu.choice :vodka, {score: 10}
216
- menu.choice :beer, {score: 20}
217
- menu.choice :wine, {score: 30}
218
- menu.choice :whisky, {score: 40}
219
- menu.choice :bourbon, {score: 50}
220
- end
221
- expect(value).to match_array([{score: 20}, {score: 50}])
222
- end
223
-
224
- it "raises error for defaults out of range" do
225
- prompt = TTY::TestPrompt.new
226
- prompt.input << "\r"
227
- prompt.input.rewind
228
- expect {
229
- prompt.multi_select("Select drinks?", default: [2, 6]) do |menu|
230
- menu.choice :vodka, {score: 10}
231
- menu.choice :beer, {score: 20}
232
- menu.choice :wine, {score: 30}
233
- menu.choice :whisky, {score: 40}
234
- menu.choice :bourbon, {score: 50}
235
- end
236
- }.to raise_error(TTY::Prompt::ConfigurationError,
237
- /default index `6` out of range \(1 - 5\)/)
238
- end
239
-
240
- it "sets prompt prefix" do
241
- prompt = TTY::TestPrompt.new(prefix: '[?] ')
242
- choices = %w(vodka beer wine whisky bourbon)
243
- prompt.input << "\r"
244
- prompt.input.rewind
245
- expect(prompt.multi_select("Select drinks?", choices)). to eq([])
246
- expect(prompt.output.string).to eq([
247
- "\e[?25l[?] Select drinks? \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
248
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
249
- " #{symbols[:radio_off]} beer\n",
250
- " #{symbols[:radio_off]} wine\n",
251
- " #{symbols[:radio_off]} whisky\n",
252
- " #{symbols[:radio_off]} bourbon",
253
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
254
- "[?] Select drinks? \n\e[?25h"
255
- ].join)
256
- end
257
-
258
- it "changes selected item color & marker" do
259
- prompt = TTY::TestPrompt.new
260
- choices = %w(vodka beer wine whisky bourbon)
261
- prompt.input << "\r"
262
- prompt.input.rewind
263
- options = {default: [1], active_color: :blue, symbols: {marker: '>'}}
264
- expect(prompt.multi_select("Select drinks?", choices, options)). to eq(['vodka'])
265
- expect(prompt.output.string).to eq([
266
- "\e[?25lSelect drinks? vodka \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
267
- "> \e[34m#{symbols[:radio_on]}\e[0m vodka\n",
268
- " #{symbols[:radio_off]} beer\n",
269
- " #{symbols[:radio_off]} wine\n",
270
- " #{symbols[:radio_off]} whisky\n",
271
- " #{symbols[:radio_off]} bourbon",
272
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
273
- "Select drinks? \e[34mvodka\e[0m\n\e[?25h"
274
- ].join)
275
- end
276
-
277
- it "changes help text" do
278
- prompt = TTY::TestPrompt.new
279
- choices = %w(vodka beer wine whisky bourbon)
280
- prompt.input << "\r"
281
- prompt.input.rewind
282
-
283
- answer = prompt.multi_select("Select drinks?", choices, help: '(Bash keyboard)')
284
-
285
- expect(answer).to eq([])
286
- expected_output = [
287
- "\e[?25lSelect drinks? \e[90m(Bash keyboard)\e[0m\n",
288
- "#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
289
- " #{symbols[:radio_off]} beer\n",
290
- " #{symbols[:radio_off]} wine\n",
291
- " #{symbols[:radio_off]} whisky\n",
292
- " #{symbols[:radio_off]} bourbon",
293
- "\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
294
- "Select drinks? \n\e[?25h"
295
- ].join
296
- expect(prompt.output.string).to eq(expected_output)
297
- end
298
-
299
- context "when paginated" do
300
- it "paginates long selections" do
301
- prompt = TTY::TestPrompt.new
302
- choices = %w(A B C D E F G H)
303
- prompt.input << "\r"
304
- prompt.input.rewind
305
-
306
- answer = prompt.multi_select("What letter?", choices, per_page: 3, default: 4)
307
-
308
- expect(answer).to eq(['D'])
309
- expected_output = [
310
- "\e[?25lWhat letter? D \e[90m(Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish)\e[0m\n",
311
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
312
- " #{symbols[:radio_off]} E\n",
313
- " #{symbols[:radio_off]} F",
314
- "\e[2K\e[1G\e[1A" * 3,
315
- "\e[2K\e[1G",
316
- "What letter? \e[32mD\e[0m\n\e[?25h",
317
- ].join
318
- expect(prompt.output.string).to eq(expected_output)
319
- end
320
-
321
- it "paginates choices as hash object" do
322
- prompt = TTY::TestPrompt.new
323
- choices = {A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8}
324
- prompt.input << "\r"
325
- prompt.input.rewind
326
-
327
- answer = prompt.multi_select("What letter?", choices, default: 4, per_page: 3)
328
-
329
- expect(answer).to eq([4])
330
- expected_output = [
331
- "\e[?25lWhat letter? D ",
332
- "\e[90m(Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish)\e[0m\n",
333
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
334
- " #{symbols[:radio_off]} E\n",
335
- " #{symbols[:radio_off]} F",
336
- "\e[2K\e[1G\e[1A" * 3, "\e[2K\e[1G",
337
- "What letter? \e[32mD\e[0m\n\e[?25h",
338
- ].join
339
- expect(prompt.output.string).to eq(expected_output)
340
- end
341
-
342
- it "paginates long selections through DSL" do
343
- prompt = TTY::TestPrompt.new
344
- choices = %w(A B C D E F G H)
345
- prompt.input << "\r"
346
- prompt.input.rewind
347
-
348
- answer = prompt.multi_select("What letter?") do |menu|
349
- menu.per_page 3
350
- menu.default 4
351
- menu.choices choices
352
- end
353
-
354
- expect(answer).to eq(['D'])
355
- expected_output = [
356
- "\e[?25lWhat letter? D ",
357
- "\e[90m(Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish)\e[0m\n",
358
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
359
- " #{symbols[:radio_off]} E\n",
360
- " #{symbols[:radio_off]} F",
361
- "\e[2K\e[1G\e[1A" * 3,
362
- "\e[2K\e[1G",
363
- "What letter? \e[32mD\e[0m\n\e[?25h",
364
- ].join
365
- expect(prompt.output.string).to eq(expected_output)
366
- end
367
-
368
- it "doesn't paginate short selections" do
369
- prompt = TTY::TestPrompt.new
370
- choices = %w(A B C D)
371
- prompt.input << "\r"
372
- prompt.input.rewind
373
- value = prompt.multi_select("What letter?", choices, per_page: 4, default: 1)
374
- expect(value).to eq(['A'])
375
-
376
- expect(prompt.output.string).to eq([
377
- "\e[?25lWhat letter? A ",
378
- "\e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
379
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m A\n",
380
- " #{symbols[:radio_off]} B\n",
381
- " #{symbols[:radio_off]} C\n",
382
- " #{symbols[:radio_off]} D",
383
- "\e[2K\e[1G\e[1A" * 4, "\e[2K\e[1G",
384
- "What letter? \e[32mA\e[0m\n\e[?25h",
385
- ].join)
386
- end
387
-
388
- it "navigates evenly paged output with right arrow until end of selection" do
389
- prompt = TTY::TestPrompt.new
390
- choices = ('1'..'12').to_a
391
- prompt.on(:keypress) { |e| prompt.trigger(:keyright) if e.value == "l" }
392
- prompt.input << "l" << "l" << "l" << " " << "\r"
393
- prompt.input.rewind
394
-
395
- answer = prompt.multi_select("What number?", choices, per_page: 4)
396
-
397
- expect(answer).to eq(["9"])
398
-
399
- expected_output = [
400
- output_helper("What number?", choices[0..3], "1", [], init: true,
401
- hint: "Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish"),
402
- output_helper("What number?", choices[4..7], "5", []),
403
- output_helper("What number?", choices[8..11], "9", []),
404
- output_helper("What number?", choices[8..11], "9", []),
405
- output_helper("What number?", choices[8..11], "9", ["9"]),
406
- "What number? \e[32m9\e[0m\n\e[?25h",
407
- ].join
408
-
409
- expect(prompt.output.string).to eq(expected_output)
410
- end
411
-
412
- it "navigates unevenly paged output with right arrow until the end of selection" do
413
- prompt = TTY::TestPrompt.new
414
- choices = ('1'..'10').to_a
415
- prompt.on(:keypress) { |e| prompt.trigger(:keyright) if e.value == "l" }
416
- prompt.input << "l" << "l" << "l" << " " << "\r"
417
- prompt.input.rewind
418
-
419
- answer = prompt.multi_select("What number?", choices, default: 4, per_page: 4)
420
-
421
- expect(answer).to eq(['4', '10'])
422
-
423
- expected_output = [
424
- output_helper("What number?", choices[3..6], "4", ["4"], init: true,
425
- hint: "Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish"),
426
- output_helper("What number?", choices[4..7], "8", ["4"]),
427
- output_helper("What number?", choices[8..9], "10", ["4"]),
428
- output_helper("What number?", choices[8..9], "10", ["4"]),
429
- output_helper("What number?", choices[8..9], "10", ["4", "10"]),
430
- "What number? \e[32m4, 10\e[0m\n\e[?25h",
431
- ].join
432
-
433
- expect(prompt.output.string).to eq(expected_output)
434
- end
435
-
436
- it "navigates left and right" do
437
- prompt = TTY::TestPrompt.new
438
- choices = ('1'..'10').to_a
439
- prompt.on(:keypress) { |e|
440
- prompt.trigger(:keyright) if e.value == "l"
441
- prompt.trigger(:keyleft) if e.value == "h"
442
- }
443
- prompt.input << "l" << "l" << "h" << " " << "\r"
444
- prompt.input.rewind
445
-
446
- answer = prompt.multi_select("What number?", choices, default: 2, per_page: 4)
447
-
448
- expect(answer).to eq(['2', '6'])
449
-
450
- expected_output = [
451
- output_helper("What number?", choices[0..3], "2", ["2"], init: true,
452
- hint: "Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish"),
453
- output_helper("What number?", choices[4..7], "6", ["2"]),
454
- output_helper("What number?", choices[8..9], "10", ["2"]),
455
- output_helper("What number?", choices[4..7], "6", ["2"]),
456
- output_helper("What number?", choices[4..7], "6", ["2", "6"]),
457
- "What number? \e[32m2, 6\e[0m\n\e[?25h",
458
- ].join
459
-
460
- expect(prompt.output.string).to eq(expected_output)
461
- end
462
-
463
- it "combines up/down navigation with left/right" do
464
- prompt = TTY::TestPrompt.new
465
- choices = ('1'..'11').to_a
466
- prompt.on(:keypress) { |e|
467
- prompt.trigger(:keyup) if e.value == "k"
468
- prompt.trigger(:keydown) if e.value == "j"
469
- prompt.trigger(:keyright) if e.value == "l"
470
- prompt.trigger(:keyleft) if e.value == "h"
471
- }
472
- prompt.input << "j" << "l" << "k" << "k" << "h" << " " << "\r"
473
- prompt.input.rewind
474
-
475
- answer = prompt.multi_select("What number?", choices, default: 2, per_page: 4)
476
-
477
- expect(answer).to eq(['2', '1'])
478
-
479
- expected_output = [
480
- output_helper("What number?", choices[0..3], "2", ["2"], init: true,
481
- hint: "Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish"),
482
- output_helper("What number?", choices[0..3], "3", ["2"]),
483
- output_helper("What number?", choices[4..7], "7", ["2"]),
484
- output_helper("What number?", choices[4..7], "6", ["2"]),
485
- output_helper("What number?", choices[3..6], "5", ["2"]),
486
- output_helper("What number?", choices[0..3], "1", ["2"]),
487
- output_helper("What number?", choices[0..3], "1", ["2", "1"]),
488
- "What number? \e[32m2, 1\e[0m\n\e[?25h",
489
- ].join
490
-
491
- expect(prompt.output.string).to eq(expected_output)
492
- end
493
- end
494
-
495
- context "with :cycle" do
496
- it "doesn't cycle by default" do
497
- prompt = TTY::TestPrompt.new
498
- choices = %w(A B C)
499
- prompt.on(:keypress) { |e| prompt.trigger(:keydown) if e.value == "j" }
500
- prompt.input << "j" << "j" << "j" << " " << "\r"
501
- prompt.input.rewind
502
-
503
- value = prompt.multi_select("What letter?", choices)
504
- expect(value).to eq(["C"])
505
-
506
- expect(prompt.output.string).to eq(
507
- output_helper("What letter?", choices, "A", [], init: true,
508
- hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
509
- output_helper("What letter?", choices, "B", []) +
510
- output_helper("What letter?", choices, "C", []) +
511
- output_helper("What letter?", choices, "C", []) +
512
- output_helper("What letter?", choices, "C", ["C"]) +
513
- "What letter? \e[32mC\e[0m\n\e[?25h"
514
- )
515
- end
516
-
517
- it "cycles when configured to do so" do
518
- prompt = TTY::TestPrompt.new
519
- choices = %w(A B C)
520
- prompt.on(:keypress) { |e| prompt.trigger(:keydown) if e.value == "j" }
521
- prompt.input << "j" << "j" << "j" << " " << "\r"
522
- prompt.input.rewind
523
-
524
- value = prompt.multi_select("What letter?", choices, cycle: true)
525
-
526
- expect(value).to eq(["A"])
527
- expect(prompt.output.string).to eq(
528
- output_helper("What letter?", choices, "A", [], init: true,
529
- hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
530
- output_helper("What letter?", choices, "B", []) +
531
- output_helper("What letter?", choices, "C", []) +
532
- output_helper("What letter?", choices, "A", []) +
533
- output_helper("What letter?", choices, "A", ["A"]) +
534
- "What letter? \e[32mA\e[0m\n\e[?25h"
535
- )
536
- end
537
-
538
- it "cycles choices using left/right arrows" do
539
- prompt = TTY::TestPrompt.new
540
- choices = ('1'..'10').to_a
541
- prompt.on(:keypress) { |e|
542
- prompt.trigger(:keyright) if e.value == "l"
543
- prompt.trigger(:keyleft) if e.value == "h"
544
- }
545
- prompt.input << "l" << "l" << "l" << "h" << " " << "\r"
546
- prompt.input.rewind
547
-
548
- answer = prompt.multi_select("What number?", choices, default: 2, per_page: 4, cycle: true)
549
-
550
- expect(answer).to eq(['2', '10'])
551
-
552
- expected_output = [
553
- "\e[?25lWhat number? 2 ",
554
- "\e[90m(Use #{up_down} and #{left_right} arrow keys, press Space to select and Enter to finish)\e[0m\n",
555
- " #{symbols[:radio_off]} 1\n",
556
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m 2\n",
557
- " #{symbols[:radio_off]} 3\n",
558
- " #{symbols[:radio_off]} 4",
559
- "\e[2K\e[1G\e[1A" * 4,
560
- "\e[2K\e[1G",
561
- "What number? 2\n",
562
- " #{symbols[:radio_off]} 5\n",
563
- "#{symbols[:marker]} #{symbols[:radio_off]} 6\n",
564
- " #{symbols[:radio_off]} 7\n",
565
- " #{symbols[:radio_off]} 8",
566
- "\e[2K\e[1G\e[1A" * 4,
567
- "\e[2K\e[1G",
568
- "What number? 2\n",
569
- " #{symbols[:radio_off]} 9\n",
570
- "#{symbols[:marker]} #{symbols[:radio_off]} 10",
571
- "\e[2K\e[1G\e[1A" * 2,
572
- "\e[2K\e[1G",
573
- "What number? 2\n",
574
- " #{symbols[:radio_off]} 1\n",
575
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m 2\n",
576
- " #{symbols[:radio_off]} 3\n",
577
- " #{symbols[:radio_off]} 4",
578
- "\e[2K\e[1G\e[1A" * 4,
579
- "\e[2K\e[1G",
580
- "What number? 2\n",
581
- " #{symbols[:radio_off]} 9\n",
582
- "#{symbols[:marker]} #{symbols[:radio_off]} 10",
583
- "\e[2K\e[1G\e[1A" * 2,
584
- "\e[2K\e[1G",
585
- "What number? 2, 10\n",
586
- " #{symbols[:radio_off]} 9\n",
587
- "#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m 10",
588
- "\e[2K\e[1G\e[1A" * 2,
589
- "\e[2K\e[1G",
590
- "What number? \e[32m2, 10\e[0m\n\e[?25h",
591
- ].join
592
-
593
- expect(prompt.output.string).to eq(expected_output)
594
- end
595
- end
596
-
597
- context "with filter" do
598
- it "doesn't lose the selection when switching between filters" do
599
- prompt = TTY::TestPrompt.new
600
- prompt.on(:keypress) { |e| prompt.trigger(:keydelete) if e.value == "\r" }
601
- prompt.input << " " # select `Tiny`
602
- prompt.input << "a" << " " # match and select `Large`
603
- prompt.input << "\u007F" # backspace (shows all)
604
- prompt.input << "\r"
605
- prompt.input.rewind
606
-
607
- answer = prompt.multi_select("What size?", %w(Tiny Medium Large Huge), filter: true)
608
- expect(answer).to eql(%w(Tiny Large))
609
-
610
- expected_prompt_output =
611
- output_helper("What size?", %w(Tiny Medium Large Huge), "Tiny", %w(), init: true,
612
- hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish, and letter keys to filter") +
613
- output_helper("What size?", %w(Tiny Medium Large Huge), "Tiny", %w(Tiny)) +
614
- output_helper("What size?", %w(Large), "Large", %w(Tiny), hint: 'Filter: "a"') +
615
- output_helper("What size?", %w(Large), "Large", %w(Tiny Large), hint: 'Filter: "a"') +
616
- output_helper("What size?", %w(Tiny Medium Large Huge), "Tiny", %w(Tiny Large)) +
617
- exit_message("What size?", %w(Tiny Large))
618
-
619
- expect(prompt.output.string).to eql(expected_prompt_output)
620
- end
621
- end
622
-
623
- context "with :disabled" do
624
- it "fails when default item is also disabled" do
625
- prompt = TTY::TestPrompt.new
626
- choices = [
627
- {name: 'vodka', disabled: true},
628
- 'beer', 'wine', 'whisky', 'bourbon'
629
- ]
630
- expect {
631
- prompt.multi_select("Select drinks?", choices, default: 1)
632
- }.to raise_error(TTY::Prompt::ConfigurationError,
633
- /default index `1` matches disabled choice item/)
634
- end
635
-
636
- it "adjusts active index to match first non-disabled choice" do
637
- choices = [
638
- {name: 'vodka', disabled: true},
639
- 'beer', 'wine', 'whisky', 'bourbon'
640
- ]
641
- prompt = TTY::TestPrompt.new
642
- prompt.input << " " << "\r"
643
- prompt.input.rewind
644
-
645
- answer = prompt.multi_select("Select drinks?", choices)
646
- expect(answer).to eq(['beer'])
647
- end
648
-
649
- it "omits disabled choice when nagivating menu" do
650
- choices = [
651
- {name: 'A'},
652
- {name: 'B', disabled: '(out)'},
653
- {name: 'C', disabled: '(out)'},
654
- {name: 'D'},
655
- {name: 'E'}
656
- ]
657
- prompt = TTY::TestPrompt.new
658
- prompt.on(:keypress) { |e| prompt.trigger(:keydown) if e.value == "j" }
659
- prompt.input << "j" << " " << "j" << " " << "\r"
660
- prompt.input.rewind
661
-
662
- answer = prompt.multi_select("What letter?", choices)
663
- expect(answer).to eq(%w[D E])
664
-
665
- expected_output =
666
- output_helper("What letter?", choices, "A", [], init: true,
667
- hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
668
- output_helper("What letter?", choices, "D", []) +
669
- output_helper("What letter?", choices, "D", %w[D]) +
670
- output_helper("What letter?", choices, "E", %w[D]) +
671
- output_helper("What letter?", choices, "E", %w[D E]) +
672
- exit_message("What letter?", %w[D E])
673
-
674
- expect(prompt.output.string).to eq(expected_output)
675
- end
676
-
677
- it "omits disabled choice when number key is pressed" do
678
- choices = [
679
- {name: 'vodka', value: 1},
680
- {name: 'beer', value: 1, disabled: true},
681
- {name: 'wine', value: 1},
682
- {name: 'whisky', value: 1, disabled: true},
683
- {name: 'bourbon', value: 1}
684
- ]
685
- prompt = TTY::TestPrompt.new
686
- prompt.input << "2" << " \r"
687
- prompt.input.rewind
688
- answer = prompt.multi_select("Select drinks?") do |menu|
689
- menu.enum ')'
690
-
691
- menu.choice :vodka, 1
692
- menu.choice :beer, 2, disabled: true
693
- menu.choice :wine, 3
694
- menu.choice :whisky, 4, disabled: true
695
- menu.choice :bourbon, 5
696
- end
697
- expect(answer).to eq([1])
698
-
699
- expected_output =
700
- output_helper("Select drinks?", choices, "vodka", [], init: true, enum: ') ',
701
- hint: "Use #{up_down} arrow or number (1-5) keys, press Space to select and Enter to finish") +
702
- output_helper("Select drinks?", choices, "vodka", [], enum: ') ') +
703
- output_helper("Select drinks?", choices, "vodka", %w[vodka], enum: ') ') +
704
- exit_message("Select drinks?", %w[vodka])
705
-
706
- expect(prompt.output.string).to eq(expected_output)
707
- end
708
- end
709
-
710
- context "with :max" do
711
- it "limits number of choices" do
712
- prompt = TTY::TestPrompt.new
713
- choices = %w(A B C)
714
- prompt.on(:keypress) { |e|
715
- prompt.trigger(:keyup) if e.value == "k"
716
- prompt.trigger(:keydown) if e.value == "j"
717
- }
718
- prompt.input << " " << "j" << " " << "j" << " " << "k" << " " << "j" << " " << "\r"
719
- prompt.input.rewind
720
-
721
- value = prompt.multi_select("What letter?", choices, max: 2, per_page: 100)
722
- expect(value).to eq(["A", "C"])
723
-
724
- expected_output =
725
- output_helper("What letter?", choices, "A", [], init: true, max: 2,
726
- hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
727
- output_helper("What letter?", choices, "A", %w[A], max: 2) +
728
- output_helper("What letter?", choices, "B", %w[A], max: 2) +
729
- output_helper("What letter?", choices, "B", %w[A B], max: 2) +
730
- output_helper("What letter?", choices, "C", %w[A B], max: 2) +
731
- output_helper("What letter?", choices, "C", %w[A B], max: 2) +
732
- output_helper("What letter?", choices, "B", %w[A B], max: 2) +
733
- output_helper("What letter?", choices, "B", %w[A], max: 2) +
734
- output_helper("What letter?", choices, "C", %w[A], max: 2) +
735
- output_helper("What letter?", choices, "C", %w[A C], max: 2) +
736
- exit_message("What letter?", %w[A C])
737
-
738
- expect(prompt.output.string).to eq(expected_output)
739
- end
740
- end
741
- end