Modificar la salida de una función de emacs lisp sin redefinirla

Unos 2 minutos de lectura Publicado:

Casi es más largo el título que la definición o solución del problema.

Por mostrar un caso real explicaré el problema que tenia. Uso el paquete Projectile, que sirve para gestionar proyectos en emacs, recomiendo fuertemente que le echéis un ojo. Cuando se han abierto unos cuantos proyectos puede usarse la función projectile-switch-project, que permite cambiar el proyecto. El tema es que muchos directorios de mi home son en realidad enlaces simbólicos a otros sistemas de ficheros. Esto hace que los proyectos se me muestren con las rutas reales, no las rutas de los enlaces simbólicos. Por ejemplo, un proyecto en /home/drymer/Documentos/Ansible/roles/upgrade-all se me muestra como /media/.secret/Casa/Documentos/Ansible/roles/upgrade-all, lo cual es horroroso.

Lo que yo necesito es hacer que los proyectos en /media/.secret/Casa/ se muestren como /home/drymer/. Investigando, vi que lo que me hacia falta era usar una función de asesoramiento. No tengo claro si se traduce así, en inglés son Advising Functions. El tema es que estas funciones permiten, entre otras cosas, modificar la salida de una función elisp sin tener que redefinirla.

Por lo tanto, hay que averiguar que función es la que hay que modificar. En este caso, la función que da el nombre a los proyectos es projectile-project-root. Ahora crearemos una función simple que ejecute un replace-regexp-in-string en la salida:

(defun daemons/projectile-project-root (arg)
(replace-regexp-in-string "\\(/media/.secret/Casa\\)" (getenv "HOME") arg))

Un ejemplo de la ejecución de esta función:

(daemons/projectile-project-root "/media/.secret/Casa/Proyectos/nikola.el")

Solo nos queda añadir el filtro:

(advice-add 'projectile-project-root :filter-return #'daemons/projectile-project-root-filter)

Desgranemos el código:

  • advice-add: Añade función de asesoramiento.
  • projectile-project-root: La función que modificaremos.
  • filter-return: De que modo modificamos la función.
  • daemons/projectile-project-root-filter: Función con la que modificaremos el comportamiento de la primera.

La parte más interesante es la de filter-return, ya que este no es el único parámetro que se puede definir. Si quisiésemos, podríamos sustituir la función entera de muchas formas distintas. De hecho, si quisiésemos redefinir una función ya definida en alguna parte, las buenas prácticas dicen que hay que usar las funciones de asesoramiento. Recomiendo leer su sección del manual.

Cualquier duda, se puede preguntar aquí o en los canales descritos en la página principal. Saludos.