tty-reader 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,158 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Reader::Line do
4
- it "provides access to the prompt" do
5
- line = described_class.new('aaa', prompt: '>> ')
6
- expect(line.prompt).to eq('>> ')
7
- expect(line.text).to eq('aaa')
8
- expect(line.size).to eq(6)
9
- expect(line.to_s).to eq(">> aaa")
10
- end
11
-
12
- it "inserts characters inside a line" do
13
- line = described_class.new('aaaaa')
14
-
15
- line[0] = 'test'
16
- expect(line.text).to eq('testaaaaa')
17
-
18
- line[4..6] = ''
19
- expect(line.text).to eq('testaa')
20
- end
21
-
22
- it "moves cursor left and right" do
23
- line = described_class.new('aaaaa')
24
-
25
- 5.times { line.left }
26
- expect(line.cursor).to eq(0)
27
- expect(line.start?).to eq(true)
28
-
29
- line.left(5)
30
- expect(line.cursor).to eq(0)
31
-
32
- line.right(20)
33
- expect(line.cursor).to eq(5)
34
- expect(line.end?).to eq(true)
35
- end
36
-
37
- it "inserts char at start of the line" do
38
- line = described_class.new('aaaaa')
39
- expect(line.cursor).to eq(5)
40
-
41
- line[0] = 'b'
42
- expect(line.cursor).to eq(1)
43
- expect(line.text).to eq('baaaaa')
44
-
45
- line.insert('b')
46
- expect(line.text).to eq('bbaaaaa')
47
- end
48
-
49
- it "inserts char at end of the line" do
50
- line = described_class.new('aaaaa')
51
- expect(line.cursor).to eq(5)
52
-
53
- line[4] = 'b'
54
- expect(line.cursor).to eq(5)
55
- expect(line.text).to eq('aaaaba')
56
- end
57
-
58
- it "inserts char inside the line" do
59
- line = described_class.new('aaaaa')
60
- expect(line.cursor).to eq(5)
61
-
62
- line[2] = 'b'
63
- expect(line.cursor).to eq(3)
64
- expect(line.text).to eq('aabaaa')
65
- end
66
-
67
- it "inserts char outside of the line size" do
68
- line = described_class.new('aaaaa')
69
- expect(line.cursor).to eq(5)
70
-
71
- line[10] = 'b'
72
- expect(line.cursor).to eq(11)
73
- expect(line.text).to eq('aaaaa b')
74
- end
75
-
76
- it "inserts chars in empty string" do
77
- line = described_class.new('')
78
- expect(line.cursor).to eq(0)
79
-
80
- line.insert('a')
81
- expect(line.cursor).to eq(1)
82
-
83
- line.insert('b')
84
- expect(line.cursor).to eq(2)
85
- expect(line.to_s).to eq('ab')
86
-
87
- line.insert('cc')
88
- expect(line.cursor).to eq(4)
89
- expect(line.to_s).to eq('abcc')
90
- end
91
-
92
- it "inserts characters with #insert call" do
93
- line = described_class.new('aaaaa')
94
- expect(line.cursor).to eq(5)
95
-
96
- line.left(2)
97
- expect(line.cursor).to eq(3)
98
-
99
- line.insert(' test ')
100
- expect(line.text).to eq('aaa test aa')
101
- expect(line.cursor).to eq(9)
102
-
103
- line.right
104
- expect(line.cursor).to eq(10)
105
- end
106
-
107
- it "removes char before current cursor position" do
108
- line = described_class.new('abcdef')
109
- expect(line.cursor).to eq(6)
110
-
111
- line.remove(2)
112
- expect(line.text).to eq('abcd')
113
- expect(line.cursor).to eq(4)
114
-
115
- line.left
116
- line.left
117
- line.remove
118
- expect(line.text).to eq('acd')
119
- expect(line.cursor).to eq(1)
120
-
121
- line.insert('x')
122
- expect(line.text).to eq('axcd')
123
- end
124
-
125
- it "deletes char under current cursor position" do
126
- line = described_class.new('abcdef')
127
-
128
- line.left(3)
129
- line.delete
130
- expect(line.text).to eq('abcef')
131
-
132
- line.right
133
- line.delete
134
- expect(line.text).to eq('abce')
135
-
136
- line.left(4)
137
- line.delete
138
- expect(line.text).to eq('bce')
139
- end
140
-
141
- it "replaces current line with new preserving cursor" do
142
- line = described_class.new('x' * 6)
143
- expect(line.text).to eq('xxxxxx')
144
- expect(line.cursor).to eq(6)
145
- expect(line.mode).to eq(:edit)
146
- expect(line.editing?).to eq(true)
147
-
148
- line.replace('y' * 8)
149
- expect(line.text).to eq('y' * 8)
150
- expect(line.cursor).to eq(8)
151
- expect(line.replacing?).to eq(true)
152
-
153
- line.insert('z')
154
- expect(line.text).to eq('y' * 8 + 'z')
155
- expect(line.cursor).to eq(9)
156
- expect(line.editing?).to eq(true)
157
- end
158
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Reader, '#publish_keypress_event' do
4
- let(:input) { StringIO.new }
5
- let(:out) { StringIO.new }
6
- let(:env) { { "TTY_TEST" => true } }
7
-
8
- let(:reader) { described_class.new(input: input, output: out, env: env) }
9
-
10
- it "publishes :keypress events" do
11
- input << "abc\n"
12
- input.rewind
13
- chars = []
14
- lines = []
15
- reader.on(:keypress) { |event| chars << event.value; lines << event.line }
16
- answer = reader.read_line
17
-
18
- expect(chars).to eq(%W(a b c \n))
19
- expect(lines).to eq(%W(a ab abc abc\n))
20
- expect(answer).to eq("abc\n")
21
- end
22
-
23
- it "publishes :keyescape events" do
24
- input << "a\e"
25
- input.rewind
26
- keys = []
27
- reader.on(:keypress) { |event| keys << "keypress_#{event.value}"}
28
- reader.on(:keyescape) { |event| keys << "keyescape_#{event.value}" }
29
-
30
- answer = reader.read_line
31
- expect(keys).to eq(["keypress_a", "keyescape_\e", "keypress_\e"])
32
- expect(answer).to eq("a\e")
33
- end
34
-
35
- it "publishes :keyup for read_keypress" do
36
- input << "\e[Aaa"
37
- input.rewind
38
- keys = []
39
- reader.on(:keypress) { |event| keys << "keypress_#{event.value}" }
40
- reader.on(:keyup) { |event| keys << "keyup_#{event.value}" }
41
- reader.on(:keydown) { |event| keys << "keydown_#{event.value}" }
42
-
43
- answer = reader.read_keypress
44
- expect(keys).to eq(["keyup_\e[A", "keypress_\e[A"])
45
- expect(answer).to eq("\e[A")
46
- end
47
-
48
- it "publishes :keydown event for read_keypress" do
49
- input << "\e[Baa"
50
- input.rewind
51
- keys = []
52
- reader.on(:keypress) { |event| keys << "keypress_#{event.value}" }
53
- reader.on(:keyup) { |event| keys << "keyup_#{event.value}" }
54
- reader.on(:keydown) { |event| keys << "keydown_#{event.value}" }
55
-
56
- answer = reader.read_keypress
57
- expect(keys).to eq(["keydown_\e[B", "keypress_\e[B"])
58
- expect(answer).to eq("\e[B")
59
- end
60
-
61
- it "publishes :keynum event" do
62
- input << "5aa"
63
- input.rewind
64
- keys = []
65
- reader.on(:keypress) { |event| keys << "keypress_#{event.value}" }
66
- reader.on(:keyup) { |event| keys << "keyup_#{event.value}" }
67
- reader.on(:keynum) { |event| keys << "keynum_#{event.value}" }
68
-
69
- answer = reader.read_keypress
70
- expect(keys).to eq(["keynum_5", "keypress_5"])
71
- expect(answer).to eq("5")
72
- end
73
-
74
- it "publishes :keyreturn event" do
75
- input << "\r"
76
- input.rewind
77
- keys = []
78
- reader.on(:keypress) { |event| keys << "keypress" }
79
- reader.on(:keyup) { |event| keys << "keyup" }
80
- reader.on(:keyreturn) { |event| keys << "keyreturn" }
81
-
82
- answer = reader.read_keypress
83
- expect(keys).to eq(["keyreturn", "keypress"])
84
- expect(answer).to eq("\r")
85
- end
86
-
87
- it "subscribes to multiple events" do
88
- input << "\n"
89
- input.rewind
90
- keys = []
91
- reader.on(:keyenter) { |event| keys << "keyenter" }
92
- .on(:keypress) { |event| keys << "keypress" }
93
-
94
- answer = reader.read_keypress
95
- expect(keys).to eq(["keyenter", "keypress"])
96
- expect(answer).to eq("\n")
97
- end
98
-
99
- it "subscribes to ctrl+X type of event event" do
100
- input << ?\C-z
101
- input.rewind
102
- keys = []
103
- reader.on(:keyctrl_z) { |event| keys << "ctrl_z" }
104
-
105
- answer = reader.read_keypress
106
- expect(keys).to eq(['ctrl_z'])
107
- expect(answer).to eq(?\C-z)
108
- end
109
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Reader, '#read_keypress' do
4
- let(:input) { StringIO.new }
5
- let(:out) { StringIO.new }
6
- let(:env) { { "TTY_TEST" => true } }
7
-
8
- it "reads single key press" do
9
- reader = described_class.new(input: input, output: out, env: env)
10
- input << "\e[Aaaaaaa\n"
11
- input.rewind
12
-
13
- answer = reader.read_keypress
14
-
15
- expect(answer).to eq("\e[A")
16
- end
17
-
18
- it 'reads multibyte key press' do
19
- reader = described_class.new(input: input, output: out, env: env)
20
- input << "ㄱ"
21
- input.rewind
22
-
23
- answer = reader.read_keypress
24
-
25
- expect(answer).to eq("ㄱ")
26
- end
27
-
28
- context 'when Ctrl+C pressed' do
29
- it "defaults to raising InputInterrupt" do
30
- reader = described_class.new(input: input, output: out, env: env)
31
- input << "\x03"
32
- input.rewind
33
-
34
- expect {
35
- reader.read_keypress
36
- }.to raise_error(TTY::Reader::InputInterrupt)
37
- end
38
-
39
- it "sends interrupt signal when :signal option is chosen" do
40
- reader = described_class.new(
41
- input: input,
42
- output: out,
43
- interrupt: :signal,
44
- env: env)
45
- input << "\x03"
46
- input.rewind
47
-
48
- allow(Process).to receive(:pid).and_return(666)
49
- allow(Process).to receive(:kill)
50
- expect(Process).to receive(:kill).with('SIGINT', 666)
51
-
52
- reader.read_keypress
53
- end
54
-
55
- it "exits with 130 code when :exit option is chosen" do
56
- reader = described_class.new(
57
- input: input,
58
- output: out,
59
- interrupt: :exit,
60
- env: env)
61
- input << "\x03"
62
- input.rewind
63
-
64
- expect {
65
- reader.read_keypress
66
- }.to raise_error(SystemExit)
67
- end
68
-
69
- it "evaluates custom handler when proc object is provided" do
70
- handler = proc { raise ArgumentError }
71
- reader = described_class.new(
72
- input: input,
73
- output: out,
74
- interrupt: handler,
75
- env: env)
76
- input << "\x03"
77
- input.rewind
78
-
79
- expect {
80
- reader.read_keypress
81
- }.to raise_error(ArgumentError)
82
- end
83
-
84
- it "skips handler when handler is nil" do
85
- reader = described_class.new(
86
- input: input,
87
- output: out,
88
- interrupt: :noop,
89
- env: env)
90
- input << "\x03"
91
- input.rewind
92
-
93
- expect(reader.read_keypress).to eq("\x03")
94
- end
95
- end
96
- end
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Reader, '#read_line' do
4
- let(:input) { StringIO.new }
5
- let(:output) { StringIO.new }
6
- let(:env) { { "TTY_TEST" => true } }
7
-
8
- subject(:reader) { described_class.new(input: input, output: output, env: env) }
9
-
10
- it 'masks characters' do
11
- input << "password\n"
12
- input.rewind
13
-
14
- answer = reader.read_line(echo: false)
15
-
16
- expect(answer).to eq("password\n")
17
- end
18
-
19
- it "echoes characters back" do
20
- input << "password\n"
21
- input.rewind
22
-
23
- answer = reader.read_line
24
-
25
- expect(answer).to eq("password\n")
26
- expect(output.string).to eq([
27
- "\e[2K\e[1Gp",
28
- "\e[2K\e[1Gpa",
29
- "\e[2K\e[1Gpas",
30
- "\e[2K\e[1Gpass",
31
- "\e[2K\e[1Gpassw",
32
- "\e[2K\e[1Gpasswo",
33
- "\e[2K\e[1Gpasswor",
34
- "\e[2K\e[1Gpassword",
35
- "\e[2K\e[1Gpassword\n"
36
- ].join)
37
- end
38
-
39
- it "doesn't echo characters back" do
40
- input << "password\n"
41
- input.rewind
42
-
43
- answer = reader.read_line(echo: false)
44
-
45
- expect(answer).to eq("password\n")
46
- expect(output.string).to eq("\n")
47
- end
48
-
49
- it "displays a prompt before input" do
50
- input << "aa\n"
51
- input.rewind
52
-
53
- answer = reader.read_line('>> ')
54
-
55
- expect(answer).to eq("aa\n")
56
- expect(output.string).to eq([
57
- ">> ",
58
- "\e[2K\e[1G>> a",
59
- "\e[2K\e[1G>> aa",
60
- "\e[2K\e[1G>> aa\n"
61
- ].join)
62
- end
63
-
64
- it "displays custom input with a prompt" do
65
- input << "aa\n"
66
- input.rewind
67
-
68
- answer = reader.read_line("> ", value: "xx")
69
-
70
- expect(answer).to eq("xxaa\n")
71
- expect(output.string).to eq([
72
- "> xx",
73
- "\e[2K\e[1G> xxa",
74
- "\e[2K\e[1G> xxaa",
75
- "\e[2K\e[1G> xxaa\n"
76
- ].join)
77
- end
78
-
79
- it 'deletes characters when backspace pressed' do
80
- input << "aa\ba\bcc\n"
81
- input.rewind
82
-
83
- answer = reader.read_line
84
-
85
- expect(answer).to eq("acc\n")
86
- end
87
-
88
- it 'reads multibyte line' do
89
- input << "한글"
90
- input.rewind
91
-
92
- answer = reader.read_line
93
-
94
- expect(answer).to eq("한글")
95
- end
96
-
97
- it "supports multiline prompts" do
98
- allow(TTY::Screen).to receive(:width).and_return(50)
99
- prompt = "one\ntwo\nthree"
100
- input << "aa\n"
101
- input.rewind
102
-
103
- answer = reader.read_line(prompt)
104
-
105
- expect(answer).to eq("aa\n")
106
- expect(output.string).to eq([
107
- prompt,
108
- "\e[2K\e[1G\e[1A" * 2,
109
- "\e[2K\e[1G",
110
- prompt + "a",
111
- "\e[2K\e[1G\e[1A" * 2,
112
- "\e[2K\e[1G",
113
- prompt + "aa",
114
- "\e[2K\e[1G\e[1A" * 2,
115
- "\e[2K\e[1G",
116
- prompt + "aa\n"
117
- ].join)
118
- end
119
- end