Proteger contra escritura bloques de código en Org
En muchos documentos de Org suelo incluir bloques de código con funciones en Elisp que se evalúan durante el proceso de
exportación, y siempre cabe el escrúpulo de prevenir cualquier edición accidental de ese código valioso. Por supuesto,
usando un sistema de control de versiones cualquier desaguisado es revertible, felizmente. Pero tampoco está de más la
posibildad de asegurar fácilmente esos bloques y protegerlos contra escritura, y ser capaces también de liberarlos con
pareja agilidad. Se me ocurrió, para ello, escribir estas funciones que comento a continuación, y que sacan buen
provecho de la herramienta org-element-map
, incluida en la biblioteca org-element
.
Para empezar, necesitamos definir una función que nos añada la propiedad de texto read-only
a todos los bloques de
código en un búfer dado:
(defun protege-bloques () (interactive) (org-element-map (org-element-parse-buffer) 'src-block (lambda (bloque) (let ((desde (org-element-property :begin bloque)) (hasta (org-element-property :end bloque))) (add-text-properties desde hasta '(read-only t))))))
Seguida por esta otra función que los desprotege. Eso sí, ojo, con el añadido de la variable local inhibit-read-only
con valor non-nil
, ya que Emacs se habrá tomado demasiado al pie de la letra lo de «read only», a la manera del
guardian de exagerado celo que no nos deja entrar en nuestra propia casa.
(defun desprotege-bloques () (interactive) (org-element-map (org-element-parse-buffer) 'src-block (lambda (bloque) (let* ((desde (org-element-property :begin bloque)) (hasta (org-element-property :end bloque)) (inhibit-read-only t)) (remove-text-properties desde hasta '(read-only t))))))
Pero, claro, con lo anteror no vamos a ningún sitio, ya que lo que pretendemos es proteger ciertos bloques (por ejemplo,
los que llevan el encabezado :protegido
) y no todos los que tenemos en nuestro documento. Para ello, es necesario esta
tercera función, que es la que realmente nos hará la criba:
(defun bloque-solo-lectura () (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward ":protegido" nil t) (save-restriction (org-narrow-to-block) (protege-bloques)))))
Por último, la función la podemos anclar al hook
de Org Mode:
(add-hook 'org-mode-hook 'bloque-solo-lectura)
Aunque yo sería más partidario de evaluarla como simple variable local en los documentos donde queramos que actúe. Por ejemplo, poniendo en la primera línea de cada fichero:
# -*- eval: (bloque-solo-lectura) -*-
(Y siempre que queramos eliminar la resticción del bloque podremos evaluar la función desprotege-bloques
).
∞
Publicado: 12/02/20
Última actualización: 21/01/22
Esta obra está bajo una licencia de Creative Commons Reconocimiento-NoComercial 4.0 Internacional.