Emacs - connect to daemon (if it exists) without using emacsclient

1.7k Views Asked by At

If I have emacs running as a daemon on my system, I can connect to it easily using emacsclient. This I know. However, what I would like to know is, is there a way to tell emacs (not emacsclient) to behave like emacsclient if a daemon is already running?

e.g.

# emacs daemon is not running
emacs # should start a new frame

# ...

# emacs daemon IS running
emacs # should actually behave like emacsclient, i.e. connect to my daemon

Is there anything I can do to my init.el to replicate this kind of behaviour?

3

There are 3 best solutions below

0
On BEST ANSWER

I don't think so, but can you achieve a similar effect by using emacsclient with an empty string as the the --alternate-editor option? From http://www.gnu.org/s/libtool/manual/emacs/emacsclient-Options.html#emacsclient-Options:

-a command

--alternate-editor=command

. . . As a special exception, if command is the empty string, then emacsclient starts Emacs in daemon mode and then tries connecting again.

0
On

Here's what I do. It's like the solution by @philippe-carpin, in the sense that it's a script that does multiple steps:

  • If emacs daemon is not running: start it, create a frame
  • If daemon but no frame: create a frame
  • If daemon with frame: focus that frame

In all cases you can pass filename(s) that will be opened.

In addition, my script only tries to run a piece of elisp just once and if there's no daemon it will not start an emacs process to run that elisp. So it should be slightly faster.

get_emacs_daemon_state () {
    emacs_get_state_script='(if (> (length (frame-list)) 1) "daemon-with-frame" "daemon-no-frame")'
    emacsclient -e "$emacs_get_state_script" -a "echo no-daemon" 2>/dev/null |
        tr -d \" | cut -d' ' -f1
}

state=$(get_emacs_daemon_state)
create_frame_arg=""

if [[ $state = no-daemon ]]; then
    emacs --daemon
fi
if [[ $state != daemon-with-frame ]]; then
    create_frame_arg="--create-frame"
fi

client="emacsclient --no-wait $create_frame_arg"
if [[ $# -gt 0 ]]; then
    # open files passed as arguments
    $client "$@"
else
    # if no file passed, we just focus the frame
    $client --eval "(select-frame-set-input-focus (selected-frame))" >/dev/null
fi
0
On

You can do the -a '' thing with emacsclient but what I do and a lot of people do is to have some kind of script that basically does what emacsclient '' does in multiple steps.

My version is something like this BASH script: The part you are interested in is the ensure-server-is-running function. This is the "main function" of the script, what follows is the ensure-server-is-running function and the rest is there after that for your curiosity but does not contribute to answering the question.

#!/bin/bash
# ec.sh
#
# [function definitions]
#

ensure-server-is-running
ensure-frame-exists

focus-current-frame

Ensuring that the server is running

# ec.sh function definition
# From https://emacs.stackexchange.com/a/12896/19972
function server-is-running() {
    emacsclient -e '(+ 1 0)' > /dev/null 2>&1
}

function ensure-server-is-running(){
    if ! server-is-running ; then
        echo "Need to start daemon, press enter to continue, C-c to abort"
        read
        emacs --daemon
    fi
}

And the other two function:

# ec.sh function definition
# From https://superuser.com/a/862809
function frame-exists() {
    emacsclient -n -e "(if (> (length (frame-list)) 1) 't)" 2>/dev/null | grep -v nil >/dev/null 2>&1
}

function ensure-frame-exists() {
    if ! frame-exists ; then
        emacsclient -c --no-wait
    fi
}

# From https://emacs.stackexchange.com/a/54139/19972
function focus-current-frame() {
    # Doesn't work a frame exists and is in a terminal
    emacsclient --eval "(progn (select-frame-set-input-focus (selected-frame)))"
}

focus-current-frame is something that will make the OS put you in the current Emacs Frame. This is the most important feature. For me I insert an adapted version of this into a MacOS Automator app. When there is an emacs GUI frame, doing Spotlight Search "EmacsC" (usually just typing the "e" is enough), puts me in my emacs window. It's a super fast way of switching to an emacs window.