Ви дійсно не можете змінити C-[прив’язку на картах рівня користувачів, як це було б зроблено global-set-key
. Однак ви можете змінити це як подія на клавіатурі, перш ніж воно дістанеться до цих клавіш. Ви можете сказати, наприклад:
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
а потім використовувати [control-bracketleft]
у ваших картах. Досить просто, чи не так?
Режисерська в
На жаль, це не так просто, і це рішення потребує певних коригувань, які виявляться дуже болісними. Вас попередили. Але давайте розберемося спочатку, чому карти на рівні користувача не можуть відповісти на це питання. Далі я посилаюсь на посібник Emacs Lisp для emacs 26.1, коли я кажу "бачити щось" без більшої точності.
C-[інтерпретується на дуже ранній стадії як символ управління ASCII ESC
(див. 21.7.1 - Події на клавіатурі ). Цей код розповсюджується на всі інші місця як префікс для більш довгих послідовностей. Для цього є причина: ESC
насправді мета-префікс (див. meta-prefix-char
), І всі прив'язки, які M-щось читають
, перетворяться на послідовність, яка починається з ESC
. Таким чином, зміни глобальної карти буде недостатньо: спочатку потрібно змінити meta-prefix-char
, а потім перезавантажити ESC
нову meta-prefix-char
в кожній карті, яка використовується, M-перш ніж можна безпечно зробити карту C-[.
Добре тоді, звичайно: давайте використовувати input-decode-map
. Існує кілька подібних карт, які ми можемо спокуситись використовувати (див. Розділи 21.8.3 та 22.14), але давайте дотримуватимемось цієї. І добре ... це працює! Ви закінчили, чи не так?
Власне, ні, історія тут не закінчується. Це працює ... поки ви використовуєте віконну систему. Якщо через невдачу ви потрапили до в'язниці на консолі linux в аварійному стані, ви розумієте, наскільки драматичною стала ситуація: клавіші зі стрілками Homeі, звичайно, M-прив’язки - це все сміття. Чому? Тому що, коли термінал каже ESC
(що він робить, коли ви вводите C-[), він дійсно означає ESC
і запускає послідовність такого ж типу, яку він використовує для передачі символів, що не належать до ASCII.
Спостерігаючи за катастрофою, ви можете вважати розумним захистити вищезгадану input-decode-map
модифікацію таким чином, що вона активується лише у випадку, якщо віконна система керує клавіатурою:
(let ((frame (framep (selected-frame))))
(or (eq t frame)
(eq 'pc frame)
(define-key input-decode-map
(kbd "C-[")
[control-bracketleft])
)))
Потім термінали працюють, як раніше.
Тепер ми можемо мати справу з C-[терміналами? Насправді, так, ми можемо, як на консолі Linux, так і на інших емуляторах терміналів, з якими я можу грати. Але це робить історію досить довгою, оскільки на сцену виходять нові персонажі. Бо це вже не один emacs: термінал зараз відіграє центральну роль.
Давайте надамо слух тому, що має сказати консоль Linux. Введіть C-vперед якоюсь клавішею, щоб почути це просто. C-[є ESC
; так і є Esc. Стрілка вгору звучить як ESC [ A
, поки M-aє
ESC A
. Хм ... Схоже, це мета-кругообіг в електронних системах, чи не так? У всякому разі.
Якщо ми не готові зіграти деякі трюки на основі часу, який минув між персонажними подіями (який, до речі, не відрізнятиметься
Escвід C-[), схоже, у нас немає іншого вибору, як сказати консолі, що ми насправді не маємо на увазі ESC
коли ми друкуємо C-[. Більше того, виявляється досить скоро, що C-[це не єдина проблема з кодами терміналів акцій: модифікатори в більшості випадків стирають передану інформацію. Нам потрібно налаштувати термінал з тієї самої причини, що ми налаштовуємо emacs: це було б набагато практичніше, якби ми це зробили.
У цей момент ви наважитеся глибоко зазирнути в очі документації свого терміналу: підручні сторінки loadkeys(1)
для консолі linux, для xterm
xterm(1)
в розділі Користувацькі прив’язки ключів та що-небудь, що я не знаю для інших терміналів. В KDE konsole
, ви можете задати користувальницькі переклади в Налаштування / Edit Current Profile ...
потім Keyboard . Ось уривок з ~/.local/share/konsole/Test.keytab
гри після цього останнього діалогового вікна:
key [+Ctrl+AnyModifier : "\EO*["
Після отримання терміналу ESC O 5 [
для
надсилання C-[(як у наведеній вище конфігурації), ви можете повернутися до emacs. Звичайно, ви ще не закінчили.
Щоб доручити emacs, яким діалектом використовується даний термінал, ви можете скоригуватися input-decode-map
. Так, це випадково той самий, який ми змінили на початку цієї історії, і це саме те, що
term/xterm.el
стосується xterm. Хорошим місцем для коригування є tty-setup-hook
(див. Розділ 40.1.3):
(add-hook 'tty-setup-hook
(lambda ()
(let ((term (getenv "TERM")))
(cond
(;; xterm-function-map not in doc, but in term/xterm.el
(boundp 'xterm-function-map)
(map-my-term-codes xterm-function-map))
((equal term "linux")
(map-my-term-codes input-decode-map))
)
)))
Будьте в курсі, що цей гак працює лише в тому випадку, якщо ви перебуваєте в терміналі. Таким чином, ви не можете вставити сюди код для ініціалізації віконної системи. Ось функція перекладу сама по собі:
(defun map-my-term-codes (map)
(define-key map (kbd "M-O 5 [")
[control-bracketleft])
)
І тоді можна трохи відпочити: це кінець подорожі. Звичайно, якщо вам не байдуже термінали, це швидко, оскільки ви пропустите всю хворобливу частину. Але ви визнаєте, це теж досить неповно.
Дві заключні ноти:
Я вибираю ESC O 5 [
кодувати C-[. Це лише приклад: я не буду робити вигляд, що це вдалий вибір. Тільки 5
частина, що означає C-, здається, підкоряється якійсь усталеній конвенції
конфігурація консолі linux залишає поганий смак: здається, неможливо зробити прив'язку без використання проміжного існуючого символу, а ті, які мені знадобляться
, не існують . Я використовую символи в F21- F246діапазоні , як і в більшості прикладів інтернет, але це не дуже задовольняє. Це нормально для декількох непов'язаних прив'язок, але це не буде слугувати систематичною схемою.
Редагувати
- Я закінчив це зі Escсправою - яка має свою особистість - в іншому дописі: Як видалити прив’язки до ключа префіксу ESC
ось фрагмент конфігурації для подачі loadkeys
. Я поміщаю це в /root/custom.kmap і завантажую його, коли мені потрібно (що рідко). Моя фактична конфігурація також відображає стрілки та різні комбінації модифікатора, але це досить довго, вибір символів та послідовностей сумнівний, і я не впевнений, що клавіші моєї клавіатури будуть відповідати вашим. Тож давайте тримати це на належному рівні: це не що інше, як ілюстрація.
keymaps 0-127
# http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
# web+man:keymaps
# web+man:loadkeys
# escape
keycode 1 = F100
alt keycode 1 = Escape # keep the Escape behavior somewhere
# keycode 26 = bracketleft
control keycode 26 = F115 # Control_bracketleft does not exist
string F100 = "\033OO" # map this to [escape] in map-my-term-codes
string F115 = "\033O5["