changeset 3952:f9dfc2872fb0

(describe_map_tree): Insert key_heading here. New arg TITLE. (describe_buffer_bindings): Corresponding changes. (shadow_lookup): New function. (describe_map_2): Call it. SHADOW is now a list of maps. (describe_vector): Likewise. (describe_map): SHADOW is now a list of maps. (describe_map_tree): Likewise. (describe_buffer_bindings): Build suitable list to pass as SHADOW. (Faccessible_keymaps): New arg PREFIX. Callers changed. (describe_map_tree): New arg PREFIX. (Fdescribe_bindings): New arg PREFIX. Pass to describe_buffer_bindings along with buffer. (describe_buffer_bindings): Extract PREFIX and pass along.
author Richard M. Stallman <rms@gnu.org>
date Fri, 02 Jul 1993 05:21:05 +0000
parents 9da0fb7d815e
children d0c23febc08c
files src/keymap.c
diffstat 1 files changed, 156 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/src/keymap.c	Fri Jul 02 04:00:38 1993 +0000
+++ b/src/keymap.c	Fri Jul 02 05:21:05 1993 +0000
@@ -1044,15 +1044,19 @@
 /* Help functions for describing and documenting keymaps.		*/
 
 DEFUN ("accessible-keymaps", Faccessible_keymaps, Saccessible_keymaps,
-  1, 1, 0,
+  1, 2, 0,
   "Find all keymaps accessible via prefix characters from KEYMAP.\n\
 Returns a list of elements of the form (KEYS . MAP), where the sequence\n\
 KEYS starting from KEYMAP gets you to MAP.  These elements are ordered\n\
 so that the KEYS increase in length.  The first element is (\"\" . KEYMAP).")
-  (startmap)
-     Lisp_Object startmap;
+  (startmap, prefix)
+     Lisp_Object startmap, prefix;
 {
-  Lisp_Object maps, tail;
+  Lisp_Object maps, good_maps, tail;
+  int prefixlen = 0;
+
+  if (!NILP (prefix))
+    prefixlen = XINT (Flength (prefix));
 
   maps = Fcons (Fcons (Fmake_vector (make_number (0), Qnil),
 		       get_keymap (startmap)),
@@ -1131,7 +1135,7 @@
 	  else if (CONSP (elt))
 	    {
 	      register Lisp_Object cmd = get_keyelt (XCONS (elt)->cdr);
-	      register Lisp_Object tem;
+	      register Lisp_Object tem, filter;
 
 	      /* Ignore definitions that aren't keymaps themselves.  */
 	      tem = Fkeymapp (cmd);
@@ -1142,7 +1146,7 @@
 		  tem = Frassq (cmd, maps);
 		  if (NILP (tem))
 		    {
-		      /* let elt be the event defined by this map entry.  */
+		      /* Let elt be the event defined by this map entry.  */
 		      elt = XCONS (elt)->car;
 
 		      /* If the last key in thisseq is meta-prefix-char, and
@@ -1157,8 +1161,8 @@
 			  /* This new sequence is the same length as
 			     thisseq, so stick it in the list right
 			     after this one.  */
-			  XCONS (tail)->cdr =
-			    Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
+			  XCONS (tail)->cdr
+			    = Fcons (Fcons (tem, cmd), XCONS (tail)->cdr);
 			}
 		      else
 			nconc2 (tail,
@@ -1170,7 +1174,35 @@
 	}
     }
 
-  return maps;
+  if (NILP (prefix))
+    return maps;
+
+  /* Now find just the maps whose access prefixes start with PREFIX.  */
+
+  good_maps = Qnil;
+  for (; CONSP (maps); maps = XCONS (maps)->cdr)
+    {
+      Lisp_Object elt, thisseq;
+      elt = XCONS (maps)->car;
+      thisseq = XCONS (elt)->car;
+      /* The access prefix must be at least as long as PREFIX,
+	 and the first elements must match those of PREFIX.  */
+      if (XINT (Flength (thisseq)) >= prefixlen)
+	{
+	  int i;
+	  for (i = 0; i < prefixlen; i++)
+	    {
+	      Lisp_Object i1;
+	      XFASTINT (i1) = i;
+	      if (!EQ (Faref (thisseq, i1), Faref (prefix, i1)))
+		break;
+	    }
+	  if (i == prefixlen)
+	    good_maps = Fcons (elt, good_maps);
+	}
+    }
+
+  return Fnreverse (good_maps);
 }
 
 Lisp_Object Qsingle_key_description, Qkey_description;
@@ -1424,10 +1456,10 @@
     global_keymap = current_global_map;
 
   if (!NILP (local_keymap))
-    maps = nconc2 (Faccessible_keymaps (get_keymap (local_keymap)),
-		   Faccessible_keymaps (get_keymap (global_keymap)));
+    maps = nconc2 (Faccessible_keymaps (get_keymap (local_keymap), Qnil),
+		   Faccessible_keymaps (get_keymap (global_keymap), Qnil));
   else
-    maps = Faccessible_keymaps (get_keymap (global_keymap));
+    maps = Faccessible_keymaps (get_keymap (global_keymap), Qnil);
 
   found = Qnil;
 
@@ -1616,35 +1648,40 @@
 
 /* describe-bindings - summarizing all the bindings in a set of keymaps.  */
 
-DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 0, "",
+DEFUN ("describe-bindings", Fdescribe_bindings, Sdescribe_bindings, 0, 1, "",
   "Show a list of all defined keys, and their definitions.\n\
-The list is put in a buffer, which is displayed.")
-  ()
+The list is put in a buffer, which is displayed.\n\
+An optional argument PREFIX, if non-nil, should be a key sequence;\n\
+then we display only bindings that start with that prefix.")
+  (prefix)
+     Lisp_Object prefix;
 {
   register Lisp_Object thisbuf;
   XSET (thisbuf, Lisp_Buffer, current_buffer);
   internal_with_output_to_temp_buffer ("*Help*",
 				       describe_buffer_bindings,
-				       thisbuf);
+				       Fcons (thisbuf, prefix));
   return Qnil;
 }
 
+/* ARG is (BUFFER . PREFIX).  */
+
 static Lisp_Object
-describe_buffer_bindings (descbuf)
-     Lisp_Object descbuf;
+describe_buffer_bindings (arg)
+     Lisp_Object arg;
 {
+  Lisp_Object descbuf, prefix, shadow;
   register Lisp_Object start1, start2;
 
-  char *key_heading
-    = "\
-key             binding\n\
----             -------\n";
   char *alternate_heading
     = "\
 Alternate Characters (use anywhere the nominal character is listed):\n\
 nominal         alternate\n\
 -------         ---------\n";
 
+  descbuf = XCONS (arg)->car;
+  prefix = XCONS (arg)->cdr;
+
   Fset_buffer (Vstandard_output);
 
   /* Report on alternates for keys.  */
@@ -1681,6 +1718,9 @@
   {
     int i, nmaps;
     Lisp_Object *modes, *maps;
+    Lisp_Object shadow;
+
+    shadow = Qnil;
 
     /* Temporarily switch to descbuf, so that we can get that buffer's
        minor modes correctly.  */
@@ -1688,6 +1728,9 @@
     nmaps = current_minor_maps (&modes, &maps);
     Fset_buffer (Vstandard_output);
 
+    shadow = Qnil;
+
+    /* Print the minor mode maps.  */
     for (i = 0; i < nmaps; i++)
       {
 	if (XTYPE (modes[i]) == Lisp_Symbol)
@@ -1699,26 +1742,24 @@
 	else
 	  insert_string ("Strangely Named");
 	insert_string (" Minor Mode Bindings:\n");
-	insert_string (key_heading);
-	describe_map_tree (maps[i], 0, Qnil);
+	describe_map_tree (maps[i], 0, shadow, prefix, 0);
+	shadow = Fcons (maps[i], shadow);
 	insert_char ('\n');
       }
   }
 
+  /* Print the (major mode) local map.  */
   start1 = XBUFFER (descbuf)->keymap;
   if (!NILP (start1))
     {
-      insert_string ("Local Bindings:\n");
-      insert_string (key_heading);
-      describe_map_tree (start1, 0, Qnil);
+      describe_map_tree (start1, 0, shadow, prefix,
+			 "Major Mode Bindings:\n");
+      shadow = Fcons (start1, shadow);
       insert_string ("\n");
     }
 
-  insert_string ("Global Bindings:\n");
-  if (NILP (start1))
-    insert_string (key_heading);
-
-  describe_map_tree (current_global_map, 0, XBUFFER (descbuf)->keymap);
+  describe_map_tree (current_global_map, 0, shadow, prefix,
+		     "Global Bindings:\n");
 
   Fset_buffer (descbuf);
   return Qnil;
@@ -1728,55 +1769,79 @@
     followed by those of all maps reachable through STARTMAP.
    If PARTIAL is nonzero, omit certain "uninteresting" commands
     (such as `undefined').
-   If SHADOW is non-nil, it is another map;
-    don't mention keys which would be shadowed by it.  */
+   If SHADOW is non-nil, it is a list of maps;
+    don't mention keys which would be shadowed by any of them.
+   PREFIX, if non-nil, says mention only keys that start with PREFIX.
+   TITLE, if not 0, is a string to insert at the beginning.  */
 
 void
-describe_map_tree (startmap, partial, shadow)
-     Lisp_Object startmap, shadow;
+describe_map_tree (startmap, partial, shadow, prefix, title)
+     Lisp_Object startmap, shadow, prefix;
      int partial;
+     char *title;
 {
-  register Lisp_Object elt, sh;
   Lisp_Object maps;
   struct gcpro gcpro1;
+  char *key_heading
+    = "\
+key             binding\n\
+---             -------\n";
 
-  maps = Faccessible_keymaps (startmap);
+  maps = Faccessible_keymaps (startmap, prefix);
   GCPRO1 (maps);
 
+  if (!NILP (maps))
+    {
+      if (title)
+	insert_string (title);
+      insert_string (key_heading);
+    }
+
   for (; !NILP (maps); maps = Fcdr (maps))
     {
+      register Lisp_Object elt, prefix, sub_shadows, tail;
+
       elt = Fcar (maps);
-      sh = Fcar (elt);
+      prefix = Fcar (elt);
 
-      /* If there is no shadow keymap given, don't shadow.  */
-      if (NILP (shadow))
-	sh = Qnil;
+      sub_shadows = Qnil;
+
+      for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
+	{
+	  Lisp_Object shmap;
+
+	  shmap = XCONS (tail)->car;
 
-      /* If the sequence by which we reach this keymap is zero-length,
-	 then the shadow map for this keymap is just SHADOW.  */
-      else if ((XTYPE (sh) == Lisp_String
-		&& XSTRING (sh)->size == 0)
-	       || (XTYPE (sh) == Lisp_Vector
-		   && XVECTOR (sh)->size == 0))
-	sh = shadow;
+	  /* If the sequence by which we reach this keymap is zero-length,
+	     then the shadow map for this keymap is just SHADOW.  */
+	  if ((XTYPE (prefix) == Lisp_String
+	       && XSTRING (prefix)->size == 0)
+	      || (XTYPE (prefix) == Lisp_Vector
+		  && XVECTOR (prefix)->size == 0))
+	    ;
+	  /* If the sequence by which we reach this keymap actually has
+	     some elements, then the sequence's definition in SHADOW is
+	     what we should use.  */
+	  else
+	    {
+	      shmap = Flookup_key (shadow, Fcar (elt), Qt);
+	      if (XTYPE (shmap) == Lisp_Int)
+		shmap = Qnil;
+	    }
 
-      /* If the sequence by which we reach this keymap actually has
-	 some elements, then the sequence's definition in SHADOW is
-	 what we should use.  */
-      else
-	{
-	  sh = Flookup_key (shadow, Fcar (elt), Qt);
-	  if (XTYPE (sh) == Lisp_Int)
-	    sh = Qnil;
+	  /* If shmap is not nil and not a keymap,
+	     it completely shadows this map, so don't
+	     describe this map at all.  */
+	  if (!NILP (shmap) && NILP (Fkeymapp (shmap)))
+	    goto skip;
+
+	  if (!NILP (shmap))
+	    sub_shadows = Fcons (shmap, sub_shadows);
 	}
 
-      /* If sh is null (meaning that the current map is not shadowed),
-	 or a keymap (meaning that bindings from the current map might
-	 show through), describe the map.  Otherwise, sh is a command
-	 that completely shadows the current map, and we shouldn't
-	 bother.  */
-      if (NILP (sh) || !NILP (Fkeymapp (sh)))
-	describe_map (Fcdr (elt), Fcar (elt), partial, sh);
+      describe_map (Fcdr (elt), Fcar (elt), partial, sub_shadows);
+
+    skip: ;
     }
 
   UNGCPRO;
@@ -1831,6 +1896,24 @@
   describe_map_2 (map, keysdesc, describe_command, partial, shadow);
 }
 
+/* Like Flookup_key, but uses a list of keymaps SHADOW instead of a single map.
+   Returns the first non-nil binding found in any of those maps.  */
+
+static Lisp_Object
+shadow_lookup (shadow, key, flag)
+     Lisp_Object shadow, key, flag;
+{
+  Lisp_Object tail, value;
+
+  for (tail = shadow; CONSP (tail); tail = XCONS (tail)->cdr)
+    {
+      value = Flookup_key (XCONS (tail)->car, key, flag);
+      if (!NILP (value))
+	return value;
+    }
+  return Qnil;
+}
+
 /* Insert a description of KEYMAP into the current buffer.  */
 
 static void
@@ -1841,7 +1924,7 @@
      int partial;
      Lisp_Object shadow;
 {
-  Lisp_Object definition, event;
+  Lisp_Object tail, definition, event;
   Lisp_Object tem;
   Lisp_Object suppress;
   Lisp_Object kludge;
@@ -1859,17 +1942,17 @@
 
   GCPRO3 (elt_prefix, definition, kludge);
 
-  for (; CONSP (keymap); keymap = Fcdr (keymap))
+  for (tail = XCONS (keymap)->cdr; CONSP (tail); tail = Fcdr (tail))
     {
       QUIT;
 
-      if (XTYPE (XCONS (keymap)->car) == Lisp_Vector)
-	describe_vector (XCONS (keymap)->car,
+      if (XTYPE (XCONS (tail)->car) == Lisp_Vector)
+	describe_vector (XCONS (tail)->car,
 			 elt_prefix, elt_describer, partial, shadow);
       else
 	{
-	  event = Fcar_safe (Fcar (keymap));
-	  definition = get_keyelt (Fcdr_safe (Fcar (keymap)));
+	  event = Fcar_safe (Fcar (tail));
+	  definition = get_keyelt (Fcdr_safe (Fcar (tail)));
 
 	  /* Don't show undefined commands or suppressed commands.  */
 	  if (NILP (definition)) continue;
@@ -1886,11 +1969,11 @@
 	  XVECTOR (kludge)->contents[0] = event;
 	  if (!NILP (shadow))
 	    {
-	      tem = Flookup_key (shadow, kludge, Qt);
+	      tem = shadow_lookup (shadow, kludge, Qt);
 	      if (!NILP (tem)) continue;
 	    }
 
-	  tem = Flookup_key (map, kludge, Qt);
+	  tem = Flookup_key (keymap, kludge, Qt);
 	  if (! EQ (tem, definition)) continue;
 
 	  if (first)
@@ -1988,7 +2071,7 @@
 	  Lisp_Object tem;
 	  
 	  XVECTOR (kludge)->contents[0] = make_number (i);
-	  tem = Flookup_key (shadow, kludge, Qt);
+	  tem = shadow_lookup (shadow, kludge, Qt);
 
 	  if (!NILP (tem)) continue;
 	}