tty-prompt 0.18.1 → 0.19.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +174 -63
- data/Rakefile +2 -2
- data/examples/ask_blank.rb +9 -0
- data/examples/enum_select_disabled.rb +1 -1
- data/examples/enum_select_paged.rb +1 -1
- data/examples/expand_auto.rb +29 -0
- data/examples/mask.rb +1 -1
- data/examples/multi_select.rb +1 -1
- data/examples/multi_select_disabled_paged.rb +22 -0
- data/examples/multi_select_paged.rb +1 -1
- data/examples/select_disabled_paged.rb +22 -0
- data/examples/select_paginated.rb +1 -1
- data/lib/tty/prompt.rb +46 -10
- data/lib/tty/prompt/{enum_paginator.rb → block_paginator.rb} +19 -18
- data/lib/tty/prompt/choice.rb +1 -3
- data/lib/tty/prompt/enum_list.rb +31 -9
- data/lib/tty/prompt/expander.rb +19 -1
- data/lib/tty/prompt/keypress.rb +30 -35
- data/lib/tty/prompt/list.rb +112 -40
- data/lib/tty/prompt/mask_question.rb +2 -3
- data/lib/tty/prompt/multi_list.rb +36 -12
- data/lib/tty/prompt/paginator.rb +37 -25
- data/lib/tty/prompt/question.rb +29 -5
- data/lib/tty/prompt/slider.rb +16 -8
- data/lib/tty/prompt/symbols.rb +30 -6
- data/lib/tty/prompt/timer.rb +75 -0
- data/lib/tty/prompt/version.rb +1 -1
- data/spec/spec_helper.rb +18 -2
- data/spec/unit/ask_spec.rb +45 -4
- data/spec/unit/{enum_paginator_spec.rb → block_paginator_spec.rb} +14 -5
- data/spec/unit/choice/from_spec.rb +16 -0
- data/spec/unit/enum_select_spec.rb +104 -32
- data/spec/unit/expand_spec.rb +104 -12
- data/spec/unit/keypress_spec.rb +2 -8
- data/spec/unit/mask_spec.rb +9 -1
- data/spec/unit/multi_select_spec.rb +348 -118
- data/spec/unit/paginator_spec.rb +29 -10
- data/spec/unit/select_spec.rb +390 -108
- data/spec/unit/slider_spec.rb +48 -6
- data/spec/unit/timer_spec.rb +29 -0
- data/tty-prompt.gemspec +4 -6
- metadata +17 -46
- data/lib/tty/prompt/timeout.rb +0 -78
data/spec/unit/keypress_spec.rb
CHANGED
@@ -59,14 +59,8 @@ RSpec.describe TTY::Prompt::Question, '#keypress' do
|
|
59
59
|
it "timeouts when no key provided" do
|
60
60
|
prompt = TTY::TestPrompt.new(interrupt: :exit)
|
61
61
|
|
62
|
-
prompt.keypress("Press any key or continue in :countdown", timeout: 0.
|
62
|
+
prompt.keypress("Press any key or continue in :countdown", timeout: 0.01)
|
63
63
|
|
64
|
-
expect(prompt.output.string).to
|
65
|
-
"Press any key or continue in 0.1 ",
|
66
|
-
"\e[2K\e[1G",
|
67
|
-
"Press any key or continue in 0 ",
|
68
|
-
"\e[2K\e[1G",
|
69
|
-
"Press any key or continue in 0 \n"
|
70
|
-
].join)
|
64
|
+
expect(prompt.output.string).to include("Press any key or continue in 0.00")
|
71
65
|
end
|
72
66
|
end
|
data/spec/unit/mask_spec.rb
CHANGED
@@ -9,7 +9,9 @@ RSpec.describe TTY::Prompt, '#mask' do
|
|
9
9
|
it "masks output by default" do
|
10
10
|
prompt.input << "pass\r"
|
11
11
|
prompt.input.rewind
|
12
|
+
|
12
13
|
answer = prompt.mask("What is your password?")
|
14
|
+
|
13
15
|
expect(answer).to eql("pass")
|
14
16
|
expect(prompt.output.string).to eq([
|
15
17
|
"What is your password? ",
|
@@ -31,7 +33,9 @@ RSpec.describe TTY::Prompt, '#mask' do
|
|
31
33
|
it 'masks output with custom character' do
|
32
34
|
prompt.input << "pass\r"
|
33
35
|
prompt.input.rewind
|
36
|
+
|
34
37
|
answer = prompt.mask("What is your password?") { |q| q.mask('*') }
|
38
|
+
|
35
39
|
expect(answer).to eql("pass")
|
36
40
|
expect(prompt.output.string).to eq([
|
37
41
|
"What is your password? ",
|
@@ -53,7 +57,9 @@ RSpec.describe TTY::Prompt, '#mask' do
|
|
53
57
|
it "masks with unicode character" do
|
54
58
|
prompt.input << "lov\n"
|
55
59
|
prompt.input.rewind
|
60
|
+
|
56
61
|
answer = prompt.mask("What is your password?", mask: "\u2665")
|
62
|
+
|
57
63
|
expect(answer).to eql("lov")
|
58
64
|
expect(prompt.output.string).to eq([
|
59
65
|
"What is your password? ",
|
@@ -73,10 +79,12 @@ RSpec.describe TTY::Prompt, '#mask' do
|
|
73
79
|
it 'ignores mask if echo is off' do
|
74
80
|
prompt.input << "pass\n"
|
75
81
|
prompt.input.rewind
|
82
|
+
|
76
83
|
answer = prompt.mask('What is your password?') do |q|
|
77
84
|
q.echo false
|
78
85
|
q.mask '*'
|
79
86
|
end
|
87
|
+
|
80
88
|
expect(answer).to eql("pass")
|
81
89
|
expect(prompt.output.string).to eq([
|
82
90
|
"What is your password? ",
|
@@ -96,11 +104,11 @@ RSpec.describe TTY::Prompt, '#mask' do
|
|
96
104
|
end
|
97
105
|
|
98
106
|
it "validates input" do
|
107
|
+
prompt = TTY::TestPrompt.new(symbols: {dot: '*'})
|
99
108
|
prompt.input << "no\nyes\n"
|
100
109
|
prompt.input.rewind
|
101
110
|
answer = prompt.mask('What is your password?') do |q|
|
102
111
|
q.echo true
|
103
|
-
q.mask '*'
|
104
112
|
q.validate(/[a-z]{3,4}/)
|
105
113
|
q.messages[:valid?] = 'Not valid'
|
106
114
|
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
RSpec.describe TTY::Prompt do
|
4
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]}"}
|
5
7
|
|
6
8
|
def output_helper(prompt, choices, active, selected, options = {})
|
7
9
|
raise ":init requires :hint" if options[:init] && options[:hint].nil?
|
@@ -12,7 +14,9 @@ RSpec.describe TTY::Prompt do
|
|
12
14
|
out = []
|
13
15
|
out << "\e[?25l" if init
|
14
16
|
out << prompt << " "
|
17
|
+
out << "(max. #{options[:max]}) " if options[:max]
|
15
18
|
out << selected.join(', ')
|
19
|
+
out << " " if init && !selected.empty?
|
16
20
|
out << "\e[90m" if init
|
17
21
|
out << (init ? "(#{hint})\e[0m" : " (#{hint})") if hint
|
18
22
|
out << "\n"
|
@@ -21,7 +25,7 @@ RSpec.describe TTY::Prompt do
|
|
21
25
|
disabled = choice.is_a?(Hash) ? choice[:disabled] : false
|
22
26
|
num = (i + 1).to_s + enum if enum
|
23
27
|
|
24
|
-
prefix = name == active ? "#{symbols[:
|
28
|
+
prefix = name == active ? "#{symbols[:marker]} " : " "
|
25
29
|
prefix += if disabled
|
26
30
|
"\e[31m#{symbols[:cross]}\e[0m #{num}#{name} #{disabled}"
|
27
31
|
elsif selected.include?(name)
|
@@ -48,17 +52,20 @@ RSpec.describe TTY::Prompt do
|
|
48
52
|
choices = %i(vodka beer wine whisky bourbon)
|
49
53
|
prompt.input << "\r"
|
50
54
|
prompt.input.rewind
|
55
|
+
|
51
56
|
expect(prompt.multi_select("Select drinks?", choices)). to eq([])
|
52
|
-
|
53
|
-
|
54
|
-
"
|
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",
|
55
61
|
" #{symbols[:radio_off]} beer\n",
|
56
62
|
" #{symbols[:radio_off]} wine\n",
|
57
63
|
" #{symbols[:radio_off]} whisky\n",
|
58
64
|
" #{symbols[:radio_off]} bourbon",
|
59
65
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
60
66
|
"Select drinks? \n\e[?25h"
|
61
|
-
].join
|
67
|
+
].join
|
68
|
+
expect(prompt.output.string).to eq(expected_output)
|
62
69
|
end
|
63
70
|
|
64
71
|
it "selects item when space pressed" do
|
@@ -67,23 +74,25 @@ RSpec.describe TTY::Prompt do
|
|
67
74
|
prompt.input << " \r"
|
68
75
|
prompt.input.rewind
|
69
76
|
expect(prompt.multi_select("Select drinks?", choices)). to eq(['vodka'])
|
70
|
-
|
71
|
-
|
72
|
-
"
|
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",
|
73
81
|
" #{symbols[:radio_off]} beer\n",
|
74
82
|
" #{symbols[:radio_off]} wine\n",
|
75
83
|
" #{symbols[:radio_off]} whisky\n",
|
76
84
|
" #{symbols[:radio_off]} bourbon",
|
77
85
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
78
86
|
"Select drinks? vodka\n",
|
79
|
-
"#{symbols[:
|
87
|
+
"#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
|
80
88
|
" #{symbols[:radio_off]} beer\n",
|
81
89
|
" #{symbols[:radio_off]} wine\n",
|
82
90
|
" #{symbols[:radio_off]} whisky\n",
|
83
91
|
" #{symbols[:radio_off]} bourbon",
|
84
92
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
85
93
|
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
86
|
-
].join
|
94
|
+
].join
|
95
|
+
expect(prompt.output.string).to eq(expected_output)
|
87
96
|
end
|
88
97
|
|
89
98
|
it "selects item when space pressed but doesn't echo item if echo: false" do
|
@@ -92,23 +101,25 @@ RSpec.describe TTY::Prompt do
|
|
92
101
|
prompt.input << " \r"
|
93
102
|
prompt.input.rewind
|
94
103
|
expect(prompt.multi_select("Select drinks?", choices, echo: false)). to eq(['vodka'])
|
95
|
-
|
96
|
-
|
97
|
-
"
|
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",
|
98
108
|
" #{symbols[:radio_off]} beer\n",
|
99
109
|
" #{symbols[:radio_off]} wine\n",
|
100
110
|
" #{symbols[:radio_off]} whisky\n",
|
101
111
|
" #{symbols[:radio_off]} bourbon",
|
102
112
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
103
113
|
"Select drinks? \n",
|
104
|
-
"#{symbols[:
|
114
|
+
"#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
|
105
115
|
" #{symbols[:radio_off]} beer\n",
|
106
116
|
" #{symbols[:radio_off]} wine\n",
|
107
117
|
" #{symbols[:radio_off]} whisky\n",
|
108
118
|
" #{symbols[:radio_off]} bourbon",
|
109
119
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
110
120
|
"Select drinks? \n\e[?25h"
|
111
|
-
].join
|
121
|
+
].join
|
122
|
+
expect(prompt.output.string).to eq(expected_output)
|
112
123
|
end
|
113
124
|
|
114
125
|
it "sets choice custom values" do
|
@@ -117,23 +128,24 @@ RSpec.describe TTY::Prompt do
|
|
117
128
|
prompt.input << " \r"
|
118
129
|
prompt.input.rewind
|
119
130
|
expect(prompt.multi_select("Select drinks?", choices)).to eq([1])
|
120
|
-
|
121
|
-
"\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
122
|
-
"#{symbols[:
|
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",
|
123
134
|
" #{symbols[:radio_off]} beer\n",
|
124
135
|
" #{symbols[:radio_off]} wine\n",
|
125
136
|
" #{symbols[:radio_off]} whisky\n",
|
126
137
|
" #{symbols[:radio_off]} bourbon",
|
127
138
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
128
139
|
"Select drinks? vodka\n",
|
129
|
-
"#{symbols[:
|
140
|
+
"#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m vodka\n",
|
130
141
|
" #{symbols[:radio_off]} beer\n",
|
131
142
|
" #{symbols[:radio_off]} wine\n",
|
132
143
|
" #{symbols[:radio_off]} whisky\n",
|
133
144
|
" #{symbols[:radio_off]} bourbon",
|
134
145
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
135
146
|
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
136
|
-
].join
|
147
|
+
].join
|
148
|
+
expect(prompt.output.string).to eq(expected_output)
|
137
149
|
end
|
138
150
|
|
139
151
|
it "sets choice name and value through DSL" do
|
@@ -141,6 +153,7 @@ RSpec.describe TTY::Prompt do
|
|
141
153
|
prompt.input << " \r"
|
142
154
|
prompt.input.rewind
|
143
155
|
value = prompt.multi_select("Select drinks?") do |menu|
|
156
|
+
menu.symbols marker: '>', radio_off: '-', radio_on: '='
|
144
157
|
menu.enum ')'
|
145
158
|
|
146
159
|
menu.choice :vodka, {score: 1}
|
@@ -150,19 +163,19 @@ RSpec.describe TTY::Prompt do
|
|
150
163
|
end
|
151
164
|
expect(value).to eq([{score: 1}])
|
152
165
|
expect(prompt.output.string).to eq([
|
153
|
-
"\e[?25lSelect drinks? \e[90m(Use arrow or number (1-5) keys, press Space to select and Enter to finish)\e[0m\n",
|
154
|
-
"
|
155
|
-
"
|
156
|
-
"
|
157
|
-
"
|
158
|
-
"
|
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",
|
159
172
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
160
173
|
"Select drinks? vodka\n",
|
161
|
-
"
|
162
|
-
"
|
163
|
-
"
|
164
|
-
"
|
165
|
-
"
|
174
|
+
"> \e[32m=\e[0m 1) vodka\n",
|
175
|
+
" - 2) beer\n",
|
176
|
+
" - 3) wine\n",
|
177
|
+
" - 4) whisky\n",
|
178
|
+
" - 5) bourbon",
|
166
179
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
167
180
|
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
168
181
|
].join)
|
@@ -183,12 +196,12 @@ RSpec.describe TTY::Prompt do
|
|
183
196
|
end
|
184
197
|
expect(value).to match_array([{score: 20}, {score: 50}])
|
185
198
|
expect(prompt.output.string).to eq([
|
186
|
-
"\e[?25lSelect drinks? beer, bourbon \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
199
|
+
"\e[?25lSelect drinks? beer, bourbon \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
187
200
|
" #{symbols[:radio_off]} vodka\n",
|
188
201
|
" \e[32m#{symbols[:radio_on]}\e[0m beer\n",
|
189
202
|
" #{symbols[:radio_off]} wine\n",
|
190
203
|
" #{symbols[:radio_off]} whisky\n",
|
191
|
-
"#{symbols[:
|
204
|
+
"#{symbols[:marker]} \e[32m#{symbols[:radio_on]}\e[0m bourbon",
|
192
205
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
193
206
|
"Select drinks? \e[32mbeer, bourbon\e[0m\n\e[?25h",
|
194
207
|
].join)
|
@@ -231,8 +244,8 @@ RSpec.describe TTY::Prompt do
|
|
231
244
|
prompt.input.rewind
|
232
245
|
expect(prompt.multi_select("Select drinks?", choices)). to eq([])
|
233
246
|
expect(prompt.output.string).to eq([
|
234
|
-
"\e[?25l[?] Select drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
235
|
-
"#{symbols[:
|
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",
|
236
249
|
" #{symbols[:radio_off]} beer\n",
|
237
250
|
" #{symbols[:radio_off]} wine\n",
|
238
251
|
" #{symbols[:radio_off]} whisky\n",
|
@@ -247,10 +260,10 @@ RSpec.describe TTY::Prompt do
|
|
247
260
|
choices = %w(vodka beer wine whisky bourbon)
|
248
261
|
prompt.input << "\r"
|
249
262
|
prompt.input.rewind
|
250
|
-
options = {default: [1], active_color: :blue, marker: '>'}
|
263
|
+
options = {default: [1], active_color: :blue, symbols: {marker: '>'}}
|
251
264
|
expect(prompt.multi_select("Select drinks?", choices, options)). to eq(['vodka'])
|
252
265
|
expect(prompt.output.string).to eq([
|
253
|
-
"\e[?25lSelect drinks? vodka \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
266
|
+
"\e[?25lSelect drinks? vodka \e[90m(Use #{up_down} arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
254
267
|
"> \e[34m#{symbols[:radio_on]}\e[0m vodka\n",
|
255
268
|
" #{symbols[:radio_off]} beer\n",
|
256
269
|
" #{symbols[:radio_off]} wine\n",
|
@@ -266,95 +279,217 @@ RSpec.describe TTY::Prompt do
|
|
266
279
|
choices = %w(vodka beer wine whisky bourbon)
|
267
280
|
prompt.input << "\r"
|
268
281
|
prompt.input.rewind
|
269
|
-
|
270
|
-
|
282
|
+
|
283
|
+
answer = prompt.multi_select("Select drinks?", choices, help: '(Bash keyboard)')
|
284
|
+
|
285
|
+
expect(answer).to eq([])
|
286
|
+
expected_output = [
|
271
287
|
"\e[?25lSelect drinks? \e[90m(Bash keyboard)\e[0m\n",
|
272
|
-
"#{symbols[:
|
288
|
+
"#{symbols[:marker]} #{symbols[:radio_off]} vodka\n",
|
273
289
|
" #{symbols[:radio_off]} beer\n",
|
274
290
|
" #{symbols[:radio_off]} wine\n",
|
275
291
|
" #{symbols[:radio_off]} whisky\n",
|
276
292
|
" #{symbols[:radio_off]} bourbon",
|
277
293
|
"\e[2K\e[1G\e[1A" * 5, "\e[2K\e[1G",
|
278
294
|
"Select drinks? \n\e[?25h"
|
279
|
-
].join
|
295
|
+
].join
|
296
|
+
expect(prompt.output.string).to eq(expected_output)
|
280
297
|
end
|
281
298
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
expect(value).to eq(['D'])
|
289
|
-
expect(prompt.output.string).to eq([
|
290
|
-
"\e[?25lWhat letter? D \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
291
|
-
"#{symbols[:pointer]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
|
292
|
-
" #{symbols[:radio_off]} E\n",
|
293
|
-
" #{symbols[:radio_off]} F\n",
|
294
|
-
"\e[90m(Move up or down to reveal more choices)\e[0m",
|
295
|
-
"\e[2K\e[1G\e[1A" * 4, "\e[2K\e[1G",
|
296
|
-
"What letter? \e[32mD\e[0m\n\e[?25h",
|
297
|
-
].join)
|
298
|
-
end
|
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
|
299
305
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
"What letter? \e[32mD\e[0m\n\e[?25h",
|
315
|
-
].join)
|
316
|
-
end
|
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
|
317
320
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
value = prompt.multi_select("What letter?") do |menu|
|
324
|
-
menu.per_page 3
|
325
|
-
menu.page_help '(Wiggle thy finger up or down to see more)'
|
326
|
-
menu.default 4
|
327
|
-
menu.choices choices
|
328
|
-
end
|
329
|
-
expect(value).to eq(['D'])
|
330
|
-
expect(prompt.output.string).to eq([
|
331
|
-
"\e[?25lWhat letter? D \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
332
|
-
"#{symbols[:pointer]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
|
333
|
-
" #{symbols[:radio_off]} E\n",
|
334
|
-
" #{symbols[:radio_off]} F\n",
|
335
|
-
"\e[90m(Wiggle thy finger up or down to see more)\e[0m",
|
336
|
-
"\e[2K\e[1G\e[1A" * 4, "\e[2K\e[1G",
|
337
|
-
"What letter? \e[32mD\e[0m\n\e[?25h",
|
338
|
-
].join)
|
339
|
-
end
|
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
|
340
326
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
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
|
348
341
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
"
|
353
|
-
|
354
|
-
|
355
|
-
"
|
356
|
-
|
357
|
-
|
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
|
358
493
|
end
|
359
494
|
|
360
495
|
context "with :cycle" do
|
@@ -370,7 +505,7 @@ RSpec.describe TTY::Prompt do
|
|
370
505
|
|
371
506
|
expect(prompt.output.string).to eq(
|
372
507
|
output_helper("What letter?", choices, "A", [], init: true,
|
373
|
-
hint: "Use arrow keys, press Space to select and Enter to finish") +
|
508
|
+
hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
|
374
509
|
output_helper("What letter?", choices, "B", []) +
|
375
510
|
output_helper("What letter?", choices, "C", []) +
|
376
511
|
output_helper("What letter?", choices, "C", []) +
|
@@ -385,11 +520,13 @@ RSpec.describe TTY::Prompt do
|
|
385
520
|
prompt.on(:keypress) { |e| prompt.trigger(:keydown) if e.value == "j" }
|
386
521
|
prompt.input << "j" << "j" << "j" << " " << "\r"
|
387
522
|
prompt.input.rewind
|
523
|
+
|
388
524
|
value = prompt.multi_select("What letter?", choices, cycle: true)
|
525
|
+
|
389
526
|
expect(value).to eq(["A"])
|
390
527
|
expect(prompt.output.string).to eq(
|
391
528
|
output_helper("What letter?", choices, "A", [], init: true,
|
392
|
-
hint: "Use arrow keys, press Space to select and Enter to finish") +
|
529
|
+
hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
|
393
530
|
output_helper("What letter?", choices, "B", []) +
|
394
531
|
output_helper("What letter?", choices, "C", []) +
|
395
532
|
output_helper("What letter?", choices, "A", []) +
|
@@ -397,6 +534,64 @@ RSpec.describe TTY::Prompt do
|
|
397
534
|
"What letter? \e[32mA\e[0m\n\e[?25h"
|
398
535
|
)
|
399
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
|
400
595
|
end
|
401
596
|
|
402
597
|
context "with filter" do
|
@@ -413,7 +608,8 @@ RSpec.describe TTY::Prompt do
|
|
413
608
|
expect(answer).to eql(%w(Tiny Large))
|
414
609
|
|
415
610
|
expected_prompt_output =
|
416
|
-
output_helper("What size?", %w(Tiny Medium Large Huge), "Tiny", %w(), init: true,
|
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") +
|
417
613
|
output_helper("What size?", %w(Tiny Medium Large Huge), "Tiny", %w(Tiny)) +
|
418
614
|
output_helper("What size?", %w(Large), "Large", %w(Tiny), hint: 'Filter: "a"') +
|
419
615
|
output_helper("What size?", %w(Large), "Large", %w(Tiny Large), hint: 'Filter: "a"') +
|
@@ -467,7 +663,8 @@ RSpec.describe TTY::Prompt do
|
|
467
663
|
expect(answer).to eq(%w[D E])
|
468
664
|
|
469
665
|
expected_output =
|
470
|
-
output_helper("What letter?", choices, "A", [], init: true,
|
666
|
+
output_helper("What letter?", choices, "A", [], init: true,
|
667
|
+
hint: "Use #{up_down} arrow keys, press Space to select and Enter to finish") +
|
471
668
|
output_helper("What letter?", choices, "D", []) +
|
472
669
|
output_helper("What letter?", choices, "D", %w[D]) +
|
473
670
|
output_helper("What letter?", choices, "E", %w[D]) +
|
@@ -500,7 +697,8 @@ RSpec.describe TTY::Prompt do
|
|
500
697
|
expect(answer).to eq([1])
|
501
698
|
|
502
699
|
expected_output =
|
503
|
-
output_helper("Select drinks?", choices, "vodka", [], init: true, enum: ') ',
|
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") +
|
504
702
|
output_helper("Select drinks?", choices, "vodka", [], enum: ') ') +
|
505
703
|
output_helper("Select drinks?", choices, "vodka", %w[vodka], enum: ') ') +
|
506
704
|
exit_message("Select drinks?", %w[vodka])
|
@@ -508,4 +706,36 @@ RSpec.describe TTY::Prompt do
|
|
508
706
|
expect(prompt.output.string).to eq(expected_output)
|
509
707
|
end
|
510
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
|
511
741
|
end
|