tty-prompt 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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