aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKim F. Storm2002-02-23 22:00:37 +0000
committerKim F. Storm2002-02-23 22:00:37 +0000
commita1df473f03585f099f2921bcf268294349941630 (patch)
tree01bec0a3942287379213ea0d2cf7a30e5a54edc8 /src
parent0edda6b89df6af82bb35b02f3aa79278805bd3cf (diff)
downloademacs-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.c158
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. */
90Lisp_Object Vdefine_key_rebound_commands; 90Lisp_Object Vdefine_key_rebound_commands;
91 91
92Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item; 92Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap;
93 93
94/* Alist of elements like (DEL . "\d"). */ 94/* Alist of elements like (DEL . "\d"). */
95static Lisp_Object exclude_keys; 95static Lisp_Object exclude_keys;
96 96
97/* Pre-allocated 2-element vector for Fremap_command to use. */
98static 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
975If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at 978If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at
976the front of KEYMAP. 979the front of KEYMAP. */)
977
978KEY may also be a command name which is remapped to DEF. In this case,
979DEF 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
1067DEFUN ("remap-command", Fremap_command, Sremap_command, 1, 1, 0,
1068 doc: /* Return the remapping for command COMMAND in current keymaps.
1069Returns 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. */
1391int
1392is_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
1426DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, 1403DEFUN ("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);