After having used emacs for a couple of months now, I discovered the emacs --daemon option today and was astonished. Having quite a big emacs config, it takes ages for emacs to start preventing me from using it as the standard editor for config files etc. The --daemon mode starts emacs in the background acting as a server and allows one to create emacs frames using the emacsclient in various ways. EMacs shows up lightning-fast then and becomes an option for the always-to-use text editor.

ALL THE TIME

Here is my setup on how to work with emacs and use it as an editor for quickly editing files on the command line.

Starting the daemon using systemd

I switched from sysVinit to systemd some time ago, so the most convenient thing to do is to start the emacs daemon using a custom systemd service file. Put the following code into the file /etc/systemd/system/multi-user.target.wants/emacs.service:

[Unit]
Description=Emacs: the extensible, self-documenting text editor

[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))"
Restart=always
User=YOUR_USERNAME

Make sure you insert your username in the bottom line. Now, enable the service executing systemctl enable emacs.service and after the next boot the daemon is started automatically.

Shell aliases and sudo-ing

One thing you will quickly notice is that sudo emacsclient ... doesn’t work since the daemon runs under your username. To be able to edit files as root, we need to load the tramp plugin of emacs. Put the following line somewhere in your .emacs or .emacs.d/init.el:

(require 'tramp)

Now, you would use emacsclient -c /sudo::/etc/somefile which is still a bit too long for quick file editing. (As well as the emacsclient command itself). This is why we create shell aliases. I am using zsh which is why I will use its syntax here.

export EDITOR="emacsclient -t -n -a nano"
alias ec='emacsclient -c -n -a nano'
alias et='emacsclient -t -a nano'
ecs() { emacsclient -c -n -a emacs "/sudo::$*" }
ets() { emacsclient -t -a emacs "/sudo::$*" }

It sets emacs as the default editor and defines the commands ec (emacs in a separate window) and et (emacs in the terminal) as well as its sudo friends for write-protected files, ecs and ets. Simply put the code in your .zshrc or .bashrc (after editing it to fit bash’s syntax) and restart the terminal. Then you can use ec/et/ecs/ets /some/directory/some/file to edit the file. I think tramp uses ssh to connect to your pc as root, so you might need to install ssh to use it.

Comments

  • anon Nov. 20, 2011, 7:44 p.m. reply

    Tramp doesn’t need ssh to sudo.
    stackoverflow.com/questions/95631/open-a-file-with-su-sudo-inside-emacs/2071375#2071375

    • Oli Nov. 20, 2011, 7:55 p.m. reply

      Thanks for the tipp. I edited the article accordingly.

  • Fredrik Feb. 2, 2012, 10:35 p.m. reply

    Thanks for the tip, emacsclient seems quite convenient! On my eee-pc, the startup speed improved noticably. But my color settings stopped working… maybe I should try the color-theme machinery.

  • mob Feb. 13, 2012, 4:42 a.m. reply

    I didn’t know I could use tramp like that, thanks. It really bogged to start emacs and then use tramp mode.

  • Ron Aug. 12, 2012, 2:36 p.m. reply

    Have you had an issue of default-directory being set to /, or ansi-term defaulting to sh (opposed to zsh in my case)?

    • Roy Sept. 7, 2012, 9:27 p.m. reply

      I’ve noticed that. The service is being started outside of the usual bash environment, or any shell, even if you specify the user. there are parameters like WorkingDirectory=, Enviroment= and EnvironmentFile= that can be used, but those don’t read scripts like .bashrc or even /etc/passwd, they just take variable-assignment pairs, so you have to set them all yourself.
      One thing I’ve been trying is

      ExecStart=/bin/su -l -c “emacs —daemon”

      which seems to work. just be sure to unset User= , otherwise it will run su as you, and fail since it doesn’t have permission.

  • anonymous Nov. 3, 2013, 1:39 p.m. reply

    A while ago, I wrote a (zsh) shell function to handle the emacsclient/emacs+sudo handling (including the fact that emacsclient and emacs take different arguments for GUI/CLI toggling). Thought I’d share it

    edit() {
        local use_sudo=false use_cli=false ignore_daemon=false
        while getopts cns name; do
        case ${name} in
            s) use_sudo=true;;
            c) use_cli=true;;
            n) ignore_daemon=true;;
        esac
        done
        shift $((OPTIND-1))
    
        local args
        args=()
    
        ## sanitise paths for sudo
        for arg in "${@}"; do
        if [[ "${arg}" == /* ]]; then
            new_arg=${arg}
        else
            new_arg=${PWD}/${arg}
        fi
        ${use_sudo} && new_arg=/sudo::${new_arg}
        args=( "${args[@]}" "${new_arg}" )
        done
    
        local opts cmd
        if ${ignore_daemon}; then
        cmd=emacs
        if ${use_cli}; then
            opts=-nw
        else
            opts=
        fi
        else
        cmd=emacsclient
        if ${use_cli}; then
            opts=-t
        else
            opts=-c
        fi
        fi
    
        echo "Running ${cmd} ${opts} ${args[@]}"
        ${cmd} ${opts} "${args[@]}"
    }
    

    Hope this ends up looking sort of okay. You can invoke it e.g. as ‘edit -nc foo bar’ (c=CLI, n=new process) to get a new non-graphical emacs process or ‘edit -s foo bar’ (s=sudo) to get a graphical client of your daemon, with foo and bar opened using root privileges.

    • Oli Nov. 3, 2013, 2 p.m. reply

      Hi, thank you! (I am just realizing I need to work on the formatting of comments a little bit. :) )

Write comment