diff options
| author | Kim F. Storm | 2002-02-23 22:00:37 +0000 |
|---|---|---|
| committer | Kim F. Storm | 2002-02-23 22:00:37 +0000 |
| commit | a1df473f03585f099f2921bcf268294349941630 (patch) | |
| tree | 01bec0a3942287379213ea0d2cf7a30e5a54edc8 /src | |
| parent | 0edda6b89df6af82bb35b02f3aa79278805bd3cf (diff) | |
| download | emacs-a1df473f03585f099f2921bcf268294349941630.tar.gz emacs-a1df473f03585f099f2921bcf268294349941630.zip | |
The following changes rework my patch of 2002-02-06 which
added command remapping by entering the commands directly into
the keymaps. Now, command remapping uses an explicit `remap'
prefix in the keymaps, i.e. [remap COMMAND].
(Qremap, remap_command_vector): New variables.
(is_command_symbol): Removed function.
(Fdefine_key): No longer accept a symbol for KEY. Added
validation of [remap COMMAND] argument for KEY. The DEF is no
longer required to be a symbol when remapping a command.
(Fremap_command): New function to remap command through keymaps.
(Flookup_key): Perform command remapping initiated by
Fremap_command directly for speed.
(Fkey_binding): Use Fremap_command for command remapping.
(where_is_internal): Handle new command remapping representation.
(syms_of_keymap): Intern Qremap, initialize remap_command_vector,
staticpro them. Defsubr Fremap_command.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keymap.c | 158 |
1 files changed, 69 insertions, 89 deletions
diff --git a/src/keymap.c b/src/keymap.c index d37e7bd1480..fcb56bd44ae 100644 --- a/src/keymap.c +++ b/src/keymap.c | |||
| @@ -89,11 +89,14 @@ Lisp_Object Vkey_translation_map; | |||
| 89 | when Emacs starts up. t means don't record anything here. */ | 89 | when Emacs starts up. t means don't record anything here. */ |
| 90 | Lisp_Object Vdefine_key_rebound_commands; | 90 | Lisp_Object Vdefine_key_rebound_commands; |
| 91 | 91 | ||
| 92 | Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item; | 92 | Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap; |
| 93 | 93 | ||
| 94 | /* Alist of elements like (DEL . "\d"). */ | 94 | /* Alist of elements like (DEL . "\d"). */ |
| 95 | static Lisp_Object exclude_keys; | 95 | static Lisp_Object exclude_keys; |
| 96 | 96 | ||
| 97 | /* Pre-allocated 2-element vector for Fremap_command to use. */ | ||
| 98 | static Lisp_Object remap_command_vector; | ||
| 99 | |||
| 97 | /* A char with the CHAR_META bit set in a vector or the 0200 bit set | 100 | /* A char with the CHAR_META bit set in a vector or the 0200 bit set |
| 98 | in a string key sequence is equivalent to prefixing with this | 101 | in a string key sequence is equivalent to prefixing with this |
| 99 | character. */ | 102 | character. */ |
| @@ -973,10 +976,7 @@ DEF is anything that can be a key's definition: | |||
| 973 | or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP. | 976 | or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP. |
| 974 | 977 | ||
| 975 | If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at | 978 | If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at |
| 976 | the front of KEYMAP. | 979 | the front of KEYMAP. */) |
| 977 | |||
| 978 | KEY may also be a command name which is remapped to DEF. In this case, | ||
| 979 | DEF must be a symbol or nil (to remove a previous binding of KEY). */) | ||
| 980 | (keymap, key, def) | 980 | (keymap, key, def) |
| 981 | Lisp_Object keymap; | 981 | Lisp_Object keymap; |
| 982 | Lisp_Object key; | 982 | Lisp_Object key; |
| @@ -992,29 +992,18 @@ DEF must be a symbol or nil (to remove a previous binding of KEY). */) | |||
| 992 | 992 | ||
| 993 | keymap = get_keymap (keymap, 1, 1); | 993 | keymap = get_keymap (keymap, 1, 1); |
| 994 | 994 | ||
| 995 | if (SYMBOLP (key)) | 995 | if (!VECTORP (key) && !STRINGP (key)) |
| 996 | { | ||
| 997 | /* A command may only be remapped to another command. */ | ||
| 998 | |||
| 999 | /* I thought of using is_command_symbol above and below instead | ||
| 1000 | of SYMBOLP, since remapping only works for sych symbols. | ||
| 1001 | However, to make that a requirement would make it impossible | ||
| 1002 | to remap a command before it has been defined, e.g. if a minor | ||
| 1003 | mode were to remap a command of another minor mode which has | ||
| 1004 | not yet been loaded, it would fail. So just use the least | ||
| 1005 | restrictive sanity check here. */ | ||
| 1006 | if (!SYMBOLP (def)) | ||
| 1007 | key = wrong_type_argument (Qsymbolp, def); | ||
| 1008 | else | ||
| 1009 | key = Fmake_vector (make_number (1), key); | ||
| 1010 | } | ||
| 1011 | else if (!VECTORP (key) && !STRINGP (key)) | ||
| 1012 | key = wrong_type_argument (Qarrayp, key); | 996 | key = wrong_type_argument (Qarrayp, key); |
| 1013 | 997 | ||
| 1014 | length = XFASTINT (Flength (key)); | 998 | length = XFASTINT (Flength (key)); |
| 1015 | if (length == 0) | 999 | if (length == 0) |
| 1016 | return Qnil; | 1000 | return Qnil; |
| 1017 | 1001 | ||
| 1002 | /* Check for valid [remap COMMAND] bindings. */ | ||
| 1003 | if (VECTORP (key) && EQ (AREF (key, 0), Qremap) | ||
| 1004 | && (length != 2 || !SYMBOLP (AREF (key, 1)))) | ||
| 1005 | wrong_type_argument (Qvectorp, key); | ||
| 1006 | |||
| 1018 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) | 1007 | if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) |
| 1019 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); | 1008 | Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); |
| 1020 | 1009 | ||
| @@ -1073,6 +1062,19 @@ DEF must be a symbol or nil (to remove a previous binding of KEY). */) | |||
| 1073 | } | 1062 | } |
| 1074 | } | 1063 | } |
| 1075 | 1064 | ||
| 1065 | /* This function may GC (it calls Fkey_binding). */ | ||
| 1066 | |||
| 1067 | DEFUN ("remap-command", Fremap_command, Sremap_command, 1, 1, 0, | ||
| 1068 | doc: /* Return the remapping for command COMMAND in current keymaps. | ||
| 1069 | Returns nil if COMMAND is not remapped. */) | ||
| 1070 | (command) | ||
| 1071 | Lisp_Object command; | ||
| 1072 | { | ||
| 1073 | /* This will GCPRO the command argument. */ | ||
| 1074 | ASET (remap_command_vector, 1, command); | ||
| 1075 | return Fkey_binding (remap_command_vector, Qnil, Qt); | ||
| 1076 | } | ||
| 1077 | |||
| 1076 | /* Value is number if KEY is too long; nil if valid but has no definition. */ | 1078 | /* Value is number if KEY is too long; nil if valid but has no definition. */ |
| 1077 | /* GC is possible in this function if it autoloads a keymap. */ | 1079 | /* GC is possible in this function if it autoloads a keymap. */ |
| 1078 | 1080 | ||
| @@ -1105,9 +1107,19 @@ recognize the default bindings, just as `read-key-sequence' does. */) | |||
| 1105 | 1107 | ||
| 1106 | keymap = get_keymap (keymap, 1, 1); | 1108 | keymap = get_keymap (keymap, 1, 1); |
| 1107 | 1109 | ||
| 1108 | /* Command remapping is simple. */ | 1110 | /* Perform command remapping initiated by Fremap_command directly. |
| 1109 | if (SYMBOLP (key)) | 1111 | This is strictly not necessary, but it is faster and it returns |
| 1110 | return access_keymap (keymap, key, t_ok, 0, 1); | 1112 | nil instead of 1 if KEYMAP doesn't contain command remappings. */ |
| 1113 | if (EQ (key, remap_command_vector)) | ||
| 1114 | { | ||
| 1115 | /* KEY has format [remap COMMAND]. | ||
| 1116 | Lookup `remap' in KEYMAP; result is nil or a keymap containing | ||
| 1117 | command remappings. Then lookup COMMAND in that keymap. */ | ||
| 1118 | if ((keymap = access_keymap (keymap, Qremap, t_ok, 0, 1), !NILP (keymap)) | ||
| 1119 | && (keymap = get_keymap (keymap, 0, 1), CONSP (keymap))) | ||
| 1120 | return access_keymap (keymap, AREF (key, 1), t_ok, 0, 1); | ||
| 1121 | return Qnil; | ||
| 1122 | } | ||
| 1111 | 1123 | ||
| 1112 | if (!VECTORP (key) && !STRINGP (key)) | 1124 | if (!VECTORP (key) && !STRINGP (key)) |
| 1113 | key = wrong_type_argument (Qarrayp, key); | 1125 | key = wrong_type_argument (Qarrayp, key); |
| @@ -1386,41 +1398,6 @@ OLP if non-nil indicates that we should obey `overriding-local-map' and | |||
| 1386 | return keymaps; | 1398 | return keymaps; |
| 1387 | } | 1399 | } |
| 1388 | 1400 | ||
| 1389 | /* Like Fcommandp, but looks specifically for a command symbol, and | ||
| 1390 | doesn't signal errors. Returns 1 if FUNCTION is a command symbol. */ | ||
| 1391 | int | ||
| 1392 | is_command_symbol (function) | ||
| 1393 | Lisp_Object function; | ||
| 1394 | { | ||
| 1395 | if (!SYMBOLP (function) || EQ (function, Qunbound)) | ||
| 1396 | return 0; | ||
| 1397 | |||
| 1398 | function = indirect_function (function); | ||
| 1399 | if (SYMBOLP (function) && EQ (function, Qunbound)) | ||
| 1400 | return 0; | ||
| 1401 | |||
| 1402 | if (SUBRP (function)) | ||
| 1403 | return (XSUBR (function)->prompt != 0); | ||
| 1404 | |||
| 1405 | if (COMPILEDP (function)) | ||
| 1406 | return ((ASIZE (function) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE); | ||
| 1407 | |||
| 1408 | if (CONSP (function)) | ||
| 1409 | { | ||
| 1410 | Lisp_Object funcar; | ||
| 1411 | |||
| 1412 | funcar = Fcar (function); | ||
| 1413 | if (SYMBOLP (funcar)) | ||
| 1414 | { | ||
| 1415 | if (EQ (funcar, Qlambda)) | ||
| 1416 | return !NILP (Fassq (Qinteractive, Fcdr (Fcdr (function)))); | ||
| 1417 | if (EQ (funcar, Qautoload)) | ||
| 1418 | return !NILP (Fcar (Fcdr (Fcdr (Fcdr (function))))); | ||
| 1419 | } | ||
| 1420 | } | ||
| 1421 | return 0; | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | /* GC is possible in this function if it autoloads a keymap. */ | 1401 | /* GC is possible in this function if it autoloads a keymap. */ |
| 1425 | 1402 | ||
| 1426 | DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, | 1403 | DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, |
| @@ -1503,12 +1480,10 @@ is non-nil, `key-binding' returns the unmapped command. */) | |||
| 1503 | /* If the result of the ordinary keymap lookup is an interactive | 1480 | /* If the result of the ordinary keymap lookup is an interactive |
| 1504 | command, look for a key binding (ie. remapping) for that command. */ | 1481 | command, look for a key binding (ie. remapping) for that command. */ |
| 1505 | 1482 | ||
| 1506 | if (NILP (no_remap) && is_command_symbol (value)) | 1483 | if (NILP (no_remap) && SYMBOLP (value)) |
| 1507 | { | 1484 | { |
| 1508 | Lisp_Object value1; | 1485 | Lisp_Object value1; |
| 1509 | 1486 | if (value1 = Fremap_command (value), !NILP (value1)) | |
| 1510 | value1 = Fkey_binding (value, accept_default, Qt); | ||
| 1511 | if (!NILP (value1) && is_command_symbol (value1)) | ||
| 1512 | value = value1; | 1487 | value = value1; |
| 1513 | } | 1488 | } |
| 1514 | 1489 | ||
| @@ -2272,9 +2247,12 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2272 | 2247 | ||
| 2273 | /* If this command is remapped, then it has no key bindings | 2248 | /* If this command is remapped, then it has no key bindings |
| 2274 | of its own. */ | 2249 | of its own. */ |
| 2275 | if (NILP (no_remap) && is_command_symbol (definition) | 2250 | if (NILP (no_remap) && SYMBOLP (definition)) |
| 2276 | && !NILP (Fkey_binding (definition, Qnil, Qt))) | 2251 | { |
| 2277 | return Qnil; | 2252 | Lisp_Object tem; |
| 2253 | if (tem = Fremap_command (definition), !NILP (tem)) | ||
| 2254 | return Qnil; | ||
| 2255 | } | ||
| 2278 | 2256 | ||
| 2279 | found = keymaps; | 2257 | found = keymaps; |
| 2280 | while (CONSP (found)) | 2258 | while (CONSP (found)) |
| @@ -2383,37 +2361,32 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap) | |||
| 2383 | 2361 | ||
| 2384 | while (!NILP (sequences)) | 2362 | while (!NILP (sequences)) |
| 2385 | { | 2363 | { |
| 2386 | Lisp_Object sequence; | 2364 | Lisp_Object sequence, remapped, function; |
| 2387 | Lisp_Object remapped; | ||
| 2388 | 2365 | ||
| 2389 | sequence = XCAR (sequences); | 2366 | sequence = XCAR (sequences); |
| 2390 | sequences = XCDR (sequences); | 2367 | sequences = XCDR (sequences); |
| 2391 | 2368 | ||
| 2392 | /* If the current sequence is of the form [command], | 2369 | /* If the current sequence is a command remapping with |
| 2393 | this may be a remapped command, so look for the key | 2370 | format [remap COMMAND], find the key sequences |
| 2394 | sequences which run that command, and return those | 2371 | which run COMMAND, and use those sequences instead. */ |
| 2395 | sequences instead. */ | ||
| 2396 | remapped = Qnil; | 2372 | remapped = Qnil; |
| 2397 | if (NILP (no_remap) | 2373 | if (NILP (no_remap) |
| 2398 | && VECTORP (sequence) && XVECTOR (sequence)->size == 1) | 2374 | && VECTORP (sequence) && XVECTOR (sequence)->size == 2 |
| 2375 | && EQ (AREF (sequence, 0), Qremap) | ||
| 2376 | && (function = AREF (sequence, 1), SYMBOLP (function))) | ||
| 2399 | { | 2377 | { |
| 2400 | Lisp_Object function; | 2378 | Lisp_Object remapped1; |
| 2401 | 2379 | ||
| 2402 | function = AREF (sequence, 0); | 2380 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); |
| 2403 | if (is_command_symbol (function)) | 2381 | if (CONSP (remapped1)) |
| 2404 | { | 2382 | { |
| 2405 | Lisp_Object remapped1; | 2383 | /* Verify that this key binding actually maps to the |
| 2406 | remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); | 2384 | remapped command (see below). */ |
| 2407 | if (CONSP (remapped1)) | 2385 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) |
| 2408 | { | 2386 | continue; |
| 2409 | /* Verify that this key binding actually maps to the | 2387 | sequence = XCAR (remapped1); |
| 2410 | remapped command (see below). */ | 2388 | remapped = XCDR (remapped1); |
| 2411 | if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) | 2389 | goto record_sequence; |
| 2412 | continue; | ||
| 2413 | sequence = XCAR (remapped1); | ||
| 2414 | remapped = XCDR (remapped1); | ||
| 2415 | goto record_sequence; | ||
| 2416 | } | ||
| 2417 | } | 2390 | } |
| 2418 | } | 2391 | } |
| 2419 | 2392 | ||
| @@ -3646,6 +3619,12 @@ and applies even for keys that have ordinary bindings. */); | |||
| 3646 | Qmenu_item = intern ("menu-item"); | 3619 | Qmenu_item = intern ("menu-item"); |
| 3647 | staticpro (&Qmenu_item); | 3620 | staticpro (&Qmenu_item); |
| 3648 | 3621 | ||
| 3622 | Qremap = intern ("remap"); | ||
| 3623 | staticpro (&Qremap); | ||
| 3624 | |||
| 3625 | remap_command_vector = Fmake_vector (make_number (2), Qremap); | ||
| 3626 | staticpro (&remap_command_vector); | ||
| 3627 | |||
| 3649 | where_is_cache_keymaps = Qt; | 3628 | where_is_cache_keymaps = Qt; |
| 3650 | where_is_cache = Qnil; | 3629 | where_is_cache = Qnil; |
| 3651 | staticpro (&where_is_cache); | 3630 | staticpro (&where_is_cache); |
| @@ -3658,6 +3637,7 @@ and applies even for keys that have ordinary bindings. */); | |||
| 3658 | defsubr (&Smake_keymap); | 3637 | defsubr (&Smake_keymap); |
| 3659 | defsubr (&Smake_sparse_keymap); | 3638 | defsubr (&Smake_sparse_keymap); |
| 3660 | defsubr (&Scopy_keymap); | 3639 | defsubr (&Scopy_keymap); |
| 3640 | defsubr (&Sremap_command); | ||
| 3661 | defsubr (&Skey_binding); | 3641 | defsubr (&Skey_binding); |
| 3662 | defsubr (&Slocal_key_binding); | 3642 | defsubr (&Slocal_key_binding); |
| 3663 | defsubr (&Sglobal_key_binding); | 3643 | defsubr (&Sglobal_key_binding); |