Як зв’язати С- [по-справжньому?


10

C-[еквівалент клавіші втечі на англійських клавіатурах США, таким чином, будь-яка спроба прив’язати її буде зіпсувати M-поведінку.

Здається, Emacs не має проблем із розмовою <escape>та C-[розділенням у кадрах графічного інтерфейсу. Наступні роботи добре, а в’язки, починаючи з цього, M-залишаються працювати:

(global-set-key (kbd "<escape>") (lambda () (interactive) (message "<escape>")))

Однак, якщо я пов'язую

(global-set-key (kbd "C-[") (lambda () (interactive) (message "C-[")))

раптом emacs збожеволіє і зобов'язує, як M-xперерва. Більше того, натискання C-[відмовляється запускати зв'язану лямбда. Цікаво, що C-x @ c [(застосувати управління модифікатором до відкритої дужки) все ще говориться C-[ is undefined.

Чи є якийсь спосіб зв’язати щось, C-[не порушуючи emacs?

Відповіді:


7

Ви дійсно не можете змінити 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["
    

1
Дякую, це чудова відповідь. Але, безумовно, навіть чудова відповідь, як це, безумовно, не потрібно стискати 34 рази вгорі на першій сторінці. Кожна помилка має невелику вартість, яку поділяє спільнота: перевірка на наявність спаму, пошук нового цікавого вмісту тощо. Можливо, ви могли б згрупувати незначні покращення разом? Або просто дотримуйтесь того, що у вас є. Якщо говорити з досвіду, то тут немає такого ідеального, як ідеальний пост, у якийсь момент вам просто потрібно рухатися далі.
перестань бути злим"

@Gilles Зрозумів, і вибач за це. Мені не було відомо, що існує якесь питання, яке коригує це за бажанням
Champignac

0

Наступне рішення трохи хитро, але, здається, працює:

Нехай ~/.xbindkeysrcмістять таке:

"xvkbd -xsendevent -text '\[Control_L]\[F13]'"
  m:0x14 + c:34

"xvkbd -xsendevent -text '\[Control_L]\[F14]'"
  m:0x14 + c:35

Тепер xbindkeysперекладемо C-[на C-<f13>та C-]до C-<f14>, щоб вони могли вільно зв’язуватися в emacs. Ви, ймовірно , хочете зв'язати abort-recursive-editз чим - то іншим , ніж C-], наприклад, C-S-g.

Мінус у тому, що зараз C-[порушено в кожному додатку, крім Emacs, що можна виправити, додавши певну логіку, щоб перевірити, чи передається комбінація клавіш на emacs ...


FWIW, я не думаю, що в цьому є щось особливе C-].
Малабарба

Так, ні я, але чомусь моє C-]прив'язування припинило свою роботу після того, як я запустив Xbindkeys, тож і я відскочив.
Крістоф Маруссі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.