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. */
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;
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);
}
}
+/* 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. */
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);
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,
/* 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;
}
/* 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))
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;
+ Lisp_Object remapped1;
- function = AREF (sequence, 0);
- if (is_command_symbol (function))
+ 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;
}
}
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);
defsubr (&Smake_keymap);
defsubr (&Smake_sparse_keymap);
defsubr (&Scopy_keymap);
+ defsubr (&Sremap_command);
defsubr (&Skey_binding);
defsubr (&Slocal_key_binding);
defsubr (&Sglobal_key_binding);