Instalar Emacs como servicio
Table of Contents
Los usarios de emacs tenemos un complejo de inferioridad respecto del tiempo de arranque de la aplicación. Se han hecho muchos intentos para mejorarlo, como el portable dumper o profile-dot-emacs, pero es innegable que vi y vscode arrancan más rápido.
Al final, la mejor solución no es reducir el tiempo de arranque, sino camuflarlo. La mayoría de usuarios de emacs no abren una instancia cada vez que lo necesitan, sino que emacs está corriendo permanentemente y se abren nuevas frames o windows. La forma de trabajo sería la siguiente
- Abrir una instancia de emacs y arrancar el servidor.
- Cuando se necesite abrir un fichero, no se ejecuta una nueva instancia de emacs, sino que se utiliza emacsclient. Este se conecta a la instancia inicial.
El hack final es hacer que la instancia de emacs se arranque automáticamente al iniciar sesión, o mejor aún, cuando se inicia el sistema como un servicio.
Utilizo este mismo fichero org para publicar esta entrada y para configurar mis ordenadores GNU Linux, con literate programming. Para activar la ejecución de bloques shell
necesito ejecutar el siguiente bloque elisp
:
(org-babel-do-load-languages 'org-babel-load-languages '( (shell . t)))
1. Servicio
Basado en https://www.emacswiki.org/emacs/EmacsAsDaemon, utilizo la versión de centos, ya que funciona en centos y ubuntu. La diferencia está en el directorio que uso para dejar la unit:
- En centos es
/usr/lib/systemd/system/emacs@.service
- Ubuntu es
/lib/systemd/system/emacs@.service
Este bloque de código se ejecuta en el directorio /sudo::
, lo que indica a emacs que debe ejecutarlo con sudo
utilizando TRAMP.
SERVICEFILE=/lib/systemd/system/emacs@.service EMACSDIR=/usr/local/bin sudo tee > $SERVICEFILE <<EOF [Unit] Description=Emacs: the extensible, self-documenting text editor [Service] Type=forking ExecStart=$EMACSDIR/emacs --daemon --user %i ExecStop=$EMACSDIR/emacsclient --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))" Restart=always User=%i WorkingDirectory=/home/%i [Install] WantedBy=multi-user.target EOF chmod u+r,g+r,o+r $SERVICEFILE sudo systemctl daemon-reload sudo systemctl enable emacs@alvaro
2. Cliente
2.1. fichero .desktop
Sistemas con Gnome o KDE utilizan ficheros .desktop
para añadir aplicaciones a sus menús de inicio. Voy a añadir una nueva aplicación para emacsclient
, basándome en el fichero .desktop
que ya viene con emacs y la documentación en https://specifications.freedesktop.org/desktop-entry-spec/latest/index.html
EMACSDIR=/usr/local/bin cat > ~/.local/share/applications/emacsclient.desktop <<EOF #!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Name=GNU Emacs Client GenericName=Text Editor Comment=View and edit files MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; Exec=$EMACSDIR/emacsclient --create-frame --alternate-editor "" %F Type=Application Icon=$HOME/.local/share/applications/emacsclient.svg Terminal=false Categories=Utility;Development;TextEditor; StartupWMClass=Emacs EOF
2.2. Icono
Para estar seguro de que el icono existe, copio el fichero svg
que tengo para emacs26 al lado del fichero .desktop
.
cat > ~/.local/share/applications/emacsclient.svg <<EOF <?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" id="svg4768" viewBox="0.171 0.201 512 512" height="48" width="48" version="1.0"><metadata id="metadata70"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><!-- Gnu Emacs Icon Copyright (C) 2008-2019 Free Software Foundation, Inc. Author: Nicolas Petton <nicolas@petton.fr> This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. --><!-- Created with Inkscape (http://www.inkscape.org/) --><defs id="defs4770"><linearGradient id="linearGradient4292"><stop id="stop4294" offset="0" style="stop-color:#411f5d;stop-opacity:1" /><stop id="stop4296" offset="1" style="stop-color:#5b2a85;stop-opacity:1" /></linearGradient><linearGradient id="linearGradient4284"><stop offset="0" style="stop-color:#8381c5;stop-opacity:1" id="stop4286" /><stop id="stop4290" style="stop-color:#7e55b3;stop-opacity:0.99607843" offset="0.56639391" /><stop offset="1" style="stop-color:#a52ecb;stop-opacity:0.99215686" id="stop4288" /></linearGradient><linearGradient id="linearGradient4898"><stop id="stop4278" style="stop-color:#bab8db;stop-opacity:1" offset="0" /><stop id="stop4280" style="stop-color:#5955a9;stop-opacity:0.99159664" offset="1" /></linearGradient><linearGradient id="linearGradient3294"><stop offset="0" style="stop-color:#6376e6;stop-opacity:1" id="stop3296" /><stop offset="0.50094414" style="stop-color:#222989;stop-opacity:1" id="stop3302" /><stop offset="1" style="stop-color:#00003d;stop-opacity:1" id="stop3298" /></linearGradient><linearGradient id="linearGradient3284"><stop offset="0" style="stop-color:#000000;stop-opacity:1" id="stop3286" /><stop offset="0.84845906" style="stop-color:#000000;stop-opacity:0.49803922" id="stop3292" /><stop offset="1" style="stop-color:#000000;stop-opacity:0" id="stop3288" /></linearGradient><linearGradient id="linearGradient3274"><stop offset="0" style="stop-color:#000000;stop-opacity:1" id="stop3276" /><stop offset="1" style="stop-color:#000000;stop-opacity:0" id="stop3278" /></linearGradient><linearGradient id="linearGradient3262"><stop offset="0" style="stop-color:#000000;stop-opacity:1" id="stop3264" /><stop offset="1" style="stop-color:#000000;stop-opacity:0" id="stop3266" /></linearGradient><linearGradient id="linearGradient3242"><stop offset="0" style="stop-color:#282828;stop-opacity:1" id="stop3244" /><stop offset="0.39253417" style="stop-color:#808080;stop-opacity:1" id="stop3252" /><stop offset="1" style="stop-color:#d9d9d9;stop-opacity:1" id="stop3246" /></linearGradient><linearGradient id="linearGradient3202"><stop offset="0" style="stop-color:#2b2b2b;stop-opacity:1" id="stop3204" /><stop offset="0.5" style="stop-color:#828383;stop-opacity:1" id="stop3250" /><stop offset="1" style="stop-color:#dadbdb;stop-opacity:1" id="stop3206" /></linearGradient><linearGradient id="linearGradient4966"><stop offset="0" style="stop-color:#b6b3d8;stop-opacity:1" id="stop4968" /><stop offset="1" style="stop-color:#b6b3d8;stop-opacity:0" id="stop4970" /></linearGradient><linearGradient id="linearGradient4938"><stop offset="0" style="stop-color:#000000;stop-opacity:1" id="stop4940" /><stop offset="1" style="stop-color:#000000;stop-opacity:0" id="stop4942" /></linearGradient><linearGradient id="linearGradient4282"><stop offset="0" style="stop-color:#bab8db;stop-opacity:1" id="stop4900" /><stop offset="1" style="stop-color:#5955a9;stop-opacity:0.99159664" id="stop4902" /></linearGradient><linearGradient id="linearGradient4876"><stop offset="0" style="stop-color:#d3d2e8;stop-opacity:1" id="stop4878" /><stop offset="1" style="stop-color:#5955a9;stop-opacity:0.99159664" id="stop4880" /></linearGradient><radialGradient gradientTransform="matrix(0.6817439,0,0,0.5905355,-3.8523706,-28.935273)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4898" id="radialGradient4892" fy="-108.96888" fx="20.951529" r="266.76535" cy="-108.96888" cx="20.951529" /><radialGradient gradientTransform="matrix(1,0,0,0.1854103,0,383.88493)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4938" id="radialGradient4944" fy="471.26172" fx="233.8876" r="170.49393" cy="471.26172" cx="233.8876" /><radialGradient gradientTransform="matrix(1,0,0,0.9121621,0,32.654948)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient4966" id="radialGradient4972" fy="371.76376" fx="299.70135" r="76.696358" cy="371.76376" cx="299.70135" /><radialGradient gradientTransform="matrix(0.414705,0.3300575,-0.5059004,0.6356454,346.95314,49.479585)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3202" id="radialGradient3210" fy="390.45248" fx="289.44067" r="17.67668" cy="390.45248" cx="289.44067" /><radialGradient gradientTransform="matrix(0.414705,0.3300575,-0.5059004,0.6356454,448.41009,-65.398074)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3202" id="radialGradient3238" fy="382.14804" fx="283.50717" r="17.67668" cy="382.14804" cx="283.50717" /><radialGradient gradientTransform="matrix(-6.5565014e-2,-5.9721765e-2,1.6871024,-1.8521705,171.90774,540.51473)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3242" id="radialGradient3248" fy="181.18982" fx="418.45551" r="63.068935" cy="181.18982" cx="418.45551" /><radialGradient gradientTransform="matrix(0.4055116,-3.3440123e-2,0.1034174,4.3988695,177.23251,-1191.6649)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3262" id="radialGradient3268" fy="357.33591" fx="354.51709" r="33.712105" cy="357.33591" cx="354.51709" /><radialGradient gradientTransform="matrix(-0.1339874,-0.1146812,0.3079048,-0.3597394,444.23592,395.03849)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3274" id="radialGradient3280" fy="223.55537" fx="510.58469" r="132.28336" cy="223.55537" cx="510.58469" /><radialGradient gradientTransform="matrix(-1.2497569,1.3798305,-9.6289463e-2,-7.2974479e-2,674.3826,-70.590682)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3284" id="radialGradient3290" fy="-158.17821" fx="284.4671" r="110.2972" cy="-158.17821" cx="284.4671" /><radialGradient gradientTransform="matrix(-0.1008165,-8.0872321e-2,1.0745309,-1.3395252,13.843287,784.79288)" gradientUnits="userSpaceOnUse" xlink:href="#linearGradient3294" id="radialGradient3300" fy="356.62274" fx="425.51019" r="143.34167" cy="356.62274" cx="425.51019" /><filter height="1.088351" y="-0.044175496" width="1.0892536" x="-0.044626798" id="filter4350" style="color-interpolation-filters:sRGB"><feGaussianBlur id="feGaussianBlur4352" stdDeviation="8.7848425" /></filter><linearGradient y2="300.73987" x2="236.61363" y1="-161.8512" x1="-122.20192" spreadMethod="pad" gradientTransform="matrix(0.87385837,0,0,0.82818057,246.00762,250.28138)" gradientUnits="userSpaceOnUse" id="linearGradient4245" xlink:href="#linearGradient4284" /><linearGradient y2="66.018341" x2="173.94518" y1="396.6066" x1="447.80933" gradientTransform="matrix(0.98684959,0,0,0.98684959,3.0344187,2.5250397)" gradientUnits="userSpaceOnUse" id="linearGradient4247" xlink:href="#linearGradient4292" /></defs><rect style="fill:none;display:none" id="rect4772" y="0.20100001" x="0.171" height="512" width="512" /><g style="display:none" id="g4788"><g style="display:inline" id="g4790" /></g><g style="display:none" id="g4806"><g style="display:inline" id="g4808"><path style="fill:#050505;display:none" id="path4810" d="M 349.098,256.651 C 348.833,256.397 386.735,284.256 388.519,281.663 C 394.881,272.411 470.565,188.526 473.303,165.427 C 473.545,163.424 472.787,161.331 472.787,161.331 C 472.787,161.331 471.597,161.187 466.462,157.017 C 463.77,154.825 460.979,152.436 460.979,152.436 C 444.925,153.434 403.094,193.995 349.917,256.004" /></g></g><path style="opacity:0.40500004;fill:#211f46;fill-opacity:0.99607843;stroke:#0a0b1b;stroke-width:8.53333378;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4350)" id="path4233" d="m 491.66937,257.75916 c 0,131.79436 -105.76,238.63481 -236.22155,238.63481 -130.46155,0 -236.221539,-106.84045 -236.221539,-238.63481 0,-131.79437 105.759989,-238.634808 236.221539,-238.634808 130.46155,0 236.22155,106.840438 236.22155,238.634808 z" transform="matrix(0.98684957,0,0,0.98684957,3.0344041,2.5250397)" /><path d="m 488.23812,256.89456 c 0,130.06121 -104.3692,235.49665 -233.1151,235.49665 -128.7459,0 -233.115201,-105.43544 -233.115201,-235.49665 0,-130.06123 104.369301,-235.49666 233.115201,-235.49666 128.7459,0 233.1151,105.43543 233.1151,235.49666 z" id="path4235" style="opacity:1;fill:url(#linearGradient4245);fill-opacity:1;stroke:url(#linearGradient4247);stroke-width:13.33816814;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><path d="m 175.0003,422.31057 c 0,0 19.7385,1.39634 45.1312,-0.84159 10.2834,-0.9063 49.3267,-4.74128 78.5169,-11.14289 0,0 35.5899,-7.61669 54.6301,-14.63335 19.9225,-7.34185 30.7636,-13.57304 35.6433,-22.40243 -0.2128,-1.80907 1.5024,-8.22438 -7.685,-12.07788 -23.4887,-9.85199 -50.73,-8.06998 -104.6338,-9.21285 -59.7772,-2.05391 -79.6627,-12.05971 -90.2556,-20.11838 -10.1579,-8.17519 -5.05,-30.79254 38.4742,-50.71499 21.9244,-10.60898 107.8705,-30.18698 107.8705,-30.18698 -28.9451,-14.30725 -82.9186,-39.45893 -94.0134,-44.89023 -9.7308,-4.76348 -25.303,-11.93595 -28.6785,-20.61368 -3.8271,-8.33089 9.0383,-15.50726 16.2248,-17.56236 23.1448,-6.67602 55.8182,-10.82538 85.5548,-11.29122 14.9472,-0.23417 17.3734,-1.19586 17.3734,-1.19586 20.6243,-3.42116 34.2014,-17.53175 28.5446,-39.87876 -5.0783,-22.81046 -31.8617,-36.21365 -57.3138,-31.57361 -23.9682,4.36956 -81.7378,21.15007 -81.7378,21.15007 71.4075,-0.61803 83.3592,0.57378 88.697,8.03676 3.1523,4.40742 -1.4324,10.45068 -20.4765,13.56099 -20.733,3.38616 -63.8312,7.46399 -63.8312,7.46399 -41.3449,2.4554 -70.4682,2.61974 -79.203,21.11314 -5.7065,12.08196 6.0854,22.7633 11.2538,29.4493 21.8407,24.28905 53.3882,37.38879 73.6948,47.03553 7.6405,3.62963 30.0586,10.48407 30.0586,10.48407 -65.8782,-3.62335 -113.4003,16.6055 -141.2764,39.89622 -31.5288,29.16261 -17.581403,63.92354 47.0124,85.3268 38.1517,12.6416 57.0725,18.58695 113.9815,13.46232 33.52,-1.80673 38.8041,-0.73155 39.1383,2.01892 0.4705,3.87242 -37.2311,13.49165 -47.524,16.4606 -26.1853,7.55306 -94.8276,22.80438 -95.1712,22.87835 z" id="path4237" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></svg> EOF
3. Problemas
- emacsclient no encuentra el socket: añadir el parámetro
-s
con/tmp/emacs1000/server
. El número1000
indica el identificador del usuario. También puede especificarse la variableserver-socket-dir
al iniciar el servidor.