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.

<section id="comments" class="comment-list"><h1>Comments</h1><ul> <li class="comment"> <div class="head"> <span class="author">anon</span> <span class="date">Nov. 20, 2011, 7:44 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-126">reply</a> </span> </div> <div class="text"><p>Tramp doesn&rsquo;t need ssh to sudo.<br /> stackoverflow.com/questions/95631/open-a-file-with-su-sudo-inside-emacs/2071375#2071375</p></div> </li> <ul> <li class="comment"> <div class="head"> <span class="author">Oli</span> <span class="date">Nov. 20, 2011, 7:55 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-127">reply</a> </span> </div> <div class="text"><p>Thanks for the tipp. I edited the article accordingly.</p></div> </li> </ul> <li class="comment"> <div class="head"> <span class="author">Fredrik</span> <span class="date">Feb. 2, 2012, 10:35 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-128">reply</a> </span> </div> <div class="text"><p>Thanks for the tip, emacsclient seems quite convenient! On my eee-pc, the startup speed improved noticably. But my color settings stopped working&hellip; maybe I should try the color-theme machinery.</p></div> </li> <li class="comment"> <div class="head"> <span class="author">mob</span> <span class="date">Feb. 13, 2012, 4:42 a.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-129">reply</a> </span> </div> <div class="text"><p>I didn&rsquo;t know I could use tramp like that, thanks. It really bogged to start emacs and then use tramp mode.</p></div> </li> <li class="comment"> <div class="head"> <span class="author">Ron</span> <span class="date">Aug. 12, 2012, 2:36 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-130">reply</a> </span> </div> <div class="text"><p>Have you had an issue of default-directory being set to /, or ansi-term defaulting to sh (opposed to zsh in my case)?</p></div> </li> <ul> <li class="comment"> <div class="head"> <span class="author">Roy</span> <span class="date">Sept. 7, 2012, 9:27 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-131">reply</a> </span> </div> <div class="text"><p>I&rsquo;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&rsquo;t read scripts like .bashrc or even /etc/passwd, they just take variable-assignment pairs, so you have to set them all yourself.<br /> One thing I&rsquo;ve been trying is</p> <p>ExecStart=/bin/su -l -c &ldquo;emacs &mdash;daemon&rdquo;</p> <p>which seems to work. just be sure to unset User= , otherwise it will run su as you, and fail since it doesn&rsquo;t have permission.</p></div> </li> </ul> <li class="comment"> <div class="head"> <span class="author">anonymous</span> <span class="date">Nov. 3, 2013, 1:39 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-201">reply</a> </span> </div> <div class="text"><p>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&rsquo;d share it</p> <div class="codehilite"><pre>edit() { local use_sudo=false use_cli=false ignore_daemon=false while getopts cns name; do case <span class="cp">${</span><span class="n">name</span><span class="cp">}</span> 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 "<span class="cp">${</span><span class="err">@</span><span class="cp">}</span>"; do if [[ "<span class="cp">${</span><span class="n">arg</span><span class="cp">}</span>" == /* ]]; then new_arg=<span class="cp">${</span><span class="n">arg</span><span class="cp">}</span> else new_arg=<span class="cp">${</span><span class="n">PWD</span><span class="cp">}</span>/<span class="cp">${</span><span class="n">arg</span><span class="cp">}</span> fi <span class="cp">${</span><span class="n">use_sudo</span><span class="cp">}</span> <span class="err">&amp;&amp;</span> new_arg=/sudo::<span class="cp">${</span><span class="n">new_arg</span><span class="cp">}</span> args=( "<span class="cp">${</span><span class="n">args</span><span class="p">[</span><span class="err">@</span><span class="p">]</span><span class="cp">}</span>" "<span class="cp">${</span><span class="n">new_arg</span><span class="cp">}</span>" ) done local opts cmd if <span class="cp">${</span><span class="n">ignore_daemon</span><span class="cp">}</span>; then cmd=emacs if <span class="cp">${</span><span class="n">use_cli</span><span class="cp">}</span>; then opts=-nw else opts= fi else cmd=emacsclient if <span class="cp">${</span><span class="n">use_cli</span><span class="cp">}</span>; then opts=-t else opts=-c fi fi echo "Running <span class="cp">${</span><span class="n">cmd</span><span class="cp">}</span> <span class="cp">${</span><span class="n">opts</span><span class="cp">}</span> <span class="cp">${</span><span class="n">args</span><span class="p">[</span><span class="err">@</span><span class="p">]</span><span class="cp">}</span>" <span class="cp">${</span><span class="n">cmd</span><span class="cp">}</span> <span class="cp">${</span><span class="n">opts</span><span class="cp">}</span> "<span class="cp">${</span><span class="n">args</span><span class="p">[</span><span class="err">@</span><span class="p">]</span><span class="cp">}</span>" } </pre></div> <p>Hope this ends up looking sort of okay. You can invoke it e.g. as &lsquo;edit -nc foo bar&rsquo; (c=CLI, n=new process) to get a new non-graphical emacs process or &lsquo;edit -s foo bar&rsquo; (s=sudo) to get a graphical client of your daemon, with foo and bar opened using root privileges.</p></div> </li> <ul> <li class="comment"> <div class="head"> <span class="author">Oli</span> <span class="date">Nov. 3, 2013, 2 p.m.</span> <span class="actions"> <a href="#" class="add-reply" id="comment-202">reply</a> </span> </div> <div class="text"><p>Hi, thank you! (I am just realizing I need to work on the formatting of comments a little bit. :) )</p></div> </li> </ul> </ul></section>

Write comment