LINUX.ORG.RU

[Emacs] Странности с привязками клавиш

 


0

0

Простая, казалось бы, процедура - назначить нужные мне сочетания клавиш в Емаксе - занимает у меня уже не первый день.
Странный этот Емакс со всех сторон :-)
У меня версия GNU Emacs 22.3.1.

Вот, например, такой .emacs:

(global-set-key [A-g] 'goto-line) ; переход на строку
(global-set-key [A-backspace] 'undo) ; откат

Почему-то первая привязка в иксовом варианте Емакса срабатывает по
alt-g-g вмесо alt-g.

А нажатие alt-backspace в иксовом варианте вообще вызывает удаление слова вместо отмены.

Так и должно быть?

Теперь такой конфиг:

(global-set-key [M-g] 'goto-line) ; переход на строку
(global-set-key [M-backspace] 'undo) ; откат

Первая привязка в иксовом и консольном вариантах Емакса срабатывает по alt-g-g вместо alt-g.

Вторая в иксовом варианте работает нормально, а в консольном вызывает удаление слова вместо отмены.

Это правильно?

Далее такой конфиг:

(global-set-key "\M-[" 'upcase-word)
(global-set-key [f8] 'overwrite-mode)

При этом в иксовой версии нормально работают оба сочетания (альт-[ и F8). А в консольной первое работает, а F8 почему-то вместо overwrite-mode добавляет к слову "19~" и делает upcase-word.

Ничего не понимаю!

Теперь такой конфиг:

(cua-mode)

В иксовой версии shift+стрелки обеспечивают выделение, в консольной - нет. Как так?

И вот такое:

(global-set-key [s-backspace] 'overwrite-mode)

В исксовой версии win-backspace работает нормально. Консольный же Емакс в konsole по win-backspace отрабатывает, похоже, просто backspace. В "настоящей" консоли (ушёл из Иксов по ctrl-alt-f2 и там запустил Емакс) по первому нажатию win-backspace Емакс вместо включения режима замены говорит "C-h (Type ? for further options)-".



Re: [Emacs] Странности с привязками клавиш
P.S.

Вот такая строка:

(global-set-key [M-g] 'goto-line)

работает по alt-g-g, а такая:

(global-set-key "\M-g" 'goto-line)

просто по alt-g.

sergey_feo
() автор топика

> (global-set-key [A-g] 'goto-line)

> в иксовом варианте Емакса срабатывает по alt-g-g вмесо alt-g.


1. Alt — это не Meta!

2. `M-g` — стандартный префикс для `goto-keymap`, а `M-g M-g` по
умолчанию привязано к `goto-line`, а потому так и работает.

> (global-set-key [A-backspace] 'undo)


> А нажатие alt-backspace в иксовом варианте вообще вызывает удаление

> слова вместо отмены.


Разумеется, ведь нажатие Alt-Backspace порождает клавиатурное событие
`[M-backspace]` (из одной клавиши `<M-backspace>`, которая
транслируется в `M-DEL`), привязку которого ты не менял.

> (global-set-key [M-g] 'goto-line)


> в иксовом и консольном вариантах Емакса срабатывает по alt-g-g

> вместо alt-g.


Раз уж ты не хочешь использовать для своего удобства функцию `kdb`, то
обрати внимание на то, что в векторной форме представления
клавиатурных событий модификатор Meta пишеттся как `?\M`, поэтому
правильно биндинг выглядит так:

(global-set-key [?\M-g] 'goto-line)

Биндинг с `[M-backspace]` работает за счёт того, что это событие
воспринимается как нажатие специальной кнопки `<M-backspace>`.

> а F8 почему-то вместо overwrite-mode добавляет к слову "19~" и

> делает upcase-word.


Это из-за чего-то типа

string F8 = "\033[19~"

в используемом тобой консольном файле keymap :)

Sphinx ★★☆☆
()
Ответ на: комментарий от Sphinx

>> (global-set-key [A-g] 'goto-line) ; переход на строку
>> в иксовом варианте Емакса срабатывает по alt-g-g вмесо alt-g.

> 1. Alt — это не Meta!

> 2. `M-g` — стандартный префикс для `goto-keymap`, а `M-g M-g` по

> умолчанию привязано к `goto-line`, а потому так и работает.


Т.е. не то, чтобы (global-set-key [A-g] 'goto-line) работало как alt-g-g. Оно вообще не работало. Теперь понятно.

>> (global-set-key [A-backspace] 'undo)

>> А нажатие alt-backspace в иксовом варианте вообще вызывает удаление

>> слова вместо отмены.


> Разумеется, ведь нажатие Alt-Backspace порождает клавиатурное

> событие

> `[M-backspace]` (из одной клавиши `<M-backspace>`, которая

> транслируется в `M-DEL`), привязку которого ты не менял.


Хорошо, [A-backspace] - это некорректно и потому, как я понимаю, Емакс его не воспринимает и действует по умолчанию. Но [?\A-backspace] должно работать?

> в векторной форме представления

> клавиатурных событий модификатор Meta пишеттся как `?\M`, поэтому

> правильно биндинг выглядит так:

> (global-set-key [?\M-g] 'goto-line)


Да, спасибо, так работает. Значит, я везде векторную форму неправильно написал :-)
Но если написать по аналогии

(global-set-key [?\M-backspace] 'undo)

то получаю ругательство "Invalid read syntax: ?".

Это как раз из-за того, что M-backspace - специальное сочетание?
Зачем нужно это специальное сочетание? По-моему, это лишняя сущность. И без неё в Емаксе сложности хватает.

>> а F8 почему-то вместо overwrite-mode добавляет к слову "19~" и

>> делает upcase-word.


> Это из-за чего-то типа

> string F8 = "\033[19~"

> в используемом тобой консольном файле keymap :)


Немного недопонял: это консоль кривая (string F8 = "\033[19~" - неправильно), Емакс кривой (должен понимать такие вещи) или я кривой? Кого настраивать надо? :-)
По-моему, вещи вроде keymap - почти всегда внутреннее дело ОС и программ, и пользователя они касаться в большинстве случаев не должны.

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

> Но [?\A-backspace] должно работать?

Нет, твой Alt порождает модификатор Meta. Хочешь нажимать Alt-Bs —
привязывай [M-backspace].

> (global-set-key [?\M-backspace] 'undo)


Нет, такой синтаксис с символьными обозначениями использовать нельзя
(см. «2.3.3 Character Type»).

Чтобы не путаться, пользуйся `kbd`:

(global-set-key (kbd "M-\b") 'undo)

> Немного недопонял: это консоль кривая


Как я понимаю, просто в консоли обычно функциональные клавиши где-то в
используемом файле keymap (см. `/usr/share/keymaps/`) привязываются к
каким-то сочетаниям. Не знаю, зачем это и что это. Это работает ДО
Емакса, так что его колбасит :)

Sphinx ★★☆☆
()
Ответ на: комментарий от Sphinx

>> (global-set-key [?\M-backspace] 'undo)
> Нет, такой синтаксис с символьными обозначениями использовать нельзя

> (см. «2.3.3 Character Type»).


Просмотрел по одной диагонали и по другой, но просветления не наступило.
Да, backspace там не упоминается. Зато есть \b и примеры выкрутасов вроде ?\C-\M-b и ?\M-\002. Составленный по аналогии выкрутас
(global-set-key "?\M-\b" 'undo) приводит к ругани "error: Key sequence ? C-M-h starts with non-prefix key ?". А (global-set-key [?\M-\b] 'goto-line) игнорируется.

> Чтобы не путаться, пользуйся `kbd`:

> (global-set-key (kbd "M-\b") 'undo)


Есть способ задания привязок клавиш строками, есть векторами, а это какой-то секретный третий способ. В Emacs Manual'е, встроенном в мою версию Емакса (22.3.1), в п. 57.4.6 «Rebinding Keys in Your Init File» я этого не нашёл :-)
Зато вот тут:
http://www.xemacs.org/Documentation/21.5/html/xemacs-faq_8.html
рассказывается про read-kbd-macro, которая подозрительно похожа на kbd: "Another (even safer) way to be sure of the key-sequences is to use the read-kbd-macro function, which takes a string like `C-c <up>', and converts it to the internal key representation of the Emacs you use. The function is available both on XEmacs and GNU Emacs".
Т.е. read-kbd-macro берёт аргументом вроде как человеко-читаемое описание клавиш и переделывает в нужное конкретному Емаксу представление.
При этом в справке моего Емакса говорится, что read-kbd-macro "Read the region as a keyboard macro definition", а человеко-читаемую форму в представление переделывает kbd: "Convert keys to the internal Emacs key representation."

Что же всё-таки лучше: kbd или read-kbd-macro? И чем они лучше векторной формы?


P.S. Огромное спасибо, что потратили своё личное время на разбирательство с моими проблемами :-)

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

А, совсем забыл про проблему с F8.

Вот с этим:

(global-set-key "\M-[" 'upcase-word)
(global-set-key [f8] 'overwrite-mode)

в консольной версии F8 не работает (точнее, делает не то). Но без первой строчки, т.е. вот так:

(global-set-key [f8] 'overwrite-mode)

- работает! Т.е. keymap здесь не причём, это всё-таки где-то в Емаксе странность.

То же самое с kbd:

так:

(global-set-key (kbd "M-[") 'upcase-word)
(global-set-key (kbd "<f8>") 'overwrite-mode)

F8 в консольном варианте не работает (делает не то), а без первой строчки работает.

sergey_feo
() автор топика

Для правильной работы Backspace в терминале xterm надо добавить в .Xdefaults
(решение с емаксвики)

xterm*ttyModes: erase ^?
xterm*VT100*translations:       #override \
    <Key>BackSpace: string(0x7f)
xterm*backarrowKeyIsErase:      true

проблема с
(global-set-key "\M-[" 'upcase-word)
(global-set-key [f8] 'overwrite-mode) 
возникает из за того что f8 == \033[19~ , META == ESC == \033 , и вот когда вы назначаете M-[ то получаете \033[ , и поэтому при нажатие f8 вначале выполняется M-[ и вставляется 19~. А вот как решить не совсем ясно, можно конечно не назначать это сочетание (что не есть выход), можно попробовать сказать емаксу что META != ESC.

madepa
()
Ответ на: комментарий от madepa

> добавить в .Xdefaults

Но все, кроме Емакса, в konsole понимают забой нормально. Не получится так, что решение с Емаксвики Емакс исправит, а остальное попортит? :-)

> сказать емаксу что META != ESC.

А как это сказать?

А вообще, я уже отказался от M-[ и отчаялся настроить консольный Емакс...

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

В Emacs, backspace ≠ \b.

> это какой-то секретный третий способ.


Это написано в «(elisp)22.1 Key Sequences».

(kbd keys) == (read-kbd-macro keys)

На самом деле есть ещё способ описывать события через списки типа
`(control meta ?a))` и функцию `event-convert-list` :)

Sphinx ★★☆☆
()
Ответ на: комментарий от Sphinx

Я пока остановился на третьем варианте:
(global-set-key (kbd "M-<backspace>") 'undo)

Эх, если бы хоть один вариант работал в консоли безо всяких хитростей :-)

sergey_feo
() автор топика
Ответ на: комментарий от sergey_feo

Не готовый рецепт, но кое-что работает...

Итак имею: Debian, консоль (консольную, т.е. не в X), emacs 22.2.1

Желаю: привязать control-f11 на org-clock-in, shift-f11 на org-clock-out

Делаю:

1. В /etc/console-setup/boottime.kmap.gz корежу строчку:

keycode 87 = F11 F21 F51 F61 F31 F41 F81 F81 Console_11 Console_2...

на

keycode 87 = F11 F14 F81 F81 F13 F14 F81 F81 Console_11 Console_2...

и добавляю в конце файла:

string F13 = "\033[25~"

string F14 = "\033[25~"

2. В .emacs пишу:

(global-set-key [f13] 'org-clock-in)

(global-set-key [f14] 'org-clock-in)

Это работает. Почему не готовый рецепт: на самом деле хотел привязку не к Shift, а к Alt, но не получилось. Возможно просто не дорыл до конца.

greyrp
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.