Revista Tecnología

Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (I – Configuración general)

Publicado el 19 diciembre 2017 por Gaspar Fernández Moreno @gaspar_fm

Emacs ha sido mi editor de texto preferido durante más de 10 años. Y, aunque casi desde el principio (desde que empecé a usarlo en serio) quise personalizarlo con Creando configuración personalizada para Emacs. .emacs.d explicaciones detalladas Configuración general)Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (I – Configuración general)
las opciones que más o menos consideraba interesantes, esa configuración ha estado durante muchos años abandonada. Funcionando bien, pero abandonada. Y, sin aprovechar muchas de las nuevas características y extensiones que están disponibles.

El año pasado, me animé a publicar mi .emacs.d en GitHub. Con muchas novedades, aunque no me terminaba de convencer al 100% y, como estas cosas pueden ser un tanto duras (reconozco que una configuración de Emacs desde cero puede desanimar a cualquiera), he decidido hacer estos pequeños apuntes. Para conseguir una configuración sin calentarnos la cabeza en exceso, pero con cierto detalle, para que todos podamos modificarla y personalizarla a nuestro gusto.

Nota: El post original de la configuración de Emacs se me ha alargado demasiado, aunque incluye mucho código. Así que lo he dividido en varias partes que iré publicando estos días e incluiré un resumen para digerir todo esto de forma sencilla.

En este post sobre la configuración general de Emacs me voy a centrar en la descripción general de todo lo que quiero configurar y aspectos como la ventana, la modeline, el gestor de paquetes y de código externo, ventanas y algunos modos generales. Además, incluyo agradecimientos a muchos de los desarrolladores que hacen esto posible (recordemos que aunque sea una configuración, en Emacs todo viene programado en Emacs Lisp). También cabe decir que las últimas versiones de Emacs compilan el código Lisp para agilizar su ejecución, por lo que no tenemos que obsesionarnos con la pérdida de velocidad de un lenguaje interpretado.

Antes de empezar

Hay ciertas extensiones que, aunque son tremendamente buenas, no las he incluido en mi configuración porque realmente no las uso, o tengo otras alternativas. Aunque Emacs puede convertirse incluso en nuestro gestor de ventanas, para algunas acciones, como el correo, lector RSS, notas, etc utilizo programas externos que me resultan más amigables. Así que, aunque muchos usuarios de Emacs las aman con locura, no incorporaré:

En unos días me gustaría publicar la configuración completa en mi GitHub. Aún tengo que retocar algunas partes y poner algunos comentarios para que quede completa. A partir de ese momento, la última versión de la configuración estará en esa web. Desde aquí se podrá seguir consultando la guía y alguna información importante, sobre todo el desarrollo y las explicaciones, pero tal vez en el futuro vayan cambiando algunas cosas o vaya variando de forma fina ciertos aspectos, o incluyendo algún nuevo modo y algunas cosas no las actualizaré aquí.

Probando configuraciones

Como compartí en un post anterior sobre Emacs, la configuración de Emacs suele ser por usuario. Eso imposibilita poder probar varias configuraciones del editor en la misma sesión de usuario. Aunque podemos utilizar este pequeño código y pegarlo en nuestro ~/.emacs:

De esta forma, el fichero de configuración que se utilice será ~/.emacs y, a partir de ahí, atendiendo al valor de la variable de entorno EMACS_USER_DIR podremos cargar la configuración que queramos. Si nuestra configuración la estamos probando, por ejemplo en el directorio ~/.emacs.d_new podemos hacer:


Y se ejecutará el programa con la configuración deseada.

Agradecimiento a muchos grandes desarrolladores

Mi configuración no sería posible sin los miles de personas alrededor del mundo que han hecho posible GNU Emacs (M-x about-emacs), todos los que han desarrollado plugins (iré detallando autores) y a todos los que han publicado sus .emacs.d por Internet y de los cuales he ido cogiendo algunos recortes. En este post no soy el autor de muchas de las funciones ni los trozos de código que hay publicados, aunque sí que los he probado todos. También he desarrollado algunas partes, y me he basado en el trabajo de otros para completar algunas funcionalidades. Especialmente deberían funcionar a partir de Emacs 24.5 que, aunque no es el último (vamos por Emacs 25.3 a día de hoy), es el que muchas distribuciones traen en sus repositorios. De todas formas, también debe ser compatible con la última versión de Emacs.

En estos ficheros incluiré líneas de código de:

Archivos y directorios: organización

Debemos recordar que la configuración podemos complicarla un montón. Y, en este directorio, además de configuración, irán los ficheros de los módulos, extensiones y temas que queramos utilizar. Por otro lado podremos también encontrar archivos de caché, diccionarios, colecciones de código para autorrellenar, layouts guardadas, etc.
Emacs, también tiene varias formas de incluir módulos:

  • Desde el SO. Es decir, podemos instalar los módulos desde el repositorio de nuestro sistema operativo. Y estos módulos serán a nivel de sistema afectando a todos los usuarios. De todas formas, en la actualidad cada vez se usa menos esta forma de hacer las cosas. Lo suyo es hacerlo desde la configuración de Emacs. Él se encarga de las actualizaciones, incluso puede ser que una versión del plugin no nos funcione y debamos imponer una anterior para una configuración, o que nuestra distribución no nos dé la última, y si nos llevamos la configuración de un ordenador a otro, no funcione.
  • Desde los repositorios de Emacs. Emacs tiene su propio gestor de paquetes, muy chulo, muy estilo Emacs. Y, muchas extensiones las utilizaremos de esta manera. Es más, si instalas una de las configuraciones que alguien ha subido a Internet, la primera vez, Emacs tardará muchísimo en arrancar porque tendrá que descargar y compilar todos los módulos que utilicemos.
  • Copiados directamente en .emacs.d. Todas las extensiones del mundo, no están en el repositorio. O tal vez, la versión que nos interesa. Así que podemos copiar todos los archivos .el del módulo dentro de nuestro .emacs.d

Lo bueno es que si cambiamos de ordenador, podemos llevarnos toda la configuración, junto con módulos y demás a cualquier lado.

Básicamente vamos a tener esta estructura. Aunque se irán añadiendo algunos directorios y archivos automáticamente para facilitarnos las cosas:

.
├── custom.el : Variables personalizadas. Algunos programas suelen escribir aquí, mejor no lo toquemos.
├── elpa : Directorio donde se almacenan todos los paquetes descargados de Emacs
├── init.el : Fichero principal de configuración
├── lisp : Ficheros que se llaman directamente desde el fichero de configuración
│ └── lib : Bibliotecas que usarán los diferentes archivos de configuracíón
├── semanticdb : Base de datos de ficheros, bibliotecas, etc para autocompletado
├── settings.el : Variables de configuración personales
├── site-lisp : Módulos LISP que no están en el gestor de paquetes y debemos añadir a mano

Características que necesito

Aunque, mientras creamos la configuración vamos a descubrir cosas que están muy bien, lo primordial, para mí, es lo siguiente:

  • Lenguajes preferidos: C, C++, Bash, Python, PHP, SQL, HTML, CSS, Javascript. Son lenguajes con los que voy a pasar mucho tiempo y me interesa que todo funcionen a las mil maravillas y estén personalizados. Tanto el coloreado como la indentación. Además, a veces tendré que utilizar varias indentaciones diferentes dependiendo del proyecto. Ya sabéis, hay que adaptarse a las reglas de estilo de cada desarrollo.
  • Otros lenguajes: SCSS, Ruby, XML, Java. No los suelo usar mucho y me apaño con lo básico.
  • Números de línea en el lateral izquierdo. Como casi todos los editores.
  • Auto completado de código. Aunque Emacs tiene muy buenas funciones de autocompletado con la combinación M-/, en ocasiones necesitamos un autocompletado de código más inteligente, basado en el propio lenguaje y el código que estamos escribiendo, capaz de escanear variables y clases para delimitar de forma más concreta lo que vamos a escribir y ahorrar tiempo. Yo utilizaré auto-completion-mode y semantic.

Empezamos init.el

Vamos a empezar a picar nuestro init.el . Aunque básicamente lo que vamos a hacer es incluir cosas. De todas formas, al principio y al final hacemos algunas cosas interesantes como:

  • Definir la ruta desde la que cargará archivos: lisp/
  • Activar un cronómetro que nos dirá cuánto tarda Emacs en arrancar y nos permitirá afinar la configuración o ver si hay algún módulo que está metiendo la pata en el arranque.
  • Definir el garbage collection cuando haya terminado. Esto lo podríamos meter en una función si queremos.
  • Cargar archivos settings.el y custom.el
  • Incluir muchas configuraciones individuales.

En medio del fichero dice ";;; Require everything" pongo un require y puntos suspensivos. Eso es porque vamos a requerir cada uno de los ficheros que pongamos ahí dentro de lisp/ . Por supuesto que podemos poner todo en un archivo, y que éste sea tremendamente grande, pero vamos a hacer las cosas bien y vamos a dejarlo curioso. Cada parte que queramos inicializar la escribiremos en un archivo. Si es el tema, init-theme, si es la ventana init-window, si es un conjunto de herramientas para python, init-python, y así sucesivamente. Y dentro de cada uno, puede haber más requires.

Con esto nos acostumbramos un poco a Lisp. Además, vemos que al final del fichero ponemos (provide 'init). Eso lo haremos al final de cada fichero, proporcionando un nombre adecuado en cada archivo (todos no van a ser init).

Utilidades y gestor de paquetes

Creando configuración personalizada para Emacs. .emacs.d explicaciones detalladas Configuración general)Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (I – Configuración general)
Aquí incluiremos cosas generales, en general son ficheros pequeños, incluiremos funciones de bibliotecas (las bibliotecas las pondré al final) y prepararemos el gestor de paquetes de Emacs para que automáticamente descargue e instale paquetes que necesitamos y no estén instalados.
Además, aunque intentaremos tirar de gestor de paquetes para todo, así tendremos actualizaciones automáticas y tendremos al día muchas de las utilidades de Emacs; algunas no están presentes en este gestor, o puede que necesitemos versiones diferentes para nuestro sistema. Tenemos que tener en cuenta que si tenemos una versión de Emacs algo antigua, habrá paquetes del gestor de paquetes que sean demasiado nuevos para nosotros, así que tendremos que incluir una versión algo más antigua. Esto lo podemos hacer copiándolo a site-lisp/

init-utils.el

init-site-lisp.el

Nos ayuda a cargar los ficheros que hay en site-lisp sin trabajar mucho.

init-elpa.el

Inicializa el sistema de paquetes ELPA (Emacs Lisp Package Archive) y la instalación bajo demanda de paquetes:

Configuración del tema: init-theme.el

Antes usaba otro tema, que se puede ver comentado. Ahora utilizo color-theme, de nuevo, con el que tenemos un montón de temas de color muy chulos para elegir. Además, introduzco definiciones de color para linum (que lo veremos después), ya que el color de resaltado de línea del tema no me termina de convencer.

Configuración del entorno gráfico GUI (init-gui.el)

¿Cómo quiero el entorno gráficao de Emacs? No lo explico todo, pero sí algunas cosas interesantes:

  • No utilizo diálogos del entorno gráfico. Navego por los archivos desde los buffers de Emacs y en lugar de diálogos uso el minibuffer. Por eso, use-file-dialog y use-dialog-box los pongo a nil.
  • Personalizo el título de la ventana
  • Desactivo también tool-bar-mode para la barra de herramientas, menu-bar-mode para los menús y set-scroll-bar-mode para la barra de scroll
  • Uso linum-mode para mostrar los números de línea y hl-line para resaltar la línea actual (parte de la configuración extraída de aquí)
  • No me gusta que Control+Z minimice la ventana. Muchas veces lo pulso por equivocación
  • Cuando hay algún error, o se acaba el autocompletado, o los buffers llegan a su fin, Emacs, hace sonar la campana, o el altavoz interno del ordenador. Se puede vincular a un sonido del sistema de error, pero muchas veces mientras editamos suena demasiado. Yo prefiero tener una señal visible y sutil (invierto los colores de parte de la mode-line, es el visible-bell.
  • Defino algunas teclas personalizadas (vemos más adelante el resumen de teclas)
  • Escribe fecha y hora en la modeline

Como parte de la configuración del entorno, podemos incluir la configuración de la mode-line. Aunque la he incluido aparte porque a cada uno nos gusta una mode-line, así podemos elegirla, y probar con y sin mode-line. A mí me gustó mucho la smart-mode-line, a la que le podemos poner el tema de la powerline. Además, he utilizado también anzu-mode para mostrar el número de resultados de las búsquedas en la modeline.

init-modeline.el

Miscelánea de edición: init-misc.el

Aquí incluyo algunas cosas interesantes. Aunque hay mucho comentado como neotree, flycheck, flyspell y yasnippet que ya no los uso; voy a incluir y configurar algunos plugins curiosos que están muy bien:

  • uniquify, originalmente escrito por Dick King, ¡en el 86! una extensión con más de 30 años que sigue siendo mantenida. Nos servirá para que Emacs renombre los buffers de un modo único. En este caso, cuando hay dos buffers con un archivo abierto con el mismo nombre, se añade al nombre del buffer el nombre del directorio donde se encuentra. Así no hay confusión. El comportamiento normal de Emacs es añadir <2> o <3> al archivo, por lo que es más lioso. Este plugin suele venir instalado con Emacs, aunque desactivado.
  • recent-files, nos da la posibilidad de abrir archivos recientes.
  • smex. por Cornelius Mika. Aumenta la funcionalidad de M-x haciendo que las búsquedas de órdenes y escritura de argumentos sean más intuitivas. Esta extensión reordena los comandos colocando los más utilizados primero, así nos resultará más cómodo acceder a ellos.
  • (fset 'yes-or-no-p 'y-or-n-p). Emacs, por defecto, en su afán por la seguridad, obliga a escribir "yes" o "no" de forma completa ante determinadas acciones consideradas peligrosas. Sobre todo cuando podemos perder información con ello. Aunque desde el punto de vista de la usabilidad es una pérdida de tiempo escribirlo completo cuando puedes pulsar y o n. De todas formas, esto debemos usarlo bajo nuestra responsabilidad, porque siempre podemos cargarnos algo y la culpa ya no será de Emacs.
  • mmm-mode, original de Michael Shulman. Nos da la posibilidad de poder utilizar varios major modes, en un mismo buffer. Los major modes suelen estar ligados a lenguajes de programación, proporcionando anidado y coloreado. Y, puede que, a veces, tengamos que editar un archivo en el que haya implicados varios lenguajes. El ejemplo más claro es cuando dentro de un archivo HTML, escribimos código Javascript y CSS, y puede que incluso PHP también. En ese caso, queremos que el código se coloree en consecuencia.
  • annotate, nos permite hacer anotaciones en el código que no se escribirán (a priori) en el mismo archivo (sino en un archivo de texto nuestro dentro del directorio de .emacs.d). Es útil cuando queremos hacer algo para que sólo lo veamos nosotros, escribir pequeñas notas al lado del código. Eso sí, este modo no es compatible con el modo fci (del que hablaremos más tarde), así que cuando se active este, desactivaremos fci.
  • htmlize, [autor] que crea archivos HTML de los archivos fuente que tenemos, o estamos editando. Conservando los estilos de anidado y coloreado de código. Muy útil para mostrar fragmentos de código a otras personas, o para incluir en documentación.
  • ido-mode, nos da muchas facilidades a la hora de abrir y guardar archivos con C-x C-f como búsquedas automáticas de archivos parecidos (por si no escribimos el nombre exacto o no estamos en la ruta correcta) y navegación inteligente por las carpetas.
  • regex-tool, muestra una ventana nueva en la que podemos trabajar para crear nuestras expresiones regulares cómodamente.
  • ¡Chequeos extra de seguridad! Es importante que los paquetes que nos descarguemos del gestor lo hagan desde fuentes oficiales y verificadas. Por lo tanto, verificaremos los certificados SSL para asegurarnos que conectamos con los verdaderos servidores y nadie los está suplantando.
  • visual-regexp, realiza un reemplazo de cadenas con expresiones regulares de forma visual.
  • annotate, nos permite hacer anotaciones en el código. No se guardarán en los mismos archivos, sino en un archivo de anotaciones aparte. Es muy útil para cuando dejamos para luegos, o queremos dejar una nota para nosotros sin que la vean otras personas.
  • Otros paquetes interesantes: restclient, async, s, restart-emacs
  • Algunas pequeñas configuraciones como: teclas para búsquedas en historial, abrir un terminal

Aquí tenemos el archivo:

Inicialización de las ventanas

Creando configuración personalizada para Emacs. .emacs.d explicaciones detalladas Configuración general)Creando una configuración personalizada para Emacs. Mi .emacs.d con explicaciones detalladas (I – Configuración general)
Recordemos que en Emacs, el concepto de frame y window difiere de lo que estamos acostumbrados. Y es que Emacs, es más antiguo que nuestros conceptos de marco y ventana. Por lo tanto, para Emacs una ventana o window es cada una de las subdivisiones en las que podemos partir el punto de vista. Mientras que un frame es cada una de las nuevas ventanas que instanciamos de la aplicación. Al principio choca un poco, pero te terminas acostumbrando.
Por lo tanto, mi archivo init-windows.el será el siguiente:

Utilidades varias

En mi configuración, como dije al principio, he incluido utilidades de varios desarrolladores. Estas utilidades las estoy colocando dentro de ~/.emacs.d/lisp/lib/. Serán funciones que no trae Emacs de serie y que aumentan su funcionalidad. Todos estos ficheros se cargarán automáticamente cuando se ejecute init-utils.el:

Encontramos utilidades para recargar, eliminar y renombrar buffers, entre otras. Poéis ejecutar algunas de estas funciones directamente con M-x o evaluando con M-:

sachachua.el

Algunas funciones tomadas prestado de Sacha Chua:

Funciones tomadas de la distribución Prelude. Por ahora sólo una, pero abierto está para introducir más... Esta función, copia al portapapeles el nombre de fichero actual, es algo muy útil de vez en cuando.

sanityinc.el

Son funciones y utilidades creadas por Steve Purcell. Hay de todo, están más o menos documentadas y muy probadas. Tal vez algunas como las que manejan transparencia no funcionen en todos los entornos, aunque deberían. Pero sólo tenemos que echarles un ojo.
También cuenta con algunos trucos para que popup.el no haga cosas raras en la pantalla en combinación con el famoso fci-mode del que hablaremos en un futuro post.

Son funciones que he recopilado, modificado o hecho yo. Por ahora voy a enseñar sólo dos, para poner el modo pantalla completa y para monitorizar el tiempo de carga de Emacs. Aunque en futuras versiones habrá algunas funciones más.

Mis teclas personalizadas

En estos ficheros he definido muchas teclas y acciones personalizadas:

  • Click con el botón izquierdo en un número de línea: selecciona dicha línea
  • Arrastral ratón desde un número de línea a otro: selecciona todas esas líneas
  • C-z : NO minimiza la ventana
  • C-c e: Abre un terminal eshell
  • C-x o: Cambia ventana, comportamiento habitual, aunque cuando hay más de 2 ventanas mostrará una pantalla especial para seleccionar la ventana a la que vamos a saltar.
  • C-x 2: Divide las ventanas de manera vertical (comportamiento habitual, modificado ligeramente)
  • C-x 3: Divide las ventanas de manera horizontal (comportamiento habitual, modificado ligeramente)
  • C-x 1: Elimina todas las ventanas menos la actual.
  • C-x |: Crea dos ventanas verticales.
  • C-x _: Crea dos ventanas horizontales.
  • C-x 2: Divide las ventanas de manera vertical (comportamiento habitual, modificado ligeramente)
  • C-c down (Control+abajo): Hace que la ventana actual sólo pueda mostrar el buffer actual (o lo deshace).
  • M-down (Alt+Abajo) : Disminuye la visibilidad de la ventana (aumenta transparencia)
  • M-up (Alt+Arriba): Aumenta la visibilidad de la ventana.
  • M-0 (Alt+0): Ventana visible al 100%, reset de opacidad.
  • M-f (Alt+f): Modo pantalla completa (fullscreen).
  • s-C-+ (Super+Control+ +): Aumenta el tamaño de letra.
  • s-C- (Super+Control+ -): Disminuye el tamaño de letra.
  • F12: Recarga el fichero actual descartando cambios y sin preguntar.
  • s-h (Super+h): Resalta la línea actual en todos los buffers.
  • s-r (Super+r): Abrir archivos recientes.
  • M-% (Alt+%): Reemplazar texto
  • s- (Super-Espacio): Reemplazar texto (tecla alternativa, aunque puede que choque con algunos entornos de ventanas
  • F7: Muestra el buffer más reciente en la "otra" ventana. Si se pulsa de nuevo, vuelve a mostrar el buffer que había anteriormente.

En el minibuffer

  • <prior> (Página atrás) : Autocompletado con valores previos del historial. (Comportamiento como readline aquí)
  • <next> (Página adelante) : Autocompletado con valores siguientes del historial. (Comportamiento como readline aquí)

Siguiente post

En el siguiente post tocaré temas como sesiones y ayuda para la edición de texto. Se utilizarán algunas funciones dentro de lib. Y empezará a tomar algo de forma el entorno con muchas utilidades.

También podría interesarte...


Volver a la Portada de Logo Paperblog