(Fkey_description): Add optional PREFIX arg.
authorKim F. Storm <storm@cua.dk>
Fri, 16 Apr 2004 21:16:33 +0000 (21:16 +0000)
committerKim F. Storm <storm@cua.dk>
Fri, 16 Apr 2004 21:16:33 +0000 (21:16 +0000)
Combine prefix with KEYS to make up the full key sequence to describe.
Correlate meta_prefix_char and following (simple) key to describe
as meta modifier.  All callers changed.
(describe_map): Rename arg `keys' to `prefix'.  Remove local
`elt_prefix' var.  Use Fkey_description with prefix instead of
elt_prefix combined with Fsingle_key_description.
(describe_vector): Declare static.  Replace arg `elt_prefix' with
`prefix'.  Add KEYMAP_P arg.  Add local var `elt_prefix'; use it
if !KEYMAP_P. Use Fkey_description with prefix instead of
Fsingle_key_description.

src/keymap.c

index b181c3c..c9991c1 100644 (file)
@@ -121,6 +121,9 @@ static void describe_translation P_ ((Lisp_Object, Lisp_Object));
 static void describe_map P_ ((Lisp_Object, Lisp_Object,
                              void (*) P_ ((Lisp_Object, Lisp_Object)),
                              int, Lisp_Object, Lisp_Object*, int));
+static void describe_vector P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+                                void (*) (Lisp_Object, Lisp_Object), int,
+                                Lisp_Object, Lisp_Object, int *, int, int));
 static void silly_event_symbol_error P_ ((Lisp_Object));
 \f
 /* Keymap object support - constructors and predicates.                        */
@@ -687,7 +690,7 @@ map_keymap (map, fun, args, data, autoload)
        tail = XCDR (tail))
     {
       Lisp_Object binding = XCAR (tail);
-      
+
       if (CONSP (binding))
        map_keymap_item (fun, args, XCAR (binding), XCDR (binding), data);
       else if (VECTORP (binding))
@@ -1160,7 +1163,7 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
        /* We must use Fkey_description rather than just passing key to
           error; key might be a vector, not a string.  */
        error ("Key sequence %s uses invalid prefix characters",
-              SDATA (Fkey_description (key)));
+              SDATA (Fkey_description (key, Qnil)));
     }
 }
 
@@ -1791,9 +1794,9 @@ accessible_keymaps_1 (key, cmd, maps, tail, thisseq, is_metized)
       int meta_bit = meta_modifier;
       Lisp_Object last = make_number (XINT (Flength (thisseq)) - 1);
       tem = Fcopy_sequence (thisseq);
-      
+
       Faset (tem, last, make_number (XINT (key) | meta_bit));
-      
+
       /* This new sequence is the same length as
         thisseq, so stick it in the list right
         after this one.  */
@@ -1944,78 +1947,109 @@ Lisp_Object Qsingle_key_description, Qkey_description;
 
 /* This function cannot GC.  */
 
-DEFUN ("key-description", Fkey_description, Skey_description, 1, 1, 0,
+DEFUN ("key-description", Fkey_description, Skey_description, 1, 2, 0,
        doc: /* Return a pretty description of key-sequence KEYS.
+Optional arg PREFIX is the sequence of keys leading up to KEYS.
 Control characters turn into "C-foo" sequences, meta into "M-foo"
 spaces are put between sequence elements, etc.  */)
-     (keys)
-     Lisp_Object keys;
+  (keys, prefix)
+     Lisp_Object keys, prefix;
 {
   int len = 0;
   int i, i_byte;
-  Lisp_Object sep;
-  Lisp_Object *args = NULL;
+  Lisp_Object *args;
+  int size = Flength (keys);
+  Lisp_Object list;
+  Lisp_Object sep = build_string (" ");
+  Lisp_Object key;
+  int add_meta = 0;
+
+  if (!NILP (prefix))
+    size += Flength (prefix);
+
+  /* This has one extra element at the end that we don't pass to Fconcat.  */
+  args = (Lisp_Object *) alloca (size * 4 * sizeof (Lisp_Object));
+
+  /* In effect, this computes
+     (mapconcat 'single-key-description keys " ")
+     but we shouldn't use mapconcat because it can do GC.  */
 
-  if (STRINGP (keys))
+ next_list:
+  if (!NILP (prefix))
+    list = prefix, prefix = Qnil;
+  else if (!NILP (keys))
+    list = keys, keys = Qnil;
+  else
     {
-      Lisp_Object vector;
-      vector = Fmake_vector (Flength (keys), Qnil);
-      for (i = 0, i_byte = 0; i < SCHARS (keys); )
+      if (add_meta)
        {
-         int c;
-         int i_before = i;
-
-         FETCH_STRING_CHAR_ADVANCE (c, keys, i, i_byte);
-         if (SINGLE_BYTE_CHAR_P (c) && (c & 0200))
-           c ^= 0200 | meta_modifier;
-         XSETFASTINT (AREF (vector, i_before), c);
+         args[len] = Fsingle_key_description (meta_prefix_char, Qnil);
+         len += 2;
        }
-      keys = vector;
+      else if (len == 0)
+       return empty_string;
+      return Fconcat (len - 1, args);
     }
 
-  if (VECTORP (keys))
-    {
-      /* In effect, this computes
-        (mapconcat 'single-key-description keys " ")
-        but we shouldn't use mapconcat because it can do GC.  */
+  if (STRINGP (list))
+    size = SCHARS (list);
+  else if (VECTORP (list))
+    size = XVECTOR (list)->size;
+  else if (CONSP (list))
+    size = Flength (list);
+  else
+    wrong_type_argument (Qarrayp, list);
 
-      len = XVECTOR (keys)->size;
-      sep = build_string (" ");
-      /* This has one extra element at the end that we don't pass to Fconcat.  */
-      args = (Lisp_Object *) alloca (len * 2 * sizeof (Lisp_Object));
+  i = i_byte = 0;
 
-      for (i = 0; i < len; i++)
+  while (i < size)
+    {
+      if (STRINGP (list))
        {
-         args[i * 2] = Fsingle_key_description (AREF (keys, i), Qnil);
-         args[i * 2 + 1] = sep;
+         int c;
+         FETCH_STRING_CHAR_ADVANCE (c, list, i, i_byte);
+         if (SINGLE_BYTE_CHAR_P (c) && (c & 0200))
+           c ^= 0200 | meta_modifier;
+         XSETFASTINT (key, c);
+       }
+      else if (VECTORP (list))
+       {
+         key = AREF (list, i++);
+       }
+      else
+       {
+         key = XCAR (list);
+         list = XCDR (list);
+         i++;
        }
-    }
-  else if (CONSP (keys))
-    {
-      /* In effect, this computes
-        (mapconcat 'single-key-description keys " ")
-        but we shouldn't use mapconcat because it can do GC.  */
-
-      len = XFASTINT (Flength (keys));
-      sep = build_string (" ");
-      /* This has one extra element at the end that we don't pass to Fconcat.  */
-      args = (Lisp_Object *) alloca (len * 2 * sizeof (Lisp_Object));
 
-      for (i = 0; i < len; i++)
+      if (add_meta)
+       {
+         if (!INTEGERP (key)
+             || EQ (key, meta_prefix_char)
+             || (XINT (key) & meta_modifier))
+           {
+             args[len++] = Fsingle_key_description (meta_prefix_char, Qnil);
+             args[len++] = sep;
+             if (EQ (key, meta_prefix_char))
+               continue;
+           }
+         else
+           XSETINT (key, (XINT (key) | meta_modifier) & ~0x80);
+         add_meta = 0;
+       }
+      else if (EQ (key, meta_prefix_char))
        {
-         args[i * 2] = Fsingle_key_description (XCAR (keys), Qnil);
-         args[i * 2 + 1] = sep;
-         keys = XCDR (keys);
+         add_meta = 1;
+         continue;
        }
+      args[len++] = Fsingle_key_description (key, Qnil);
+      args[len++] = sep;
     }
-  else
-    keys = wrong_type_argument (Qarrayp, keys);
-
-  if (len == 0)
-    return empty_string;
-  return Fconcat (len * 2 - 1, args);
+  goto next_list;
 }
 
+
 char *
 push_key_description (c, p, force_multibyte)
      register unsigned int c;
@@ -2937,7 +2971,7 @@ key             binding\n\
          if (!NILP (prefix))
            {
              insert_string (" Starting With ");
-             insert1 (Fkey_description (prefix));
+             insert1 (Fkey_description (prefix, Qnil));
            }
          insert_string (":\n");
        }
@@ -3062,7 +3096,7 @@ describe_translation (definition, args)
     }
   else if (STRINGP (definition) || VECTORP (definition))
     {
-      insert1 (Fkey_description (definition));
+      insert1 (Fkey_description (definition, Qnil));
       insert_string ("\n");
     }
   else if (KEYMAPP (definition))
@@ -3072,20 +3106,19 @@ describe_translation (definition, args)
 }
 
 /* Describe the contents of map MAP, assuming that this map itself is
-   reached by the sequence of prefix keys KEYS (a string or vector).
+   reached by the sequence of prefix keys PREFIX (a string or vector).
    PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above.  */
 
 static void
-describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
+describe_map (map, prefix, elt_describer, partial, shadow, seen, nomenu)
      register Lisp_Object map;
-     Lisp_Object keys;
+     Lisp_Object prefix;
      void (*elt_describer) P_ ((Lisp_Object, Lisp_Object));
      int partial;
      Lisp_Object shadow;
      Lisp_Object *seen;
      int nomenu;
 {
-  Lisp_Object elt_prefix;
   Lisp_Object tail, definition, event;
   Lisp_Object tem;
   Lisp_Object suppress;
@@ -3095,15 +3128,6 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
 
   suppress = Qnil;
 
-  if (!NILP (keys) && XFASTINT (Flength (keys)) > 0)
-    {
-      /* Call Fkey_description first, to avoid GC bug for the other string.  */
-      tem = Fkey_description (keys);
-      elt_prefix = concat2 (tem, build_string (" "));
-    }
-  else
-    elt_prefix = Qnil;
-
   if (partial)
     suppress = intern ("suppress-keymap");
 
@@ -3113,7 +3137,7 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
   kludge = Fmake_vector (make_number (1), Qnil);
   definition = Qnil;
 
-  GCPRO3 (elt_prefix, definition, kludge);
+  GCPRO3 (prefix, definition, kludge);
 
   for (tail = map; CONSP (tail); tail = XCDR (tail))
     {
@@ -3122,13 +3146,13 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
       if (VECTORP (XCAR (tail))
          || CHAR_TABLE_P (XCAR (tail)))
        describe_vector (XCAR (tail),
-                        elt_prefix, Qnil, elt_describer, partial, shadow, map,
-                        (int *)0, 0);
+                        prefix, Qnil, elt_describer, partial, shadow, map,
+                        (int *)0, 0, 1);
       else if (CONSP (XCAR (tail)))
        {
          event = XCAR (XCAR (tail));
 
-         /* Ignore bindings whose "keys" are not really valid events.
+         /* Ignore bindings whose "prefix" are not really valid events.
             (We get these in the frames and buffers menu.)  */
          if (!(SYMBOLP (event) || INTEGERP (event)))
            continue;
@@ -3167,11 +3191,8 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
              first = 0;
            }
 
-         if (!NILP (elt_prefix))
-           insert1 (elt_prefix);
-
          /* THIS gets the string to describe the character EVENT.  */
-         insert1 (Fsingle_key_description (event, Qnil));
+         insert1 (Fkey_description (kludge, prefix));
 
          /* Print a description of the definition of this character.
             elt_describer will take care of spacing out far enough
@@ -3184,9 +3205,9 @@ describe_map (map, keys, elt_describer, partial, shadow, seen, nomenu)
             using an inherited keymap.  So skip anything we've already
             encountered.  */
          tem = Fassq (tail, *seen);
-         if (CONSP (tem) && !NILP (Fequal (XCAR (tem), keys)))
+         if (CONSP (tem) && !NILP (Fequal (XCAR (tem), prefix)))
            break;
-         *seen = Fcons (Fcons (tail, keys), *seen);
+         *seen = Fcons (Fcons (tail, prefix), *seen);
        }
     }
 
@@ -3214,7 +3235,7 @@ This is text showing the elements of vector matched against indices.  */)
   specbind (Qstandard_output, Fcurrent_buffer ());
   CHECK_VECTOR_OR_CHAR_TABLE (vector);
   describe_vector (vector, Qnil, describer, describe_vector_princ, 0,
-                  Qnil, Qnil, (int *)0, 0);
+                  Qnil, Qnil, (int *)0, 0, 0);
 
   return unbind_to (count, Qnil);
 }
@@ -3249,28 +3270,32 @@ This is text showing the elements of vector matched against indices.  */)
    indices at higher levels in this char-table,
    and CHAR_TABLE_DEPTH says how many levels down we have gone.
 
+   KEYMAP_P is 1 if vector is known to be a keymap, so map ESC to M-.
+
    ARGS is simply passed as the second argument to ELT_DESCRIBER.  */
 
-void
-describe_vector (vector, elt_prefix, args, elt_describer,
+static void
+describe_vector (vector, prefix, args, elt_describer,
                 partial, shadow, entire_map,
-                indices, char_table_depth)
+                indices, char_table_depth, keymap_p)
      register Lisp_Object vector;
-     Lisp_Object elt_prefix, args;
+     Lisp_Object prefix, args;
      void (*elt_describer) P_ ((Lisp_Object, Lisp_Object));
      int partial;
      Lisp_Object shadow;
      Lisp_Object entire_map;
      int *indices;
      int char_table_depth;
+     int keymap_p;
 {
   Lisp_Object definition;
   Lisp_Object tem2;
+  Lisp_Object elt_prefix = Qnil;
   register int i;
   Lisp_Object suppress;
   Lisp_Object kludge;
   int first = 1;
-  struct gcpro gcpro1, gcpro2, gcpro3;
+  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   /* Range of elements to be handled.  */
   int from, to;
   /* A flag to tell if a leaf in this level of char-table is not a
@@ -3286,11 +3311,23 @@ describe_vector (vector, elt_prefix, args, elt_describer,
 
   definition = Qnil;
 
+  if (!keymap_p)
+    {
+      /* Call Fkey_description first, to avoid GC bug for the other string.  */
+      if (!NILP (prefix) && XFASTINT (Flength (prefix)) > 0)
+       {
+         Lisp_Object tem;
+         tem = Fkey_description (prefix, Qnil);
+         elt_prefix = concat2 (tem, build_string (" "));
+       }
+      prefix = Qnil;
+    }
+
   /* This vector gets used to present single keys to Flookup_key.  Since
      that is done once per vector element, we don't want to cons up a
      fresh vector every time.  */
   kludge = Fmake_vector (make_number (1), Qnil);
-  GCPRO3 (elt_prefix, definition, kludge);
+  GCPRO4 (elt_prefix, prefix, definition, kludge);
 
   if (partial)
     suppress = intern ("suppress-keymap");
@@ -3383,12 +3420,13 @@ describe_vector (vector, elt_prefix, args, elt_describer,
       else
        character = i;
 
+      ASET (kludge, 0, make_number (character));
+
       /* If this binding is shadowed by some other map, ignore it.  */
       if (!NILP (shadow) && complete_char)
        {
          Lisp_Object tem;
 
-         ASET (kludge, 0, make_number (character));
          tem = shadow_lookup (shadow, kludge, Qt);
 
          if (!NILP (tem)) continue;
@@ -3400,7 +3438,6 @@ describe_vector (vector, elt_prefix, args, elt_describer,
        {
          Lisp_Object tem;
 
-         ASET (kludge, 0, make_number (character));
          tem = Flookup_key (entire_map, kludge, Qt);
 
          if (!EQ (tem, definition))
@@ -3441,7 +3478,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
       else if (CHAR_TABLE_P (vector))
        {
          if (complete_char)
-           insert1 (Fsingle_key_description (make_number (character), Qnil));
+           insert1 (Fkey_description (kludge, prefix));
          else
            {
              /* Print the information for this character set.  */
@@ -3457,7 +3494,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
        }
       else
        {
-         insert1 (Fsingle_key_description (make_number (character), Qnil));
+         insert1 (Fkey_description (kludge, prefix));
        }
 
       /* If we find a sub char-table within a char-table,
@@ -3466,9 +3503,9 @@ describe_vector (vector, elt_prefix, args, elt_describer,
       if (CHAR_TABLE_P (vector) && SUB_CHAR_TABLE_P (definition))
        {
          insert ("\n", 1);
-         describe_vector (definition, elt_prefix, args, elt_describer,
+         describe_vector (definition, prefix, args, elt_describer,
                           partial, shadow, entire_map,
-                          indices, char_table_depth + 1);
+                          indices, char_table_depth + 1, keymap_p);
          continue;
        }
 
@@ -3506,6 +3543,8 @@ describe_vector (vector, elt_prefix, args, elt_describer,
        {
          insert (" .. ", 4);
 
+         ASET (kludge, 0, make_number (i));
+
          if (!NILP (elt_prefix))
            insert1 (elt_prefix);
 
@@ -3513,7 +3552,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
            {
              if (char_table_depth == 0)
                {
-                 insert1 (Fsingle_key_description (make_number (i), Qnil));
+                 insert1 (Fkey_description (kludge, prefix));
                }
              else if (complete_char)
                {
@@ -3532,7 +3571,7 @@ describe_vector (vector, elt_prefix, args, elt_describer,
            }
          else
            {
-             insert1 (Fsingle_key_description (make_number (i), Qnil));
+             insert1 (Fkey_description (kludge, prefix));
            }
        }