emacsclient: create a frame if a frame does not exist

I start emacs server using

emacs --daemon

then open files using

emacsclient filename.ext

but the first file has to be opened using

emacsclient -c filename.ext

in order to create a new frame which can be later used by subsequent files without using -c command line flag for emacsclient.

I want to automate this. "if there is no emacs frame, emacsclient should create a frame else it should use the current frame". How can it be done?


Solution 1:

This is like dimitri's solution, but it handles the case when emacs was launched as emacs --daemon. emacs --daemon makes a hidden window that causes xprop to give a false positive when checking for an existing window.

#!/bin/bash

emacsclient -n -e "(> (length (frame-list)) 1)" | grep -q t
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n -a "" "$@"
fi

Solution 2:

You can first create a frame if there isn't one already, then open the file in a now existing frame. Here's a snippet that creates a frame on the initial display if there isn't any frame now opened on a window display. You may wish to tweak this in a number of ways, such as checking whether there is already a frame on the display with x-display-list. You need (require 'cl) in your `.emacs. This may require some adaptation to work on Windows or Aqua.

emacsclient -e '(unless (find-if (lambda (f)
                                   (let ((p (frame-parameters f)))
                                     (assq '\''window-system p)))
                                 (frame-list))
                  (make-frame-on-display (getenv "DISPLAY")))'
emacsclient filename.ext

Solution 3:

Here is the emacs-client.sh script I use under Linux to do exactly what you ask for:

#!/bin/sh

xprop -name emacs >/dev/null 2>/dev/null
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n -a "" "$@"
fi

Solution 4:

I think adding Gilles' function to server-switch-hook might do what you want. Unfortunately, I can't seem to get emacs --daemon working to test it.

(add-hook 'server-switch-hook
          (lambda ()
            (unless (find-if (lambda (f)
                               (let ((p (frame-parameters f)))
                                 (assq 'window-system p)))
                             (frame-list))
              (make-frame-on-display (getenv "DISPLAY")))))