I want to use emacs as VISUAL with server-mode. As a test, I write the following in a terminal:

emacsclient -F "((left . 0) (top . 0))" -c -n file

This behaves exactly as expected; it opens my file file in GUI window with the right geometry, exactly the behaviour I want from $VISUAL filename. So I add the following line to the end of my .bashrc:

export VISUAL='emacsclient -F "((left . 0) (top . 0))" -c -n file'

Now I test this from a terminal:

$ source .bashrc
$ $VISUAL file
*ERROR*: End of file during parsing

I recognize that as an error thrown by emacs when it evaluates elisp with mismatched delimiters. I thought at first that I might be doing something wrong with single and double quotes, but this doesn't explain the error; emacs is starting, but somewhere it's running into some problem with a mismatched delimiter.

Question: (1) Why is emacs throwing an error when called from $VISUAL like this, despite the fact that the command itself works correctly? (2) How do I fix it?

P.S. I'm on GNU Emacs 26.3 and GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu); thanks in advance for your help.


The problem is how the shell expands $VISUAL. When the shell expands a variable outside of double quotes ($VISUAL as opposed to "$VISUAL"), it splits the value into words (and treats each word as a shell wildcard pattern, but that's not relevant here). So it runs the command emacsclient with the arguments -F, "((left . 0), (top . 0))", -c, -n, file, file. The error message you're seeing comes from parsing "((left . 0) which is an unterminated string.

There's no standard for the syntax of VISUAL: some applications use the equivalent of running $VISUAL filename in a shell, while others use the equivalent of taking the value of VISUAL, appending the (quoted) file name and running the result through a shell (which would do what you want), and there are even other cases (I've seen applications that want VISUAL to be a path to an executable file with no arguments, but that's uncommon). So you should keep it simple. If you need to pass arguments with spaces, use a wrapper script.

In my configuration, I use

export VISUAL="$HOME/bin/EDITOR"

and I have a script called EDITOR that dispatches to emacslient (and for me also has a fallback if Emacs isn't installed). For you that wrapper script would be

exec emacsclient -F "((left . 0) (top . 0))" -c -n "$@"
  • This works perfectly, except that I need to explicitly write the path of $HOME for some reason. It seems the heart of my problems go a little deeper into gnome-terminal as well. Thanks for fixing my emacs query!
    – User12345
    Aug 27 '20 at 16:54
  • Nope, nevermind: I forgot I was on a login shell... I am my own worst enemy :) Thanks again very much!
    – User12345
    Aug 27 '20 at 17:02

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.