[Not an answer: the OP provided his own answer which works. This is just an explanation of why the original attempt didn't work out.]
After suspending the emacs process, you then execute emacsclient -n file2
. That writes the message to the communication socket and waits for emacs to acknowledge receipt, but emacs does not respond. If you wait long enough, the client complains that the server is not responding and asks you to press C-c
to put it out of its misery. If, before the timeout, you suspend the client with C-z
, and bring back emacs with fg %1
(or its synonym %1
), then emacs gets a backtrace:
Debugger entered--Lisp error: (cl-assertion-failed ((eq (match-end 0) (length string)) nil))
cl--assertion-failed((eq (match-end 0) (length string)))
server--process-filter-1(#<process server <3>> "-dir /home/nick/ -nowait -current-frame -tty /dev/pts/2 xterm-256color -file /tmp/foo2 \n-suspend \n")
server--process-filter-all-pending()
server-process-filter(#<process server <3>> "-dir /home/nick/ -nowait -current-frame -tty /dev/pts/2 xterm-256color -file /tmp/foo2 \n-suspend \n")
Note that the string that the process filter received from the client consists of two lines:
-dir /home/nick/ -nowait -current-frame -tty /dev/pts/2 xterm-256color -file /tmp/foo2
-suspend
Now if you look at the source of server--process-filter-1
(just press RET
on the link in the backtrace) and read the code, you'll see the following:
...
;; In earlier versions of server.el (where we used an `emacsserver'
;; process), there could be multiple lines. Nowadays this is not
;; supported any more.
(cl-assert (eq (match-end 0) (length string)))
...
So it's the two-line message that is sent in the original attempt that's causing the failure.
By adding the &
in the emacsclient
invocation, you put it in the background without having to suspend it, so bringing the server back with %1
allows the server to read the (now single-line) command, acknowledge it allowing the emacsclient -n
invocation to exit and then carry out the command.