Запустить команду в новом фрейме с демоном/клиентом в Emacs

Это, возможно, довольно просто, но я не нашел ничего полезного, когда гуглил. Итак, вот оно :)

Я использую Emacs в режиме демона (emacs --daemon), и это очень удобно. Я также использую dvorak и обнаружил, что переназначение C-j на C-c (и наоборот) действительно удобно в долгосрочной перспективе, и использую для этого следующее:

(keyboard-translate ?\C-j ?\C-c)
(keyboard-translate ?\C-c ?\C-j)

Это прекрасно работает, когда не используется Emacs в качестве демона. Когда я запускаю новый клиент (cli/gui), C-j больше не привязан к C-c. Что?

Итак, я думаю, мне нужно будет запустить keyboard-translate после создания нового клиентского фрейма, но я понятия не имею, как это сделать. Я пытался использовать defadvice, который где-то нашел, но не смог заставить его работать, поэтому сдался и удалил его.


person monotux    schedule 21.02.2011    source источник


Ответы (3)


C-h f keyboard-translate RET говорит, что:

Эта переменная имеет отдельную привязку для каждого терминала. См. Информационный узел `(elisp)Несколько дисплеев'.

что указывает нам правильное направление, хотя в этой документации есть ошибка, поскольку указанный информационный узел не существует. Поиск показывает, что узел на самом деле переименован в (elisp)Multiple terminals, что вы также можете прочитать здесь: http://www.gnu.org/s/emacs/manual/html_node/elisp/Multiple-Terminals.html

В системах GNU и Unix каждый X-дисплей представляет собой отдельный графический терминал [...] Emacs может даже подключаться к другим текстовым терминалам, взаимодействуя с программой emacsclient.

Таким образом, когда вы запускаете emacs в качестве демона, вы еще не подключены к терминалу (или, по крайней мере, не к тому, который вам полезен), и поэтому ваши команды не генерируют привязки для терминала(ов), которые вы в конечном итоге используете. с использованием.

Переменная after-make-frame-functions предоставляет один из способов решения этой проблемы.

(defun my-dvorak-translations (&optional frame)
  "Re-map keys in the current terminal."
  (with-selected-frame (or frame (selected-frame))
    (keyboard-translate ?\C-j ?\C-c)
    (keyboard-translate ?\C-c ?\C-j)))
;; Evaluate both now (for non-daemon emacs) and upon frame creation
;; (for new terminals via emacsclient).
(my-dvorak-translations)
(add-hook 'after-make-frame-functions 'my-dvorak-translations)

Экспериментально кажется безопасным повторять ваши команды, поэтому нам не нужно беспокоиться о выполнении этого только один раз для каждого терминала (но если бы мы это сделали, мы могли бы использовать (get-device-terminal FRAME), чтобы помочь с этим).

person phils    schedule 21.02.2011

Чтобы расширить ответ Фила:

В Emacs 26.1 мне приходилось запускать переводы клавиатуры в контексте нового фрейма, например так:

(defun make-keyboard-translations ()
  (keyboard-translate ?\C-j ?\C-c))

(defun setup-frame-keyboard (frame)
  (with-selected-frame frame
    (make-keyboard-translations)))

(make-keyboard-translations)
(add-hook 'after-make-frame-functions #'setup-frame-keyboard)
person ens    schedule 11.12.2018
comment
Я не знаю, автоматически ли after-make-frame-functions выбирал кадр тогда или нет, но в последнее время этого точно не было ... Я был немного поражен, найдя этот старый ответ и заметив свою ошибку. Рад видеть, что вы добавили это исправление. - person phils; 08.06.2021

Другой хук, который запускается каждый раз, когда вызывается emacsclient, это server-visit-hook, который, возможно, более подходит, чем after-make-frame-functions.

(add-hook 'server-visit-hook 
     (lambda ()
          (keyboard-translate ?\C-j ?\C-c)
          (keyboard-translate ?\C-c ?\C-j)))
person Gen.Sec.    schedule 19.04.2012
comment
Будет ли это учитывать ситуацию, когда новый клиент/фрейм открывается без списка файлов? - person phils; 20.04.2012