Notxor tiene un blog

Defenestrando la vida

Trasteando con yasnippets

2022-02-13

Hace poco, por Mastodon, el amigo Giorgio habló de yasnippets y de cómo le habían servido para ser más productivo en su trabajo... he de confesaros que las uso poco, o casi nada, para ser sinceros. Con Python las utilicé, porque elpy las usa, pero para el resto de modos, normalmente, ni las tengo instaladas. No porque no sean útiles, sino porque yo no suelo utilizarlas. Sin embargo, entiendo que cada uno tiene sus costumbres y su flujo de trabajo y que, yasnippet, puede ser muy útil a otra gente. Por esto, en este artículo contaré cómo instalar y configurar el paquete y cómo crear nuestros propios snippets para adecuarlo a nuestras necesidades. Incluso, quizá hablándome de ello a mí mismo, termine por cogerle el gusto.

Como digo, utilicé snippets programando en Python con Emacs. Con elpy los snippets vienen de serie... a todo ésto creo que todos sabemos lo que es un snippet (al menos los que programan un poco), pero es posible que haya quien no, o está de más tirar de la definición en la Wikipedia:

Snippet es un término del idioma inglés utilizado en programación para referirse a pequeñas partes reusables de código fuente, código máquina o texto. Comúnmente son definidas como unidades o métodos funcionales que se pueden integrar fácilmente en módulos mucho más grandes, aportando funcionalidad.

Wikipedia

Por expresarlo más rápidamente o de forma más directa: son pequeñas plantillas de código que nos ahorran tecleos. En Emacs la gestión de estos bloques de código la podemos realizar con yasnippet (que significa, según su página, «Yet Another Snippet» extension for Emacs).

No utilizando elpy lo tenía muy abandonado, porque no lo suelo usar, el funcionamiento es muy útil, especialmente para programar, aunque no sólo para esa actividad: hay snippets que sirven para muchas otras cosas. Por poner un ejemplo, si tenemos activos los snippets en org-mode y queremos introducir una línea con la fecha pulso la combinación C-c & C-s (luego veremos cómo configurar las teclas).

Vemos que los snippets no sólo introducen texto por nosotros sino que también nos proporcionan paradas de tabulador que nos permiten introducir opciones simplemente avanzando con el tabulador (y retrocediendo con S-<TAB>).

Muy bonito, ¿ahora cómo hacemos para que nuestro Emacs haga estas cosas?

Instalación de los paquetes necesarios

En un principio, instalando el paquete yasnippet sería suficiente. Sin embargo, recomiendo instalar algunos paquetes auxiliares que nos facilitarán el uso de snippets:

  • yasnippet, proporciona la funcionalidad principal.
  • yasnippet-snippets, proporciona una larga lista de snippets para multitud de modos y lenguajes de programación.
  • ivy-yassnipet, proporciona integración de yasnippet con ivy. También existe un paquete helm-yasnippet, si utilizas helm para proporcionarte menús interactivos.

La instalación de los paquetes es la habitual. Por ejemplo, para el principal de yasnippet:

M-x package-install <RET> yasnippet

Con eso ya tendríamos toda la funcionalidad de los snippets, pero no adelantamos nada si no tenemos plantillas que utilizar. Tenemos que crearlas, lo que puede ser un trabajo arduo y aburrido haciéndolo desde cero. Para ahorrarnos ese tedioso trabajo, el paquete yasnippet-snippets nos proporciona decenas (si no, cientos), de plantillas ya preparadas y revisadas para multitud de modos. Incluso, para aquellos que no utilizas, por lo que el paquete ocupará más espacio en disco del estrictamente necesario, aunque no tanto como para que te debas preocupar por ello.

En cualquier momento, podemos consultar qué snippets tenemos disponibles según el modo en el que estemos con el comando

M-x yas-describe-tables
Captura-pantalla-tabla-snippets.png

No es necesario que nos aprendamos toda la tabla, pero si trabajamos habitualmente con este sistema podemos aprendernos el key del snippet y luego utilizar el comando yas-expand (que yo lo tengo mapeado a la combinación s-y, luego explicaré cómo). Con eso sólo, es decir, tecleando el key y una combinación de teclas nos expandirá toda la plantilla. Nos podremos mover por los puntos de tabulador pulsando <TAB> para ir hacia adelante y <S-TAB> para ir hacia atrás, como ya vimos antes.

Ahora que tenemos instalado el modo, vamos a configurarlo un poco.

Configuración de los snippets

El primer paso que hay que hacer es decidir si lo vas a utilizar siempre. Es decir, si quieres que automáticamente se cargue esta funcionalidad en tu Emacs cada vez que inicia. Esto enlentecerá el arranque del editor porque revisará todos los snippets para tenerlos a mano. Recuerda que Emacs no es el editor más rápido de arrancar. O simplemente no quieres ocupar memoria con algo que no vas a utilizar. Por ejemplo, en mi caso, sólo los suelo usar programando, por lo que por defecto no los tengo activados.

En el manual del modo yasnippet recomiendan (cómo no) tenerlo permanentemente activado. Su configuración es sencilla:

(require 'yasnippet)

(yas-global-mode t)

En mi caso, como no lo quiero cargado continuamente lo he retocado un poco y he acomodado las combinaciones de teclas a mi gusto. El retoque del código de configuración se debe principalmente a que utilizo use-package.

(use-package yasnippet
  :defer t)
(global-set-key (kbd "C-c x")   'ivy-yasnippet)
(global-set-key (kbd "C-c y")   'yas-minor-mode)
(global-set-key (kbd "s-y")     'yas-expand)

Con esas tres teclas y otras tres que define el modo yasnippet en su código, tenemos configurada casi toda la funcionalidad que se necesita.

Table 1: Resumen de combinaciones de teclas
Combinación Comando Significado
C-c & C-s yas-insert-snippet Insertar un snippet por nombre
C-c & C-v yas-visit-snippet-file Editar un snippet
C-c & C-n yas-new-snippet Crear un nuevo snippet
C-c y yas-minor-mode Activar el modo
C-c x ivy-yasnippet Abrir lista de snippets en ivy
s-y yas-expand Expandir un snippet por su clave

Explico un poco más detalladamente las tres últimas combinaciones, que son las configuraciones de tecla que he añadido yo y las otras, que son las propias del modo, las veremos en el siguiente epígrafe:

  • yas-minor-mode: es la función para activar el modo menor de yasnippet que nos permite utilizarlo. Lo activo con configuración de teclas incluida porque al no abrirse universalmente, activarlo sólo afecta al buffer donde lo activas. Para trabajar con Python no hace falta, porque elpy lo activa automáticamente al abrir un fichero .py. Si quieres activarlo siempre para un modo concreto siempre puedes poner un hook. Por ejemplo, si quisiéramos que se activara siempre que editamos un archivo org añadiríamos:

    (add-hook 'org-mode-hook 'yas-minor-mode)
    
  • ivy-yasnippet: nos muestra en ivy la lista de snippets disponibles para el modo mayor del buffer desde el que la llamamos. Cuando comenzamos a teclear un nombre, la lista filtra aquellos nombres que coincidan con lo que vamos escribiendo. Si no estamos seguros de cuál es el snippet que necesitamos podemos recorrer la lista que muestra y el contenido del snippet nos lo va mostrando en el punto del cursor en el buffer.
  • yas-expand: lo que hace es expandir un snippet a partir de su clave key. Cuando llevas un tiempo utilizando esta herramienta, terminas, a fuerza de verlas, aprendiéndote esas claves. Sobre todo, si es un snippet que utilizas con asiduidad, lo más rápido es aprenderse la key y expandirla sin buscar por la lista. Además, en este caso, he utilizado una combinación de tecla poco habitual. Normalmente en Emacs se utilizan <control> (C) y <meta> (M), con o sin <shift> (S), sin embargo utilizo <super> (s), la que algunos llaman tecla windows y otros la tapamos con una pegatina de un pingüino.

Estas funcionalidades son comodidades, si lo queréis llamar así, porque en realidad, lo mínimo que necesitas para trabajar con snippets es crearlos, modificarlos y llamarlos. Esa funcionalidad básica la detallo en el siguiente punto poniendo un pequeño ejemplo de creación de snippet.

Crear nuestros snippets

Al activar el modo yasnippet por defecto nos activa tres combinaciones de teclas para lanzar sus comandos principales. Figuran en la tabla del apartado anterior. Esos tres comandos son:

  • Crear un snippet (C-c & C-n)
  • Editar un snippet que ya existe (C-c & C-v)
  • Insertar en el buffer de edición un snippet (C-c & C-s)

Por supuesto, si utilizas estas funciones de manera habitual, sería buena idea cambiar la combinación de teclas por algo más sencillo y rápido de teclear. En mi caso las he dejado así porque normalmente utilizo la funcionalidad de ivy-yasnippet o la expansión directa de la clave (las pocas que me sé).

Vamos a ver cómo es un snippet por dentro par hacernos una idea. Por ejemplo, si tecleamos:

C-c & C-v current-date

nos abrirá un buffer con el siguiente contenido

# -*- mode: snippet -*-
# name: current-date
# key: dd
# contributor : Kristof Molnar-Tatai <kristof.mlnr@gmail.com>
# --
`(format-time-string "%Y-%m-%d")`       

De ese código podemos extraer alguna información interesante:

  • Los ficheros que guardan los snippets se suelen guardar sin extensión, por eso se añade la primera línea de mode seguida de la cabecera del mismo que está dividida en etiquetas o campos.
  • La cabecera se separa del texto del snippet mediante la línea # --
  • Se pueden introducir formas lisp que devuelvan una cadena.

Para ilustrarlo mejor, vamos a crear un nuevo snippet. Imagina que tienes que hacer muchos informes psicológicos, como puede ser mi caso, sobre los tests que van haciendo los clientes y el encabezado de todos ellos es muy similar o repetitivo, por lo que decides crear una plantilla de encabezado para incrustarla cuando escribes tus informes con Emacs.

Al pulsar C-c & C-n nos abrirá un buffer con el siguiente contenido:

# -*- mode: snippet -*-
# name:
# key:
# --

El cursor aparece en la línea # name:. Atentos, porque lo que hace es crear un buffer y añadir un snippet con la estructura del mismo. Lo único que tenemos que hacer es rellenar los datos y avanzar pulsando <TAB>.

Para no liarme mucho más con las explicaciones muestro el contenido final y luego lo explicamos:

# -*- mode: snippet -*-
# name: informe-cabecera
# key: inf-cab
# --
INFORME que realiza /D. Fulanito de Tal/ con D.N.I. nº 123456789Z
sobre los resultados obtenidos en la prueba ${1:test psicológico}
por D/ña. ${2:Menganito de Cual}, con D.N.I. nº ${3:987654321A}, a
petición del interesado.

El texto es lo de menos, puede ser cualquier otro, lo importante es que nos fijemos dónde lo guarda yasnippet. Por defecto, al hacerlo nos sugerirá un directorio llamado:

~/.emacs.d/snippets/[nombre-del-modo]

En el caso anterior, lo queremos para hacer es tener un snipper para insertar una cabecera. En la mayoría de los casos lo único que cambiará será el test que se pasó y los datos, el nombre y el DNI, del cliente:

  • ${1:test psicológico}
  • ${2:Menganito de Cual}
  • ${3:987654321A}

Como se puede apreciar, las paradas de tabulador se denotan por ${...}. En este caso se han tenido en cuenta textos por defecto, pero los campos podrían haber sido, por ejemplo ${1:}. No hay necesidad de incluir ese texto, con los números es suficiente para establecer las paradas, pero puede venir muy bien cuando además hay algún contenido frecuente, para ahorrar aún más tecleos.

Por último, si ya tenemos nuestro snippet creado y lo que queremos es cambiar o corregir algún aspecto de él, utilizaremos la combinación C-c & C-v o utilizaremos el comando M-x yas-visit-snippet-file para modificarlo.

Conclusiones

Esta es una entrada cortita, porque esta herramienta es muy sencilla de utilizar, pero con una gran utilidad, especialmente para programación. Nos ahorrará bastante trabajo de escritura repetitiva, aparte de evitar errores tontos como meter «;» donde corresponde «:» en una expresión y que el programa tarde un poco más en compilar, dándonos de cabezazos hasta descubrir el sutil error de tecleo.

Para otros menesteres nos viene bien para introducir algunos tipos de información repetitiva en textos. No lo suelo utilizar en org-mode, pero sí me es muy útil en html para no olvidarme de cerrar ninguna etiqueta. Cada uno decidirá cómo puede adecuar la herramienta a su modo de trabajar, cuándo le es útil y cuando no.

Categoría: emacs yasnippets

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.