4

On Linux, the Ctrl-[ key combination appears to be equivalent to hitting the Esc key. I would like to define the Ctrl-[ as a shortcut in Emacs but I am unable to because by the time the keystroke gets to Emacs it looks like the Esc key was pressed. Is there anyway to disable this behavior so that Ctrl-[ simply means Ctrl-[?

Running Ubuntu 9.10 with GNOME.

2
  • Which linux? Which window manager?
    – sje397
    Commented Aug 9, 2010 at 16:18
  • which xterm are you using? Commented Aug 9, 2010 at 17:18

2 Answers 2

6

Assuming you're running Emacs directly under a windowing system (Cocoa, MS-DOS, Windows, X, ...) and not inside a text terminal (gnome-terminal, konsole, rxvt, xterm, ...), it's possible.

(define-key key-translation-map [?\C-\[] [(control left_bracket)])
(define-key key-translation-map [escape] [?\e])
(define-key function-key-map [escape] nil)
(define-key function-key-map [?\e] nil)
(when (boundp 'local-function-key-map)
  ;;(define-key local-function-key-map [escape] nil)
  (defun remove-escape-from-local-function-key-map ()
    (define-key local-function-key-map [?\e] nil)
    (define-key local-function-key-map [escape] nil))
  (add-hook 'term-setup-hook 'remove-escape-from-local-function-key-map))

There are three different input events at play here:

  • Ctrl+[, i.e., the control modifier together with a key that sends the character [. Emacs would normally show this as C-[ (and C-[ accepted by kbd), if it didn't have a special case for this, as explained below.

  • Character number 27, which is sent by the Esc key on some systems. Emacs shows this as ESC when displaying key sequences, and \e in strings.

  • The Esc key itself (in X Window, this means the Escape keysym). Emacs shows this as escape unless translated (see below).

Emacs normally translates escape into ESC, but this is done at a relatively high level, in function-key-map, so it can be overridden by modifying function-key-map or by defining a binding for escape in the global keymap or a local keymap. GNU Emacs 23 introduces local-function-key-map which applies per terminal type.

Emacs always translates C-[ into ESC, at a very low level (in keyboard.c). This is not configurable.

However Emacs provides a way to translate keys at a relatively low level: key-translation-map. This applies before any global or local binding, but only for keys that are not in function-key-map. So the trick is to exchange ESC and escape at that point.

These mechanisms are described in the Emacs Lisp manual under the heading "Translation keymaps".


By the way, similar principles apply to

  • C-i, TAB, \t tab
  • C-m, RET, \r, return
0

Depending on your xterm, you might be able to use bindkey. Try executing this command at the shell prompt:

bindkey ^] tty-dsusp

You must log in to answer this question.