Khung GUI
Trong các khung GUI (cho dù X11, Windows, OSX, '), Emacs đọc Tabkhóa dưới dạng tab
phím chức năng. Tuy nhiên, vì Tabkhóa trên các thiết bị đầu cuối truyền thống gửi ký tự ^I
( Control + I), Emacs dịch tab
phím chức năng thành ký tự Control + I (ký tự 9), được hiển thị dưới dạng TAB
. Bản dịch này được thực hiện thông qua function-key-map
.
Một bản dịch tương tự xảy ra với một số phím chức năng khác. ( Backspacevà Deletelà một trường hợp gai góc mà tôi sẽ không thảo luận chi tiết ở đây.)
Function key Translated to character Notes
Number Name Decomposition
backspace 127 DEL Ctrl+? May be translated to C-h instead
tab 9 TAB Ctrl+I
linefeed 10 LFD Ctrl+J Few keyboards have this key
return 13 RET Ctrl+M
escape 27 ESC Ctrl+[
Nếu bạn muốn tách Tabkhỏi Ctrl+ Ihoàn toàn, hãy xóa liên kết khỏi function-key-map
:
(define-key function-key-map [tab] nil)
Tuy nhiên, điều này không hữu ích lắm, bởi vì các mục trong function-key-map
bị ghi đè bởi các ràng buộc trong các keymap cụ thể theo chế độ hoặc trong bản đồ toàn cầu. Vì vậy, nếu bạn muốn xác định một ràng buộc khác cho tab
, chỉ cần thực hiện (trong Elisp, không tương tác, bởi vì dấu nhắc đọc chính áp dụng function-key-map
bản dịch để cuối cùng bạn không bị đảo ngược TAB
và không tab
):
(global-set-key [tab] '…)
(define-key some-mode-map [tab] '…)
Tất cả các chế độ tiêu chuẩn sửa đổi hành động của Tabkhóa đều thực hiện bằng cách sửa đổi TAB
khóa, đó là biệt danh cho C-i
ký tự được tạo bởi tổ hợp phím Ctrl+ I. Nếu bạn muốn các ràng buộc tiêu chuẩn được áp dụng tab
thay vì C-i
, hãy để lại function-key-map
và chế độ keymap một mình, và thay vào đó chuyển hướng Ctrl+ Isang một khóa khác.
(define-key input-decode-map [(control ?i)] [control-i])
(define-key input-decode-map [(control ?I)] [(shift control-i)])
(define-key some-mode-map [control-i] '…)
Bây giờ Emacs sẽ báo cáo Ctrl+ Inhư là <control-i>
(dịch từ TAB
). Điều này không đẹp, nhưng không thể tránh khỏi: việc in ấn nhân vật 9 như TAB
được tích hợp vào mã nguồn Emacs.
Khung thiết bị đầu cuối
Trong các khung thiết bị đầu cuối, vấn đề khó hơn và thường là không thể. Thiết bị đầu cuối không truyền khóa, chúng truyền ký tự (chính xác hơn là trên thực tế, chúng truyền byte). Các Tabphím được truyền như các ký tự tab - đó là Control + I, giống như những gì tổ hợp phím Ctrl+ Itạo ra. Các phím chức năng không có ký tự tương ứng (như phím con trỏ) được truyền dưới dạng các chuỗi thoát, tức là các chuỗi ký tự bắt đầu bằng ESC
= Control + [(đó là lý do tại sao Emacs định nghĩa escapelà khóa tiền tố - ESC
phải là tiền tố). Xem Làm thế nào để đầu vào bàn phím và đầu ra văn bản hoạt động? để có thêm nền tảng.
Có một vài thiết bị đầu cuối có thể được cấu hình để gửi các chuỗi khóa khác nhau cho các phím chức năng, nhưng không nhiều. Cả libtermkey / libtickit của LeoNerd và xterm của Thomas Dickey (kể từ phiên bản 216) đều hỗ trợ điều này. Trong Xterm, tính năng này là tùy chọn và được kích hoạt thông qua modifyOtherKeys
tài nguyên. Tuy nhiên, tôi không biết bất kỳ trình giả lập thiết bị đầu cuối phổ biến nào ngoài xterm hỗ trợ điều này, đặc biệt là nhiều trình giả lập được xây dựng trên libvte . Một số trình giả lập thiết bị đầu cuối cho phép bạn thực hiện việc này một cách thủ công thông qua sự tương ứng do người dùng xác định từ các tổ hợp phím để thoát khỏi chuỗi.
Cơ chế này cho phép phân biệt nhiều tổ hợp phím, không chỉ tab / Ci, return / Cm và esc / C- [. Xem các vấn đề với keybindings khi sử dụng terminal để có mô tả chi tiết hơn.
Tính năng xterm cơ bản được hỗ trợ kể từ Emacs 24.4. Tuy nhiên, nguyên tắc cơ bản (đặc biệt Tab, Return, Escape, Backspace) vẫn gửi ký tự điều khiển truyền thống, bởi vì đó là những gì các ứng dụng mong đợi. Có một chế độ trong đó Ctrl+ lettergửi một chuỗi thoát thay vì ký tự điều khiển. Vì vậy, để phân biệt các phím chức năng với các Ctrlkết hợp trên Emacs 24.4, hãy sửa đổi sự hỗ trợ của nó modifyOtherKeys
để sử dụng chế độ này bằng cách đặt tài nguyên thành 2 thay vì 1.
;; xterm with the resource ?.VT100.modifyOtherKeys: 2
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
"Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
(if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
(and (<= ?a c) (<= c ?z)))
(logand c ?\x1f)
(logior (lsh 1 26) c))))
(if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
(if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
(vector c))
(defun my-eval-after-load-xterm ()
(when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
;; Override the standard definition to set modifyOtherKeys to 2 instead of 1
(defun xterm-turn-on-modify-other-keys ()
"Turn the modifyOtherKeys feature of xterm back on."
(let ((terminal (frame-terminal)))
(when (and (terminal-live-p terminal)
(memq terminal xterm-modify-other-keys-terminal-list))
(send-string-to-terminal "\e[>4;2m" terminal))))
(let ((c 32))
(while (<= c 126)
(mapc (lambda (x)
(define-key xterm-function-map (format (car x) c)
(apply 'character-apply-modifiers c (cdr x))))
'(;; with ?.VT100.formatOtherKeys: 0
("\e\[27;3;%d~" meta)
("\e\[27;5;%d~" control)
("\e\[27;6;%d~" control shift)
("\e\[27;7;%d~" control meta)
("\e\[27;8;%d~" control meta shift)
;; with ?.VT100.formatOtherKeys: 1
("\e\[%d;3~" meta)
("\e\[%d;5~" control)
("\e\[%d;6~" control shift)
("\e\[%d;7~" control meta)
("\e\[%d;8~" control meta shift)))
(setq c (1+ c)))))
(define-key xterm-function-map "")
t)
(eval-after-load "xterm" '(my-eval-after-load-xterm))