Whenever I use emacsclient, I tend to use it without a file argument. This is because my emacs file finder is generally better than my shell file finder.

Unfortunately, when emacsclient is not given a file argument, neither server-visit-hook nor server-switch-hook are fired, and I'm left without crucial bits of server setup.

How can I work around this limitation?

EDIT: Added example code.

(let ((my/evil-mode-line-face-cookies nil))
  (defun my/evil-set-mode-line-face (&rest args)
    (cl-destructuring-bind (bg-color fg-color)
        (pcase evil-state
          (`normal  '("white" "blue"))
          (`emacs   '("white" "green"))
          (`insert  '("black" "grey"))
          (`visual  '("white" "cyan"))
          (`replace '("white" "red"))
          (other    '("grey"  "black")))
      (mapc #'face-remap-remove-relative my/evil-mode-line-face-cookies)
      (setq my/evil-mode-line-face-cookies
            (list (face-remap-add-relative
                   `((:foreground ,fg-color :background ,bg-color)

                   `((:foreground ,fg-color)

(add-hook 'post-command-hook #'my/evil-set-mode-line-face)
(add-hook 'after-make-frame-functions #'my/evil-set-mode-line-face)
  • What do you do in those hooks? If you are using dired as your file finder, then you could simply pass the directory as your argument. – suvayu Sep 9 '15 at 8:50
  • @suvayu I do things like initialize clipboard handlers and xterm-mouse-mode, which are specific to the current frame. I also set some faces depending on the current display's color capabilities. – PythonNut Sep 9 '15 at 17:36
  • 1
    You could move those to before-make-frame-hook or after-make-frame-functions. Then you would have the advantage of your customisations working also in a normal session. – suvayu Sep 9 '15 at 19:51
  • @suvayu those hooks aren't run for terminal sessions. – PythonNut Sep 10 '15 at 0:08
  • PythonNut: Sure they are. You just need to both run the function directly in your init file, and also add it to the hook, as unless you start emacs as a daemon, the initial frame is created before your init file runs. – phils Sep 10 '15 at 0:40

after-make-frame-functions is what I use in these situations.

Here's an example, adapted from https://stackoverflow.com/a/5066313/324105

(defun my-frame-behaviours (&optional frame)
  "Make frame- and/or terminal-local changes."
  (with-selected-frame (or frame (selected-frame))
    ;; do things...
;; Evaluate immediately (for non-daemon emacs), and also
;; upon frame creation (for new terminals via emacsclient).
(add-hook 'after-make-frame-functions 'my-frame-behaviours)
  • This is not working for the specific case of adding relative face remaps based on the current evil-state. I have no idea why. – PythonNut Sep 10 '15 at 15:16
  • Add an example to the question? – phils Sep 10 '15 at 20:28
  • I've added it (with some simplifications). – PythonNut Sep 10 '15 at 20:32
  • Oh well it's obviously because I'm not including your (with-selected-frame ...) bits. Sorry about that. – PythonNut Sep 10 '15 at 20:36
  • That may have been due to my starting with example code which was all about terminal-local changes, and which consequently didn't include that wrapper (because the frame wasn't actually important on that occasion). Glad to hear it's working now. – phils Sep 10 '15 at 21:56

Another, possibly more hacky, solution:

(defun my/server-init (&rest args)
  (message "Initializing the server!"))
(advice-add 'server-execute :after #'my/server-init)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.