Context / initial need (works fine)
I wrote and use a script that generates a file and uses
emacsclient to edit it in an existing or new instance of
emacs, in a new window.
Similar to Set up Emacs on Windows to start a single instance and open files in the existing instance - Emacs Stack Exchange, it boils down to:
exec emacsclient -c -s "$SOCKETNAME" -a emacs "$GENERATEDFILENAME" <>/dev/null
It's been working for years.
emacs open a new frame, opens the requested file there. Works both if emacs already launched or not (my init files include
server-start). So far, so good.
Wish: open file and run some simple expression
That on opening the new file, the cursor, instead of landing on the first line, lands (1) at the end of the buffer or (2) at the end of some specific line.
Search before you ask
I actually use several one emacs instance per project, similar to frames - From File Manager, open file in specific instance of Emacs - Emacs Stack Exchange. So there are several emacs instances with servers that may be active at a given time.
But there's no finite, known-in-advance, list of servers/projects. So running that many servers in
.xinitrc like in emacsclient - Multiple Emacs instances each with their own server? - Emacs Stack Exchange is not an option.
Try before you ask
Interactive experiment in
emacs session, OK
goes to the end of the buffer, and
C-u 11 move-end-of-line
move the cursor 11-1 lines down then at the end of that line.
So far, so good.
Scripted, new emacs instance: OK
Let's try first running a new instance.
emacs --eval "(find-file \"$GENERATEDFILENAME\")" --eval "(end-of-buffer)"
Line above correctly runs a new emacs instance, opens the requested file and puts cursor at end of buffer. So far so good.
Scripted, existing emacs instance through
Let's run an emacs instance and make sure
server-start is run.
emacsclient -s "$SOCKETNAME" -e '(end-of-buffer)'
Line above outputs
nil, showing that it connects to the
emacs-server, but does not move the cursor.
emacsclient -c -s server- --eval "(find-file \"$GENERATEDFILENAME\")" --eval "(end-of-buffer)"
Line above appears to open file and put cursor at end.
emacsclient do the job in both cases (emacs already running, and new emacs): NOK
emacsclient -c -s server- -a emacs --eval "(find-file \"$GENERATEDFILENAME\")" --eval "(end-of-buffer)"
- If emacs already runs with server, work okay.
- If emacs does not already run, instead of running the expressions, if opens two buffers names like the expression, as if the command was
emacs "(find-file \"$GENERATEDFILENAME\")" "(end-of-buffer)"
Bad bad bad. :-(
Showing why "no emacs running" case fails
strace shows what happens.
When running emacs directly:
execve("/usr/bin/emacs", ["emacs", "--eval", "(find-file \"2015y12m28d-18h23m49"..., "--eval", "(end-of-buffer)"], [/* 68 vars */]) = 0
When emacsclient calls emacs (in this case
execve("/usr/bin/emacsclient", ["emacsclient", "-c", "-s", "server-", "-a", "emacs", "--eval", "(find-file \"gfn.txt\")", "--eval", "(end-of-buffer)"], [/* 68 vars */]) = 0 execve("/usr/bin/emacs", ["--eval", "(find-file \"gfn.txt\")", "(end-of-buffer)"], [/* 68 vars */]) = 0
As you can see,
emacsclient does not call
emacs the same way when using --eval. Instead
--eval which does not conform to exec tradition, and the other
--eval is skipped.
emacsclient does not assume that alternate editor is emacs or even emacs compliant.
Just in case, environment is Linux Mint 17.2 64-bit, which is base on Ubuntu 14.04.
Now what? Questions
- Should we consider
emacsclientbehavior in the
exec()call a bug? It sure has some inconsistency.
- Is there a simple way to have desired behavior: run the expressions either on an existing emacs instance or a new if none exists?