¿Cómo puedo evaluar elisp en un archivo orgmode cuando se abre?

13

Tengo el código elisp que me gustaría ejecutar en los archivos de orgmode cuando se cargan (diferentes para diferentes archivos y definidos en el archivo). ¿Hay alguna forma de hacer esto? No vi nada en http://orgmode.org/manual/In_002dbuffer-settings.html

Si puedo agregar algo a la inicialización de emacs que ejecuta un bloque de código con un nombre especial cada vez que se carga un archivo orgmode, podría ser una solución, pero no estoy seguro de cómo hacerlo, e idealmente hay algo incorporado.

avv
fuente
1
¿Variables locales de archivo, tal vez?
Dan
¡Eso funciona! ¿Quieres convertirlo en una respuesta que pueda aceptar?
avv
Pensándolo mejor, es un entorno muy desordenado para editar, por lo que una buena solución sería que la variable local del archivo ejecute un bloque de código con nombre.
avv
¿Envolverlo en un progn o una lambda, tal vez?
Dan
3
También puede usar, # -*- eval: (lisp code here) -*-pero también debe ser consciente de los peligros. Incluso si no comparte estos documentos con nadie más, la naturaleza interpretada de Emacs Lisp significará que un cambio puede ocasionar accidentalmente la pérdida de datos. Además, el modo de enlace suena como una mejor opción si desea ejecutar el mismo código para más de un archivo.
wvxvw

Respuestas:

9

Esta solución no requiere cambios en init.el(con modificaciones menores). Sin embargo, implica evaluaciones locales de archivo, pero eso es exactamente lo que solicitó el OP. Las ventajas de la solución son:

  • pide confirmación para evaluar el código
  • El código elisp se puede editar y probar dentro del entorno org-babel
  • como la solución no requiere modificaciones en init.elel archivo orgmode, puede compartirse entre usuarios (de confianza)

Estoy reformulando la solución aquí.

Agregue un bloque src en algún lugar de su archivo:

#+NAME: startup
#+BEGIN_SRC emacs-lisp
(your-code-here)
#+END_SRC

Luego, coloque esto al final de su orgmode-file:

# Local Variables:
# eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))
# End:

Agregué (outline-hide-sublevels 1)porque me gusta ocultar el bloque src dentro de un encabezado y quiero que los subniveles se oculten en el inicio. Sin esta declaración, los subniveles se expandirán por (org-babel-goto-named-src-block "startup").

Con esta solución, emacs pedirá 2 veces permiso para ejecutar (primero: aplicar variables locales; segundo: ejecutar "inicio" -src-block). Como tengo muchos bloques src en mi archivo, configuré otra variable local de archivo org-confirm-babel-evaluate, como esta:

# Local Variables:
# org-confirm-babel-evaluate: nil
# eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))
# End:

Advertencia: con esta adición, emacs solicitará solo una vez permiso para ejecutar; todos los bloques src en ese archivo ahora se pueden ejecutar sin más confirmación. Como otros han señalado antes, este comportamiento podría ser peligroso y debe tener mucho cuidado con esta configuración.

Sin embargo, argumentaría que esta solución (especialmente la primera versión) es más segura que la que ofrece Joe Corneli porque al menos se le pedirá confirmación para ejecutar. La solución de Joe evaluará el bloque especial sin confirmación, si se encuentra en el archivo. Un atacante tendría que adivinar el nombre del bloque especial, por supuesto ...

Estoy usando este enfoque para escribir documentos grandes que requieren, por ejemplo, adaptaciones a los mecanismos de exportación de la organización.

ben
fuente
5

org-mode... Además de cualquier outline-modegancho que su modo padre podría haber ejecutado, este modo ejecuta el gancho org-mode-hook, como el paso final durante la inicialización.

Entonces, en su init.el:

(defun function-that-finds-and-evaluates-special-block ()
;; DWIM :-)
)
(add-hook 'org-mode-hook 'function-that-finds-and-evaluates-special-block)
Joe Corneli
fuente
Esto me suena más razonable que los archivos locales variables para esta tarea. Pero tal vez me estoy perdiendo algo.
Dibujó
@ Joe Corneli ¿Y qué pondrías en el archivo de organización real?
incandescentman
Nada especial excepto el "bloque especial".
Joe Corneli
3

Ya que pides

(diferente para diferentes archivos, y definido en el archivo mismo)

entonces, prueba esta solución .

Usuario de Emacs
fuente
¿Te importaría explicar por qué el voto negativo?
Usuario de Emacs el
Es porque se desaconsejan las respuestas que son solo enlaces a otras respuestas. Dicho esto, ¿tal vez esta pregunta es una tonta de la que vinculaste?
Linus Arver
1

Estoy de acuerdo con la sugerencia de @Joe Corneli sobre el uso de un gancho.

También se me ocurre que podría aprovechar los marcadores aquí: coloque un salto de marcador específico en el gancho. Una ventaja de un marcador para el bloque de código es que generalmente se reubica automáticamente (por ejemplo, a medida que cambia el contenido del archivo), por lo que la ubicación del bloque generalmente se debe solucionar automáticamente.

[Pero no me queda claro por qué tiene el código en los archivos del modo Org, en lugar de en otro lugar. Estamos tomando eso como algo dado, según el enunciado del problema, pero me pregunto por qué lo está haciendo. Hacernos saber más sobre el diseño a ese respecto podría conducir a una mejor ayuda.]

Dibujó
fuente
0

He intentado mejorar el código de Joe Corneli:

Lo necesita en su archivo init.el:

  (defun tdh/eval-startblock ()
    (if (member "startblock" (org-babel-src-block-names))
      (save-excursion
        (org-babel-goto-named-src-block "startblock")
        (org-babel-execute-src-block))
      nil
      )
    )
  (add-hook 'org-mode-hook 'tdh/eval-startblock)

Cada vez que abra un búfer de modo org, buscará un bloque de origen llamado startblock, si lo encuentra, lo ejecutará.

En sus archivos de modo org, puede poner:

#+NAME: startblock
#+BEGIN_SRC emacs-lisp
  ;; Any code you want
#+END_SRC
Thomas Dehaeze
fuente