[Top][All Lists]

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

bind buffer-modifying keys to `undefined' in buffers where no modificati

From: Drew Adams
Subject: bind buffer-modifying keys to `undefined' in buffers where no modification should occur?
Date: Sun, 17 Oct 2004 12:57:03 -0700

Many key sequences that modify a buffer are globally bound, so they remain
in effect even in buffers that you cannot (or should not usually) modify.
For instance, in Dired, the key sequences listed at the end of this message
are bound to buffer-modifying commands that cannot be used in Dired.

Of course, a buffer whose modification is inappropriate should be read-only,
so such commands will have no effect anyway. But even if such a buffer is
read-only, the key bindings of such commands remain. Users see them and can
mistakenly think that those key sequences are already "taken", so
unavailable for binding to other commands.

PROPOSAL: It would be clearer for users to have such buffer-modifying keys
rebound locally to a no-op command called `undefined' (as is done in
`suppress-keymap' for keys bound to `self-insert-command').

[Effectively "unbinding" such key sequences in the given major mode would be
better, of course, if it can be done. By that I mean nullifying any global
binding for the key sequence when in that major mode, not just removing the
key sequence from a local map (where it probably isn't, anyway).]

With buffer-modifying commands bound to `undefined' in this way, a user
could more easily see what keys are still available for binding (yes, he
could always check `C-h b', but this would be an additional aide). If he
asked (`C-h c'), say, about `C-d', instead of being told that it is bound to
`delete-char', and needing to think about whether that command is
appropriate/useful in the current buffer, he would be told that `C-d' is
bound to `undefined' (or is unbound in the current mode, if there is a way
to effectively unbind it, as mentioned).

If he tries to use such a neutered key sequence, nothing happens, instead of
getting error feedback that the buffer is read-only. Is that better or
worse? PRO: Even if bound to `undefined', the effect is as if the key
sequence were not bound. And, this is consistent with what we do for
`self-insert-command' keys. CON: In a keyboard macro, the no-op might
confuse the user; an error message might be clearer.

_How_ this might be implemented could be open for discussion, if the feature
itself makes sense to people. If it's best to discuss this after the
release, OK.

Perhaps we could provide something similar to `suppress-keymap', but which
would nullify not just `self-insert-command' but all (or most)
buffer-modifying commands that are bound to keys.

For years I've used the following hack to "undefine" buffer-modifying keys.
(I'm not suggesting this is the way to go, but it illustrates the effect for
a user.) I have a global variable `buffer-modifying-cmds' whose value is a
list of commands like those listed below. Then, you can (optionally) call
function `undefine-killer-commands' to neuter those commands in a given

(defsubst undefine-killer-commands (keymap &optional oldmap)
  "Bind to `undefined' KEYMAP keys bound to buffer-modifying commands.
If optional arg OLDMAP is specified, rebinds in KEYMAP as `undefined'
the keys that are currently bound to buffer-modifying commands in
OLDMAP.  The buffer-modifying commands used: `buffer-modifying-cmds'."
  (mapcar (function (lambda (cmd) (undefine-keys-bound-to cmd keymap

(defsubst undefine-keys-bound-to (command keymap &optional oldmap)
  "Bind to `undefined' all keys currently bound to COMMAND in KEYMAP.
If optional argument OLDMAP is specified, rebinds in KEYMAP as
`undefined' all keys that are currently bound to COMMAND in OLDMAP."
  (substitute-key-definition command 'undefined keymap oldmap))

For instance, for Dired I do this to "undefine" some bindings that would try
to modify a Dired buffer. Those key sequences then appear to the user as
available for local (Dired) definition (bound to "undefined").

  (undefine-killer-commands dired-mode-map (current-global-map))

[As mentioned, it would be preferable to effectively _unbind_ such key
sequences when in a given mode (like Dired). I tried
(substitute-key-definition command nil keymap oldmap), but that doesn't do
the job. I also tried (define-key command nil keymap) (and
`local-unset-key', which ultimately uses define-key with nil), but that
doesn't work either. I guess all of those, or at least the latter, just
remove the key sequence from the local map (where it isn't, anyway). What's
needed is to somehow remove it from the global map whenever you are in the
given mode. Perhaps I'm missing something obvious here - can you effectively
unbind a (global) key sequence for a given mode?]

Here are some currently defined killer-command key sequences, which we might
want to undefine somehow in most read-only modes:

C-x DEL                backward-kill-sentence
ESC <C-backspace>      backward-kill-sexp
<C-backspace>          backward-kill-word
C-x C-o                delete-blank-lines
C-d                    delete-char
M-\                    delete-horizontal-space
M-^                    delete-indentation
C-x r d                delete-rectangle
<menu-bar><edit><clear> delete-region
M-q                    fill-paragraph
M-j                    indent-new-comment-line
M-SPC                  just-one-space
C-k                    kill-line
C-x r k                kill-rectangle
C-w                    kill-region
M-k                    kill-sentence
C-M-k                  kill-sexp
<C-S-backspace>        kill-whole-line
M-d                    kill-word
<insertline>           open-line
C-x r o                open-rectangle
C-q                    quoted-insert
C-M-o                  split-line
C-t                    transpose-chars
C-x C-t                transpose-lines
C-M-t                  transpose-sexps
M-t                    transpose-words
C-y                    yank
M-y                    yank-pop
C-x r y                yank-rectangle
M-z                    zap-to-char

reply via email to

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