tty-reader 0.7.0 → 0.8.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.
@@ -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