Notxor tiene un blog

Defenestrando la vida

Abreviaturas en Emacs

2022-06-02

Una de las formas de ahorrar algunas pulsaciones de teclas es utilizar abreviaturas. Ya hablé por aquí de los snippets, que serían plantillas más o menos extensas de estructuras de texto repetitivas. Las abreviaturas son sus hermanas pequeñas y consisten en algo tan sencillo como sustituir un texto corto, una abreviatura, por una expresión más larga de una o más palabras.

Para hacerlo todo más práctico, voy a mostrar dos ejemplos sencillos y de ese modo creo que será más comprensible el mecanismo de las abreviaturas. He hecho una copia de seguridad de las abreviaturas que tengo definidas para mí, y partiré de cero para no enfangar las mías con las pruebas que pueda hacer en el presente artículo.

Hay que tener en cuenta que las abreviaturas pueden ser generales y encontrarse disponibles para todos los modos, o pueden ser locales del modo mayor que esté activo. Aunque generalmente, programando, suelen ser más útiles los snippets y completion, también podemos aprovechar la inmediatez de las abreviaturas. Los ejemplos que voy a mostrar comprenden las dos opciones: definiré uno de manera global y otro de manera local. Aunque, como veréis, el procedimiento es el mismo y sólo cambia el comando invocado.

Por otro lado, también podemos decir que las abreviaturas son un modo menor (abbrev-mode) que nos permite utilizarlas. Más adelante veremos que podemos usarlas sin necesidad de tener el modo activo invocando un comando; sin embargo, la mayor parte de su potencia se deriva de la sustitución automágica de textos mientras escribimos.

Definir abreviaturas

Imagina que tenemos un texto largo que se repite con cierta frecuencia y queremos escribir menos, pero que el texto sea completo. No parto de una lista completamente vacía, pues hay algunos modos como pydev que proporcionan sus correspondientes abreviaturas. Pero si utilizas el comando list-abbrevs, te aparecerá algo como lo siguiente:

Captura de pantalla_lista-vacia.png

Por poner un ejemplo, voy a definir una abreviatura desde el siguiente supuesto: cuando escribo artículos es muy habitual que tenga que escribir muchas veces la palabra Emacs, porque es uno de mis temas favoritos. Como me voy a dejar la yema de los dedos en el intento, voy a escribir una abreviatura que cuando me encuentre en org-mode, que es el modo en el que escribo los artículos, me permita escribirlo con un par de pulsaciones de tecla, es decir, que cuando yo escriba em<SPC> lo expanda a Emacs. El procedimiento es sencillo:

  1. Escribo la palabra completa: Emacs
  2. Después pulso C-x a l
  3. Me pide una abreviatura: em<RET>

Ya está, a partir de ahora, cuando esté activado abbrev-mode en el modo mayor org-mode y yo escriba em, Emacs escribirá toda la palabra por mí. Para comprobarlo, veamos nuestra lista de abreviaturas modificada:

Captura_abreviatura-emacs.png

Cuando sólo queremos expandir una palabra es sencillo. Algo más lioso cuando queremos sustituir varias palabras, pero porque tenemos que decirle a Emacs cuántas debe tomar con el prefijo C-u num. Vamos a suponer que quiero definir la abreviatura del texto siguiente:

GNU's not Unix

y quiero establecerla a gnu. Es decir, cada vez que pulse las teclas g, n, u, <SPC>, ─siendo éste último cualquier carácter considerado como tal, no sólo la tecla de espacio, también la coma, el punto, etc.─, lo sustituirá por el texto completo. Para definirlo, hago el siguiente procedimiento:

  1. Escribo el texto completo: «GNU's not Unix»
  2. Nada más escribirlo pulso la siguiente combinación de teclas: C-u 3 C-x a g. Fijaos que en esta ocasión estoy utilizando C-x a g y por tanto la definición será global.
  3. En la línea de estado nos pide la abreviatura: gnu<RET>

Como he dicho antes, he cambiado el comando para hacerlo global y he utilizado el prefijo C-u 3 para indicarle a Emacs que debe utilizar las tres palabras anteriores a la posición del cursor. Podemos comprobarlo también mirando la lista de abreviaturas.

Captura_abreviaturas.png

Aprovecho para llamar la atención sobre la lista de abreviaciones. Nos abre un buffer de nombre *Abbrevs*, pero vemos que el modo es edit-abbrevs, lo que nos da pie a modificarlas directamente en ese espacio. Por ejemplo, puesto que suelo escribir la palabra Emacs, generalmente en cursiva, he aprovechado y he puesto los delimitadores de este tipo de letra en la expresión. Tras guardar con C-x C-s, cada vez que escriba em el editor lo cambiará por /Emacs/.

Otra forma de modificar el contenido de las abreviaciones es, una vez que lo tenemos salvado en un fichero, por defecto ~/.emacs.d/abbrev_defs, podemos modificar el código fuente, que en nuestro caso aparecerá del siguiente modo:

;;-*-coding: utf-8;-*-
(define-abbrev-table 'global-abbrev-table
  '(
    ("gnu" "GNU's not Unix" nil :count 0)
   ))

(define-abbrev-table 'org-mode-abbrev-table
  '(
    ("em" "/Emacs/" nil :count 5)
   ))

Resumen de comandos

Hay poco más que contar una vez que comprendes cómo funciona este modo. Para resumir un poco las cosas que se pueden hacer con él, voy a dar un repaso a los principales comandos, la combinación de teclas asignada y para qué sirve cada uno. Por ejemplo, para definir abreviaturas y gestionarlas se utilizan los siguientes comandos:

C-x a g (add-global-abbrev)
Define una abreviatura global que estará disponible en todos los modos. Es el equivalente interactivo al comando M-x define-global-abbrev <RET> abrv <RET> expresión <RET>
C-x a l (add-mode-abbrev)
Define una abreviatura para el modo mayor activo en ese momento. Es el equivalente interactivo al comando M-x define-mode-abbrev <RET> abrv <RET> expresion <RET>.
M-x kill-all-abbrevs
Elimina todas las abreviaturas definidas.
C-x a i g (inverse-add-global-abbrev)
Define una palabra en el texto del buffer como una abreviatura global y solicitará su correspondiente expansión en el minibuffer.
C-x a i l (inverse-add-mode-abbrev)
Define una palabra del buffer como abreviatura del modo. Funciona de manera similar al anterior comando.
M-x edit-abbrevs
Nos muestra la lista de abreviaturas definidas en un buffer y nos permite modificarlas.
M-x write-abbrev-file <RET> nombre <RET>
Escribe en el archivo nombre todas las definiciones de abreviaturas activas.
M-x read-abbrev-file <RET> nombre <RET>
Lee el archivo nombre y carga las definiciones de abreviaturas que contiene. Hay otro comando similar, quietly-read-abbrev-file, cuya única diferencia es que no muestra ningún mensaje en el minibuffer.

Estos dos últimos comandos son muy útiles cuando queremos mantener nuestras abreviaturas agrupadas por temática. Me explico: hay veces en que un área de nuestro trabajo necesita ciertas abreviaturas y pueden chocar con otras que tengamos definida en otras áreas. Estos comandos nos permiten tener varios archivos, que podemos activar según el tema en el que estemos trabajando.

Hay algunos otros comandos que nos permiten controlar la expansión del contenido de las abreviaturas.

C-x a e (expand-abbrev)
Expande la abreviatura. Es efectivo incluso cuando abbrev-mode no está activo. Vamos, que normalmente, si estuviera activo, no lo necesitarás. Pero es bueno saber que si se te ha olvidado activarlo o, por algún motivo lo has desactivado, puedes seguir utilizando tus abreviaturas definidas.
M-x unexpand-abbrev
Su función es dejar la abreviatura tal cual sin expandirla, pero hablaré un poco más en el siguiente apartado.
M-x expand-region-abbrevs
Expande todas las abreviaturas que se encuentren en la región seleccionada.
M-/ (dabbrev-expand)
Expande la palabra en el buffer como una abreviatura dinámica. Es decir, busca en el buffer la última palabra que comience igual y la expande. Por ejemplo, si comenzamos a escribir abr y pulsamos M-/ en este buffer, lo expandirá, posiblemente, a la palabra abreviatura. Un comando similar es hippie-expand que si lo usamos repetidamente nos muestra varias posibles expansiones, en lugar de sólo la última, por lo que me parece más útil y os recomiendo más su uso.

También puede ocurrir que hayamos definido nosotros, o algún modo lo haga, abreviaturas en el sistema y que por olvido o desconocimiento estemos tecleando todo el texto. Se puede habilitar a Emacs que nos avise de que un determinado texto tiene definida una abreviatura activando en nuestro init.el la variable abbrev-suggest. De esta manera nos advertirá de que contamos con la posibilidad de ahorrarnos tecleos. Si nos hemos perdido algunos de esos avisos podemos utilizar el comando abbrev-suggest-show-report que nos hará un informe de todas las sugerencias que nos haya hecho el sistema durante la sesión de trabajo.

Recomendaciones

Es posible que haya ocasiones que no queramos que nos sustituya la abreviatura por su expresión. Ya hemos visto que el comando es M-x unexpand-abbrev. Otra opción, que es la que uso yo, en curarnos en salud y utilizar abreviaturas con caracteres especiales que sea raro que se necesiten tal cual en un texto. Por ejemplo, para mis cosas suelo utilizar de prefijo el carácter ' o el ¡. Por hacerlo más gráfico, mi modo usual para definir los ejemplos del principio del artículo, hubiera sido utilizar 'g en lugar de gnu y 'e en lugar de em para las abreviaturas. De esta forma es más raro encontrarse el caso de tener que revertir una sustitución.

Por defecto, unexpand-abbrev no está mapeada a ninguna tecla. Si utilizas habitualmente las abreviaturas y lo necesitas, considera el mapear dicha función a una combinación de teclas. En el manual recomiendan utilizar C-q. En mi caso, dado que utilizo el sistema anterior, no suelo necesitarlo, pero está bien recordar que tienes la posibilidad de hacerlo.

Como vimos en el apartado anterior hippie-expand es un comando también bastante más útil que el simple dabbrev-expand y, es posible, que quieras mapear la combinación M-/ a aquel comando en lugar de al que viene mapeado por defecto.

Conclusiones

Mientras programo me resulta más cómodo el uso de completion y de snippets que el de abreviaturas. Sin embargo, también reconozco puede ser útil. Aunque, se me ha dado el caso que acostumbrado a algunas abreviaturas en Emacs, al tener que cambiar de editor, se me ha hecho la adaptación un poco pesada. Tecleaba la abreviatura y al ver que no se expandía recordaba que no estaba en Emacs y que tenía que teclear el texto correctamente.

Las abreviaturas pueden representar un gran ahorro de pulsaciones de teclas. Pero también significa que debes invertir tiempo en ajustar y afinar todo tu sistema de abreviaturas para que te sean útiles a largo plazo.

Categoría: emacs

Comentarios

Debido a algunos ataques mailintencionados a través de la herramienta de comentarios, he decidido no proporcionar dicha opción en el Blog. Si alguien quiere comentar algo, me puede encontrar en Mastodon y en Diaspora con el nick de Notxor.

También se ha abierto un grupo en Telegram, para usuarios de esa red.

Disculpen las molestias.