LINUX.ORG.RU

emacs проблема с define-key


0

2

Я буквально пару недель программирую в Emacs Lisp и наткнулся на ошибку, которую не могу побороть: Вот так код работает полностью нормально, без ошибок и предупреждений:

(define-key paredit-mode-map (kbd "M-J")   'paredit-join-sexp-ex)
(define-key paredit-mode-map (kbd "C-k")   'paredit-kill-ex)
(define-key paredit-mode-map (kbd "M-k")   'paredit-kill-backward)

(define-key paredit-mode-map (kbd "M-[") 'paredit-wrap-square)
(define-key paredit-mode-map (kbd "M-{") 'paredit-wrap-curly)

(define-key paredit-mode-map (kbd ")")   'paredit-close-round-ex)
(define-key paredit-mode-map (kbd "}")   'paredit-close-curly-ex) 
(define-key paredit-mode-map (kbd "]")   'paredit-close-square-ex)
(define-key paredit-mode-map (kbd "M-)")   'paredit-close-round-ex-and-newline)
(define-key paredit-mode-map (kbd "M-}")   'paredit-close-curly-ex-and-newline)
(define-key paredit-mode-map (kbd "M-]")   'paredit-close-square-ex-and-newline)
(define-key paredit-mode-map (kbd "C-]")   'paredit-forward-slurp-sexp)
(define-key paredit-mode-map (kbd "C-[")   'paredit-backward-slurp-sexp)
(define-key paredit-mode-map (kbd "C-)")   'paredit-forward-barf-sexp)
(define-key paredit-mode-map (kbd "C-(")   'paredit-backward-barf-sexp)
Но если первые три define-key переместить вниз этого кода, то при перезапуске имакса будет получено:

error: Key sequence M-J starts with non-prefix key ESC

По идее т.к. эти строки идут подряд, то никакой код не должен выполняется, кроме define-key... Это баг?

Кто-нибудь сталкивался с подобным?

22.12 Changing Key Bindings, третий абзац.

22.1 Key Sequences, второй абзац.

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

А, нет. Макрос kbd понимает и такой формат.

Zubok ★★★★★
()

Ну-ка, закомменти

(define-key paredit-mode-map (kbd «C-[») 'paredit-backward-slurp-sexp)

И запусти Emacs снова

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

Ну-ка, закомменти

(define-key paredit-mode-map (kbd «C-[») 'paredit-backward-slurp-sexp)

если закомментить, действительно работает... мистика... неужели баг в define-key?

arte-at-marte
() автор топика
Ответ на: комментарий от arte-at-marte

если закомментить, действительно работает... мистика... неужели баг в define-key?

Не-а, не баг, а фича. Символ «^[» (C-[) - это ESC. Он же и Meta. Его не надо переназначать. Иначе получешь то, что получаешь. Я не сразу это заметил, поэтому меня тоже такое поведение показалось мистическим, а потом вгляделся.

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

Хм... действительно, он единственный из ключей, начинающихся на Control отказывается работать... Но, блин, надо быть умолишенным, чтобы придумать «C-[» использовать в качестве Meta. ~~" И где Вы только откопали эту информацию... сколько всего перечитал, но в упор такого не помню, хотя точно обратил бы внимание... А как ее все таки переопределить или где почитать на эту тему, не подскажете? Ато гугл не дает адекватных результатов при употреблении «C-[», «control bracket» и т.д. И через C-h справку по ней нельзя получить так как это префикс... Я пользуюсь раскладкой Дворака для программистов и здесь это очень удобная клавишая, находящаяся там же, где цифра 2 на qwerty и нажимается без шифта. Ну и просто хочется, чтобы все работало как задумано...

В любом случае спасибо! сам бы я не разобрался...

arte-at-marte
() автор топика
Ответ на: комментарий от arte-at-marte

man ascii -> посмотреть где находится ESC и «[», подумать что означает Ctrl, ????, выгода.

anonymous
()
Ответ на: комментарий от arte-at-marte

Это багаж еще со времен ASCII терминалов. С этим можно жить вполне. Решить проблему можно либо используя другой модификатор - у нас есть еще Super, Hyper, Shift.

В принципе, можно перебиндить Meta на другую комбинацию, а «C-[» забиндить на свое действие. Есть переменная meta-prefix-char (она описана в документации), которая, собственно, и делает преобразование в символ ESC (код 27). Можешь сделать гадость и переопределить ее для режима paredit. Тогда «M-J» на тебя не обидется, но и ^[, и <ESC> станут функцией paredit-backward-slurp-sexp.

Сюда же. Префиксные комбинации тоже можно перевесить на другие комбинации. См. http://www.gnu.org/software/emacs/manual/html_node/elisp/Prefix-Keys.html#Pre...

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

Кстати недавно в emacs-devel проскакивало предложение разделить в GUI enter, tab и С-m, C-i, так как это нужно только в терминале. Так что от устаревших частей понемногу избавятся.

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

Если присвоить meta-prefix-char новое значение, то перестают работать не только ^[ и ESC, но и Meta т.е. в моем случае Alt...

А вот

(keyboard-translate ?\C-\[ ?\H-\[ )

с последующим биндом на H-[

(define-key paredit-mode-map (kbd "H-[") 'paredit-backward-slurp-sexp)

работает отлично! В том числе для C-m и C-i. Правда Hyper я и так использую, поэтому задал трансляцию в сочетания типо мета-гипер-супер тильда... :)

Проблема решена, и, что важнее, стала понятной. Большое спасибо за помощь!

arte-at-marte
() автор топика
Ответ на: комментарий от arte-at-marte

Ан нет... решена, да не полностью: запустил имакс в... не знаю как правильно сказать, в консоли? Ну, в общем без Иксов. И здесь из-за такой трансляции вообще все сочeтания с Meta стали переводиться в paredit-backward-slurp-sexp. При этом, судя по выводу showkey виноват в этом Имакс...

Похоже прав был Zubok. проще всего с этим смириться и не трогать «C-[» и компанию... :'(

arte-at-marte
() автор топика
Ответ на: комментарий от arte-at-marte

Если не используется emacs-daemon, можно использовать переменную window-system для настройки трансляции только в терминале. Вот пример:

(if window-system
	   (message "Not terminal")
	 (message "Terminal"))
Как оно будет работать с emacs-daemon - не знаю.

Array
()
Ответ на: комментарий от arte-at-marte

решена, да не полностью: запустил имакс в... не знаю как правильно сказать, в консоли?

Речь о текстовой Linux console?

И здесь из-за такой трансляции вообще все сочeтания с Meta стали переводиться в paredit-backward-slurp-sexp. При этом, судя по выводу showkey виноват в этом Имакс...

Не-а, это ограничение Linux Console. Там просто нет ни Super, ни Hyper. Это фишки X Window System в твоем случае.

http://www.gnu.org/software/emacs/emacs-faq.html#Binding-combinations-of-modi...

www.linux.org.ru/books/GNU/emacs/emacs_7.html#SEC18

Zubok ★★★★★
()
Ответ на: комментарий от arte-at-marte

Я вот тут подумал, что то, что я привел выше про Hyper и Super, все правдиво, но не совсем релевантно проблеме, с которой ты столкнулся в консоли.

В консоли Emacs первый ESC (С-[) из любой последовательности M+<символ> (ESC символ) сразу же транслирует в твою H-[. Ну и получается, что в одну и ту же функцию. В иксах же M+<символ> приходит в Emacs не в виде ESC+<символ>.

Zubok ★★★★★
()
Ответ на: комментарий от arte-at-marte

а зачем пользоваться консолью?

anonymous
()
Ответ на: комментарий от arte-at-marte

Вот еще интересное: ты можешь эмулировать Hyper и Super комбинацией:

C-x @ h <символ>, C-x @ s <символ>

(см. функции event-apply-hyper-modifier, event-apply-super-modifier и подобные).

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

Речь о текстовой Linux console?

Ну, похоже о ней... :)

Если не используется emacs-daemon, можно использовать переменную window-system

Эта переменная nil, даже если демон стартует в Иксах. Однако в клиенте, если он стартует в иксах, то эта переменная имеет значение 'x. Я этим пользуюсь, чтобы менять настройки цветов т.к. они отображаются очень по разному. Правда нормального(ну т.е. не считая ловушек и пр) способа запустить код именно в клиенте, кроме как передать его при запуске с помощью --eval я не нашел... Кстати еще можно использовать функцию daemonp, которая возвращает истину (ну т.е. не nil), если текущий процесс является демоном.

Вот еще интересное: ты можешь эмулировать Hyper и Super комбинацией:

Хм... а я даже и не заметли, что они не работают... :) Как то так получилось, что я повесил на них исключительно узкоспециализированные команды, которыми попросту не пользуюсь в консоли, но event-apply-*-modifier все же взял на вооружение.

В иксах же M+<символ> приходит в Emacs не в виде ESC+<символ>.

И в консоли вроде бы приходит не в виде ESC+<символ>. Во всяком случае showkey адекватно распознает коды контрола, альта и прочих. Так что это косяк где то в Имаксе...

ограничение Linux Console. Там просто нет ни Super, ни Hyper.

По дефолту да, их нет, но, кстати я когда переходил на раскладку Дворака, подумал, что очень не рационально развивать скорость печати на разных раскладках(русской и английской) по отдельности, тем более, что ЙЦУКЕН, как и QWERTY, тоже мягко говоря не оптимальна. И поэтому написал свою русскую раскладку-транслит с Дворака. Я ее написал не только для Иксов, но и для консоли. И я помню, что в настройках раскладки для консоли можно было указать чем является клавиша, в т.ч. super, hyper и пр. А сейчас и вовсе в консоли используют конфиги xkb. Думаю тем более должно работать...

arte-at-marte
() автор топика
Ответ на: комментарий от arte-at-marte

В иксах же M+<символ> приходит в Emacs не в виде ESC+<символ>.

И в консоли вроде бы приходит не в виде ESC+<символ>. Во всяком случае showkey адекватно распознает коды контрола, альта и прочих. Так что это косяк где то в Имаксе...

Хых, да нет же! Emacs не работает с клавиатурой напрямую. Он не считывает эти коды, которые тебе показывает showkey. Emacs работает с терминалом и получает символы все от него.

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