Emacs es un Lispboard
¿Qué hubiera pasado si el buffer por defecto de Emacs hubiera sido un emulador de terminal? Conceptualmente, desde fuera, se percibiría como una terminal vitaminada con Lisp como scripting. Tal vez hablaríamos de iTerm2 vs Emacs, o de Kitty vs Emacs, o incluso Bash vs Emacs. ¿Y si el buffer por defecto hubiera sido Dired, el explorador de archivos? A lo mejor la historia hubiera creado rivalidades tales como Total Commander vs Emacs, o Finder vs Emacs.
Pero la historia fue otra. Ya sabemos que si levantas una instancia de Emacs sin ningún tipo de configuración, lo que ves es un buffer con el siguiente mensaje:
;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with ‘C-x C-f’ and enter text in its buffer.
Un bloc de notas con un intérprete de Lisp embebido. Su rival natural es Vim con un intérprete embebido (Vimscript). Sin embargo, el editor que a todos nos ha hecho memorizar el :q! se quedó en el buffer, mientras que Emacs se fue expandiendo con más y más software hasta convertirse en una interfaz del sistema operativo.
Soy un entusiasta de Emacs, y tal vez por ello este artículo pierda credibilidad. Sin embargo, no te vengo a hablar de lo fantástico que es el editor del ñú, ni de convencerte de que lo uses. Mi objetivo es expresarte por qué el navegador web es su auténtico rival natural, y por qué Emacs es un Lispboard donde construyes cómo quieres trabajar.
Imaginemos un entorno de trabajo perfecto
Para ponernos en contexto, hagamos un ejercicio de imaginación.
Supongamos que quiero trabajar en un único lugar para todos mis contextos, tanto personales como laborales. Así memorizo mis atajos, aplico mis configuraciones y no tengo que cambiar de contexto. Todo está bajo la misma ventana.
Es un problema, ya que implica fusionar programas que no tienen nada que ver entre sí pero que deben colaborar. Por ejemplo, un emulador de terminal, un cliente de correo y un editor de código (o IDE). Con un sistema de layouts, dentro de la misma ventana, podría tener una columna con la bandeja de entrada de mis correos, otra con la terminal y una tercera con mi IDE listo para picar lo que necesite. En este espacio, sería sencillo programar un script en bash, lanzarlo desde la terminal y recibir un correo con el resultado. Todo en la misma ventana, sin cambiar de contexto, con los mismos atajos, la misma tipografía y el mismo tema. Incluso podría añadir una cuarta columna con un cliente de Git para versionar el script y subirlo a un repositorio remoto. O ya que estamos, una quinta columna con mi agente favorito de IA capaz de leer tanto mi código como el resto de paneles.
Acabamos de crear una interfaz.
Pero esta no sería la parte más útil: los programas estarían integrados entre sí, cada uno viviendo en su ámbito y a la vez en otro global. Ello me permite que si activo el corrector ortográfico en el editor de código con cierta configuración, también se active en la terminal, en el cliente de correo al componer mensajes o cuando escribo commits. Todo con la misma interactividad y configuración. No son cuatro binarios aislados que conectas con tuberías, sino que son programas escritos en el mismo lenguaje, se ejecutan sobre el mismo runtime y comparten el mismo bus de eventos.
Acabamos de crear un conector.
Ahora quitamos una capa innecesaria: el script de bash. Si ya tengo un intérprete embebido en esta misma ventana, puedo crear mis propios scripts. No necesito un binario externo. Ya no necesito ni salir de la ventana, ni tocar el sistema operativo. Todos mis scripts, prototipos y flujos de trabajo pueden vivir juntos.
Acabamos de crear un hábitat.
Solo queda un problema con el runtime: mañana cambiaré de portátil, o querré trabajar desde un servidor, y no pienso reconstruir mi entorno desde cero. Quiero que mis scripts funcionen exactamente igual independientemente del sistema operativo y del hardware. Que un script se comporte de la misma manera en Windows, en una Raspberry Pi o en un Android barato. Necesito que el entorno entero sea un runtime multiplataforma con bytecode que se ejecute en cualquier lado.
Acabamos de crear una máquina virtual.
Ahora, para terminar de redondear la idea, usaremos Lisp como lenguaje de scripting y a todo el conjunto lo llamaremos Emacs. Aunque yo prefiero llamarlo de otra forma: un Lispboard. Como una breadboard de electrónica, una placa donde cada módulo que pinchas comparte bus con todos los demás, solo que aquí los módulos están escritos en Lisp.
Y si durante este ejercicio has pensado "esto me suena: pestañas, aplicaciones y una máquina virtual multiplataforma... es mi navegador", guárdate esa intuición. Al final del artículo volveremos a ella.
¿Qué no es Emacs?
Con lo mencionado hasta ahora quiero desmentir algunos mitos que rodean a Emacs:
- No es un editor de texto: es un entorno de trabajo completo, con un lenguaje de scripting embebido, su software y un runtime multiplataforma. El editor es un programa más dentro de ese entorno, al igual que lo es el terminal, el cliente de correo, IRC, gestor de archivos o el navegador web (sí, Emacs trae uno).
- No es un sistema operativo: es un entorno de trabajo que corre sobre un sistema operativo, y que puede sustituir a muchos de los programas que este ofrece. Pero no tiene drivers, ni kernel, ni herramientas de bajo nivel. No puede ejecutarse sin un sistema operativo.
- No es un IDE: no hay por defecto un conjunto de herramientas enfocadas para programar en un lenguaje concreto. Para ello debes usar backends de LSP, depuradores y linters, que se instalan como paquetes. Pero sí que puedes llegar a tenerlo, es uno de sus usos más comunes.
Lo que sí es: un intérprete de Lisp y un framework que corren sobre el sistema operativo de la forma más agnóstica posible, y que reimplementan buena parte de los programas que este ofrece.
Mi flujo de trabajo
Scripting y prototipado
Cuando tú piensas: "Voy a crear un script sencillo en bash para automatizar una tarea", yo pienso: "Voy a crear una función en Elisp". Y además, le daré una interfaz gráfica si necesito crear flags o incluir texto.
Por ejemplo, supongamos que tienes la necesidad de crear un script para ti, no para un proceso CI/CD o cron. El objetivo es hacer backups de una carpeta concreta (tal vez en la nube). Podrías acabar con un comando como este:
./backup.sh /home/usuario/carpeta /home/usuario/backup
Pero además incluyes una flag para crear un zip:
./backup.sh -z /home/usuario/carpeta /home/usuario/backup
Pues en lugar de pasar por la terminal, yo creo una función en Elisp que hace lo mismo, y le añado un pequeño panel.
Lanzo:
M-x my/backup RET
Y se mostrará un buffer con una interfaz como esta:
Backup de carpeta
Carpeta: [ /home/usuario/carpeta ]
Destino: [ /home/usuario/backup ]
[ ] Comprimir en zip
[ Cancelar ] [ Ejecutar ]
Con inputs, checkboxes y botones. Sin tener que acordarme ni de dónde estaba, ni de sus parámetros u orden.
Si has trabajado antes con Lisp, verás que el código es muy básico:
(require 'widget)
;; Logic
(defun my/backup-run (folder target zip)
"Sync FOLDER into TARGET with rsync, or compress it to a zip when ZIP."
(let* ((folder (expand-file-name folder))
(target (expand-file-name target))
(command
(if zip
(format "zip -r %s %s"
(shell-quote-argument
(expand-file-name
(format-time-string "backup-%Y-%m-%d.zip") target))
(shell-quote-argument folder))
(format "rsync -a %s/ %s"
(shell-quote-argument folder)
(shell-quote-argument target)))))
(async-shell-command command "*Backup log*")))
;; UI
(defun my/backup ()
"Open a panel to back up a folder."
(interactive)
(switch-to-buffer "*Backup*")
(kill-all-local-variables)
(let ((inhibit-read-only t))
(erase-buffer))
(remove-overlays)
(widget-insert "Backup de carpeta\n\n")
(let* ((folder (widget-create 'editable-field
:format "Carpeta: %v\n"
"/home/usuario/carpeta"))
(target (widget-create 'editable-field
:format "Destino: %v\n"
"/home/usuario/backup"))
(zip (widget-create 'checkbox nil)))
(widget-insert " Comprimir en zip\n\n")
(widget-create 'push-button
:notify (lambda (&rest _) (kill-buffer))
"Cancelar")
(widget-insert " ")
(widget-create 'push-button
:notify (lambda (&rest _)
(my/backup-run (widget-value folder)
(widget-value target)
(widget-value zip))
(kill-buffer))
"Ejecutar"))
(use-local-map widget-keymap)
(widget-setup))
Y esto escala más allá de los juguetes. Con este mismo enfoque tengo montados sistemas de todo tipo. Por ejemplo la newsletter de este blog: gestión de suscriptores, genero el HTML de los correos a partir de archivos org, hago el envío, me envío previas y analizo los datos. Todo en Elisp, local y con un panel de control sencillo integrado a otras herramientas.
La clave del ejemplo es que no estoy creando un script para un sistema operativo o intérprete, sino una función para mi entorno de trabajo. Estoy construyendo un nuevo flujo de trabajo, en un espacio donde puedo programar mis propias herramientas, conectarlas entre ellas o construir una encima de otra. Podría crear un sistema de notificación asíncrono para avisarme cuando algo termine, y conectarlo más adelante con la herramienta anterior sin ningún coste.
Y todo esto lo puedo hacer porque tengo un lenguaje de scripting embebido, un conjunto de bibliotecas (como widget.el para crear interfaces gráficas) y un runtime multiplataforma que me asegura que mis scripts funcionarán igual en cualquier sistema operativo. Eso es un Lispboard.
Programación y desarrollo
Quiero hacer hincapié en que separo las tareas o entornos por pestañas. Y dentro de cada pestaña tengo un layout con los buffers (o software) que necesito.
En la pestaña de IDE suelo abrir:
- Un editor de texto con algún backend de LSP y depurador (dap-mode, Eglot, etc.).
- Un compañero de pair programming con IA (chatgpt-shell conectado a Claude).
- Un cliente de Git (Magit) para versionar y revisar los cambios de la IA.
Aunque voy intercalando algunos temporales como el explorador de archivos (Dired con o sin TRAMP), el terminal (vterm), el cliente de HTTP (verb), Docker (docker.el), navegador web (eww) o el gestor de proyectos (Projectile).
Trabajar en Emacs con este nivel de integración es un placer difícil de describir. Entiendes por qué enamora a quienes lo usan para programar.
Notas y estudio
Todo lo que pienso, planifico o estudio acaba en texto plano. La base es org-mode: notas, tareas y planificación. Encima construyo con Denote la gestión de mis apuntes: cada nota es un archivo con los metadatos en el propio nombre, enlazadas entre sí. Y cuando el material de estudio es un PDF o un EPUB, lo leo sin salir con pdf-tools o nov.
Alrededor orbitan piezas pequeñas que completan la rutina como jit-spell subrayando mis faltas al vuelo (¿recuerdas el corrector que se configura una vez y funciona en todas partes? Es este) y wallabag para leer o guardar artículos que quiero estudiar más tarde con calma.
Comunicación: chats, correo y redes sociales
Aunque no lo parezca, la comunidad a lo largo de las décadas ha ido construyendo un pack de herramientas de comunicación excelentes. Incluso para un mismo protocolo hay varias implementaciones, y cada una tiene sus ventajas.
En mi caso, tengo una pestaña en exclusividad para el correo con mu4e. Cubre todas las necesidades que puedo esperar de un cliente de correo: redactar, responder, reenviar, filtrar, buscar, etiquetar, marcar como leído/no leído, etc. Y lo debe hacer bien porque es el canal de comunicación más importante que tengo: listas de correo, discusiones en torno a un Pull Request, mensajes de otros desarrolladores, notificaciones de servicios, y todo lo propio de una vida personal y profesional.
En otra pestaña tengo divididos un conjunto de chats:
- IRC con ERC conectado a Libera.Chat. Por aquí, curiosamente, es donde he conocido a más gente y he podido hablar con muchos desarrolladores de software libre. No entiendo ese afán por considerarla obsoleta.
- Mastodon con mastodon.el para el Fediverso.
- Org Social con org-social.el para leer las publicaciones en mi red social favorita (no soy imparcial, lo sé y no me importa).
- Telegram con telega.el, que me permite leer y responder mensajes de grupos y canales.
Solo salgo para Teams y Discord, ambos canales de comunicación de mi trabajo. Y WhatsApp, cuyo uso en Emacs aún no me convence.
Noticias y lectura
Mi principal fuente de información es el RSS con Elfeed, casi todos blogs personales. Uso clientes para los agregadores, hackernews-modern y lobsters (ambos hechos por mí). Con Gnus leo algunos grupos de noticias de Usenet (sigue vivo, y se lee de maravilla) y con Elpher me paseo por Gemini o Gopher. Cuando quiero abrir un enlace web, le doy una oportunidad a eww, el navegador web de Emacs. Si es ilegible, ya me voy a Firefox o similares (tengo un atajo).
Ocio
La jornada laboral es más agradable escuchando música, de ahí EMMS apoyado en mpv. Y cuando quiero desconectar un rato, me gusta jugar al ajedrez con chess, sea solo o con un amigo en línea. Al fin y al cabo, la placa también está para divertirse.
Emacs es un Lispboard
La comunidad tiene una expresión para esta forma de trabajar: living in Emacs. Se lleva escribiendo sobre ello décadas, y al final del artículo te dejo las lecturas que más me han marcado. Pero fíjate que vivir en Emacs describe un hábito; lo que he intentado enseñarte es la consecuencia. Todo lo que has visto no es una colección de programas, es una sola placa donde cada módulo comparte bus con los demás. Una interfaz, un conector, un hábitat y una máquina virtual (literal: Elisp se compila a bytecode). Un Lispboard para jugar o para hacer tu trabajo más eficiente.
Su rival es el navegador web. Cumple más requisitos de los que nos gusta admitir: es una máquina virtual multiplataforma (de JavaScript) y dentro vive media humanidad, con su correo, su chat, su música y su oficina. Pero falla en lo esencial: las pestañas son silos que no comparten bus, no puedes cablear tu correo con tu chat, y ningún módulo es tuyo: cada uno pertenece a un tercero que puede cambiarlo, llenarlo de publicidad o cerrarlo mañana. Además, el acceso al propio host es limitado: no es fácil tocar el disco ni hablar con el sistema operativo. El navegador es un Lispboard de alquiler, con casero. Emacs es el único que puedes poseer.
Para ir terminando, quiero aclarar que usar Emacs no es nostalgia, es que todavía no ha aparecido nada comparable. El 0,1% que lo usamos y lo exprimimos a diario lo hacemos porque nos permite trabajar de una forma que ningún otro software nos permite. Posiblemente con nuestra configuración tengamos una relación de por vida. Siempre hay algo que tocar, mejorar o automatizar. Y si no lo hay, lo creamos. Emacs no es libre por su licencia GPL, sino porque es el único lugar donde puedes vivir y trabajar a tu manera.
Referencias
- Why Emacs is still my interface to my computer, el artículo que me animó a escribir este.
- Living in Emacs, de Irreal: vivir en Emacs como un jardín japonés, un proceso que busca la perfección pero nunca está completo.
- Living in the Browser vs. Living in Emacs, también de Irreal, sobre la dicotomía entre las dos grandes interfaces de nuestro tiempo.
- Emacs: Everything's a Buffer, sobre el buffer como unidad universal de interacción.
- How I use Emacs, de Joshua Blais.
- I Tried Living Completely Using Just Emacs, de FadinGeek: el experimento de vivir solo con Emacs contado desde fuera.
- Life in Emacs (revisited), de scut.
- ¿Por qué los usuarios de Emacs lo usan para todo?. Si quieres más razones propias, es un buen complemento.
- Imaginemos un entorno de trabajo perfecto
- ¿Qué no es Emacs?
- Mi flujo de trabajo
- Scripting y prototipado
- Programación y desarrollo
- Notas y estudio
- Comunicación: chats, correo y redes sociales
- Noticias y lectura
- Ocio
- Emacs es un Lispboard
- Referencias
This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.
Will you buy me a coffee?
This is how I keep writing without ads or paywalls.
Sure, it's on me!
Comments
There are no comments yet.