|
23 | 23 | from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig
|
24 | 24 | from _pyrepl.simple_interact import _strip_final_indent
|
25 | 25 | from _pyrepl.unix_eventqueue import EventQueue
|
26 |
| -from _pyrepl.simple_interact import InteractiveColoredConsole |
| 26 | +from _pyrepl.input import KeymapTranslator |
| 27 | +from _pyrepl.keymap import parse_keys, compile_keymap |
27 | 28 |
|
28 | 29 |
|
29 | 30 | def more_lines(unicodetext, namespace=None):
|
@@ -646,10 +647,10 @@ def test_updown_arrow_with_completion_menu(self):
|
646 | 647 | events = itertools.chain(
|
647 | 648 | code_to_events(code),
|
648 | 649 | [
|
649 |
| - Event(evt='key', data='up', raw=bytearray(b'\x1bOA')), |
| 650 | + Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), |
650 | 651 | Event(evt="key", data="down", raw=bytearray(b"\x1bOB")),
|
651 | 652 | ],
|
652 |
| - code_to_events("\n") |
| 653 | + code_to_events("\n"), |
653 | 654 | )
|
654 | 655 | reader = self.prepare_reader(events, namespace=namespace)
|
655 | 656 | output = multiline_input(reader, namespace)
|
@@ -1046,13 +1047,185 @@ def test_setpos_fromxy_in_wrapped_line(self):
|
1046 | 1047 | self.assertEqual(reader.pos, 9)
|
1047 | 1048 |
|
1048 | 1049 | def test_up_arrow_after_ctrl_r(self):
|
1049 |
| - events = iter([ |
1050 |
| - Event(evt='key', data='\x12', raw=bytearray(b'\x12')), |
1051 |
| - Event(evt='key', data='up', raw=bytearray(b'\x1bOA')), |
1052 |
| - ]) |
| 1050 | + events = iter( |
| 1051 | + [ |
| 1052 | + Event(evt="key", data="\x12", raw=bytearray(b"\x12")), |
| 1053 | + Event(evt="key", data="up", raw=bytearray(b"\x1bOA")), |
| 1054 | + ] |
| 1055 | + ) |
1053 | 1056 |
|
1054 | 1057 | reader, _ = handle_all_events(events)
|
1055 | 1058 | self.assert_screen_equals(reader, "")
|
1056 | 1059 |
|
1057 |
| -if __name__ == '__main__': |
| 1060 | + |
| 1061 | +class KeymapTranslatorTests(unittest.TestCase): |
| 1062 | + def test_push_single_key(self): |
| 1063 | + keymap = [("a", "command_a")] |
| 1064 | + translator = KeymapTranslator(keymap) |
| 1065 | + evt = Event("key", "a") |
| 1066 | + translator.push(evt) |
| 1067 | + result = translator.get() |
| 1068 | + self.assertEqual(result, ("command_a", ["a"])) |
| 1069 | + |
| 1070 | + def test_push_multiple_keys(self): |
| 1071 | + keymap = [("ab", "command_ab")] |
| 1072 | + translator = KeymapTranslator(keymap) |
| 1073 | + evt1 = Event("key", "a") |
| 1074 | + evt2 = Event("key", "b") |
| 1075 | + translator.push(evt1) |
| 1076 | + translator.push(evt2) |
| 1077 | + result = translator.get() |
| 1078 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 1079 | + |
| 1080 | + def test_push_invalid_key(self): |
| 1081 | + keymap = [("a", "command_a")] |
| 1082 | + translator = KeymapTranslator(keymap) |
| 1083 | + evt = Event("key", "b") |
| 1084 | + translator.push(evt) |
| 1085 | + result = translator.get() |
| 1086 | + self.assertEqual(result, (None, ["b"])) |
| 1087 | + |
| 1088 | + def test_push_invalid_key_with_stack(self): |
| 1089 | + keymap = [("ab", "command_ab")] |
| 1090 | + translator = KeymapTranslator(keymap) |
| 1091 | + evt1 = Event("key", "a") |
| 1092 | + evt2 = Event("key", "c") |
| 1093 | + translator.push(evt1) |
| 1094 | + translator.push(evt2) |
| 1095 | + result = translator.get() |
| 1096 | + self.assertEqual(result, (None, ["a", "c"])) |
| 1097 | + |
| 1098 | + def test_push_character_key(self): |
| 1099 | + keymap = [("a", "command_a")] |
| 1100 | + translator = KeymapTranslator(keymap) |
| 1101 | + evt = Event("key", "a") |
| 1102 | + translator.push(evt) |
| 1103 | + result = translator.get() |
| 1104 | + self.assertEqual(result, ("command_a", ["a"])) |
| 1105 | + |
| 1106 | + def test_push_character_key_with_stack(self): |
| 1107 | + keymap = [("ab", "command_ab")] |
| 1108 | + translator = KeymapTranslator(keymap) |
| 1109 | + evt1 = Event("key", "a") |
| 1110 | + evt2 = Event("key", "b") |
| 1111 | + evt3 = Event("key", "c") |
| 1112 | + translator.push(evt1) |
| 1113 | + translator.push(evt2) |
| 1114 | + translator.push(evt3) |
| 1115 | + result = translator.get() |
| 1116 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 1117 | + |
| 1118 | + def test_push_transition_key(self): |
| 1119 | + keymap = [("a", {"b": "command_ab"})] |
| 1120 | + translator = KeymapTranslator(keymap) |
| 1121 | + evt1 = Event("key", "a") |
| 1122 | + evt2 = Event("key", "b") |
| 1123 | + translator.push(evt1) |
| 1124 | + translator.push(evt2) |
| 1125 | + result = translator.get() |
| 1126 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 1127 | + |
| 1128 | + def test_push_transition_key_interrupted(self): |
| 1129 | + keymap = [("a", {"b": "command_ab"})] |
| 1130 | + translator = KeymapTranslator(keymap) |
| 1131 | + evt1 = Event("key", "a") |
| 1132 | + evt2 = Event("key", "c") |
| 1133 | + evt3 = Event("key", "b") |
| 1134 | + translator.push(evt1) |
| 1135 | + translator.push(evt2) |
| 1136 | + translator.push(evt3) |
| 1137 | + result = translator.get() |
| 1138 | + self.assertEqual(result, (None, ["a", "c"])) |
| 1139 | + |
| 1140 | + def test_push_invalid_key_with_unicode_category(self): |
| 1141 | + keymap = [("a", "command_a")] |
| 1142 | + translator = KeymapTranslator(keymap) |
| 1143 | + evt = Event("key", "\u0003") # Control character |
| 1144 | + translator.push(evt) |
| 1145 | + result = translator.get() |
| 1146 | + self.assertEqual(result, (None, ["\u0003"])) |
| 1147 | + |
| 1148 | + def test_empty(self): |
| 1149 | + keymap = [("a", "command_a")] |
| 1150 | + translator = KeymapTranslator(keymap) |
| 1151 | + self.assertTrue(translator.empty()) |
| 1152 | + evt = Event("key", "a") |
| 1153 | + translator.push(evt) |
| 1154 | + self.assertFalse(translator.empty()) |
| 1155 | + translator.get() |
| 1156 | + self.assertTrue(translator.empty()) |
| 1157 | + |
| 1158 | + |
| 1159 | +class TestParseKeys(unittest.TestCase): |
| 1160 | + def test_single_character(self): |
| 1161 | + self.assertEqual(parse_keys("a"), ["a"]) |
| 1162 | + self.assertEqual(parse_keys("b"), ["b"]) |
| 1163 | + self.assertEqual(parse_keys("1"), ["1"]) |
| 1164 | + |
| 1165 | + def test_escape_sequences(self): |
| 1166 | + self.assertEqual(parse_keys("\\n"), ["\n"]) |
| 1167 | + self.assertEqual(parse_keys("\\t"), ["\t"]) |
| 1168 | + self.assertEqual(parse_keys("\\\\"), ["\\"]) |
| 1169 | + self.assertEqual(parse_keys("\\'"), ["'"]) |
| 1170 | + self.assertEqual(parse_keys('\\"'), ['"']) |
| 1171 | + |
| 1172 | + def test_control_sequences(self): |
| 1173 | + self.assertEqual(parse_keys("\\C-a"), ["\x01"]) |
| 1174 | + self.assertEqual(parse_keys("\\C-b"), ["\x02"]) |
| 1175 | + self.assertEqual(parse_keys("\\C-c"), ["\x03"]) |
| 1176 | + |
| 1177 | + def test_meta_sequences(self): |
| 1178 | + self.assertEqual(parse_keys("\\M-a"), ["\033", "a"]) |
| 1179 | + self.assertEqual(parse_keys("\\M-b"), ["\033", "b"]) |
| 1180 | + self.assertEqual(parse_keys("\\M-c"), ["\033", "c"]) |
| 1181 | + |
| 1182 | + def test_keynames(self): |
| 1183 | + self.assertEqual(parse_keys("\\<up>"), ["up"]) |
| 1184 | + self.assertEqual(parse_keys("\\<down>"), ["down"]) |
| 1185 | + self.assertEqual(parse_keys("\\<left>"), ["left"]) |
| 1186 | + self.assertEqual(parse_keys("\\<right>"), ["right"]) |
| 1187 | + |
| 1188 | + def test_combinations(self): |
| 1189 | + self.assertEqual(parse_keys("\\C-a\\n\\<up>"), ["\x01", "\n", "up"]) |
| 1190 | + self.assertEqual(parse_keys("\\M-a\\t\\<down>"), ["\033", "a", "\t", "down"]) |
| 1191 | + |
| 1192 | + |
| 1193 | +class TestCompileKeymap(unittest.TestCase): |
| 1194 | + def test_empty_keymap(self): |
| 1195 | + keymap = {} |
| 1196 | + result = compile_keymap(keymap) |
| 1197 | + self.assertEqual(result, {}) |
| 1198 | + |
| 1199 | + def test_single_keymap(self): |
| 1200 | + keymap = {b"a": "action"} |
| 1201 | + result = compile_keymap(keymap) |
| 1202 | + self.assertEqual(result, {b"a": "action"}) |
| 1203 | + |
| 1204 | + def test_nested_keymap(self): |
| 1205 | + keymap = {b"a": {b"b": "action"}} |
| 1206 | + result = compile_keymap(keymap) |
| 1207 | + self.assertEqual(result, {b"a": {b"b": "action"}}) |
| 1208 | + |
| 1209 | + def test_empty_value(self): |
| 1210 | + keymap = {b"a": {b"": "action"}} |
| 1211 | + result = compile_keymap(keymap) |
| 1212 | + self.assertEqual(result, {b"a": {b"": "action"}}) |
| 1213 | + |
| 1214 | + def test_multiple_empty_values(self): |
| 1215 | + keymap = {b"a": {b"": "action1", b"b": "action2"}} |
| 1216 | + result = compile_keymap(keymap) |
| 1217 | + self.assertEqual(result, {b"a": {b"": "action1", b"b": "action2"}}) |
| 1218 | + |
| 1219 | + def test_multiple_keymaps(self): |
| 1220 | + keymap = {b"a": {b"b": "action1", b"c": "action2"}} |
| 1221 | + result = compile_keymap(keymap) |
| 1222 | + self.assertEqual(result, {b"a": {b"b": "action1", b"c": "action2"}}) |
| 1223 | + |
| 1224 | + def test_nested_multiple_keymaps(self): |
| 1225 | + keymap = {b"a": {b"b": {b"c": "action"}}} |
| 1226 | + result = compile_keymap(keymap) |
| 1227 | + self.assertEqual(result, {b"a": {b"b": {b"c": "action"}}}) |
| 1228 | + |
| 1229 | + |
| 1230 | +if __name__ == "__main__": |
1058 | 1231 | unittest.main()
|
0 commit comments