tty-prompt 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -3
- data/CHANGELOG.md +12 -0
- data/README.md +3 -3
- data/appveyor.yml +2 -0
- data/lib/tty/prompt/keypress.rb +7 -4
- data/lib/tty/prompt/reader.rb +1 -1
- data/lib/tty/prompt/reader/win_api.rb +14 -0
- data/lib/tty/prompt/reader/win_console.rb +9 -2
- data/lib/tty/prompt/timeout.rb +44 -23
- data/lib/tty/prompt/version.rb +1 -1
- data/tty-prompt.gemspec +6 -3
- metadata +21 -131
- data/spec/spec_helper.rb +0 -45
- data/spec/unit/ask_spec.rb +0 -132
- data/spec/unit/choice/eql_spec.rb +0 -22
- data/spec/unit/choice/from_spec.rb +0 -29
- data/spec/unit/choices/add_spec.rb +0 -12
- data/spec/unit/choices/each_spec.rb +0 -13
- data/spec/unit/choices/find_by_spec.rb +0 -10
- data/spec/unit/choices/new_spec.rb +0 -10
- data/spec/unit/choices/pluck_spec.rb +0 -9
- data/spec/unit/collect_spec.rb +0 -33
- data/spec/unit/converters/convert_bool_spec.rb +0 -58
- data/spec/unit/converters/convert_char_spec.rb +0 -11
- data/spec/unit/converters/convert_custom_spec.rb +0 -14
- data/spec/unit/converters/convert_date_spec.rb +0 -34
- data/spec/unit/converters/convert_file_spec.rb +0 -17
- data/spec/unit/converters/convert_number_spec.rb +0 -39
- data/spec/unit/converters/convert_path_spec.rb +0 -18
- data/spec/unit/converters/convert_range_spec.rb +0 -22
- data/spec/unit/converters/convert_regex_spec.rb +0 -12
- data/spec/unit/converters/convert_string_spec.rb +0 -21
- data/spec/unit/converters/on_error_spec.rb +0 -9
- data/spec/unit/distance/distance_spec.rb +0 -73
- data/spec/unit/enum_paginator_spec.rb +0 -65
- data/spec/unit/enum_select_spec.rb +0 -310
- data/spec/unit/error_spec.rb +0 -20
- data/spec/unit/evaluator_spec.rb +0 -67
- data/spec/unit/expand_spec.rb +0 -198
- data/spec/unit/keypress_spec.rb +0 -58
- data/spec/unit/mask_spec.rb +0 -132
- data/spec/unit/multi_select_spec.rb +0 -319
- data/spec/unit/multiline_spec.rb +0 -77
- data/spec/unit/new_spec.rb +0 -20
- data/spec/unit/ok_spec.rb +0 -10
- data/spec/unit/paginator_spec.rb +0 -63
- data/spec/unit/question/checks_spec.rb +0 -97
- data/spec/unit/question/default_spec.rb +0 -31
- data/spec/unit/question/echo_spec.rb +0 -38
- data/spec/unit/question/in_spec.rb +0 -115
- data/spec/unit/question/initialize_spec.rb +0 -12
- data/spec/unit/question/modifier/apply_to_spec.rb +0 -24
- data/spec/unit/question/modifier/letter_case_spec.rb +0 -41
- data/spec/unit/question/modifier/whitespace_spec.rb +0 -51
- data/spec/unit/question/modify_spec.rb +0 -41
- data/spec/unit/question/required_spec.rb +0 -92
- data/spec/unit/question/validate_spec.rb +0 -115
- data/spec/unit/question/validation/call_spec.rb +0 -31
- data/spec/unit/question/validation/coerce_spec.rb +0 -30
- data/spec/unit/reader/history_spec.rb +0 -172
- data/spec/unit/reader/key_event_spec.rb +0 -86
- data/spec/unit/reader/line_spec.rb +0 -110
- data/spec/unit/reader/publish_keypress_event_spec.rb +0 -94
- data/spec/unit/reader/read_keypress_spec.rb +0 -80
- data/spec/unit/reader/read_line_spec.rb +0 -68
- data/spec/unit/reader/read_multiline_spec.rb +0 -60
- data/spec/unit/result_spec.rb +0 -40
- data/spec/unit/say_spec.rb +0 -67
- data/spec/unit/select_spec.rb +0 -359
- data/spec/unit/slider_spec.rb +0 -96
- data/spec/unit/statement/initialize_spec.rb +0 -15
- data/spec/unit/suggest_spec.rb +0 -28
- data/spec/unit/warn_spec.rb +0 -21
- data/spec/unit/yes_no_spec.rb +0 -235
@@ -1,92 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
RSpec.describe TTY::Prompt::Question, '#required' do
|
4
|
-
|
5
|
-
subject(:prompt) { TTY::TestPrompt.new }
|
6
|
-
|
7
|
-
it 'requires value to be present' do
|
8
|
-
prompt.input << "Piotr"
|
9
|
-
prompt.input.rewind
|
10
|
-
prompt.ask('What is your name?') { |q| q.required(true) }
|
11
|
-
expect(prompt.output.string).to eq([
|
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",
|
18
|
-
"\e[1A\e[2K\e[1G",
|
19
|
-
"What is your name? \e[32mPiotr\e[0m\n"
|
20
|
-
].join)
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'requires value to be present with option' do
|
24
|
-
prompt.input << " \nPiotr"
|
25
|
-
prompt.input.rewind
|
26
|
-
prompt.ask('What is your name?', required: true)
|
27
|
-
expect(prompt.output.string).to eq([
|
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",
|
32
|
-
"\e[31m>>\e[0m Value must be provided\e[1A",
|
33
|
-
"\e[2K\e[1G",
|
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",
|
40
|
-
"\e[2K\e[1G",
|
41
|
-
"\e[1A\e[2K\e[1G",
|
42
|
-
"What is your name? \e[32mPiotr\e[0m\n"
|
43
|
-
].join)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "doesn't require value to be present" do
|
47
|
-
prompt.input << ''
|
48
|
-
prompt.input.rewind
|
49
|
-
answer = prompt.ask('What is your name?') { |q| q.required(false) }
|
50
|
-
expect(answer).to be_nil
|
51
|
-
end
|
52
|
-
|
53
|
-
it "uses required in validation check" do
|
54
|
-
prompt.input << " \nexists\ntest\n"
|
55
|
-
prompt.input.rewind
|
56
|
-
answer = prompt.ask('File name?') do |q|
|
57
|
-
q.required(true)
|
58
|
-
q.validate { |v| !(v =~ /exists/) }
|
59
|
-
q.messages[:required?] = 'File name must not be empty!'
|
60
|
-
q.messages[:valid?] = 'File already exists!'
|
61
|
-
end
|
62
|
-
expect(answer).to eq('test')
|
63
|
-
expect(prompt.output.string).to eq([
|
64
|
-
"File name? ",
|
65
|
-
"\e[2K\e[1GFile name? ",
|
66
|
-
"\e[2K\e[1GFile name? ",
|
67
|
-
"\e[2K\e[1GFile name? \n",
|
68
|
-
"\e[31m>>\e[0m File name must not be empty!",
|
69
|
-
"\e[1A\e[2K\e[1G",
|
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",
|
78
|
-
"\e[31m>>\e[0m File already exists!",
|
79
|
-
"\e[1A\e[2K\e[1G",
|
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",
|
86
|
-
"\e[2K\e[1G",
|
87
|
-
"\e[1A\e[2K\e[1G",
|
88
|
-
"File name? \e[32mtest\e[0m\n",
|
89
|
-
].join)
|
90
|
-
expect(answer).to eq('test')
|
91
|
-
end
|
92
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
RSpec.describe TTY::Prompt::Question, '#validate' do
|
4
|
-
|
5
|
-
subject(:prompt) { TTY::TestPrompt.new }
|
6
|
-
|
7
|
-
it 'validates input with regex' do
|
8
|
-
prompt.input << 'p.m'
|
9
|
-
prompt.input.rewind
|
10
|
-
|
11
|
-
answer = prompt.ask('What is your username?') do |q|
|
12
|
-
q.validate(/^[^\.]+\.[^\.]+/)
|
13
|
-
end
|
14
|
-
|
15
|
-
expect(answer).to eq('p.m')
|
16
|
-
expect(prompt.output.string).to eq([
|
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",
|
21
|
-
"\e[1A\e[2K\e[1G",
|
22
|
-
"What is your username? \e[32mp.m\e[0m\n"
|
23
|
-
].join)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'validates input with proc' do
|
27
|
-
prompt.input << 'piotr.murach'
|
28
|
-
prompt.input.rewind
|
29
|
-
|
30
|
-
answer = prompt.ask('What is your username?') do |q|
|
31
|
-
q.validate { |input| input =~ /^[^\.]+\.[^\.]+/ }
|
32
|
-
end
|
33
|
-
|
34
|
-
expect(answer).to eq('piotr.murach')
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'understands custom validation like :email' do
|
38
|
-
prompt.input << 'piotr@example.com'
|
39
|
-
prompt.input.rewind
|
40
|
-
|
41
|
-
answer = prompt.ask('What is your email?') do |q|
|
42
|
-
q.validate :email
|
43
|
-
end
|
44
|
-
|
45
|
-
expect(answer).to eq('piotr@example.com')
|
46
|
-
end
|
47
|
-
|
48
|
-
it "provides default error message for wrong input" do
|
49
|
-
prompt.input << "wrong\np@m.com\n"
|
50
|
-
prompt.input.rewind
|
51
|
-
|
52
|
-
answer = prompt.ask('What is your email?') do |q|
|
53
|
-
q.validate :email
|
54
|
-
end
|
55
|
-
|
56
|
-
expect(answer).to eq('p@m.com')
|
57
|
-
expect(prompt.output.string).to eq([
|
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",
|
65
|
-
"\e[31m>>\e[0m Your answer is invalid (must match :email)\e[1A",
|
66
|
-
"\e[2K\e[1G",
|
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",
|
76
|
-
"\e[2K\e[1G",
|
77
|
-
"\e[1A\e[2K\e[1G",
|
78
|
-
"What is your email? \e[32mp@m.com\e[0m\n"
|
79
|
-
].join)
|
80
|
-
end
|
81
|
-
|
82
|
-
it "provides custom error message for wrong input" do
|
83
|
-
prompt.input << "wrong\np@m.com"
|
84
|
-
prompt.input.rewind
|
85
|
-
|
86
|
-
answer = prompt.ask('What is your email?') do |q|
|
87
|
-
q.validate :email
|
88
|
-
q.messages[:valid?] = 'Not an email!'
|
89
|
-
end
|
90
|
-
|
91
|
-
expect(answer).to eq('p@m.com')
|
92
|
-
expect(prompt.output.string).to eq([
|
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",
|
100
|
-
"\e[31m>>\e[0m Not an email!\e[1A",
|
101
|
-
"\e[2K\e[1G",
|
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",
|
110
|
-
"\e[2K\e[1G",
|
111
|
-
"\e[1A\e[2K\e[1G",
|
112
|
-
"What is your email? \e[32mp@m.com\e[0m\n"
|
113
|
-
].join)
|
114
|
-
end
|
115
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
RSpec.describe TTY::Prompt::Question::Validation, '#call' do
|
4
|
-
let(:pattern) { /^[^\.]+\.[^\.]+/ }
|
5
|
-
|
6
|
-
it "validates nil input" do
|
7
|
-
validation = described_class.new(pattern)
|
8
|
-
expect(validation.(nil)).to eq(false)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "validates successfully when the value matches pattern" do
|
12
|
-
validation = described_class.new(pattern)
|
13
|
-
expect(validation.('piotr.murach')).to eq(true)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "validates with a proc" do
|
17
|
-
pat = proc { |input| !pattern.match(input).nil? }
|
18
|
-
validation = described_class.new(pat)
|
19
|
-
expect(validation.call('piotr.murach')).to eq(true)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "validates with custom name" do
|
23
|
-
validation = described_class.new(:email)
|
24
|
-
expect(validation.call('piotr@example.com')).to eq(true)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "fails validation when not maching pattern" do
|
28
|
-
validation = described_class.new(pattern)
|
29
|
-
expect(validation.('piotrmurach')).to eq(false)
|
30
|
-
end
|
31
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
RSpec.describe TTY::Prompt::Question::Validation, '#coerce' do
|
4
|
-
let(:instance) { described_class.new }
|
5
|
-
|
6
|
-
it "coerces lambda into proc" do
|
7
|
-
pattern = lambda { "^[^\.]+\.[^\.]+" }
|
8
|
-
validation = described_class.new(pattern)
|
9
|
-
expect(validation.pattern).to be_a(Proc)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "doesn't coerce symbols" do
|
13
|
-
pattern = :email
|
14
|
-
validation =described_class.new(pattern)
|
15
|
-
expect(validation.pattern).to eq(:email)
|
16
|
-
end
|
17
|
-
|
18
|
-
it "coerces into regex" do
|
19
|
-
pattern = /^[^\.]+\.[^\.]+/
|
20
|
-
validation = described_class.new(pattern)
|
21
|
-
expect(validation.pattern).to be_a(Regexp)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "fails to coerce pattern into validation" do
|
25
|
-
pattern = Object.new
|
26
|
-
expect {
|
27
|
-
described_class.new(pattern)
|
28
|
-
}.to raise_error(TTY::Prompt::ValidationCoercion)
|
29
|
-
end
|
30
|
-
end
|
@@ -1,172 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
RSpec.describe TTY::Prompt::Reader::History do
|
4
|
-
it "has no lines" do
|
5
|
-
history = described_class.new
|
6
|
-
expect(history.size).to eq(0)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "doesn't navigate through empty buffer" do
|
10
|
-
history = described_class.new
|
11
|
-
expect(history.next?).to eq(false)
|
12
|
-
expect(history.previous?).to eq(false)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "allows to cycle through non-empty buffer" do
|
16
|
-
history = described_class.new(3, {cycle: true})
|
17
|
-
history << "line"
|
18
|
-
expect(history.next?).to eq(true)
|
19
|
-
expect(history.previous?).to eq(true)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "defaults maximum size" do
|
23
|
-
history = described_class.new
|
24
|
-
expect(history.max_size).to eq(512)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "presents string representation" do
|
28
|
-
history = described_class.new
|
29
|
-
expect(history.to_s).to eq("[]")
|
30
|
-
end
|
31
|
-
|
32
|
-
it "adds items to history without overflowing" do
|
33
|
-
history = described_class.new(3)
|
34
|
-
history << "line #1"
|
35
|
-
history << "line #2"
|
36
|
-
history << "line #3"
|
37
|
-
history << "line #4"
|
38
|
-
|
39
|
-
expect(history.to_a).to eq(["line #2", "line #3", "line #4"])
|
40
|
-
expect(history.index).to eq(2)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "excludes items" do
|
44
|
-
exclude = proc { |line| /line #[23]/.match(line) }
|
45
|
-
history = described_class.new(3, exclude: exclude)
|
46
|
-
history << "line #1"
|
47
|
-
history << "line #2"
|
48
|
-
history << "line #3"
|
49
|
-
|
50
|
-
expect(history.to_a).to eq(["line #1"])
|
51
|
-
expect(history.index).to eq(0)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "allows duplicates" do
|
55
|
-
history = described_class.new(3)
|
56
|
-
history << "line #1"
|
57
|
-
history << "line #1"
|
58
|
-
history << "line #1"
|
59
|
-
|
60
|
-
expect(history.to_a).to eq(["line #1", "line #1", "line #1"])
|
61
|
-
end
|
62
|
-
|
63
|
-
it "prevents duplicates" do
|
64
|
-
history = described_class.new(3, duplicates: false)
|
65
|
-
history << "line #1"
|
66
|
-
history << "line #1"
|
67
|
-
history << "line #1"
|
68
|
-
|
69
|
-
expect(history.to_a).to eq(["line #1"])
|
70
|
-
end
|
71
|
-
|
72
|
-
it "navigates through history buffer without cycling" do
|
73
|
-
history = described_class.new(3)
|
74
|
-
history << "line #1"
|
75
|
-
history << "line #2"
|
76
|
-
history << "line #3"
|
77
|
-
|
78
|
-
expect(history.index).to eq(2)
|
79
|
-
history.previous
|
80
|
-
history.previous
|
81
|
-
expect(history.index).to eq(0)
|
82
|
-
history.previous
|
83
|
-
expect(history.index).to eq(0)
|
84
|
-
history.next
|
85
|
-
history.next
|
86
|
-
expect(history.index).to eq(2)
|
87
|
-
history.next
|
88
|
-
expect(history.next?).to eq(false)
|
89
|
-
expect(history.index).to eq(2)
|
90
|
-
end
|
91
|
-
|
92
|
-
it "navigates through history buffer with cycling" do
|
93
|
-
history = described_class.new(3, cycle: true)
|
94
|
-
history << "line #1"
|
95
|
-
history << "line #2"
|
96
|
-
history << "line #3"
|
97
|
-
|
98
|
-
expect(history.index).to eq(2)
|
99
|
-
history.previous
|
100
|
-
history.previous
|
101
|
-
expect(history.index).to eq(0)
|
102
|
-
history.previous
|
103
|
-
expect(history.index).to eq(2)
|
104
|
-
expect(history.next?).to eq(true)
|
105
|
-
history.next
|
106
|
-
history.next
|
107
|
-
expect(history.index).to eq(1)
|
108
|
-
history.next
|
109
|
-
expect(history.index).to eq(2)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "checks if navigation is possible" do
|
113
|
-
history = described_class.new(3)
|
114
|
-
expect(history.previous?).to eq(false)
|
115
|
-
expect(history.next?).to eq(false)
|
116
|
-
|
117
|
-
history << "line #1"
|
118
|
-
history << "line #2"
|
119
|
-
expect(history.previous?).to eq(true)
|
120
|
-
expect(history.next?).to eq(false)
|
121
|
-
|
122
|
-
history.previous
|
123
|
-
expect(history.previous?).to eq(true)
|
124
|
-
expect(history.next?).to eq(true)
|
125
|
-
|
126
|
-
history.previous
|
127
|
-
expect(history.previous?).to eq(true)
|
128
|
-
expect(history.next?).to eq(true)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "gets line based on index" do
|
132
|
-
history = described_class.new(3, cycle: true)
|
133
|
-
history << "line #1"
|
134
|
-
history << "line #2"
|
135
|
-
history << "line #3"
|
136
|
-
|
137
|
-
expect(history[-1]).to eq('line #3')
|
138
|
-
expect(history[1]).to eq('line #2')
|
139
|
-
expect {
|
140
|
-
history[11]
|
141
|
-
}.to raise_error(IndexError, 'invalid index')
|
142
|
-
end
|
143
|
-
|
144
|
-
it "retrieves current line" do
|
145
|
-
history = described_class.new(3, cycle: true)
|
146
|
-
expect(history.get).to eq(nil)
|
147
|
-
|
148
|
-
history << "line #1"
|
149
|
-
history << "line #2"
|
150
|
-
history << "line #3"
|
151
|
-
|
152
|
-
expect(history.get).to eq("line #3")
|
153
|
-
history.previous
|
154
|
-
history.previous
|
155
|
-
expect(history.get).to eq("line #1")
|
156
|
-
history.next
|
157
|
-
expect(history.get).to eq("line #2")
|
158
|
-
end
|
159
|
-
|
160
|
-
it "clears all lines" do
|
161
|
-
history = described_class.new(3)
|
162
|
-
|
163
|
-
history << "line #1"
|
164
|
-
history << "line #2"
|
165
|
-
history << "line #3"
|
166
|
-
|
167
|
-
expect(history.size).to eq(3)
|
168
|
-
history.clear
|
169
|
-
expect(history.size).to eq(0)
|
170
|
-
expect(history.index).to eq(0)
|
171
|
-
end
|
172
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'shellwords'
|
4
|
-
require 'tty/prompt/reader/codes'
|
5
|
-
|
6
|
-
RSpec.describe TTY::Prompt::Reader::KeyEvent, '#from' do
|
7
|
-
let(:keys) { TTY::Prompt::Reader::Codes.keys }
|
8
|
-
|
9
|
-
it "parses backspace" do
|
10
|
-
event = described_class.from(keys, "\x7f")
|
11
|
-
expect(event.key.name).to eq(:backspace)
|
12
|
-
expect(event.value).to eq("\x7f")
|
13
|
-
end
|
14
|
-
|
15
|
-
it "parses lowercase char" do
|
16
|
-
event = described_class.from(keys, 'a')
|
17
|
-
expect(event.key.name).to eq(:alpha)
|
18
|
-
expect(event.value).to eq('a')
|
19
|
-
end
|
20
|
-
|
21
|
-
it "parses uppercase char" do
|
22
|
-
event = described_class.from(keys, 'A')
|
23
|
-
expect(event.key.name).to eq(:alpha)
|
24
|
-
expect(event.value).to eq('A')
|
25
|
-
end
|
26
|
-
|
27
|
-
it "parses ctrl-a to ctrl-z inputs" do
|
28
|
-
(1..26).zip('a'..'z').each do |code, char|
|
29
|
-
next if ['i', 'j', 'm'].include?(char)
|
30
|
-
event = described_class.from(keys, code.chr)
|
31
|
-
expect(event.key.name).to eq(:"ctrl_#{char}")
|
32
|
-
expect(event.value).to eq(code.chr)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# F1-F12 keys
|
37
|
-
{
|
38
|
-
f1: ["\eOP", "\e[11~"],
|
39
|
-
f2: ["\eOQ", "\e[12~"],
|
40
|
-
f3: ["\eOR", "\e[13~"],
|
41
|
-
f4: ["\eOS", "\e[14~"],
|
42
|
-
f5: [ "\e[15~"],
|
43
|
-
f6: [ "\e[17~"],
|
44
|
-
f7: [ "\e[18~"],
|
45
|
-
f8: [ "\e[19~"],
|
46
|
-
f9: [ "\e[20~"],
|
47
|
-
f10: [ "\e[21~"],
|
48
|
-
f11: [ "\e[23~"],
|
49
|
-
f12: [ "\e[24~"]
|
50
|
-
}.each do |name, codes|
|
51
|
-
codes.each do |code|
|
52
|
-
it "parses #{Shellwords.escape(code)} as #{name} key" do
|
53
|
-
event = described_class.from(keys, code)
|
54
|
-
expect(event.key.name).to eq(name)
|
55
|
-
expect(event.key.meta).to eq(false)
|
56
|
-
expect(event.key.ctrl).to eq(false)
|
57
|
-
expect(event.key.shift).to eq(false)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# arrow keys & text editing
|
63
|
-
{
|
64
|
-
up: ["\e[A"],
|
65
|
-
down: ["\e[B"],
|
66
|
-
right: ["\e[C"],
|
67
|
-
left: ["\e[D"],
|
68
|
-
clear: ["\e[E"],
|
69
|
-
home: ["\e[1~"],
|
70
|
-
insert: ["\e[2~"],
|
71
|
-
delete: ["\e[3~"],
|
72
|
-
end: ["\e[4~"],
|
73
|
-
page_up: ["\e[5~"],
|
74
|
-
page_down: ["\e[6~"]
|
75
|
-
}.each do |name, codes|
|
76
|
-
codes.each do |code|
|
77
|
-
it "parses #{Shellwords.escape(code)} as #{name} key" do
|
78
|
-
event = described_class.from(keys, code)
|
79
|
-
expect(event.key.name).to eq(name)
|
80
|
-
expect(event.key.meta).to eq(false)
|
81
|
-
expect(event.key.ctrl).to eq(false)
|
82
|
-
expect(event.key.shift).to eq(false)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|