1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
import pytest
from prompt_toolkit.input.vt100_parser import Vt100Parser
from prompt_toolkit.keys import Keys
class _ProcessorMock(object):
def __init__(self):
self.keys = []
def feed_key(self, key_press):
self.keys.append(key_press)
@pytest.fixture
def processor():
return _ProcessorMock()
@pytest.fixture
def stream(processor):
return Vt100Parser(processor.feed_key)
def test_control_keys(processor, stream):
stream.feed("\x01\x02\x10")
assert len(processor.keys) == 3
assert processor.keys[0].key == Keys.ControlA
assert processor.keys[1].key == Keys.ControlB
assert processor.keys[2].key == Keys.ControlP
assert processor.keys[0].data == "\x01"
assert processor.keys[1].data == "\x02"
assert processor.keys[2].data == "\x10"
def test_arrows(processor, stream):
stream.feed("\x1b[A\x1b[B\x1b[C\x1b[D")
assert len(processor.keys) == 4
assert processor.keys[0].key == Keys.Up
assert processor.keys[1].key == Keys.Down
assert processor.keys[2].key == Keys.Right
assert processor.keys[3].key == Keys.Left
assert processor.keys[0].data == "\x1b[A"
assert processor.keys[1].data == "\x1b[B"
assert processor.keys[2].data == "\x1b[C"
assert processor.keys[3].data == "\x1b[D"
def test_escape(processor, stream):
stream.feed("\x1bhello")
assert len(processor.keys) == 1 + len("hello")
assert processor.keys[0].key == Keys.Escape
assert processor.keys[1].key == "h"
assert processor.keys[0].data == "\x1b"
assert processor.keys[1].data == "h"
def test_special_double_keys(processor, stream):
stream.feed("\x1b[1;3D") # Should both send escape and left.
assert len(processor.keys) == 2
assert processor.keys[0].key == Keys.Escape
assert processor.keys[1].key == Keys.Left
assert processor.keys[0].data == "\x1b[1;3D"
assert processor.keys[1].data == ""
def test_flush_1(processor, stream):
# Send left key in two parts without flush.
stream.feed("\x1b")
stream.feed("[D")
assert len(processor.keys) == 1
assert processor.keys[0].key == Keys.Left
assert processor.keys[0].data == "\x1b[D"
def test_flush_2(processor, stream):
# Send left key with a 'Flush' in between.
# The flush should make sure that we process everything before as-is,
# with makes the first part just an escape character instead.
stream.feed("\x1b")
stream.flush()
stream.feed("[D")
assert len(processor.keys) == 3
assert processor.keys[0].key == Keys.Escape
assert processor.keys[1].key == "["
assert processor.keys[2].key == "D"
assert processor.keys[0].data == "\x1b"
assert processor.keys[1].data == "["
assert processor.keys[2].data == "D"
def test_meta_arrows(processor, stream):
stream.feed("\x1b\x1b[D")
assert len(processor.keys) == 2
assert processor.keys[0].key == Keys.Escape
assert processor.keys[1].key == Keys.Left
def test_control_square_close(processor, stream):
stream.feed("\x1dC")
assert len(processor.keys) == 2
assert processor.keys[0].key == Keys.ControlSquareClose
assert processor.keys[1].key == "C"
def test_invalid(processor, stream):
# Invalid sequence that has at two characters in common with other
# sequences.
stream.feed("\x1b[*")
assert len(processor.keys) == 3
assert processor.keys[0].key == Keys.Escape
assert processor.keys[1].key == "["
assert processor.keys[2].key == "*"
def test_cpr_response(processor, stream):
stream.feed("a\x1b[40;10Rb")
assert len(processor.keys) == 3
assert processor.keys[0].key == "a"
assert processor.keys[1].key == Keys.CPRResponse
assert processor.keys[2].key == "b"
def test_cpr_response_2(processor, stream):
# Make sure that the newline is not included in the CPR response.
stream.feed("\x1b[40;1R\n")
assert len(processor.keys) == 2
assert processor.keys[0].key == Keys.CPRResponse
assert processor.keys[1].key == Keys.ControlJ
|