Mercurial > emacs
changeset 43494:b5b76b498398
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.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Sat, 23 Feb 2002 22:00:37 +0000 |
parents | dcf4af6ac385 |
children | 3c0d7fbc071a |
files | src/keymap.c |
diffstat | 1 files changed, 70 insertions(+), 90 deletions(-) [+] |
line wrap: on
line diff
--- a/src/keymap.c Sat Feb 23 21:35:34 2002 +0000 +++ b/src/keymap.c Sat Feb 23 22:00:37 2002 +0000 @@ -89,11 +89,14 @@ when Emacs starts up. t means don't record anything here. */ Lisp_Object Vdefine_key_rebound_commands; -Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item; +Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap; /* Alist of elements like (DEL . "\d"). */ static Lisp_Object exclude_keys; +/* Pre-allocated 2-element vector for Fremap_command to use. */ +static Lisp_Object remap_command_vector; + /* A char with the CHAR_META bit set in a vector or the 0200 bit set in a string key sequence is equivalent to prefixing with this character. */ @@ -973,10 +976,7 @@ or a cons (KEYMAP . CHAR), meaning use definition of CHAR in map KEYMAP. If KEYMAP is a sparse keymap, the pair binding KEY to DEF is added at -the front of KEYMAP. - -KEY may also be a command name which is remapped to DEF. In this case, -DEF must be a symbol or nil (to remove a previous binding of KEY). */) +the front of KEYMAP. */) (keymap, key, def) Lisp_Object keymap; Lisp_Object key; @@ -992,29 +992,18 @@ keymap = get_keymap (keymap, 1, 1); - if (SYMBOLP (key)) - { - /* A command may only be remapped to another command. */ - - /* I thought of using is_command_symbol above and below instead - of SYMBOLP, since remapping only works for sych symbols. - However, to make that a requirement would make it impossible - to remap a command before it has been defined, e.g. if a minor - mode were to remap a command of another minor mode which has - not yet been loaded, it would fail. So just use the least - restrictive sanity check here. */ - if (!SYMBOLP (def)) - key = wrong_type_argument (Qsymbolp, def); - else - key = Fmake_vector (make_number (1), key); - } - else if (!VECTORP (key) && !STRINGP (key)) + if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); length = XFASTINT (Flength (key)); if (length == 0) return Qnil; + /* Check for valid [remap COMMAND] bindings. */ + if (VECTORP (key) && EQ (AREF (key, 0), Qremap) + && (length != 2 || !SYMBOLP (AREF (key, 1)))) + wrong_type_argument (Qvectorp, key); + if (SYMBOLP (def) && !EQ (Vdefine_key_rebound_commands, Qt)) Vdefine_key_rebound_commands = Fcons (def, Vdefine_key_rebound_commands); @@ -1073,6 +1062,19 @@ } } +/* This function may GC (it calls Fkey_binding). */ + +DEFUN ("remap-command", Fremap_command, Sremap_command, 1, 1, 0, + doc: /* Return the remapping for command COMMAND in current keymaps. +Returns nil if COMMAND is not remapped. */) + (command) + Lisp_Object command; +{ + /* This will GCPRO the command argument. */ + ASET (remap_command_vector, 1, command); + return Fkey_binding (remap_command_vector, Qnil, Qt); +} + /* Value is number if KEY is too long; nil if valid but has no definition. */ /* GC is possible in this function if it autoloads a keymap. */ @@ -1105,9 +1107,19 @@ keymap = get_keymap (keymap, 1, 1); - /* Command remapping is simple. */ - if (SYMBOLP (key)) - return access_keymap (keymap, key, t_ok, 0, 1); + /* Perform command remapping initiated by Fremap_command directly. + This is strictly not necessary, but it is faster and it returns + nil instead of 1 if KEYMAP doesn't contain command remappings. */ + if (EQ (key, remap_command_vector)) + { + /* KEY has format [remap COMMAND]. + Lookup `remap' in KEYMAP; result is nil or a keymap containing + command remappings. Then lookup COMMAND in that keymap. */ + if ((keymap = access_keymap (keymap, Qremap, t_ok, 0, 1), !NILP (keymap)) + && (keymap = get_keymap (keymap, 0, 1), CONSP (keymap))) + return access_keymap (keymap, AREF (key, 1), t_ok, 0, 1); + return Qnil; + } if (!VECTORP (key) && !STRINGP (key)) key = wrong_type_argument (Qarrayp, key); @@ -1386,41 +1398,6 @@ return keymaps; } -/* Like Fcommandp, but looks specifically for a command symbol, and - doesn't signal errors. Returns 1 if FUNCTION is a command symbol. */ -int -is_command_symbol (function) - Lisp_Object function; -{ - if (!SYMBOLP (function) || EQ (function, Qunbound)) - return 0; - - function = indirect_function (function); - if (SYMBOLP (function) && EQ (function, Qunbound)) - return 0; - - if (SUBRP (function)) - return (XSUBR (function)->prompt != 0); - - if (COMPILEDP (function)) - return ((ASIZE (function) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE); - - if (CONSP (function)) - { - Lisp_Object funcar; - - funcar = Fcar (function); - if (SYMBOLP (funcar)) - { - if (EQ (funcar, Qlambda)) - return !NILP (Fassq (Qinteractive, Fcdr (Fcdr (function)))); - if (EQ (funcar, Qautoload)) - return !NILP (Fcar (Fcdr (Fcdr (Fcdr (function))))); - } - } - return 0; -} - /* GC is possible in this function if it autoloads a keymap. */ DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0, @@ -1503,12 +1480,10 @@ /* If the result of the ordinary keymap lookup is an interactive command, look for a key binding (ie. remapping) for that command. */ - if (NILP (no_remap) && is_command_symbol (value)) + if (NILP (no_remap) && SYMBOLP (value)) { Lisp_Object value1; - - value1 = Fkey_binding (value, accept_default, Qt); - if (!NILP (value1) && is_command_symbol (value1)) + if (value1 = Fremap_command (value), !NILP (value1)) value = value1; } @@ -2272,9 +2247,12 @@ /* If this command is remapped, then it has no key bindings of its own. */ - if (NILP (no_remap) && is_command_symbol (definition) - && !NILP (Fkey_binding (definition, Qnil, Qt))) - return Qnil; + if (NILP (no_remap) && SYMBOLP (definition)) + { + Lisp_Object tem; + if (tem = Fremap_command (definition), !NILP (tem)) + return Qnil; + } found = keymaps; while (CONSP (found)) @@ -2383,37 +2361,32 @@ while (!NILP (sequences)) { - Lisp_Object sequence; - Lisp_Object remapped; + Lisp_Object sequence, remapped, function; sequence = XCAR (sequences); sequences = XCDR (sequences); - /* If the current sequence is of the form [command], - this may be a remapped command, so look for the key - sequences which run that command, and return those - sequences instead. */ + /* If the current sequence is a command remapping with + format [remap COMMAND], find the key sequences + which run COMMAND, and use those sequences instead. */ remapped = Qnil; if (NILP (no_remap) - && VECTORP (sequence) && XVECTOR (sequence)->size == 1) + && VECTORP (sequence) && XVECTOR (sequence)->size == 2 + && EQ (AREF (sequence, 0), Qremap) + && (function = AREF (sequence, 1), SYMBOLP (function))) { - Lisp_Object function; - - function = AREF (sequence, 0); - if (is_command_symbol (function)) + Lisp_Object remapped1; + + remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); + if (CONSP (remapped1)) { - Lisp_Object remapped1; - remapped1 = where_is_internal (function, keymaps, firstonly, noindirect, Qt); - if (CONSP (remapped1)) - { - /* Verify that this key binding actually maps to the - remapped command (see below). */ - if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) - continue; - sequence = XCAR (remapped1); - remapped = XCDR (remapped1); - goto record_sequence; - } + /* Verify that this key binding actually maps to the + remapped command (see below). */ + if (!EQ (shadow_lookup (keymaps, XCAR (remapped1), Qnil), function)) + continue; + sequence = XCAR (remapped1); + remapped = XCDR (remapped1); + goto record_sequence; } } @@ -3646,6 +3619,12 @@ Qmenu_item = intern ("menu-item"); staticpro (&Qmenu_item); + Qremap = intern ("remap"); + staticpro (&Qremap); + + remap_command_vector = Fmake_vector (make_number (2), Qremap); + staticpro (&remap_command_vector); + where_is_cache_keymaps = Qt; where_is_cache = Qnil; staticpro (&where_is_cache); @@ -3658,6 +3637,7 @@ defsubr (&Smake_keymap); defsubr (&Smake_sparse_keymap); defsubr (&Scopy_keymap); + defsubr (&Sremap_command); defsubr (&Skey_binding); defsubr (&Slocal_key_binding); defsubr (&Sglobal_key_binding);