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);