emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Patch for command remapping through keymaps


From: Kim F. Storm
Subject: Patch for command remapping through keymaps
Date: 28 Jan 2002 02:36:59 +0100
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1

Here is the patch (sans changelogs) which implements the remapping of
interactive commands through keymaps feature.

I plan to install this in a few days, so comments are very welcome.

Once this is in place, I think substitute-key-definition can be
rewritten to a simple call to define-key, but I haven't had time to
play with that yet.

Index: etc/NEWS
===================================================================
RCS file: /cvs/emacs/etc/NEWS,v
retrieving revision 1.581
diff -c -r1.581 NEWS
*** etc/NEWS    27 Jan 2002 18:24:04 -0000      1.581
--- etc/NEWS    28 Jan 2002 01:23:06 -0000
***************
*** 115,120 ****
--- 115,129 ----
  The info-search bindings on C-h C-f, C-h C-k and C-h C-i
  have been moved to C-h F, C-h K and C-h S.
  
+ C-h k now reports the actual command (after possible remapping) run by
+ the key sequence.
+ 
+ C-h w on a command which has been remapped now reports the command it
+ is remapped to, and the keys which can be used to run that command.
+ 
+ C-h f now reports if the command is remapped to another command, and
+ the key bindings which runs that command.
+ 
  ** C-w in incremental search now grabs either a character or a word,
  making the decision in a heuristic way.  This new job is done by the
  command `isearch-yank-word-or-char'.  To restore the old behavior,
***************
*** 394,399 ****
--- 403,450 ----
  
  
  * Lisp Changes in Emacs 21.3
+ 
+ ** Interactive commands can be remapped through keymaps.
+ 
+ This is an alternative to using defadvice or substitute-key-definition
+ to modify the behaviour of a key binding in a specific (minor) mode.
+ When a key sequence is read from the keyboard corresponds to a
+ command which has been remapped, the command it is remapped to will be
+ executed instead of the original command.  For example, if minor mode
+ my-mode need to "advice" kill-line and kill-word in "my" way, this can
+ be accomplished by writing functions my-kill-line and my-kill-word
+ (which may call kill-line and kill-word if necessary), and the make
+ with the following remappings using define-key:
+ 
+    (define-key my-mode-map 'kill-line 'my-kill-line)
+    (define-key my-mode-map 'kill-word 'my-kill-word)
+ 
+ Now, when my-mode is enabled, and the user enters C-k or M-d,
+ the commands my-kill-line and my-kill-word are run.
+ 
+ The following changes have been made to use this functionality:
+ 
+ - define-key now accepts a command name as the KEY argument,
+   identifying the command to be remapped in the specified keymap.
+   This is equivalent to specifying the command name as the only
+   element of a vector.
+ 
+ - key-binding will also remap interactive commands unless the optional
+   third argument NO-REMAP is non-nil.  It also accepts a command name
+   as the KEY argument.
+ 
+ - lookup-key now accepts a command name as the KEY argument.
+ 
+ - the new variable `this-original-command' contains the original command
+   when executing a key sequence results in a remapping of that command.
+ 
+ - where-is-internal will now return no key bindings for a remapped command
+   (e.g. kill-line if my-mode is enabled).  Instead, it will report the
+   key bindings of the original command when the argument is the
+   command it is mapped to (e.g. it will return C-k for my-kill-line).
+   It now has a new optional fifth argument, NO-REMAP, to inhibit this
+   behaviour (e.g. it will return C-k for kill-line and <kill-line> for
+   my-kill-line).
  
  ** New function substring-no-properties.
  
Index: lisp/help-fns.el
===================================================================
RCS file: /cvs/emacs/lisp/help-fns.el,v
retrieving revision 1.5
diff -c -r1.5 help-fns.el
*** lisp/help-fns.el    7 Jan 2002 05:20:33 -0000       1.5
--- lisp/help-fns.el    28 Jan 2002 01:23:06 -0000
***************
*** 207,218 ****
      (princ ".")
      (terpri)
      (when (commandp function)
!       (let ((keys (where-is-internal
!                  function overriding-local-map nil nil)))
        (when keys
!         (princ "It is bound to ")
          ;; FIXME: This list can be very long (f.ex. for self-insert-command).
!         (princ (mapconcat 'key-description keys ", "))
          (princ ".")
          (terpri))))
      ;; Handle symbols aliased to other symbols.
--- 207,226 ----
      (princ ".")
      (terpri)
      (when (commandp function)
!       (let* ((binding (and (symbolp function) (commandp function)
!                          (key-binding function nil t)))
!            (remapped (and (symbolp binding) (commandp binding) binding))
!            (keys (where-is-internal
!                  (or remapped function) overriding-local-map nil nil)))
!       (when remapped
!         (princ "It is remapped to `")
!         (princ (symbol-name remapped))
!         (princ "'"))
        (when keys
!         (princ (if remapped " which is bound to " "It is bound to "))
          ;; FIXME: This list can be very long (f.ex. for self-insert-command).
!         (princ (mapconcat 'key-description keys ", ")))
!       (when (or remapped keys)
          (princ ".")
          (terpri))))
      ;; Handle symbols aliased to other symbols.
Index: lisp/help.el
===================================================================
RCS file: /cvs/emacs/lisp/help.el,v
retrieving revision 1.243
diff -c -r1.243 help.el
*** lisp/help.el        17 Jan 2002 01:40:47 -0000      1.243
--- lisp/help.el        28 Jan 2002 01:23:07 -0000
***************
*** 412,426 ****
       (list (if (equal val "")
               fn (intern val))
           current-prefix-arg)))
!   (let* ((keys (where-is-internal definition overriding-local-map nil nil))
         (keys1 (mapconcat 'key-description keys ", "))
         (standard-output (if insert (current-buffer) t)))
      (if insert
        (if (> (length keys1) 0)
!           (princ (format "%s (%s)" keys1 definition))
          (princ (format "M-x %s RET" definition)))
        (if (> (length keys1) 0)
!         (princ (format "%s is on %s" definition keys1))
        (princ (format "%s is not on any key" definition)))))
    nil)
  
--- 412,433 ----
       (list (if (equal val "")
               fn (intern val))
           current-prefix-arg)))
!   (let* ((binding (and (symbolp definition) (commandp definition)
!                      (key-binding definition nil t)))
!        (remap (and (symbolp binding) (commandp binding) binding))
!        (keys (where-is-internal definition overriding-local-map nil nil t))
         (keys1 (mapconcat 'key-description keys ", "))
         (standard-output (if insert (current-buffer) t)))
      (if insert
        (if (> (length keys1) 0)
!           (if remap
!               (princ (format "%s (%s (%s remapped))" keys1 remap definition))
!             (princ (format "%s (%s)" keys1 definition)))
          (princ (format "M-x %s RET" definition)))
        (if (> (length keys1) 0)
!         (if remap
!             (princ (format "%s is remapped to %s which is on %s" definition 
remap keys1))
!           (princ (format "%s is on %s" definition keys1)))
        (princ (format "%s is not on any key" definition)))))
    nil)
  
Index: lisp/subr.el
===================================================================
RCS file: /cvs/emacs/lisp/subr.el,v
retrieving revision 1.284
diff -c -r1.284 subr.el
*** lisp/subr.el        25 Jan 2002 05:05:16 -0000      1.284
--- lisp/subr.el        28 Jan 2002 01:23:07 -0000
***************
*** 1571,1577 ****
  that local binding will continue to shadow any global binding
  that you make with this function."
    (interactive "KSet key globally: \nCSet key %s to command: ")
!   (or (vectorp key) (stringp key)
        (signal 'wrong-type-argument (list 'arrayp key)))
    (define-key (current-global-map) key command))
  
--- 1571,1577 ----
  that local binding will continue to shadow any global binding
  that you make with this function."
    (interactive "KSet key globally: \nCSet key %s to command: ")
!   (or (vectorp key) (stringp key) (symbolp key)
        (signal 'wrong-type-argument (list 'arrayp key)))
    (define-key (current-global-map) key command))
  
***************
*** 1589,1595 ****
    (let ((map (current-local-map)))
      (or map
        (use-local-map (setq map (make-sparse-keymap))))
!     (or (vectorp key) (stringp key)
        (signal 'wrong-type-argument (list 'arrayp key)))
      (define-key map key command)))
  
--- 1589,1595 ----
    (let ((map (current-local-map)))
      (or map
        (use-local-map (setq map (make-sparse-keymap))))
!     (or (vectorp key) (stringp key) (symbolp key)
        (signal 'wrong-type-argument (list 'arrayp key)))
      (define-key map key command)))
  
Index: src/doc.c
===================================================================
RCS file: /cvs/emacs/src/doc.c,v
retrieving revision 1.89
diff -c -r1.89 doc.c
*** src/doc.c   22 Dec 2001 13:59:08 -0000      1.89
--- src/doc.c   28 Jan 2002 01:23:08 -0000
***************
*** 671,677 ****
  
          /* Note the Fwhere_is_internal can GC, so we have to take
             relocation of string contents into account.  */
!         tem = Fwhere_is_internal (tem, keymap, Qt, Qnil);
          strp = XSTRING (string)->data + idx;
          start = XSTRING (string)->data + start_idx;
  
--- 671,677 ----
  
          /* Note the Fwhere_is_internal can GC, so we have to take
             relocation of string contents into account.  */
!         tem = Fwhere_is_internal (tem, keymap, Qt, Qnil, Qnil);
          strp = XSTRING (string)->data + idx;
          start = XSTRING (string)->data + start_idx;
  
Index: src/keyboard.c
===================================================================
RCS file: /cvs/emacs/src/keyboard.c,v
retrieving revision 1.650
diff -c -r1.650 keyboard.c
*** src/keyboard.c      26 Jan 2002 17:06:55 -0000      1.650
--- src/keyboard.c      28 Jan 2002 01:23:11 -0000
***************
*** 373,378 ****
--- 373,382 ----
  /* This is like Vthis_command, except that commands never set it.  */
  Lisp_Object real_this_command;
  
+ /* If the lookup of the command returns a binding, the original
+    command is stored in this-original-command.  It is nil otherwise.  */
+ Lisp_Object Vthis_original_command;
+ 
  /* The value of point when the last command was executed.  */
  int last_point_position;
  
***************
*** 1309,1315 ****
  Lisp_Object
  command_loop_1 ()
  {
!   Lisp_Object cmd;
    int lose;
    int nonundocount;
    Lisp_Object keybuf[30];
--- 1313,1319 ----
  Lisp_Object
  command_loop_1 ()
  {
!   Lisp_Object cmd, cmd1;
    int lose;
    int nonundocount;
    Lisp_Object keybuf[30];
***************
*** 1503,1508 ****
--- 1507,1520 ----
         reset it before we execute the command. */
        Vdeactivate_mark = Qnil;
  
+       /* Remap command through active keymaps */
+       cmd1 = Fkey_binding (cmd, Qnil, Qt);
+       if (!NILP (cmd1))
+       {
+         Vthis_original_command = cmd;
+         cmd = cmd1;
+       }
+ 
        /* Execute the command.  */
  
        Vthis_command = cmd;
***************
*** 6945,6951 ****
        Lisp_Object prefix;
  
        if (!NILP (tem))
!       tem = Fkey_binding (tem, Qnil);
  
        prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
        if (CONSP (prefix))
--- 6957,6963 ----
        Lisp_Object prefix;
  
        if (!NILP (tem))
!       tem = Fkey_binding (tem, Qnil, Qnil);
  
        prefix = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
        if (CONSP (prefix))
***************
*** 6991,6997 ****
              && SYMBOLP (XSYMBOL (def)->function)
              && ! NILP (Fget (def, Qmenu_alias)))
            def = XSYMBOL (def)->function;
!         tem = Fwhere_is_internal (def, Qnil, Qt, Qnil);
          XSETCAR (cachelist, tem);
          if (NILP (tem))
            {
--- 7003,7009 ----
              && SYMBOLP (XSYMBOL (def)->function)
              && ! NILP (Fget (def, Qmenu_alias)))
            def = XSYMBOL (def)->function;
!         tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qnil);
          XSETCAR (cachelist, tem);
          if (NILP (tem))
            {
***************
*** 9406,9412 ****
        && NILP (Vexecuting_macro)
        && SYMBOLP (function))
      bindings = Fwhere_is_internal (function, Voverriding_local_map,
!                                  Qt, Qnil);
    else
      bindings = Qnil;
  
--- 9418,9424 ----
        && NILP (Vexecuting_macro)
        && SYMBOLP (function))
      bindings = Fwhere_is_internal (function, Voverriding_local_map,
!                                  Qt, Qnil, Qnil);
    else
      bindings = Qnil;
  
***************
*** 10632,10637 ****
--- 10644,10655 ----
  The command can set this variable; whatever is put here
  will be in `last-command' during the following command.  */);
    Vthis_command = Qnil;
+ 
+   DEFVAR_LISP ("this-original-command", &Vthis_original_command,
+              doc: /* If non-nil, the original command bound to the current 
key sequence.
+ The value of `this-command' is the result of looking up the original
+ command in the active keymaps.  */);
+   Vthis_original_command = Qnil;
  
    DEFVAR_INT ("auto-save-interval", &auto_save_interval,
              doc: /* *Number of input events between auto-saves.
Index: src/keymap.c
===================================================================
RCS file: /cvs/emacs/src/keymap.c,v
retrieving revision 1.254
diff -c -r1.254 keymap.c
*** src/keymap.c        3 Jan 2002 21:28:04 -0000       1.254
--- src/keymap.c        28 Jan 2002 01:23:12 -0000
***************
*** 987,992 ****
--- 987,995 ----
  
    keymap = get_keymap (keymap, 1, 1);
  
+   if (SYMBOLP (key))
+     key = Fmake_vector (make_number (1), key);
+ 
    if (!VECTORP (key) && !STRINGP (key))
      key = wrong_type_argument (Qarrayp, key);
  
***************
*** 1084,1089 ****
--- 1087,1099 ----
  
    keymap = get_keymap (keymap, 1, 1);
  
+   if (SYMBOLP (key))
+     {
+       GCPRO1 (key);
+       cmd = access_keymap (keymap, key, t_ok, 0, 1);
+       RETURN_UNGCPRO (cmd);
+     }
+ 
    if (!VECTORP (key) && !STRINGP (key))
      key = wrong_type_argument (Qarrayp, key);
  
***************
*** 1363,1369 ****
  
  /* GC is possible in this function if it autoloads a keymap.  */
  
! DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 2, 0,
         doc: /* Return the binding for command KEY in current keymaps.
  KEY is a string or vector, a sequence of keystrokes.
  The binding is probably a symbol with a function definition.
--- 1373,1379 ----
  
  /* GC is possible in this function if it autoloads a keymap.  */
  
! DEFUN ("key-binding", Fkey_binding, Skey_binding, 1, 3, 0,
         doc: /* Return the binding for command KEY in current keymaps.
  KEY is a string or vector, a sequence of keystrokes.
  The binding is probably a symbol with a function definition.
***************
*** 1372,1385 ****
  bindings, used when nothing else in the keymap applies; this makes it
  usable as a general function for probing keymaps.  However, if the
  optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does
! recognize the default bindings, just as `read-key-sequence' does.  */)
!      (key, accept_default)
!      Lisp_Object key, accept_default;
  {
!   Lisp_Object *maps, value;
    int nmaps, i;
    struct gcpro gcpro1;
  
    GCPRO1 (key);
  
    if (!NILP (current_kboard->Voverriding_terminal_local_map))
--- 1382,1401 ----
  bindings, used when nothing else in the keymap applies; this makes it
  usable as a general function for probing keymaps.  However, if the
  optional second argument ACCEPT-DEFAULT is non-nil, `key-binding' does
! recognize the default bindings, just as `read-key-sequence' does.
! 
! Like the normal command loop, `key-binding' will remap the command
! resulting from looking up KEY by looking up the command in the
! currrent keymaps.  However, if the optional third argument NO-REMAP
! is non-nil, `key-binding' returns the unmapped command.  */)
!      (key, accept_default, no_remap)
!      Lisp_Object key, accept_default, no_remap;
  {
!   Lisp_Object *maps, value, value1;
    int nmaps, i;
    struct gcpro gcpro1;
  
+  do_remap:
    GCPRO1 (key);
  
    if (!NILP (current_kboard->Voverriding_terminal_local_map))
***************
*** 1387,1399 ****
        value = Flookup_key (current_kboard->Voverriding_terminal_local_map,
                           key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
!       RETURN_UNGCPRO (value);
      }
    else if (!NILP (Voverriding_local_map))
      {
        value = Flookup_key (Voverriding_local_map, key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
!       RETURN_UNGCPRO (value);
      }
    else
      { 
--- 1403,1415 ----
        value = Flookup_key (current_kboard->Voverriding_terminal_local_map,
                           key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
!       goto done;
      }
    else if (!NILP (Voverriding_local_map))
      {
        value = Flookup_key (Voverriding_local_map, key, accept_default);
        if (! NILP (value) && !INTEGERP (value))
!       goto done;
      }
    else
      { 
***************
*** 1404,1410 ****
        {
          value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
!           RETURN_UNGCPRO (value);
        }
  
        nmaps = current_minor_maps (0, &maps);
--- 1420,1426 ----
        {
          value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
!           goto done;
        }
  
        nmaps = current_minor_maps (0, &maps);
***************
*** 1416,1422 ****
          {
            value = Flookup_key (maps[i], key, accept_default);
            if (! NILP (value) && !INTEGERP (value))
!             RETURN_UNGCPRO (value);
          }
  
        local = get_local_map (PT, current_buffer, Qlocal_map);
--- 1432,1438 ----
          {
            value = Flookup_key (maps[i], key, accept_default);
            if (! NILP (value) && !INTEGERP (value))
!             goto done;
          }
  
        local = get_local_map (PT, current_buffer, Qlocal_map);
***************
*** 1424,1439 ****
        {
          value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
!           RETURN_UNGCPRO (value);
        }
      }
  
    value = Flookup_key (current_global_map, key, accept_default);
    UNGCPRO;
!   if (! NILP (value) && !INTEGERP (value))
!     return value;
    
!   return Qnil;
  }
  
  /* GC is possible in this function if it autoloads a keymap.  */
--- 1440,1462 ----
        {
          value = Flookup_key (local, key, accept_default);
          if (! NILP (value) && !INTEGERP (value))
!           goto done;
        }
      }
  
    value = Flookup_key (current_global_map, key, accept_default);
+  done:
    UNGCPRO;
!   if (NILP (value) || INTEGERP (value))
!     return Qnil;
! 
!   if (NILP (no_remap) && SYMBOLP (value)) {
!     value1 = Fkey_binding(value, accept_default, Qt);
!     if (!NILP (value1) && SYMBOLP (value1))
!       value = value1;
!   }
    
!   return value;
  }
  
  /* GC is possible in this function if it autoloads a keymap.  */
***************
*** 2156,2161 ****
--- 2179,2185 ----
  
  /* where-is - finding a command in a set of keymaps.                  */
  
+ static Lisp_Object where_is_internal ();
  static Lisp_Object where_is_internal_1 ();
  static void where_is_internal_2 ();
  
***************
*** 2177,2188 ****
    return Qnil;
  }
  
  /* This function can GC if Flookup_key autoloads any keymaps.  */
  
  static Lisp_Object
! where_is_internal (definition, keymaps, firstonly, noindirect)
       Lisp_Object definition, keymaps;
!      Lisp_Object firstonly, noindirect;
  {
    Lisp_Object maps = Qnil;
    Lisp_Object found, sequences;
--- 2201,2280 ----
    return Qnil;
  }
  
+ static Lisp_Object
+ remap_sequence (sequence, keymaps, firstonly, noindirect)
+      Lisp_Object sequence, keymaps;
+      Lisp_Object firstonly, noindirect;
+ {
+   Lisp_Object remapped;
+   Lisp_Object function, fun;
+ 
+   /* This code is similar to Fcommandp, but looks
+      specifically for a command symbol, and don't
+      signal errors.  */
+ 
+   function = AREF (sequence, 0);
+   if (!SYMBOLP (function) || EQ (fun, Qunbound))
+     return Qnil;
+ 
+   fun = indirect_function (function);
+   if (SYMBOLP (fun) && EQ (fun, Qunbound))
+     return Qnil;
+ 
+   if (SUBRP (fun))
+     {
+       if (!XSUBR (fun)->prompt)
+       return Qnil;
+     }
+   else if (COMPILEDP (fun))
+     {
+       if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_INTERACTIVE)
+       return Qnil;
+     }
+   else if (CONSP (fun))
+     {
+       Lisp_Object funcar;
+ 
+       funcar = Fcar (fun);
+       if (!SYMBOLP (funcar))
+       return Qnil;
+ 
+       if (EQ (funcar, Qlambda))
+       {
+         if (NILP (Fassq (Qinteractive, Fcdr (Fcdr (fun)))))
+           return Qnil;
+       }
+       else if (EQ (funcar, Qautoload))
+       {
+         if (NILP (Fcar (Fcdr (Fcdr (Fcdr (fun))))))
+           return Qnil;
+       }
+       else
+       return Qnil;
+     }
+   else
+     return Qnil;
+ 
+   remapped = where_is_internal (function, keymaps, firstonly, noindirect, Qt);
+   if (!CONSP (remapped))
+     return Qnil;
+ 
+   sequence = XCAR(remapped);
+ 
+   /* Verify that this key binding actually maps to the
+      remapped command (see below).  */
+   if (!EQ (shadow_lookup (keymaps, sequence, Qnil), function))
+     return Qt;
+ 
+   return remapped;
+ }
+ 
  /* This function can GC if Flookup_key autoloads any keymaps.  */
  
  static Lisp_Object
! where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
       Lisp_Object definition, keymaps;
!      Lisp_Object firstonly, noindirect, no_remap;
  {
    Lisp_Object maps = Qnil;
    Lisp_Object found, sequences;
***************
*** 2190,2195 ****
--- 2282,2293 ----
    /* 1 means ignore all menu bindings entirely.  */
    int nomenus = !NILP (firstonly) && !EQ (firstonly, Qnon_ascii);
  
+   /* If this command is remapped, then it has no key bindings
+      of it's own.  */
+   if (NILP (no_remap)
+       && !NILP (Fkey_binding (definition, Qnil, Qt)))
+     return Qnil;
+ 
    found = keymaps;
    while (CONSP (found))
      {
***************
*** 2295,2331 ****
            }
  
  
!         for (; !NILP (sequences); sequences = XCDR (sequences))
            {
              Lisp_Object sequence;
  
              sequence = XCAR (sequences);
  
!             /* Verify that this key binding is not shadowed by another
!                binding for the same key, before we say it exists.
  
!                Mechanism: look for local definition of this key and if
!                it is defined and does not match what we found then
!                ignore this key.
! 
!                Either nil or number as value from Flookup_key
!                means undefined.  */
!             if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition))
!               continue;
  
!             /* It is a true unshadowed match.  Record it, unless it's already
!                been seen (as could happen when inheriting keymaps).  */
!             if (NILP (Fmember (sequence, found)))
!               found = Fcons (sequence, found);
! 
!             /* If firstonly is Qnon_ascii, then we can return the first
!                binding we find.  If firstonly is not Qnon_ascii but not
!                nil, then we should return the first ascii-only binding
!                we find.  */
!             if (EQ (firstonly, Qnon_ascii))
!               RETURN_UNGCPRO (sequence);
!             else if (!NILP (firstonly) && ascii_sequence_p (sequence))
!               RETURN_UNGCPRO (sequence);
            }
        }
      }
--- 2393,2457 ----
            }
  
  
!         while (!NILP (sequences))
            {
              Lisp_Object sequence;
+             Lisp_Object remapped;
  
              sequence = XCAR (sequences);
+             sequences = XCDR (sequences);
  
!             if (NILP (no_remap)
!                 && VECTORP (sequence) && XVECTOR (sequence)->size == 1)
!               {
!                 remapped = remap_sequence (sequence, keymaps, firstonly, 
noindirect);
!                 if (EQ (remapped, Qt))
!                   continue;
!               }
!             else
!               remapped = Qnil;
  
!             if (!NILP (remapped))
!               {
!                 sequence = XCAR (remapped);
!                 remapped = XCDR (remapped);
!               }
!             else
!               {
!                 /* Verify that this key binding is not shadowed by another
!                    binding for the same key, before we say it exists.
! 
!                    Mechanism: look for local definition of this key and if
!                    it is defined and does not match what we found then
!                    ignore this key.
! 
!                    Either nil or number as value from Flookup_key
!                    means undefined.  */
!                 if (!EQ (shadow_lookup (keymaps, sequence, Qnil), definition))
!                   continue;
!               }
  
!             while (1)
!               {
!                 /* It is a true unshadowed match.  Record it, unless it's 
already
!                    been seen (as could happen when inheriting keymaps).  */
!                 if (NILP (Fmember (sequence, found)))
!                   found = Fcons (sequence, found);
! 
!                 /* If firstonly is Qnon_ascii, then we can return the first
!                    binding we find.  If firstonly is not Qnon_ascii but not
!                    nil, then we should return the first ascii-only binding
!                    we find.  */
!                 if (EQ (firstonly, Qnon_ascii))
!                   RETURN_UNGCPRO (sequence);
!                 else if (!NILP (firstonly) && ascii_sequence_p (sequence))
!                   RETURN_UNGCPRO (sequence);
!               
!                 if (!CONSP (remapped))
!                   break;
!                 sequence = XCAR (remapped);
!                 remapped = XCDR (remapped);
!               }
            }
        }
      }
***************
*** 2343,2349 ****
    return found;
  }
  
! DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 4, 0,
         doc: /* Return list of keys that invoke DEFINITION.
  If KEYMAP is non-nil, search only KEYMAP and the global keymap.
  If KEYMAP is nil, search all the currently active keymaps.
--- 2469,2475 ----
    return found;
  }
  
! DEFUN ("where-is-internal", Fwhere_is_internal, Swhere_is_internal, 1, 5, 0,
         doc: /* Return list of keys that invoke DEFINITION.
  If KEYMAP is non-nil, search only KEYMAP and the global keymap.
  If KEYMAP is nil, search all the currently active keymaps.
***************
*** 2358,2367 ****
  
  If optional 4th arg NOINDIRECT is non-nil, don't follow indirections
  to other keymaps or slots.  This makes it possible to search for an
! indirect definition itself.  */)
!      (definition, keymap, firstonly, noindirect)
       Lisp_Object definition, keymap;
!      Lisp_Object firstonly, noindirect;
  {
    Lisp_Object sequences, keymaps;
    /* 1 means ignore all menu bindings entirely.  */
--- 2484,2496 ----
  
  If optional 4th arg NOINDIRECT is non-nil, don't follow indirections
  to other keymaps or slots.  This makes it possible to search for an
! indirect definition itself.
! 
! If optional 5th arg NO-REMAP is non-nil, don't follow remapped command
! symbols to find the actual key bindings.  */)
!      (definition, keymap, firstonly, noindirect, no_remap)
       Lisp_Object definition, keymap;
!      Lisp_Object firstonly, noindirect, no_remap;
  {
    Lisp_Object sequences, keymaps;
    /* 1 means ignore all menu bindings entirely.  */
***************
*** 2382,2388 ****
      {
        Lisp_Object *defns;
        int i, j, n;
!       struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
        
        /* Check heuristic-consistency of the cache.  */
        if (NILP (Fequal (keymaps, where_is_cache_keymaps)))
--- 2511,2517 ----
      {
        Lisp_Object *defns;
        int i, j, n;
!       struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
        
        /* Check heuristic-consistency of the cache.  */
        if (NILP (Fequal (keymaps, where_is_cache_keymaps)))
***************
*** 2396,2403 ****
          where_is_cache_keymaps = Qt;
          
          /* Fill in the cache.  */
!         GCPRO4 (definition, keymaps, firstonly, noindirect);
!         where_is_internal (definition, keymaps, firstonly, noindirect);
          UNGCPRO;
  
          where_is_cache_keymaps = keymaps;
--- 2525,2532 ----
          where_is_cache_keymaps = Qt;
          
          /* Fill in the cache.  */
!         GCPRO5 (definition, keymaps, firstonly, noindirect, no_remap);
!         where_is_internal (definition, keymaps, firstonly, noindirect, 
no_remap);
          UNGCPRO;
  
          where_is_cache_keymaps = keymaps;
***************
*** 2434,2440 ****
        /* Kill the cache so that where_is_internal_1 doesn't think
         we're filling it up.  */
        where_is_cache = Qnil;
!       result = where_is_internal (definition, keymaps, firstonly, noindirect);
      }
  
    return result;
--- 2563,2569 ----
        /* Kill the cache so that where_is_internal_1 doesn't think
         we're filling it up.  */
        where_is_cache = Qnil;
!       result = where_is_internal (definition, keymaps, firstonly, noindirect, 
no_remap);
      }
  
    return result;
Index: src/keymap.h
===================================================================
RCS file: /cvs/emacs/src/keymap.h,v
retrieving revision 1.3
diff -c -r1.3 keymap.h
*** src/keymap.h        19 Nov 2001 22:46:29 -0000      1.3
--- src/keymap.h        28 Jan 2002 01:23:12 -0000
***************
*** 28,37 ****
  EXFUN (Fkeymap_prompt, 1);
  EXFUN (Fdefine_key, 3);
  EXFUN (Flookup_key, 3);
! EXFUN (Fkey_binding, 2);
  EXFUN (Fkey_description, 1);
  EXFUN (Fsingle_key_description, 2);
! EXFUN (Fwhere_is_internal, 4);
  extern Lisp_Object access_keymap P_ ((Lisp_Object, Lisp_Object, int, int, 
int));
  extern Lisp_Object get_keyelt P_ ((Lisp_Object, int));
  extern Lisp_Object get_keymap P_ ((Lisp_Object, int, int));
--- 28,37 ----
  EXFUN (Fkeymap_prompt, 1);
  EXFUN (Fdefine_key, 3);
  EXFUN (Flookup_key, 3);
! EXFUN (Fkey_binding, 3);
  EXFUN (Fkey_description, 1);
  EXFUN (Fsingle_key_description, 2);
! EXFUN (Fwhere_is_internal, 5);
  extern Lisp_Object access_keymap P_ ((Lisp_Object, Lisp_Object, int, int, 
int));
  extern Lisp_Object get_keyelt P_ ((Lisp_Object, int));
  extern Lisp_Object get_keymap P_ ((Lisp_Object, int, int));

-- 
Kim F. Storm <address@hidden> http://www.cua.dk




reply via email to

[Prev in Thread] Current Thread [Next in Thread]