[gnu.emacs] rebind-key, version 2

bbc@titan.rice.edu (Benjamin Chase) (05/14/89)

Well, it's been a month, and only one person had comments and changes
to this package for rebinding keys, so I assume it's perfect now, and
safe for all the rest of you out there :-).
Here's the cleaned up and only slightly changed version.
(Don't forget to clip my .signature from the end.)

; ----------------------------------------
; Copyright (C) 1989 Benjamin B. Chase
; Permission is granted to copy, modify, and redistribute this
; software, but only under the conditions described in the
; GNU General Public License, Version 1, as published by the
; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; This software is distributed without any warranty, and without any implied
; warranty of merchantibility or fitness.  See the GNU General Public License
; for more details.
;

; 'define-key is wimpy, and will not destroy existing bindings to make
; way for keymaps.  Here are some more powerful key binding functions.
;
; History:
;;;  7-Apr-89  Emacs Maint Acct (emacs@pawl.rpi.edu) (really tale@pawl.rpi.edu)
;;;	Cleaned up the (provide)s.
;;;	Fixed two problems with calling rebind-key interactively:
;;;	  o valid keymaps were signalled as errors because
;;;	    call-interactively quoted the symbol name.  Works properly
;;;	    now for valid keymaps.
;;;	  o You couldn't type in a key sequence for anything other than
;;;	    the global-map.  Example:  I have an O prefix in the esc-map
;;;	    that I couldn't type to because the "k" specification reads
;;;	    the O as a valid (self-insert-command) key sequence.  Now you
;;;	    can type the keys that belong to the map.
;;;	Minor aesthetic changes, mostly with `let' and not quoting nil.
;;;	  
; 	Benjamin B. Chase <bbc@rice.edu>
;	first verion of rebind-key, global-rebind-key, local-rebind-key,
;	and rebind-this-key

(provide 'rebind)

(defun rebind-key (MAP KEYS COMMAND)
  "Add the binding in MAP of string KEYS to COMMAND.
If a binding was overwritten, return the old command that was replaced,
and the key sequence that invoked it, as the pair (oldkeys . oldcommand).
Otherwise, return nil."
  (interactive "SKeymap: \nsKey sequence: \nCFunction: ")
  (if (not (keymapp MAP)) (setq MAP (symbol-value MAP)))
  (if (null KEYS) nil 
    (let ((oldbinding (lookup-key MAP KEYS)) pKEYS pKEYSbinding)
      (cond
       ((numberp oldbinding)
	(setq pKEYS (substring KEYS 0 oldbinding))
	(setq pKEYSbinding (lookup-key MAP pKEYS))
	(define-key MAP pKEYS nil)
	(define-key MAP KEYS COMMAND)
	(cons pKEYS pKEYSbinding))
       ((null oldbinding)
	(define-key MAP KEYS COMMAND)
	nil)
       (t
	(define-key MAP KEYS COMMAND)
	(cons KEYS oldbinding))))))

(defun global-rebind-key (KEYS COMMAND)
  "Add the global binding of string KEYS to COMMAND.
If a binding was overwritten, return the old command that was replaced,
and the key sequence that invoked it, as the pair (oldkeys . oldcommand).
Otherwise, return nil."
  (interactive "kKey sequence: \nCFunction:")
  (rebind-key global-map KEYS COMMAND))

(defun local-rebind-key (KEYS COMMAND)
  "Add the local binding of string KEYS to COMMAND.
If a binding was overwritten, return the old command that was replaced,
and the key sequence that invoked it, as the pair (oldkeys . oldcommand).
Otherwise, return nil."
  (interactive "kKey sequence: \nCFunction:")
  (rebind-key (current-local-map) KEYS COMMAND))

(defun rebind-this-key ()
  "Ask for a new binding for the key sequence that invoked this function.
This function is a useful binding for unused or unallocated function keys."
  (interactive)
  (let ((tck (this-command-keys)))
    (rebind-key global-map tck
                (command-execute
                 '(lambda (func)
                    (interactive "CFunction to bind to this key: ") func)))))

--

	Ben Chase, Computer Science, Rice University, Houston, Texas