;;; xterm-extras.el --- define additional function key sequences for
;;; recent versions of xterm
;; Copyright (C) 2004 P J Heslin
;; Author: Peter Heslin
;; URL: http://www.dur.ac.uk/p.j.heslin/emacs/download/xterm-extras.el
;; Version: 1.0
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; If you do not have a copy of the GNU General Public License, you
;; can obtain one by writing to the Free Software Foundation, Inc., 59
;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
;; Commentary:
;; This file provides some extra emacs keybindings for the escape
;; sequences transmitted by recent versions of xterm. It will not
;; work with the older versions of xterm that are still often found
;; in use. An up-to-date version of xterm can be obtained from
;; http://dickey.his.com/xterm/xterm.html. It includes a file called
;; ctlseqs.ms, which documents the treatment of control sequences by
;; recent xterms.
;; This implementation is somewhat limited in that it assumes a
;; standard PC keyboard and that the Alt key is being used for Meta.
;; Since both xterm and emacs support the use of a Meta key in
;; addition to the Alt key, this file probably should support that
;; usage, but as of yet it does not. In fact, this file takes the
;; modifier that xterm refers to as "alt" and maps it right to the
;; emacs "meta". For many users this is convenient, but for some it
;; will be wrong.
;; These key combinations should also work with GNU screen, provided
;; that the TERM environment variable is set to "xterm" rather than
;; "screen". This can be done in the .screenrc configuration file
;; or by using the "-T" switch like so: screen -T xterm
;; To use, put this file in your load-path, and put these lines in
;; your .emacs file:
;;
;; (when (string= "xterm" (getenv "TERM"))
;; (require 'xterm-extras)
;; (xterm-extra-keys))
;; For some extra keybindings, beyond those available from xterm by
;; default, try putting the following settings in your X resources
;; file:
;;
;; XTerm*eightBitInput: false
;; XTerm*metaSendsEscape: true
;; XTerm*backarrowKey: false
;; XTerm*modifier: meta
;;
;; XTerm.VT100.Translations: #override \
;; ~Ctrl ~Meta Shift Tab: string(0x1b) string("[z2a") \n\
;; ~Ctrl Meta ~Shift Tab: string(0x1b) string("[z3a") \n\
;; ~Ctrl Meta Shift Tab: string(0x1b) string("[z4a") \n\
;; Ctrl ~Meta ~Shift Tab: string(0x1b) string("[z5a") \n\
;; Ctrl ~Meta Shift Tab: string(0x1b) string("[z6a") \n\
;; Ctrl Meta ~Shift Tab: string(0x1b) string("[z7a") \n\
;; Ctrl Meta Shift Tab: string(0x1b) string("[z8a") \n\
;; \
;; ~Ctrl ~Meta Shift Return: string(0x1b) string("[z2b") \n\
;; ~Ctrl Meta ~Shift Return: string(0x1b) string("[z3b") \n\
;; ~Ctrl Meta Shift Return: string(0x1b) string("[z4b") \n\
;; Ctrl ~Meta ~Shift Return: string(0x1b) string("[z5b") \n\
;; Ctrl ~Meta Shift Return: string(0x1b) string("[z6b") \n\
;; Ctrl Meta ~Shift Return: string(0x1b) string("[z7b") \n\
;; Ctrl Meta Shift Return: string(0x1b) string("[z8b") \n\
;; \
;; ~Ctrl ~Meta Shift BackSpace: string(0x1b) string("[z2c") \n\
;; ~Ctrl Meta ~Shift BackSpace: string(0x1b) string("[z3c") \n\
;; ~Ctrl Meta Shift BackSpace: string(0x1b) string("[z4c") \n\
;; Ctrl ~Meta ~Shift BackSpace: string(0x1b) string("[z5c") \n\
;; Ctrl ~Meta Shift BackSpace: string(0x1b) string("[z6c") \n\
;; Ctrl Meta ~Shift BackSpace: string(0x1b) string("[z7c") \n\
;; Ctrl Meta Shift BackSpace: string(0x1b) string("[z8c") \n\
;; \
;; ~Ctrl ~Meta ~Shift Pause: string(0x1b) string("[zd") \n\
;; ~Ctrl ~Meta Shift Pause: string(0x1b) string("[z2d") \n\
;; ~Ctrl Meta ~Shift Pause: string(0x1b) string("[z3d") \n\
;; ~Ctrl Meta Shift Pause: string(0x1b) string("[z4d") \n\
;; Ctrl ~Meta ~Shift Pause: string(0x1b) string("[z5d") \n\
;; Ctrl ~Meta Shift Pause: string(0x1b) string("[z6d") \n\
;; Ctrl Meta ~Shift Pause: string(0x1b) string("[z7d") \n\
;; Ctrl Meta Shift Pause: string(0x1b) string("[z8d") \n\
;; \
;; ~Ctrl ~Meta ~Shift Sys_Req: string(0x1b) string("[ze") \n\
;; ~Ctrl ~Meta Shift Sys_Req: string(0x1b) string("[z2e") \n\
;; Ctrl ~Meta ~Shift Sys_Req: string(0x1b) string("[z5e") \n\
;; Ctrl ~Meta Shift Sys_Req: string(0x1b) string("[z6e") \n
;; Code:
(defun xterm-extra-remap-function-keys ()
;; If the system has an up-to-date xterm termcap entry, these escapes
;; have already been bound, so we remap them to suit our purposes
(define-key key-translation-map [(f13)] [S-f1])
(define-key key-translation-map [(f14)] [S-f2])
(define-key key-translation-map [(f15)] [S-f3])
(define-key key-translation-map [(f16)] [S-f4])
(define-key key-translation-map [(f17)] [S-f5])
(define-key key-translation-map [(f18)] [S-f6])
(define-key key-translation-map [(f19)] [S-f7])
(define-key key-translation-map [(f20)] [S-f8])
(define-key key-translation-map [(f21)] [S-f9])
(define-key key-translation-map [(f22)] [S-f10])
(define-key key-translation-map [(f23)] [S-f11])
(define-key key-translation-map [(f24)] [S-f12])
(define-key key-translation-map [(f25)] [C-f1])
(define-key key-translation-map [(f26)] [C-f2])
(define-key key-translation-map [(f27)] [C-f3])
(define-key key-translation-map [(f28)] [C-f4])
(define-key key-translation-map [(f29)] [C-f5])
(define-key key-translation-map [(f30)] [C-f6])
(define-key key-translation-map [(f31)] [C-f7])
(define-key key-translation-map [(f32)] [C-f8])
(define-key key-translation-map [(f33)] [C-f9])
(define-key key-translation-map [(f34)] [C-f10])
(define-key key-translation-map [(f35)] [C-f11])
(define-key key-translation-map [(f36)] [C-f12])
(define-key key-translation-map [(f37)] [S-C-f1])
(define-key key-translation-map [(f38)] [S-C-f2])
(define-key key-translation-map [(f39)] [S-C-f3])
(define-key key-translation-map [(f40)] [S-C-f4])
(define-key key-translation-map [(f41)] [S-C-f5])
(define-key key-translation-map [(f42)] [S-C-f6])
(define-key key-translation-map [(f43)] [S-C-f7])
(define-key key-translation-map [(f44)] [S-C-f8])
(define-key key-translation-map [(f45)] [S-C-f9])
(define-key key-translation-map [(f46)] [S-C-f10])
(define-key key-translation-map [(f47)] [S-C-f11])
(define-key key-translation-map [(f48)] [S-C-f12]))
(defun xterm-extra-bind-keys ()
(let ((map (make-sparse-keymap)))
;; This section is taken verbatim from term/xterm.el, which we are
;; going to overrride here, so we include these bindings again
(define-key map "\e[A" [up])
(define-key map "\e[B" [down])
(define-key map "\e[C" [right])
(define-key map "\e[D" [left])
(define-key map "\e[1~" [home])
(define-key map "\e[2~" [insert])
(define-key map "\e[3~" [delete])
(define-key map "\e[4~" [select])
(define-key map "\e[5~" [prior])
(define-key map "\e[6~" [next])
(define-key map "\e[11~" [f1])
(define-key map "\e[12~" [f2])
(define-key map "\e[13~" [f3])
(define-key map "\e[14~" [f4])
(define-key map "\e[15~" [f5])
(define-key map "\e[17~" [f6])
(define-key map "\e[18~" [f7])
(define-key map "\e[19~" [f8])
(define-key map "\e[20~" [f9])
(define-key map "\e[21~" [f10])
(define-key map "\e[23~" [f11])
(define-key map "\e[24~" [f12])
(define-key map "\e[29~" [print])
(define-key map "\e[2;2~" [S-insert])
(define-key map "\e[3;2~" [S-delete])
(define-key map "\e[5;2~" [S-prior])
(define-key map "\e[6;2~" [S-next])
(define-key map "\e[2;5~" [C-insert])
(define-key map "\e[3;5~" [C-delete])
(define-key map "\e[5;5~" [C-prior])
(define-key map "\e[6;5~" [C-next])
(define-key map "\eOA" [up])
(define-key map "\eOB" [down])
(define-key map "\eOC" [right])
(define-key map "\eOD" [left])
(define-key map "\eOF" [end])
(define-key map "\eOH" [home])
(define-key map "\eO2A" [S-up])
(define-key map "\eO2B" [S-down])
(define-key map "\eO2C" [S-right])
(define-key map "\eO2D" [S-left])
(define-key map "\eO2F" [S-end])
(define-key map "\eO2H" [S-home])
(define-key map "\eO5A" [C-up])
(define-key map "\e[1;5A" [C-up])
(define-key map "\eO5B" [C-down])
(define-key map "\e[1;5B" [C-down])
(define-key map "\eO5C" [C-right])
(define-key map "\e[1;5C" [C-right])
(define-key map "\eO5D" [C-left])
(define-key map "\e[1;5D" [C-left])
(define-key map "\eO5F" [C-end])
(define-key map "\e[1;5F" [C-end])
(define-key map "\eO5H" [C-home])
(define-key map "\e[1;5H" [C-home])
;; Even if the local machine has an up-to-date xterm and termcap
;; entry, the remote machine may not have an up-to-date termcap, in
;; which case, the escapes dealt with in the function above
;; (xterm-extras-remap-function-keys) will not have been bound to any
;; mapping, so we must bind the escapes here. We probably ought not
;; to do both, but I don't know how to detect what sort of termcap
;; entry for xterm the host machine has.
(define-key map "\eO2P" [S-f1])
(define-key map "\eO2Q" [S-f2])
(define-key map "\eO2R" [S-f3])
(define-key map "\eO2S" [S-f4])
(define-key map "\e[15;2~" [S-f5])
(define-key map "\e[17;2~" [S-f6])
(define-key map "\e[18;2~" [S-f7])
(define-key map "\e[19;2~" [S-f8])
(define-key map "\e[20;2~" [S-f9])
(define-key map "\e[21;2~" [S-f10])
(define-key map "\e[23;2~" [S-f11])
(define-key map "\e[24;2~" [S-f12])
(define-key map "\eO5P" [C-f1])
(define-key map "\eO5Q" [C-f2])
(define-key map "\eO5R" [C-f3])
(define-key map "\eO5S" [C-f4])
(define-key map "\e[15;5~" [C-f5])
(define-key map "\e[17;5~" [C-f6])
(define-key map "\e[18;5~" [C-f7])
(define-key map "\e[19;5~" [C-f8])
(define-key map "\e[20;5~" [C-f9])
(define-key map "\e[21;5~" [C-f10])
(define-key map "\e[23;5~" [C-f11])
(define-key map "\e[24;5~" [C-f12])
(define-key map "\eO6P" [S-C-f1])
(define-key map "\eO6Q" [S-C-f2])
(define-key map "\eO6R" [S-C-f3])
(define-key map "\eO6S" [S-C-f4])
(define-key map "\e[15;6~" [S-C-f5])
(define-key map "\e[17;6~" [S-C-f6])
(define-key map "\e[18;6~" [S-C-f7])
(define-key map "\e[19;6~" [S-C-f8])
(define-key map "\e[20;6~" [S-C-f9])
(define-key map "\e[21;6~" [S-C-f10])
(define-key map "\e[23;6~" [S-C-f11])
(define-key map "\e[24;6~" [S-C-f12])
;; These meta-modified combinations are not defined in termcap or
;; term/xterm.el at all. I am assuming here that the Alt key is
;; being used for Meta
(define-key map "\eO3P" [M-f1])
(define-key map "\eO3Q" [M-f2])
(define-key map "\eO3R" [M-f3])
(define-key map "\eO3S" [M-f4])
(define-key map "\e[15;3~" [M-f5])
(define-key map "\e[17;3~" [M-f6])
(define-key map "\e[18;3~" [M-f7])
(define-key map "\e[19;3~" [M-f8])
(define-key map "\e[20;3~" [M-f9])
(define-key map "\e[21;3~" [M-f10])
(define-key map "\e[23;3~" [M-f11])
(define-key map "\e[24;3~" [M-f12])
(define-key map "\eO4P" [S-M-f1])
(define-key map "\eO4Q" [S-M-f2])
(define-key map "\eO4R" [S-M-f3])
(define-key map "\eO4S" [S-M-f4])
(define-key map "\e[15;4~" [S-M-f5])
(define-key map "\e[17;4~" [S-M-f6])
(define-key map "\e[18;4~" [S-M-f7])
(define-key map "\e[19;4~" [S-M-f8])
(define-key map "\e[20;4~" [S-M-f9])
(define-key map "\e[21;4~" [S-M-f10])
(define-key map "\e[23;4~" [S-M-f11])
(define-key map "\e[24;4~" [S-M-f12])
;; These are often unavailable under X (because Alt-Ctrl-Fx is
;; used by default to change VT), but for the sake of completeness
;; they are included here.
(define-key map "\eO7P" [M-C-f1])
(define-key map "\eO7Q" [M-C-f2])
(define-key map "\eO7R" [M-C-f3])
(define-key map "\eO7S" [M-C-f4])
(define-key map "\e[15;7~" [M-C-f5])
(define-key map "\e[17;7~" [M-C-f6])
(define-key map "\e[18;7~" [M-C-f7])
(define-key map "\e[19;7~" [M-C-f8])
(define-key map "\e[20;7~" [M-C-f9])
(define-key map "\e[21;7~" [M-C-f10])
(define-key map "\e[23;7~" [M-C-f11])
(define-key map "\e[24;7~" [M-C-f12])
(define-key map "\eO8P" [S-M-C-f1])
(define-key map "\eO8Q" [S-M-C-f2])
(define-key map "\eO8R" [S-M-C-f3])
(define-key map "\eO8S" [S-M-C-f4])
(define-key map "\e[15;8~" [S-M-C-f5])
(define-key map "\e[17;8~" [S-M-C-f6])
(define-key map "\e[18;8~" [S-M-C-f7])
(define-key map "\e[19;8~" [S-M-C-f8])
(define-key map "\e[20;8~" [S-M-C-f9])
(define-key map "\e[21;8~" [S-M-C-f10])
(define-key map "\e[23;8~" [S-M-C-f11])
(define-key map "\e[24;8~" [S-M-C-f12])
;; A number of these are usually not available: for example, Shift +
;; Prior (and any other modifier) normally scrolls up; but for
;; completeness they are included here.
(define-key map "\e[5;2~" [S-prior])
(define-key map "\e[5;3~" [M-prior])
(define-key map "\e[5;4~" [M-S-prior])
(define-key map "\e[5;5~" [C-prior])
(define-key map "\e[5;6~" [C-S-prior])
(define-key map "\e[5;7~" [M-C-prior])
(define-key map "\e[5;8~" [M-C-S-prior])
(define-key map "\e[6;2~" [S-next])
(define-key map "\e[6;3~" [M-next])
(define-key map "\e[6;4~" [M-S-next])
(define-key map "\e[6;5~" [C-next])
(define-key map "\e[6;6~" [C-S-next])
(define-key map "\e[6;7~" [M-C-next])
(define-key map "\e[6;8~" [M-C-S-next])
;; The simple shift-key and control-key combinations are already
;; defined in the section from term/xterm.el reproduced above.
(define-key map "\eO3H" [M-home])
(define-key map "\eO4H" [M-S-home])
(define-key map "\eO6H" [C-S-home])
(define-key map "\eO7H" [M-C-home])
(define-key map "\eO8H" [M-C-S-home])
(define-key map "\eO3F" [M-end])
(define-key map "\eO4F" [M-S-end])
(define-key map "\eO6F" [C-S-end])
(define-key map "\eO7F" [M-C-end])
(define-key map "\eO8F" [M-C-S-end])
(define-key map "\eO3A" [M-up])
(define-key map "\eO4A" [M-S-up])
(define-key map "\eO6A" [C-S-up])
(define-key map "\eO7A" [M-C-up])
(define-key map "\eO8A" [M-C-S-up])
(define-key map "\eO3B" [M-down])
(define-key map "\eO4B" [M-S-down])
(define-key map "\eO6B" [C-S-down])
(define-key map "\eO7B" [M-C-down])
(define-key map "\eO8B" [M-C-S-down])
(define-key map "\eO3C" [M-right])
(define-key map "\eO4C" [M-S-right])
(define-key map "\eO6C" [C-S-right])
(define-key map "\eO7C" [M-C-right])
(define-key map "\eO8C" [M-C-S-right])
(define-key map "\eO3D" [M-left])
(define-key map "\eO4D" [M-S-left])
(define-key map "\eO6D" [C-S-left])
(define-key map "\eO7D" [M-C-left])
(define-key map "\eO8D" [M-C-S-left])
;; Shift+insert combinations may not be available, if they are set
;; to paste from the clipboard
(define-key map "\e[2;2~" [S-insert])
(define-key map "\e[2;3~" [M-insert])
(define-key map "\e[2;4~" [M-S-insert])
(define-key map "\e[2;5~" [C-insert])
(define-key map "\e[2;6~" [C-S-insert])
(define-key map "\e[2;7~" [M-C-insert])
(define-key map "\e[2;8~" [M-C-S-insert])
(define-key map "\e[3;2~" [S-delete])
(define-key map "\e[3;3~" [M-delete])
(define-key map "\e[3;4~" [M-S-delete])
(define-key map "\e[3;5~" [C-delete])
(define-key map "\e[3;6~" [C-S-delete])
(define-key map "\e[3;7~" [M-C-delete])
(define-key map "\e[3;8~" [M-C-S-delete])
(set-keymap-parent map (keymap-parent function-key-map))
(set-keymap-parent function-key-map map)))
(defun xterm-extra-extra-keys ()
;; These are escapes that xterm does not provide by default, but you
;; can induce xterm to send them, if you configure it to do so, by
;; using the x resource settings given at the start of this file
(define-key function-key-map "\e[z2a" [S-tab])
(define-key function-key-map "\e[z3a" [M-tab])
(define-key function-key-map "\e[z4a" [M-S-tab])
(define-key function-key-map "\e[z5a" [C-tab])
(define-key function-key-map "\e[z6a" [S-C-tab])
(define-key function-key-map "\e[z7a" [M-C-tab])
(define-key function-key-map "\e[z8a" [M-C-S-tab])
(define-key function-key-map "\e[z2b" [S-return])
(define-key function-key-map "\e[z3b" [M-return])
(define-key function-key-map "\e[z4b" [M-S-return])
(define-key function-key-map "\e[z5b" [C-return])
(define-key function-key-map "\e[z6b" [C-S-return])
(define-key function-key-map "\e[z7b" [M-C-return])
(define-key function-key-map "\e[z8b" [M-C-S-return])
(define-key function-key-map "\e[z2c" (kbd "S-DEL"))
(define-key function-key-map "\e[z3c" (kbd "M-DEL"))
(define-key function-key-map "\e[z4c" (kbd "M-S-DEL"))
(define-key function-key-map "\e[z5c" (kbd "C-DEL"))
(define-key function-key-map "\e[z6c" (kbd "C-S-DEL"))
(define-key function-key-map "\e[z7c" (kbd "M-C-DEL"))
(define-key function-key-map "\e[z8c" (kbd "M-C-S-DEL"))
(define-key function-key-map "\e[zd" [pause])
(define-key function-key-map "\e[z2d" [S-pause])
(define-key function-key-map "\e[z3d" [M-pause])
(define-key function-key-map "\e[z4d" [M-S-pause])
(define-key function-key-map "\e[z5d" [C-pause])
(define-key function-key-map "\e[z6d" [C-S-pause])
(define-key function-key-map "\e[z7d" [M-C-pause])
(define-key function-key-map "\e[z8d" [S-M-C-pause])
(define-key function-key-map "\e[ze" [Sys_Req])
(define-key function-key-map "\e[z2e" [S-Sys_Req])
(define-key function-key-map "\e[z5e" [C-Sys_Req])
(define-key function-key-map "\e[z6e" [C-S-Sys_Req]))
(defun xterm-extra-screen-keys ()
;; These are necessary when running GNU screen inside an xterm,
;; since even when running "screen -t xterm", the $TERMCAP screen
;; installs for xterm does not seem to correspond to the actual
;; escapes that are sent for a few keys:
(define-key function-key-map "\e[1~" [home])
(define-key function-key-map "\e[2~" [insert])
(define-key function-key-map "\e[4~" [end]))
(defun xterm-extra-keys ()
(xterm-extra-remap-function-keys)
(xterm-extra-bind-keys)
(xterm-extra-extra-keys)
(xterm-extra-screen-keys))
(provide 'xterm-extras)