tty-prompt 0.11.0 → 0.12.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 +25 -0
- data/README.md +66 -7
- data/examples/key_events.rb +11 -0
- data/examples/keypress.rb +3 -5
- data/examples/multiline.rb +9 -0
- data/examples/pause.rb +7 -0
- data/lib/tty/prompt.rb +82 -44
- data/lib/tty/prompt/confirm_question.rb +20 -36
- data/lib/tty/prompt/enum_list.rb +32 -23
- data/lib/tty/prompt/expander.rb +35 -31
- data/lib/tty/prompt/keypress.rb +91 -0
- data/lib/tty/prompt/list.rb +38 -23
- data/lib/tty/prompt/mask_question.rb +4 -7
- data/lib/tty/prompt/multi_list.rb +3 -1
- data/lib/tty/prompt/multiline.rb +71 -0
- data/lib/tty/prompt/question.rb +33 -35
- data/lib/tty/prompt/reader.rb +154 -38
- data/lib/tty/prompt/reader/codes.rb +4 -4
- data/lib/tty/prompt/reader/console.rb +1 -1
- data/lib/tty/prompt/reader/history.rb +145 -0
- data/lib/tty/prompt/reader/key_event.rb +4 -0
- data/lib/tty/prompt/reader/line.rb +162 -0
- data/lib/tty/prompt/reader/mode.rb +2 -2
- data/lib/tty/prompt/reader/win_console.rb +5 -1
- data/lib/tty/prompt/slider.rb +18 -12
- data/lib/tty/prompt/timeout.rb +48 -0
- data/lib/tty/prompt/version.rb +1 -1
- data/spec/unit/ask_spec.rb +15 -0
- data/spec/unit/converters/convert_bool_spec.rb +1 -0
- data/spec/unit/keypress_spec.rb +35 -6
- data/spec/unit/multi_select_spec.rb +18 -0
- data/spec/unit/multiline_spec.rb +67 -9
- data/spec/unit/question/default_spec.rb +1 -0
- data/spec/unit/question/echo_spec.rb +8 -0
- data/spec/unit/question/in_spec.rb +13 -0
- data/spec/unit/question/required_spec.rb +31 -2
- data/spec/unit/question/validate_spec.rb +39 -9
- data/spec/unit/reader/history_spec.rb +172 -0
- data/spec/unit/reader/key_event_spec.rb +12 -8
- data/spec/unit/reader/line_spec.rb +110 -0
- data/spec/unit/reader/publish_keypress_event_spec.rb +11 -0
- data/spec/unit/reader/read_line_spec.rb +32 -2
- data/spec/unit/reader/read_multiline_spec.rb +21 -7
- data/spec/unit/select_spec.rb +40 -1
- data/spec/unit/yes_no_spec.rb +48 -4
- metadata +14 -3
- data/lib/tty/prompt/history.rb +0 -16
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
class Timeout
|
6
|
+
Error = Class.new(RuntimeError)
|
7
|
+
|
8
|
+
TIMEOUT_HANDLER = proc { |t| t.raise Error, 'timeout expired' }
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@timeout_handler = options.fetch(:timeout_handler) { TIMEOUT_HANDLER }
|
12
|
+
@interval_handler = options.fetch(:interval_handler) { proc { } }
|
13
|
+
@lock = Mutex.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.timeout(secs, interval, &block)
|
17
|
+
(@scheduler ||= new).timeout(secs, interval, &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def timeout(secs, interval, &block)
|
21
|
+
return block.() if secs.nil? || secs.to_i.zero?
|
22
|
+
@lock.synchronize do
|
23
|
+
@runner = Thread.new {
|
24
|
+
run_in(secs, interval)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
block.()
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_in(secs, interval)
|
31
|
+
Thread.current.abort_on_exception = true
|
32
|
+
start = Time.now
|
33
|
+
|
34
|
+
loop do
|
35
|
+
sleep(interval)
|
36
|
+
runtime = Time.now - start
|
37
|
+
delta = secs - runtime
|
38
|
+
@interval_handler.(delta.round)
|
39
|
+
|
40
|
+
if delta < 0.0
|
41
|
+
@timeout_handler.(Thread.current)
|
42
|
+
break
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end # Scheduler
|
47
|
+
end # Prompt
|
48
|
+
end # TTY
|
data/lib/tty/prompt/version.rb
CHANGED
data/spec/unit/ask_spec.rb
CHANGED
@@ -34,6 +34,7 @@ RSpec.describe TTY::Prompt, '#ask' do
|
|
34
34
|
expect(answer).to eq(nil)
|
35
35
|
expect(prompt.output.string).to eq([
|
36
36
|
"[?] Are you Polish? ",
|
37
|
+
"\e[2K\e[1G[?] Are you Polish? \n",
|
37
38
|
"\e[1A\e[2K\e[1G",
|
38
39
|
"[?] Are you Polish? \n"
|
39
40
|
].join)
|
@@ -74,6 +75,7 @@ RSpec.describe TTY::Prompt, '#ask' do
|
|
74
75
|
expect(answer).to eq('')
|
75
76
|
expect(prompt.output.string).to eq([
|
76
77
|
"What is your name? ",
|
78
|
+
"\e[2K\e[1GWhat is your name? \n",
|
77
79
|
"\e[1A\e[2K\e[1G",
|
78
80
|
"What is your name? \n"
|
79
81
|
].join)
|
@@ -87,6 +89,7 @@ RSpec.describe TTY::Prompt, '#ask' do
|
|
87
89
|
expect(answer).to eq(nil)
|
88
90
|
expect(prompt.output.string).to eq([
|
89
91
|
"What is your name? ",
|
92
|
+
"\e[2K\e[1GWhat is your name? \n",
|
90
93
|
"\e[1A\e[2K\e[1G",
|
91
94
|
"What is your name? \n"
|
92
95
|
].join)
|
@@ -107,9 +110,21 @@ RSpec.describe TTY::Prompt, '#ask' do
|
|
107
110
|
|
108
111
|
expect(prompt.output.string).to eq([
|
109
112
|
"[?] What is your name? ",
|
113
|
+
"\e[2K\e[1G[?] What is your name? P",
|
114
|
+
"\e[2K\e[1G[?] What is your name? Pi",
|
115
|
+
"\e[2K\e[1G[?] What is your name? Pio",
|
116
|
+
"\e[2K\e[1G[?] What is your name? Piot",
|
117
|
+
"\e[2K\e[1G[?] What is your name? Piotr",
|
118
|
+
"\e[2K\e[1G[?] What is your name? Piotr\n",
|
110
119
|
"\e[1A\e[2K\e[1G",
|
111
120
|
"[?] What is your name? \e[36mPiotr\e[0m\n",
|
112
121
|
":-) What is your name? ",
|
122
|
+
"\e[2K\e[1G:-) What is your name? P",
|
123
|
+
"\e[2K\e[1G:-) What is your name? Pi",
|
124
|
+
"\e[2K\e[1G:-) What is your name? Pio",
|
125
|
+
"\e[2K\e[1G:-) What is your name? Piot",
|
126
|
+
"\e[2K\e[1G:-) What is your name? Piotr",
|
127
|
+
"\e[2K\e[1G:-) What is your name? Piotr\n",
|
113
128
|
"\e[1A\e[2K\e[1G",
|
114
129
|
":-) What is your name? \e[34mPiotr\e[0m\n"
|
115
130
|
].join)
|
@@ -19,6 +19,7 @@ RSpec.describe TTY::Prompt::Question, 'convert bool' do
|
|
19
19
|
expect(response).to eql(true)
|
20
20
|
expect(prompt.output.string).to eq([
|
21
21
|
"Do you read books? \e[90m(true)\e[0m ",
|
22
|
+
"\e[2K\e[1GDo you read books? \e[90m(true)\e[0m \n",
|
22
23
|
"\e[1A\e[2K\e[1G",
|
23
24
|
"Do you read books? \e[32mtrue\e[0m\n"
|
24
25
|
].join)
|
data/spec/unit/keypress_spec.rb
CHANGED
@@ -1,20 +1,49 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
RSpec.describe TTY::Prompt::Question, '
|
4
|
-
it '
|
3
|
+
RSpec.describe TTY::Prompt::Question, '#keypress' do
|
4
|
+
it 'receives line feed with echo on' do
|
5
|
+
prompt = TTY::TestPrompt.new
|
6
|
+
prompt.input << "\n"
|
7
|
+
prompt.input.rewind
|
8
|
+
|
9
|
+
answer = prompt.keypress("Press key:", echo: true)
|
10
|
+
|
11
|
+
expect(answer).to eq("\n")
|
12
|
+
expect(prompt.output.string).to eq([
|
13
|
+
"Press key: ",
|
14
|
+
"\e[2K\e[1G",
|
15
|
+
"Press key: \e[32m\n\e[0m\n",
|
16
|
+
].join)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'asks for a keypress with echo on' do
|
5
20
|
prompt = TTY::TestPrompt.new
|
6
21
|
prompt.input << "abcd"
|
7
22
|
prompt.input.rewind
|
8
|
-
|
23
|
+
|
24
|
+
answer = prompt.keypress("Press key:", echo: true)
|
25
|
+
|
9
26
|
expect(answer).to eq("a")
|
27
|
+
expect(prompt.output.string).to eq([
|
28
|
+
"Press key: ",
|
29
|
+
"\e[2K\e[1G",
|
30
|
+
"Press key: \e[32ma\e[0m\n",
|
31
|
+
].join)
|
10
32
|
end
|
11
33
|
|
12
|
-
it 'asks for a keypress with
|
34
|
+
it 'asks for a keypress with echo off' do
|
13
35
|
prompt = TTY::TestPrompt.new
|
14
36
|
prompt.input << "abcd"
|
15
37
|
prompt.input.rewind
|
16
|
-
|
38
|
+
|
39
|
+
answer = prompt.keypress("Press key:")
|
40
|
+
|
17
41
|
expect(answer).to eq("a")
|
42
|
+
expect(prompt.output.string).to eq([
|
43
|
+
"Press key: ",
|
44
|
+
"\e[2K\e[1G",
|
45
|
+
"Press key: \n",
|
46
|
+
].join)
|
18
47
|
end
|
19
48
|
|
20
49
|
it "interrupts input" do
|
@@ -23,7 +52,7 @@ RSpec.describe TTY::Prompt::Question, 'ask keypress' do
|
|
23
52
|
prompt.input.rewind
|
24
53
|
|
25
54
|
expect {
|
26
|
-
prompt.keypress("
|
55
|
+
prompt.keypress("Press key:")
|
27
56
|
}.to raise_error(SystemExit)
|
28
57
|
end
|
29
58
|
end
|
@@ -257,6 +257,24 @@ RSpec.describe TTY::Prompt do
|
|
257
257
|
].join)
|
258
258
|
end
|
259
259
|
|
260
|
+
it "paginates choices as hash object" do
|
261
|
+
prompt = TTY::TestPrompt.new
|
262
|
+
choices = {A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8}
|
263
|
+
prompt.input << "\r"
|
264
|
+
prompt.input.rewind
|
265
|
+
value = prompt.multi_select("What letter?", choices, default: 4, per_page: 3)
|
266
|
+
expect(value).to eq([4])
|
267
|
+
expect(prompt.output.string).to eq([
|
268
|
+
"\e[?25lWhat letter? D \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
269
|
+
"#{symbols[:pointer]} \e[32m#{symbols[:radio_on]}\e[0m D\n",
|
270
|
+
" #{symbols[:radio_off]} E\n",
|
271
|
+
" #{symbols[:radio_off]} F\n",
|
272
|
+
"\e[90m(Move up or down to reveal more choices)\e[0m",
|
273
|
+
"\e[2K\e[1G\e[1A" * 4, "\e[2K\e[1G",
|
274
|
+
"What letter? \e[32mD\e[0m\n\e[?25h",
|
275
|
+
].join)
|
276
|
+
end
|
277
|
+
|
260
278
|
it "paginates long selections through DSL" do
|
261
279
|
prompt = TTY::TestPrompt.new
|
262
280
|
choices = %w(A B C D E F G H)
|
data/spec/unit/multiline_spec.rb
CHANGED
@@ -1,19 +1,77 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
RSpec.describe TTY::Prompt::Question, '
|
4
|
-
it 'reads
|
3
|
+
RSpec.describe TTY::Prompt::Question, '#multiline' do
|
4
|
+
it 'reads no lines' do
|
5
5
|
prompt = TTY::TestPrompt.new
|
6
|
-
prompt.input << "
|
6
|
+
prompt.input << "\C-d"
|
7
7
|
prompt.input.rewind
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
answer = prompt.multiline("Description?")
|
10
|
+
|
11
|
+
expect(answer).to eq([])
|
12
|
+
expect(prompt.output.string).to eq([
|
13
|
+
"Description? \e[90m(Press CTRL-D or CTRL-Z to finish)\e[0m\n",
|
14
|
+
"\e[2K\e[1G\e[1A\e[2K\e[1G",
|
15
|
+
"Description? \n"
|
16
|
+
].join)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "uses defualt when no input" do
|
20
|
+
prompt = TTY::TestPrompt.new
|
21
|
+
prompt.input << "\C-d"
|
22
|
+
prompt.input.rewind
|
23
|
+
|
24
|
+
answer = prompt.multiline("Description?", default: 'A super sweet prompt')
|
25
|
+
|
26
|
+
expect(answer).to eq([])
|
27
|
+
expect(prompt.output.string).to eq([
|
28
|
+
"Description? \e[90m(Press CTRL-D or CTRL-Z to finish)\e[0m\n",
|
29
|
+
"\e[2K\e[1G\e[1A\e[2K\e[1G",
|
30
|
+
"Description? \e[32mA super sweet prompt\e[0m\n"
|
31
|
+
].join)
|
10
32
|
end
|
11
33
|
|
12
|
-
it
|
34
|
+
it "changes help text" do
|
13
35
|
prompt = TTY::TestPrompt.new
|
14
|
-
prompt.input << "
|
36
|
+
prompt.input << "\C-d"
|
15
37
|
prompt.input.rewind
|
16
|
-
|
17
|
-
|
38
|
+
|
39
|
+
answer = prompt.multiline("Description?") do |q|
|
40
|
+
q.default 'A super sweet prompt'
|
41
|
+
q.help '(Press thy ctrl-d to end)'
|
42
|
+
end
|
43
|
+
|
44
|
+
expect(answer).to eq([])
|
45
|
+
expect(prompt.output.string).to eq([
|
46
|
+
"Description? \e[90m(Press thy ctrl-d to end)\e[0m\n",
|
47
|
+
"\e[2K\e[1G\e[1A\e[2K\e[1G",
|
48
|
+
"Description? \e[32mA super sweet prompt\e[0m\n"
|
49
|
+
].join)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'reads multiple lines with empty lines' do
|
53
|
+
prompt = TTY::TestPrompt.new
|
54
|
+
prompt.input << "aa\n\nbb\n\n\ncc\C-d"
|
55
|
+
prompt.input.rewind
|
56
|
+
|
57
|
+
answer = prompt.multiline("Description?")
|
58
|
+
expect(answer).to eq(["aa\n", "bb\n", "cc"])
|
59
|
+
expect(prompt.output.string).to eq([
|
60
|
+
"Description? \e[90m(Press CTRL-D or CTRL-Z to finish)\e[0m\n",
|
61
|
+
"\e[2K\e[1Ga",
|
62
|
+
"\e[2K\e[1Gaa",
|
63
|
+
"\e[2K\e[1Gaa\n",
|
64
|
+
"\e[2K\e[1G\n",
|
65
|
+
"\e[2K\e[1Gb",
|
66
|
+
"\e[2K\e[1Gbb",
|
67
|
+
"\e[2K\e[1Gbb\n",
|
68
|
+
"\e[2K\e[1G\n",
|
69
|
+
"\e[2K\e[1G\n",
|
70
|
+
"\e[2K\e[1Gc",
|
71
|
+
"\e[2K\e[1Gcc",
|
72
|
+
"\e[2K\e[1G\e[1A" * 6,
|
73
|
+
"\e[2K\e[1G",
|
74
|
+
"Description? \e[32maa ...\e[0m\n"
|
75
|
+
].join)
|
18
76
|
end
|
19
77
|
end
|
@@ -12,6 +12,7 @@ RSpec.describe TTY::Prompt::Question, '#default' do
|
|
12
12
|
expect(answer).to eq(name)
|
13
13
|
expect(prompt.output.string).to eq([
|
14
14
|
"What is your name? \e[90m(Anonymous)\e[0m ",
|
15
|
+
"\e[2K\e[1GWhat is your name? \e[90m(Anonymous)\e[0m \n",
|
15
16
|
"\e[1A\e[2K\e[1G",
|
16
17
|
"What is your name? \e[32mAnonymous\e[0m\n"
|
17
18
|
].join)
|
@@ -11,6 +11,14 @@ RSpec.describe TTY::Prompt::Question, '#echo' do
|
|
11
11
|
expect(answer).to eql("password")
|
12
12
|
expect(prompt.output.string).to eq([
|
13
13
|
"What is your password? ",
|
14
|
+
"\e[2K\e[1GWhat is your password? p",
|
15
|
+
"\e[2K\e[1GWhat is your password? pa",
|
16
|
+
"\e[2K\e[1GWhat is your password? pas",
|
17
|
+
"\e[2K\e[1GWhat is your password? pass",
|
18
|
+
"\e[2K\e[1GWhat is your password? passw",
|
19
|
+
"\e[2K\e[1GWhat is your password? passwo",
|
20
|
+
"\e[2K\e[1GWhat is your password? passwor",
|
21
|
+
"\e[2K\e[1GWhat is your password? password",
|
14
22
|
"\e[1A\e[2K\e[1G",
|
15
23
|
"What is your password? \e[32mpassword\e[0m\n"
|
16
24
|
].join)
|
@@ -24,6 +24,7 @@ RSpec.describe TTY::Prompt::Question, '#in' do
|
|
24
24
|
expect(answer).to eq('8')
|
25
25
|
expect(prompt.output.string).to eq([
|
26
26
|
"How do you like it on scale 1-10? ",
|
27
|
+
"\e[2K\e[1GHow do you like it on scale 1-10? 8",
|
27
28
|
"\e[1A\e[2K\e[1G",
|
28
29
|
"How do you like it on scale 1-10? \e[32m8\e[0m\n",
|
29
30
|
].join)
|
@@ -40,6 +41,9 @@ RSpec.describe TTY::Prompt::Question, '#in' do
|
|
40
41
|
expect(answer).to eq('8.1')
|
41
42
|
expect(prompt.output.string).to eq([
|
42
43
|
"How do you like it on scale 1-10? ",
|
44
|
+
"\e[2K\e[1GHow do you like it on scale 1-10? 8",
|
45
|
+
"\e[2K\e[1GHow do you like it on scale 1-10? 8.",
|
46
|
+
"\e[2K\e[1GHow do you like it on scale 1-10? 8.1",
|
43
47
|
"\e[1A\e[2K\e[1G",
|
44
48
|
"How do you like it on scale 1-10? \e[32m8.1\e[0m\n",
|
45
49
|
].join)
|
@@ -56,6 +60,7 @@ RSpec.describe TTY::Prompt::Question, '#in' do
|
|
56
60
|
expect(answer).to eq('E')
|
57
61
|
expect(prompt.output.string).to eq([
|
58
62
|
"Your favourite vitamin? (A-K) ",
|
63
|
+
"\e[2K\e[1GYour favourite vitamin? (A-K) E",
|
59
64
|
"\e[1A\e[2K\e[1G",
|
60
65
|
"Your favourite vitamin? (A-K) \e[32mE\e[0m\n"
|
61
66
|
].join)
|
@@ -70,9 +75,13 @@ RSpec.describe TTY::Prompt::Question, '#in' do
|
|
70
75
|
expect(answer).to eq('2')
|
71
76
|
expect(prompt.output.string).to eq([
|
72
77
|
"How spicy on scale? (1-5) ",
|
78
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) A",
|
79
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) A\n",
|
73
80
|
"\e[31m>>\e[0m Value A must be within the range 1..5\e[1A",
|
74
81
|
"\e[2K\e[1G",
|
75
82
|
"How spicy on scale? (1-5) ",
|
83
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) 2",
|
84
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) 2\n",
|
76
85
|
"\e[2K\e[1G",
|
77
86
|
"\e[1A\e[2K\e[1G",
|
78
87
|
"How spicy on scale? (1-5) \e[32m2\e[0m\n"
|
@@ -91,9 +100,13 @@ RSpec.describe TTY::Prompt::Question, '#in' do
|
|
91
100
|
expect(answer).to eq('2')
|
92
101
|
expect(prompt.output.string).to eq([
|
93
102
|
"How spicy on scale? (1-5) ",
|
103
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) A",
|
104
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) A\n",
|
94
105
|
"\e[31m>>\e[0m Ohh dear what is this A doing in 1..5?\e[1A",
|
95
106
|
"\e[2K\e[1G",
|
96
107
|
"How spicy on scale? (1-5) ",
|
108
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) 2",
|
109
|
+
"\e[2K\e[1GHow spicy on scale? (1-5) 2\n",
|
97
110
|
"\e[2K\e[1G",
|
98
111
|
"\e[1A\e[2K\e[1G",
|
99
112
|
"How spicy on scale? (1-5) \e[32m2\e[0m\n"
|
@@ -10,6 +10,11 @@ RSpec.describe TTY::Prompt::Question, '#required' do
|
|
10
10
|
prompt.ask('What is your name?') { |q| q.required(true) }
|
11
11
|
expect(prompt.output.string).to eq([
|
12
12
|
"What is your name? ",
|
13
|
+
"\e[2K\e[1GWhat is your name? P",
|
14
|
+
"\e[2K\e[1GWhat is your name? Pi",
|
15
|
+
"\e[2K\e[1GWhat is your name? Pio",
|
16
|
+
"\e[2K\e[1GWhat is your name? Piot",
|
17
|
+
"\e[2K\e[1GWhat is your name? Piotr",
|
13
18
|
"\e[1A\e[2K\e[1G",
|
14
19
|
"What is your name? \e[32mPiotr\e[0m\n"
|
15
20
|
].join)
|
@@ -21,9 +26,17 @@ RSpec.describe TTY::Prompt::Question, '#required' do
|
|
21
26
|
prompt.ask('What is your name?', required: true)
|
22
27
|
expect(prompt.output.string).to eq([
|
23
28
|
"What is your name? ",
|
29
|
+
"\e[2K\e[1GWhat is your name? ",
|
30
|
+
"\e[2K\e[1GWhat is your name? ",
|
31
|
+
"\e[2K\e[1GWhat is your name? \n",
|
24
32
|
"\e[31m>>\e[0m Value must be provided\e[1A",
|
25
33
|
"\e[2K\e[1G",
|
26
34
|
"What is your name? ",
|
35
|
+
"\e[2K\e[1GWhat is your name? P",
|
36
|
+
"\e[2K\e[1GWhat is your name? Pi",
|
37
|
+
"\e[2K\e[1GWhat is your name? Pio",
|
38
|
+
"\e[2K\e[1GWhat is your name? Piot",
|
39
|
+
"\e[2K\e[1GWhat is your name? Piotr",
|
27
40
|
"\e[2K\e[1G",
|
28
41
|
"\e[1A\e[2K\e[1G",
|
29
42
|
"What is your name? \e[32mPiotr\e[0m\n"
|
@@ -38,22 +51,38 @@ RSpec.describe TTY::Prompt::Question, '#required' do
|
|
38
51
|
end
|
39
52
|
|
40
53
|
it "uses required in validation check" do
|
41
|
-
prompt.input << " \
|
54
|
+
prompt.input << " \nexists\ntest\n"
|
42
55
|
prompt.input.rewind
|
43
56
|
answer = prompt.ask('File name?') do |q|
|
44
57
|
q.required(true)
|
45
|
-
q.validate { |v|
|
58
|
+
q.validate { |v| !(v =~ /exists/) }
|
46
59
|
q.messages[:required?] = 'File name must not be empty!'
|
47
60
|
q.messages[:valid?] = 'File already exists!'
|
48
61
|
end
|
62
|
+
expect(answer).to eq('test')
|
49
63
|
expect(prompt.output.string).to eq([
|
50
64
|
"File name? ",
|
65
|
+
"\e[2K\e[1GFile name? ",
|
66
|
+
"\e[2K\e[1GFile name? ",
|
67
|
+
"\e[2K\e[1GFile name? \n",
|
51
68
|
"\e[31m>>\e[0m File name must not be empty!",
|
52
69
|
"\e[1A\e[2K\e[1G",
|
53
70
|
"File name? ",
|
71
|
+
"\e[2K\e[1GFile name? e",
|
72
|
+
"\e[2K\e[1GFile name? ex",
|
73
|
+
"\e[2K\e[1GFile name? exi",
|
74
|
+
"\e[2K\e[1GFile name? exis",
|
75
|
+
"\e[2K\e[1GFile name? exist",
|
76
|
+
"\e[2K\e[1GFile name? exists",
|
77
|
+
"\e[2K\e[1GFile name? exists\n",
|
54
78
|
"\e[31m>>\e[0m File already exists!",
|
55
79
|
"\e[1A\e[2K\e[1G",
|
56
80
|
"File name? ",
|
81
|
+
"\e[2K\e[1GFile name? t",
|
82
|
+
"\e[2K\e[1GFile name? te",
|
83
|
+
"\e[2K\e[1GFile name? tes",
|
84
|
+
"\e[2K\e[1GFile name? test",
|
85
|
+
"\e[2K\e[1GFile name? test\n",
|
57
86
|
"\e[2K\e[1G",
|
58
87
|
"\e[1A\e[2K\e[1G",
|
59
88
|
"File name? \e[32mtest\e[0m\n",
|
@@ -5,18 +5,21 @@ RSpec.describe TTY::Prompt::Question, '#validate' do
|
|
5
5
|
subject(:prompt) { TTY::TestPrompt.new }
|
6
6
|
|
7
7
|
it 'validates input with regex' do
|
8
|
-
prompt.input << '
|
8
|
+
prompt.input << 'p.m'
|
9
9
|
prompt.input.rewind
|
10
10
|
|
11
11
|
answer = prompt.ask('What is your username?') do |q|
|
12
12
|
q.validate(/^[^\.]+\.[^\.]+/)
|
13
13
|
end
|
14
14
|
|
15
|
-
expect(answer).to eq('
|
15
|
+
expect(answer).to eq('p.m')
|
16
16
|
expect(prompt.output.string).to eq([
|
17
17
|
"What is your username? ",
|
18
|
+
"\e[2K\e[1GWhat is your username? p",
|
19
|
+
"\e[2K\e[1GWhat is your username? p.",
|
20
|
+
"\e[2K\e[1GWhat is your username? p.m",
|
18
21
|
"\e[1A\e[2K\e[1G",
|
19
|
-
"What is your username? \e[
|
22
|
+
"What is your username? \e[32mp.m\e[0m\n"
|
20
23
|
].join)
|
21
24
|
end
|
22
25
|
|
@@ -43,27 +46,41 @@ RSpec.describe TTY::Prompt::Question, '#validate' do
|
|
43
46
|
end
|
44
47
|
|
45
48
|
it "provides default error message for wrong input" do
|
46
|
-
prompt.input << "
|
49
|
+
prompt.input << "wrong\np@m.com\n"
|
47
50
|
prompt.input.rewind
|
48
51
|
|
49
52
|
answer = prompt.ask('What is your email?') do |q|
|
50
53
|
q.validate :email
|
51
54
|
end
|
52
55
|
|
53
|
-
expect(answer).to eq('
|
56
|
+
expect(answer).to eq('p@m.com')
|
54
57
|
expect(prompt.output.string).to eq([
|
55
58
|
"What is your email? ",
|
59
|
+
"\e[2K\e[1GWhat is your email? w",
|
60
|
+
"\e[2K\e[1GWhat is your email? wr",
|
61
|
+
"\e[2K\e[1GWhat is your email? wro",
|
62
|
+
"\e[2K\e[1GWhat is your email? wron",
|
63
|
+
"\e[2K\e[1GWhat is your email? wrong",
|
64
|
+
"\e[2K\e[1GWhat is your email? wrong\n",
|
56
65
|
"\e[31m>>\e[0m Your answer is invalid (must match :email)\e[1A",
|
57
66
|
"\e[2K\e[1G",
|
58
67
|
"What is your email? ",
|
68
|
+
"\e[2K\e[1GWhat is your email? p",
|
69
|
+
"\e[2K\e[1GWhat is your email? p@",
|
70
|
+
"\e[2K\e[1GWhat is your email? p@m",
|
71
|
+
"\e[2K\e[1GWhat is your email? p@m.",
|
72
|
+
"\e[2K\e[1GWhat is your email? p@m.c",
|
73
|
+
"\e[2K\e[1GWhat is your email? p@m.co",
|
74
|
+
"\e[2K\e[1GWhat is your email? p@m.com",
|
75
|
+
"\e[2K\e[1GWhat is your email? p@m.com\n",
|
59
76
|
"\e[2K\e[1G",
|
60
77
|
"\e[1A\e[2K\e[1G",
|
61
|
-
"What is your email? \e[
|
78
|
+
"What is your email? \e[32mp@m.com\e[0m\n"
|
62
79
|
].join)
|
63
80
|
end
|
64
81
|
|
65
82
|
it "provides custom error message for wrong input" do
|
66
|
-
prompt.input << "
|
83
|
+
prompt.input << "wrong\np@m.com"
|
67
84
|
prompt.input.rewind
|
68
85
|
|
69
86
|
answer = prompt.ask('What is your email?') do |q|
|
@@ -71,15 +88,28 @@ RSpec.describe TTY::Prompt::Question, '#validate' do
|
|
71
88
|
q.messages[:valid?] = 'Not an email!'
|
72
89
|
end
|
73
90
|
|
74
|
-
expect(answer).to eq('
|
91
|
+
expect(answer).to eq('p@m.com')
|
75
92
|
expect(prompt.output.string).to eq([
|
76
93
|
"What is your email? ",
|
94
|
+
"\e[2K\e[1GWhat is your email? w",
|
95
|
+
"\e[2K\e[1GWhat is your email? wr",
|
96
|
+
"\e[2K\e[1GWhat is your email? wro",
|
97
|
+
"\e[2K\e[1GWhat is your email? wron",
|
98
|
+
"\e[2K\e[1GWhat is your email? wrong",
|
99
|
+
"\e[2K\e[1GWhat is your email? wrong\n",
|
77
100
|
"\e[31m>>\e[0m Not an email!\e[1A",
|
78
101
|
"\e[2K\e[1G",
|
79
102
|
"What is your email? ",
|
103
|
+
"\e[2K\e[1GWhat is your email? p",
|
104
|
+
"\e[2K\e[1GWhat is your email? p@",
|
105
|
+
"\e[2K\e[1GWhat is your email? p@m",
|
106
|
+
"\e[2K\e[1GWhat is your email? p@m.",
|
107
|
+
"\e[2K\e[1GWhat is your email? p@m.c",
|
108
|
+
"\e[2K\e[1GWhat is your email? p@m.co",
|
109
|
+
"\e[2K\e[1GWhat is your email? p@m.com",
|
80
110
|
"\e[2K\e[1G",
|
81
111
|
"\e[1A\e[2K\e[1G",
|
82
|
-
"What is your email? \e[
|
112
|
+
"What is your email? \e[32mp@m.com\e[0m\n"
|
83
113
|
].join)
|
84
114
|
end
|
85
115
|
end
|