Cuaderno de GNUtas

Enlaces personalizados (II), org-capture y enlaces multimedia

En la anterior entrada de esta miniserie dedicada a los enlaces de Org Mode y su personalización —que, presumo, terminará aquí—, habíamos visto cómo crear etiquetas ad hoc para formar nuevos tipos de enlace. Ahora veremos un caso un poco más elaborado que atañe a los enlaces de contenido multimedia y a la utilísima biblioteca de org-capture. Nos metemos en harina.

El escenario

Me resulta útil almacenar en un documento de Org los enlaces a vídeos de internet que me van pareciendo interesantes. Casi todos pertenecen a la infame plataforma de YouTube, pero accedo a ellos no desde la propia página del horroroso y fisgón servicio de Google, sino mediante una instancia pública de la interfaz libre para YouTube, Invidious. Esto trae una ventaja a un usuario cotidiano de GNU Emacs cual soy yo, además de la consabida profilaxis ética. Y es que Invidious puede abrirse sin problemas desde el navegador interno de Emacs, el eww-mode, ya que no impone al usuario la ejecución de javascript privativo. Lo que no se puede en el eww-node, claro, es reproducir el vídeo. Pero para eso contamos con el Emacs Multimedia System (abreviado EMMS) que reproducirá la URL del contenido multimedia1.

Pues bien, para ir almacenando esos enlaces a vídeos de una forma ágil y rápida la mejor opción que tenemos es org-capture. Es necesario definir una plantilla que reconozca ese tipo de enlaces y los vaya acumulando en nuestro documento de Org preparado a tal efecto, y con el formato que deseemos. Pero vayamos por parte. Antes, necesitamos definir un nuevo tipo de enlace de Org que permita reproducir una ruta multimedia mediante EMMS.

Definiendo un enlace multimedia

Una vez más, nos ayudamos de org-link-set-parameters. Nos basta con incluir, para este caso de ejemplo, además del necesario parámetro :follow, el color del enlace.

(org-link-set-parameters
   "url-media"
   :follow (lambda (ruta) (emms-play-url ruta))
   :face '(:foreground "chocolate" :underline t))

Así, si escribimos [[url-media:ruta-del-enlace]] y visitamos el enlace multimedia, se nos abrirá el reproductor que tengamos ya configurado en nuestro EMMS. Pero como lo que queremos es «capturar» de forma automática estos enlaces, y no tener que copiarlos a mano, necesitamos otra función que nos recolecte la cadena completa del enlace allí donde tengamos el cursor (recuérdese, siempre dentro del eww-mode).

Una función para copiar la ruta del enlace

Definimos, primero, esta función que mandará a la cabecera de nuestro kill-ring la ruta del enlace donde está el cursor:

(defun copia-url-enlace ()
  (let ((url (get-text-property (point) 'shr-url)))
    (kill-new (format "%s" url))))

Pero queremos activarla cada vez que llamemos a org-capture. Definimos esta segunda función con un condicional, para que se evalúe (naturalmente) sólo si estamos en el eww-mode:

(defun copia-url-para-capture-multimedia ()
    (when (equal (format "%s" major-mode) "eww-mode")
      (copia-url-enlace)))

Y la añadimos entonces a un advice-add:, para que se ejecute justo tras una llamada a org-capture:

(advice-add 'org-capture :before  #'copia-url-para-capture-multimedia)

Ahora ya sólo nos queda definir nuestra plantilla de org-capture

La plantilla para org-capture

Org-capture, y su sistema de plantillas, merecería ya una GNUta completa. Aquí nos limitaremos a dar unas pinceladas con trazo grueso. Y, para más información, remitimos como siempre a la completa documentación de esta biblioteca.

Para empezar, una plantilla de org-capture consiste en una serie de instrucciones a fin de que una entrada determinada se incluya en un determinado documento de Org. Se trata de un esqueleto para cada entrada que capturemos donde indicamos cómo queremos capturarla. Podemos escoger entre un amplio muestrario de instrucciones y variables, incluyendo la posibilidad de evaluar código Elisp entre medias. Y todo eso se recoge en la variable org-capture-templates, que es forzosamente una lista. Cada elemento de esa lista será una plantilla. En nuestro init se vería algo así como:

(setq org-capture-templates  '((plantilla-1)
                               (plantilla-2)
                               (plantilla-etc)))

Nuestra plantilla para capturar enlaces multimedia en un documento de Org (que, recordemos, tenemos ya preparado) luciría tal que así:

("M" "Enlace multimedia" entry
 (file "ruta/hacia/nuestro-archivo.org")
 "* [[url-media:%(car kill-ring)][%:description]] %^g
        Capturado en: %U" :prepend t)

Expliquemos un poco por encima los elementos.

«M»
es la letra que hemos escogido para activar nuestra captura, cuando hayamos desplegado el menú de org-capture mediante C-c c;
«Enlace multimedia»
es el nombre de ese tipo de capturas que aparecerá en el menú;
La expresión file
toma como argumento la ruta de nuestro archivo para almacenar los enlaces. Cada enlace será un encabezado de Org;
%(car kill-ring)
evaluamos ese Elisp como ruta del enlace. Simplemente extraemos el car (el primer elemento de la lista) de nuestro kill-ring. O sea, como al llamar a org-capture hemos copiado automáticamente la ruta del enlace en que está el cursor, eso estará al principio del kill-ring;
%:description
es la descripción del link. Por defecto, org-capture pondrá el nombre de la página web donde hacemos la captura;
%^g
Para que se nos abra un prompt a fin de incluir las etiquetas que queramos en la entrada capturada. Admite autocompletado para las etiquetas del documento;
%U
la fecha;
:prepend t
con valor non-nil, la variable :prepend nos colocará la última entrada capturada al principio de la lista.

Si queremos, podemos incluir algo más de información. Por ejemplo, bajo la línea de la entrada, que es la que contiene el enlace que reproducirá el medio, añadir otro enlace que sería la dirección web del medio:

"...
Capturado en: %U
Fuente: [[%:link][%:description]]"

Una floritura final

Ya que nos hemos venido arriba, igual queremos también que nuestros flamantes enlaces multimedia luzcan con un pequeño icono al principio, en cada entrada. Yo he encontrado una solución gracias al paquete all-the-icons, que si bien no resulta el colmo de la elegancia, hace un apaño. Al fin y al cabo, esto es meramente decorativo. Como a la postre siempre va a acabar mandando la fuente del enlace, tenemos que definir una cadena de texto «comodín». En mi caso, mi comodín es «¡¡¡» que debe sustituirse por el icono de una nota musical. Por supuesto, tendríamos que añadir el comodín a nuestra plantilla:

"* [[url-media:%(car kill-ring)][¡¡¡ %:description]] %^g

Y definir una función como ésta:

(require 'all-the-icons)

(defun icono-nota ()
  "Sustituye la cadena `¡¡¡' por el glifo de una nota musical y
salva el búfer"
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward "\\(¡¡¡\\)" nil t)
      (put-text-property
       (match-beginning 0) (match-end 0)
       'display
       (propertize (all-the-icons-material "music_note") 'face `(:inherit nil :family ,(all-the-icons-material-family))))))
  (save-buffer))

Y, por último, incluir la función anterior en un advice-add para que se ejecute al guardar la captura:

(advice-add 'org-capture-finalize :before #'icono-nota)

Como he dicho, esto es un apaño, y el icono de la nota musical no se mantendrá al guardar y cerrar el búfer. Así que, si insistimos en nuestra floritura (que, vuelvo a recordar, no es necesaria), tendríamos que evaluar la función anterior como variable local en nuestro documento. Por ejemplo, incluyendo al principio de todo la línea:

# -*- eval: (icono-nota) -*-

A medida que vayamos almacenando enlaces de vídeos y de otros archivos multimedia, nuestro documento acabará teniendo esta pinta:

org-capture-multimedia.png

Figura 1: Nuestra lista de enlaces a vídeos en internet

Publicado: 28/08/20

Última actualización: 07/08/22


Índice general

Acerca de...

Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.

Notas al pie de página:

1

En esta otra Gnuta ya habíamos visto cómo reproducir dentro del eww-mode un enlace multimedia mediante el EMMS.

© Juan Manuel Macías
Creado con esmero en
GNU Emacs