4

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

Interactively,

M-x end-of-buffer

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 emacsclient: OK

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.

Having emacsclient do the job in both cases (emacs already running, and new emacs): NOK

Let's add -a emacs.

emacsclient -c -s server- -a emacs --eval "(find-file \"$GENERATEDFILENAME\")" --eval "(end-of-buffer)"

Result:

  • 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 GENERATEDFILENAME is gfn.txt).

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 argv[0] is --eval which does not conform to exec tradition, and the other --eval is skipped.

Probably 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 emacsclient behavior 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?
  • To the downvoter: please explain why you downvoted. The question shows research efforts, doesn't it? It is useful to run a simple lisp expression in emacs from an external script, isn't it? Is it unclear? There must be a reason for your downvote, please explain. – Stéphane Gourichon Apr 6 '16 at 17:08
  • 1
    "Should we consider emacsclient behavior ... a bug" - Yes, see Bug#11474 – npostavs May 29 '17 at 22:41
1

Sort-of solution: emacsclient -a '' ...

Looking at the automatic links appearing at the right of the question, I saw a question not seen before: emacsclient - Opening frames from emacs-daemon - Emacs Stack Exchange. User there uses emacsclient -a '' ... which incidentally solves the issue.

I guess it allows emacsclient to assume that callee is a real emacs and therefore forward all emacs-specific call parameters.

Anyway it works now.

But... new problem of emacs process staying

With emacsclient -a '' ... the server never automatically quits.

So, emacs instances keep running forever which is not intended. This also has some side effects, like preventing to umount external filesystems (e.g. USB keys), since they are used by some emacs instance which I have to search and stop.

Still open to more explanations, other options, etc. Thanks!

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.