|
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.input import KeymapTranslator |
| 27 | +from _pyrepl.keymap import parse_keys, compile_keymap |
26 | 28 |
|
27 | 29 |
|
28 | 30 | def more_lines(unicodetext, namespace=None):
|
@@ -931,6 +933,173 @@ def test_setpos_fromxy_in_wrapped_line(self):
|
931 | 933 | reader.setpos_from_xy(0, 1)
|
932 | 934 | self.assertEqual(reader.pos, 9)
|
933 | 935 |
|
| 936 | +class KeymapTranslatorTests(unittest.TestCase): |
| 937 | + def test_push_single_key(self): |
| 938 | + keymap = [("a", "command_a")] |
| 939 | + translator = KeymapTranslator(keymap) |
| 940 | + evt = Event("key", "a") |
| 941 | + translator.push(evt) |
| 942 | + result = translator.get() |
| 943 | + self.assertEqual(result, ("command_a", ["a"])) |
| 944 | + |
| 945 | + def test_push_multiple_keys(self): |
| 946 | + keymap = [("ab", "command_ab")] |
| 947 | + translator = KeymapTranslator(keymap) |
| 948 | + evt1 = Event("key", "a") |
| 949 | + evt2 = Event("key", "b") |
| 950 | + translator.push(evt1) |
| 951 | + translator.push(evt2) |
| 952 | + result = translator.get() |
| 953 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 954 | + |
| 955 | + def test_push_invalid_key(self): |
| 956 | + keymap = [("a", "command_a")] |
| 957 | + translator = KeymapTranslator(keymap) |
| 958 | + evt = Event("key", "b") |
| 959 | + translator.push(evt) |
| 960 | + result = translator.get() |
| 961 | + self.assertEqual(result, (None, ["b"])) |
| 962 | + |
| 963 | + def test_push_invalid_key_with_stack(self): |
| 964 | + keymap = [("ab", "command_ab")] |
| 965 | + translator = KeymapTranslator(keymap) |
| 966 | + evt1 = Event("key", "a") |
| 967 | + evt2 = Event("key", "c") |
| 968 | + translator.push(evt1) |
| 969 | + translator.push(evt2) |
| 970 | + result = translator.get() |
| 971 | + self.assertEqual(result, (None, ["a", "c"])) |
| 972 | + |
| 973 | + def test_push_character_key(self): |
| 974 | + keymap = [("a", "command_a")] |
| 975 | + translator = KeymapTranslator(keymap) |
| 976 | + evt = Event("key", "a") |
| 977 | + translator.push(evt) |
| 978 | + result = translator.get() |
| 979 | + self.assertEqual(result, ("command_a", ["a"])) |
| 980 | + |
| 981 | + def test_push_character_key_with_stack(self): |
| 982 | + keymap = [("ab", "command_ab")] |
| 983 | + translator = KeymapTranslator(keymap) |
| 984 | + evt1 = Event("key", "a") |
| 985 | + evt2 = Event("key", "b") |
| 986 | + evt3 = Event("key", "c") |
| 987 | + translator.push(evt1) |
| 988 | + translator.push(evt2) |
| 989 | + translator.push(evt3) |
| 990 | + result = translator.get() |
| 991 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 992 | + |
| 993 | + def test_push_transition_key(self): |
| 994 | + keymap = [("a", {"b": "command_ab"})] |
| 995 | + translator = KeymapTranslator(keymap) |
| 996 | + evt1 = Event("key", "a") |
| 997 | + evt2 = Event("key", "b") |
| 998 | + translator.push(evt1) |
| 999 | + translator.push(evt2) |
| 1000 | + result = translator.get() |
| 1001 | + self.assertEqual(result, ("command_ab", ["a", "b"])) |
| 1002 | + |
| 1003 | + def test_push_transition_key_interrupted(self): |
| 1004 | + keymap = [("a", {"b": "command_ab"})] |
| 1005 | + translator = KeymapTranslator(keymap) |
| 1006 | + evt1 = Event("key", "a") |
| 1007 | + evt2 = Event("key", "c") |
| 1008 | + evt3 = Event("key", "b") |
| 1009 | + translator.push(evt1) |
| 1010 | + translator.push(evt2) |
| 1011 | + translator.push(evt3) |
| 1012 | + result = translator.get() |
| 1013 | + self.assertEqual(result, (None, ["a", "c"])) |
| 1014 | + |
| 1015 | + def test_push_invalid_key_with_unicode_category(self): |
| 1016 | + keymap = [("a", "command_a")] |
| 1017 | + translator = KeymapTranslator(keymap) |
| 1018 | + evt = Event("key", "\u0003") # Control character |
| 1019 | + translator.push(evt) |
| 1020 | + result = translator.get() |
| 1021 | + self.assertEqual(result, (None, ["\u0003"])) |
| 1022 | + |
| 1023 | + def test_empty(self): |
| 1024 | + keymap = [("a", "command_a")] |
| 1025 | + translator = KeymapTranslator(keymap) |
| 1026 | + self.assertTrue(translator.empty()) |
| 1027 | + evt = Event("key", "a") |
| 1028 | + translator.push(evt) |
| 1029 | + self.assertFalse(translator.empty()) |
| 1030 | + translator.get() |
| 1031 | + self.assertTrue(translator.empty()) |
| 1032 | + |
| 1033 | +class TestParseKeys(unittest.TestCase): |
| 1034 | + def test_single_character(self): |
| 1035 | + self.assertEqual(parse_keys("a"), ["a"]) |
| 1036 | + self.assertEqual(parse_keys("b"), ["b"]) |
| 1037 | + self.assertEqual(parse_keys("1"), ["1"]) |
| 1038 | + |
| 1039 | + def test_escape_sequences(self): |
| 1040 | + self.assertEqual(parse_keys("\\n"), ["\n"]) |
| 1041 | + self.assertEqual(parse_keys("\\t"), ["\t"]) |
| 1042 | + self.assertEqual(parse_keys("\\\\"), ["\\"]) |
| 1043 | + self.assertEqual(parse_keys("\\'"), ["'"]) |
| 1044 | + self.assertEqual(parse_keys('\\"'), ['"']) |
| 1045 | + |
| 1046 | + def test_control_sequences(self): |
| 1047 | + self.assertEqual(parse_keys("\\C-a"), ["\x01"]) |
| 1048 | + self.assertEqual(parse_keys("\\C-b"), ["\x02"]) |
| 1049 | + self.assertEqual(parse_keys("\\C-c"), ["\x03"]) |
| 1050 | + |
| 1051 | + def test_meta_sequences(self): |
| 1052 | + self.assertEqual(parse_keys("\\M-a"), ["\033", "a"]) |
| 1053 | + self.assertEqual(parse_keys("\\M-b"), ["\033", "b"]) |
| 1054 | + self.assertEqual(parse_keys("\\M-c"), ["\033", "c"]) |
| 1055 | + |
| 1056 | + def test_keynames(self): |
| 1057 | + self.assertEqual(parse_keys("\\<up>"), ["up"]) |
| 1058 | + self.assertEqual(parse_keys("\\<down>"), ["down"]) |
| 1059 | + self.assertEqual(parse_keys("\\<left>"), ["left"]) |
| 1060 | + self.assertEqual(parse_keys("\\<right>"), ["right"]) |
| 1061 | + |
| 1062 | + def test_combinations(self): |
| 1063 | + self.assertEqual(parse_keys("\\C-a\\n\\<up>"), ["\x01", "\n", "up"]) |
| 1064 | + self.assertEqual(parse_keys("\\M-a\\t\\<down>"), ["\033", "a", "\t", "down"]) |
| 1065 | + |
| 1066 | + |
| 1067 | +class TestCompileKeymap(unittest.TestCase): |
| 1068 | + def test_empty_keymap(self): |
| 1069 | + keymap = {} |
| 1070 | + result = compile_keymap(keymap) |
| 1071 | + self.assertEqual(result, {}) |
| 1072 | + |
| 1073 | + def test_single_keymap(self): |
| 1074 | + keymap = {b"a": "action"} |
| 1075 | + result = compile_keymap(keymap) |
| 1076 | + self.assertEqual(result, {b"a": "action"}) |
| 1077 | + |
| 1078 | + def test_nested_keymap(self): |
| 1079 | + keymap = {b"a": {b"b": "action"}} |
| 1080 | + result = compile_keymap(keymap) |
| 1081 | + self.assertEqual(result, {b"a": {b"b": "action"}}) |
| 1082 | + |
| 1083 | + def test_empty_value(self): |
| 1084 | + keymap = {b"a": {b"": "action"}} |
| 1085 | + result = compile_keymap(keymap) |
| 1086 | + self.assertEqual(result, {b"a": {b"": "action"}}) |
| 1087 | + |
| 1088 | + def test_multiple_empty_values(self): |
| 1089 | + keymap = {b"a": {b"": "action1", b"b": "action2"}} |
| 1090 | + result = compile_keymap(keymap) |
| 1091 | + self.assertEqual(result, {b"a": {b"": "action1", b"b": "action2"}}) |
| 1092 | + |
| 1093 | + def test_multiple_keymaps(self): |
| 1094 | + keymap = {b"a": {b"b": "action1", b"c": "action2"}} |
| 1095 | + result = compile_keymap(keymap) |
| 1096 | + self.assertEqual(result, {b"a": {b"b": "action1", b"c": "action2"}}) |
| 1097 | + |
| 1098 | + def test_nested_multiple_keymaps(self): |
| 1099 | + keymap = {b"a": {b"b": {b"c": "action"}}} |
| 1100 | + result = compile_keymap(keymap) |
| 1101 | + self.assertEqual(result, {b"a": {b"b": {b"c": "action"}}}) |
| 1102 | + |
934 | 1103 |
|
935 | 1104 | if __name__ == "__main__":
|
936 | 1105 | unittest.main()
|
0 commit comments