]> code.delx.au - gnu-emacs/blobdiff - src/keymap.c
(Fforward_comment): Detect generic comment at beginning of
[gnu-emacs] / src / keymap.c
index 4583d3121df70cebf126dc68b54d97bce4252cd1..4f8343bf5cfe0a8589c9c3a2d840b19cbfaf5db0 100644 (file)
@@ -1,7 +1,7 @@
 /* Manipulation of keymaps
    Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995,
                  1998, 1999, 2000, 2001, 2002, 2003, 2004,
-                 2005 Free Software Foundation, Inc.
+                 2005, 2006 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -68,7 +68,7 @@ Lisp_Object Vminibuffer_local_completion_map;
 /* keymap used for minibuffers when doing completion in filenames */
 Lisp_Object Vminibuffer_local_filename_completion_map;
 
-/* keymap used for minibuffers when doing completion in filenames 
+/* keymap used for minibuffers when doing completion in filenames
    with require-match*/
 Lisp_Object Vminibuffer_local_must_match_filename_map;
 
@@ -699,6 +699,7 @@ map_keymap (map, fun, args, data, autoload)
   struct gcpro gcpro1, gcpro2, gcpro3;
   Lisp_Object tail;
 
+  tail = Qnil;
   GCPRO3 (map, args, tail);
   map = get_keymap (map, 1, autoload);
   for (tail = (CONSP (map) && EQ (Qkeymap, XCAR (map))) ? XCDR (map) : map;
@@ -743,8 +744,10 @@ map_keymap_call (key, val, fun, dummy)
 }
 
 DEFUN ("map-keymap", Fmap_keymap, Smap_keymap, 2, 3, 0,
-       doc: /* Call FUNCTION for every binding in KEYMAP.
-FUNCTION is called with two arguments: the event and its binding.
+       doc: /* Call FUNCTION once for each event binding in KEYMAP.
+FUNCTION is called with two arguments: the event that is bound, and
+the definition it is bound to.
+
 If KEYMAP has a parent, the parent's bindings are included as well.
 This works recursively: if the parent has itself a parent, then the
 grandparent's bindings are also included and so on.
@@ -863,7 +866,7 @@ static Lisp_Object
 store_in_keymap (keymap, idx, def)
      Lisp_Object keymap;
      register Lisp_Object idx;
-     register Lisp_Object def;
+     Lisp_Object def;
 {
   /* Flush any reverse-map cache.  */
   where_is_cache = Qnil;
@@ -1190,8 +1193,11 @@ binding KEY to DEF is added at the front of KEYMAP.  */)
       if (!CONSP (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, Qnil)));
+       error ("Key sequence %s starts with non-prefix key %s",
+              SDATA (Fkey_description (key, Qnil)),
+              SDATA (Fkey_description (Fsubstring (key, make_number (0),
+                                                   make_number (idx)),
+                                       Qnil)));
     }
 }
 
@@ -1368,13 +1374,6 @@ silly_event_symbol_error (c)
 static Lisp_Object *cmm_modes = NULL, *cmm_maps = NULL;
 static int cmm_size = 0;
 
-/* Error handler used in current_minor_maps.  */
-static Lisp_Object
-current_minor_maps_error ()
-{
-  return Qnil;
-}
-
 /* Store a pointer to an array of the keymaps of the currently active
    minor modes in *buf, and return the number of maps it contains.
 
@@ -1476,9 +1475,7 @@ current_minor_maps (modeptr, mapptr)
              }
 
            /* Get the keymap definition--or nil if it is not defined.  */
-           temp = internal_condition_case_1 (Findirect_function,
-                                             XCDR (assoc),
-                                             Qerror, current_minor_maps_error);
+           temp = Findirect_function (XCDR (assoc), Qt);
            if (!NILP (temp))
              {
                cmm_modes[i] = var;
@@ -3174,6 +3171,34 @@ describe_translation (definition, args)
     insert_string ("??\n");
 }
 
+/* describe_map puts all the usable elements of a sparse keymap
+   into an array of `struct describe_map_elt',
+   then sorts them by the events.  */
+
+struct describe_map_elt { Lisp_Object event; Lisp_Object definition; int shadowed; };
+
+/* qsort comparison function for sorting `struct describe_map_elt' by
+   the event field.  */
+
+static int
+describe_map_compare (aa, bb)
+     const void *aa, *bb;
+{
+  const struct describe_map_elt *a = aa, *b = bb;
+  if (INTEGERP (a->event) && INTEGERP (b->event))
+    return ((XINT (a->event) > XINT (b->event))
+           - (XINT (a->event) < XINT (b->event)));
+  if (!INTEGERP (a->event) && INTEGERP (b->event))
+    return 1;
+  if (INTEGERP (a->event) && !INTEGERP (b->event))
+    return -1;
+  if (SYMBOLP (a->event) && SYMBOLP (b->event))
+    return (!NILP (Fstring_lessp (a->event, b->event)) ? -1
+           : !NILP (Fstring_lessp (b->event, a->event)) ? 1
+           : 0);
+  return 0;
+}
+
 /* Describe the contents of map MAP, assuming that this map itself is
    reached by the sequence of prefix keys PREFIX (a string or vector).
    PARTIAL, SHADOW, NOMENU are as in `describe_map_tree' above.  */
@@ -3197,6 +3222,13 @@ describe_map (map, prefix, elt_describer, partial, shadow,
   int first = 1;
   struct gcpro gcpro1, gcpro2, gcpro3;
 
+  /* These accumulate the values from sparse keymap bindings,
+     so we can sort them and handle them in order.  */
+  int length_needed = 0;
+  struct describe_map_elt *vect;
+  int slots_used = 0;
+  int i;
+
   suppress = Qnil;
 
   if (partial)
@@ -3208,6 +3240,12 @@ describe_map (map, prefix, elt_describer, partial, shadow,
   kludge = Fmake_vector (make_number (1), Qnil);
   definition = Qnil;
 
+  for (tail = map; CONSP (tail); tail = XCDR (tail))
+    length_needed++;
+
+  vect = ((struct describe_map_elt *)
+         alloca (sizeof (struct describe_map_elt) * length_needed));
+
   GCPRO3 (prefix, definition, kludge);
 
   for (tail = map; CONSP (tail); tail = XCDR (tail))
@@ -3222,6 +3260,7 @@ describe_map (map, prefix, elt_describer, partial, shadow,
       else if (CONSP (XCAR (tail)))
        {
          int this_shadowed = 0;
+
          event = XCAR (XCAR (tail));
 
          /* Ignore bindings whose "prefix" are not really valid events.
@@ -3262,27 +3301,10 @@ describe_map (map, prefix, elt_describer, partial, shadow,
          tem = Flookup_key (map, kludge, Qt);
          if (!EQ (tem, definition)) continue;
 
-         if (first)
-           {
-             previous_description_column = 0;
-             insert ("\n", 1);
-             first = 0;
-           }
-
-         /* THIS gets the string to describe the character EVENT.  */
-         insert1 (Fkey_description (kludge, prefix));
-
-         /* Print a description of the definition of this character.
-            elt_describer will take care of spacing out far enough
-            for alignment purposes.  */
-         (*elt_describer) (definition, Qnil);
-
-         if (this_shadowed)
-           {
-             SET_PT (PT - 1);
-             insert_string ("  (binding currently shadowed)");
-             SET_PT (PT + 1);
-           }
+         vect[slots_used].event = event;
+         vect[slots_used].definition = definition;
+         vect[slots_used].shadowed = this_shadowed;
+         slots_used++;
        }
       else if (EQ (XCAR (tail), Qkeymap))
        {
@@ -3296,6 +3318,68 @@ describe_map (map, prefix, elt_describer, partial, shadow,
        }
     }
 
+  /* If we found some sparse map events, sort them.  */
+
+  qsort (vect, slots_used, sizeof (struct describe_map_elt),
+        describe_map_compare);
+
+  /* Now output them in sorted order.  */
+
+  for (i = 0; i < slots_used; i++)
+    {
+      Lisp_Object start, end;
+
+      if (first)
+       {
+         previous_description_column = 0;
+         insert ("\n", 1);
+         first = 0;
+       }
+
+      ASET (kludge, 0, vect[i].event);
+      start = vect[i].event;
+      end = start;
+
+      definition = vect[i].definition;
+
+      /* Find consecutive chars that are identically defined.  */
+      if (INTEGERP (vect[i].event))
+       {
+         while (i + 1 < slots_used
+                && EQ (vect[i+1].event, make_number (XINT (vect[i].event) + 1))
+                && !NILP (Fequal (vect[i + 1].definition, definition))
+                && vect[i].shadowed == vect[i + 1].shadowed)
+           i++;
+         end = vect[i].event;
+       }
+
+      /* Now START .. END is the range to describe next.  */
+
+      /* Insert the string to describe the event START.  */
+      insert1 (Fkey_description (kludge, prefix));
+
+      if (!EQ (start, end))
+       {
+         insert (" .. ", 4);
+
+         ASET (kludge, 0, end);
+         /* Insert the string to describe the character END.  */
+         insert1 (Fkey_description (kludge, prefix));
+       }
+
+      /* Print a description of the definition of this character.
+        elt_describer will take care of spacing out far enough
+        for alignment purposes.  */
+      (*elt_describer) (vect[i].definition, Qnil);
+
+      if (vect[i].shadowed)
+       {
+         SET_PT (PT - 1);
+         insert_string ("\n  (that binding is currently shadowed by another mode)");
+         SET_PT (PT + 1);
+       }
+    }
+
   UNGCPRO;
 }
 
@@ -3793,11 +3877,11 @@ don't alter it yourself.  */);
   Vminibuffer_local_completion_map = Fmake_sparse_keymap (Qnil);
   Fset_keymap_parent (Vminibuffer_local_completion_map, Vminibuffer_local_map);
 
-  DEFVAR_LISP ("minibuffer-local-filename-completion-map", 
+  DEFVAR_LISP ("minibuffer-local-filename-completion-map",
               &Vminibuffer_local_filename_completion_map,
               doc: /* Local keymap for minibuffer input with completion for filenames.  */);
   Vminibuffer_local_filename_completion_map = Fmake_sparse_keymap (Qnil);
-  Fset_keymap_parent (Vminibuffer_local_filename_completion_map, 
+  Fset_keymap_parent (Vminibuffer_local_filename_completion_map,
                      Vminibuffer_local_completion_map);
 
 
@@ -3807,11 +3891,11 @@ don't alter it yourself.  */);
   Fset_keymap_parent (Vminibuffer_local_must_match_map,
                      Vminibuffer_local_completion_map);
 
-  DEFVAR_LISP ("minibuffer-local-must-match-filename-map", 
+  DEFVAR_LISP ("minibuffer-local-must-match-filename-map",
               &Vminibuffer_local_must_match_filename_map,
               doc: /* Local keymap for minibuffer input with completion for filenames with exact match.  */);
   Vminibuffer_local_must_match_filename_map = Fmake_sparse_keymap (Qnil);
-  Fset_keymap_parent (Vminibuffer_local_must_match_filename_map, 
+  Fset_keymap_parent (Vminibuffer_local_must_match_filename_map,
                      Vminibuffer_local_must_match_map);
 
   DEFVAR_LISP ("minor-mode-map-alist", &Vminor_mode_map_alist,
@@ -3851,6 +3935,9 @@ keymaps have no binding for the current key sequence but
 `read-key-sequence' replaces the matching suffix with its binding, and
 continues with the new sequence.
 
+If the binding is a function, it is called with one argument (the prompt)
+and its return value (a key sequence) is used.
+
 The events that come from bindings in `function-key-map' are not
 themselves looked up in `function-key-map'.