1

Most modern editors don't have a separate <editor>client binary. Instead, the main binary acts as a client to open a new window/the file given as an argument when possible.

Is there a way to accomplish the same in Emacs? I know about emacsclient but 1. it's not a drop-in replacement and 2. using it comfortably requires additional setup beyond copying .emacs.d to a machine -- e.g. adding a desktop file for emacsclient.

I'm envisioning something like this:

;; Start of init.el
(if (server-running-p)
    ;; Open given file in existing server
  (server-start))
3
  • related: emacs.stackexchange.com/a/47894/262
    – Tyler
    Oct 27, 2019 at 22:33
  • Unclear why you would want a desktop file for emacsclient if you've already opened emacs. Do you perhaps just want to open a new frame? If so, you can do so from any existing emacs frame with make-frame-command, bound by default to C-x 5 2.
    – Dan
    Oct 27, 2019 at 23:04
  • @Dan I don't want a desktop file for emacsclient. That's an example of what I want to avoid. I want emacs, the main binary, to act as a client to open a new window/the file given as an argument when possible.
    – Nova
    Oct 28, 2019 at 4:59

3 Answers 3

4

Nowadays several megabytes are no problem for a client program. So maybe the problem of the size of Emacs is no longer that relevant.

With Emacs 27 you can run stuff in ~/.emacs.d/early-init.el before the initial frame opens. There you can try:

(require 'server)
(if (server-running-p "server")
  (let ((file-name (expand-file-name (car (cdr command-line-args)))))
    (unwind-protect
        (server-eval-at "server" `(find-file ,file-name))
      (kill-emacs)))
  (message "Server not running."))
(server-start)

If you run emacs somefile when the Emacs server is already running somefile should be opened in the server.

This is just a proof of principle. The handling of the argument is very rudimentary. One has to refine the argument handling if one wants to use that principle for production.

I only have emacs26 on my machine. Therefore, I cannot test the early-init.el-approach. If I put the above code into ~/.emacs it opens the file given on the command line in the already running server but the client opens an initial frame before it runs the code. So there is some kind of flicker.

1

The alternative-editor option supports this. The following invocation does what you describe:

emacsclient -a""

This opens emacsclient, and starts the server if it isn't already running.

See the manual for details: https://www.gnu.org/software/emacs/manual/html_node/emacs/Invoking-emacsclient.html

3
  • I want emacs to open emacsclient, not the other way round.
    – Nova
    Oct 27, 2019 at 18:58
  • if the actual name you use to start the program is critical, you could just define an alias to map emacs to emacsclient -a""
    – Tyler
    Oct 27, 2019 at 19:02
  • That's additional setup outside Emacs, the very thing I'm trying to avoid.
    – Nova
    Oct 27, 2019 at 19:04
0

Would something like this work for you? You can save it as a script in PATH and run it instead of emacs or emacsclient.

#!/bin/bash

export REAL_EMACS_START=1
emacsclient $@ || emacs $@

EDIT:

If you want user to run emacs directly and achieve similar result, you can add the following to the top of init.el:

(unless (getenv "REAL_EMACS_START")
  (call-process-shell-command
   (format "export REAL_EMACS_START=1; (%sclient || %s) &" invocation-name invocation-name))
  (kill-emacs))
2
  • No. That's additional setup beyond copying .emacs.d to a machine.
    – Nova
    Oct 27, 2019 at 19:05
  • 1
    @Erik Please see my edit
    – xuhdev
    Oct 27, 2019 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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