0

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))
  • related: emacs.stackexchange.com/a/47894/262 – Tyler Oct 27 '19 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 '19 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. – Erik Oct 28 '19 at 4:59
3

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.

|improve this answer|||||
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

|improve this answer|||||
  • I want emacs to open emacsclient, not the other way round. – Erik Oct 27 '19 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 '19 at 19:02
  • That's additional setup outside Emacs, the very thing I'm trying to avoid. – Erik Oct 27 '19 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))
|improve this answer|||||
  • No. That's additional setup beyond copying .emacs.d to a machine. – Erik Oct 27 '19 at 19:05
  • 1
    @Erik Please see my edit – xuhdev Oct 27 '19 at 23:23

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.