tty-prompt 0.12.0 → 0.13.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/.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
|