问题
This is perhaps quite simple, but I haven't found anything useful when googling. So here it goes :)
I use Emacs in daemon mode (emacs --daemon
) and it's really handy. I also use dvorak and have found that remapping C-j to C-c (and vice versa) is really handy in the long run, and use the following for making that translation:
(keyboard-translate ?\C-j ?\C-c)
(keyboard-translate ?\C-c ?\C-j)
This works great when not using Emacs as a daemon. When I start a new client (cli/gui) C-j is no longer bound to C-c. Whaaat?
So I guess I'll need to run the keyboard-translate
after creating a new client frame, but I have no idea how to do it. I've tried with a defadvice
I found somewhere, but couldn't make it work so I gave up and removed it.
回答1:
C-h f keyboard-translate
RET says that:
This variable has a separate binding for each terminal. See Info node `(elisp)Multiple displays'.
which points us in the right direction, although there's an error in that documentation, as the referenced info node doesn't exist. A search suggests that the node is actually renamed (elisp)Multiple terminals
, which you can also read here: http://www.gnu.org/s/emacs/manual/html_node/elisp/Multiple-Terminals.html
On GNU and Unix systems, each X display is a separate graphical terminal [...] Emacs can even connect to other text-only terminals, by interacting with the emacsclient program.
So when you start emacs as a daemon, you have not yet connected to a terminal (or at least, not to one that is useful to you), and so your commands do not generate bindings for the terminal(s) that you end up using.
The after-make-frame-functions
variable provides one way to resolve this.
(defun my-dvorak-translations (&optional frame)
"Re-map keys in the current terminal."
(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)
Experimentally it appears safe to repeat your commands, so we don't need to worry about only executing this once per terminal (but if we did, we could use (get-device-terminal FRAME)
to help with that).
回答2:
Another hook that is run each time emacsclient is invoked is server-visit-hook
, which is perhaps more appropriate than after-make-frame-functions
.
(add-hook 'server-visit-hook
(lambda ()
(keyboard-translate ?\C-j ?\C-c)
(keyboard-translate ?\C-c ?\C-j)))
回答3:
To expand on phils' answer:
On Emacs 26.1 I had to run the keyboard translations in the context of the new frame, like so:
(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)
来源:https://stackoverflow.com/questions/5064390/run-command-on-new-frame-with-daemon-client-in-emacs