¿Cómo forzar una sesión de org-babel para restablecer o inicializar?

8

Si ejecuto los siguientes bloques de shell babel

#+BEGIN_SRC sh :session one :results output
  ssh staging
#+END_SRC

#+BEGIN_SRC sh :session one :results output
  hostname
#+END_SRC

Org crea un búfer de shell llamado one, se ejecuta ssh stagingy luego, después de conectarse, se ejecuta hostnameen la puesta en escena. Sin embargo, si modifico el comando ssh y lo ejecuto nuevamente, intenta ejecutarlo desde la sesión uno, desde el host de preparación. Si cierro el búfer one, restablece la sesión, ya que la próxima vez que se ejecute un comando con ese nombre de sesión, lo vuelve a crear. Lo que no he podido encontrar es un método para forzar a un bloque de babel en particular a inicializar siempre una nueva sesión.

Soy consciente de que para algunos idiomas (elisp en particular) esto no sería posible. Supongo que podría anteponer la sesión con un bloque elisp que contenga (kill-buffer "one"), pero preferiría que este fuera un argumento de encabezado si es posible. También soy consciente de que para este ejemplo simplemente podría combinar los dos en un solo bloque sin sesión, pero estoy interesado en secuencias más complicadas.

¿Existe un :prologuecomando o algún otro argumento especial :sessionque obligue a ese bloque a inicializar un nuevo shell en cada invocación?

dgtized
fuente
No existe tal opción (o un parámetro de bloque de código fuente) en Org 8.2.10, pero debería ser bastante fácil de agregar. Comenzaría por piratear org-babel-initiate-session.
Constantine

Respuestas:

5

Prueba esto

Fuerce una sesión org-babel para restablecer o inicializar mediante el uso de una instrucción condicional elisp para establecer dinámicamente el valor del encabezado : session en el primer bloque de código.

p.ej :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

En el código anterior, la función get-buffer verifica si existe un buffer llamado uno . Si es verdad, el -caché de eliminación función mata el uno búfer continuación, devuelve un valor de to nilcual se pasa a la ifdeclaración. En este ejemplo específico, la ifinstrucción anidada siempre devolverá un valor de uno . Tenga en cuenta que todavía estoy aprendiendo elisp.

A continuación se muestra el código de ejemplo actualizado:

#+BEGIN_SRC sh :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one")) :results output
  ssh staging
#+END_SRC

#+BEGIN_SRC sh :session one :results output
  hostname
#+END_SRC

Cada vez que se ejecuta el primer bloque de código, emacs le pedirá que elimine el búfer , para que pueda restablecer la sesión cuando lo desee.

EDITAR

Vaya, perdió parte de que siempre quiso que se eliminara el búfer, es decir, sin preguntar . Ejecute este bloque primero para desactivar temporalmente la solicitud de matar el búfer.

#+BEGIN_SRC elisp
  (setq kill-buffer-query-functions
    (remq 'process-kill-buffer-query-function
           kill-buffer-query-functions))
#+END_SRC

Espero que haya ayudado!

Nota: Este código se probó utilizando las siguientes versiones de emacs y org-mode.

GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14)
Org-mode version 8.2.10 (8.2.10-29-g89a0ac-elpa)

En conclusión, encontré inspiración técnica para esta respuesta en el sitio web org-scraps y este código de ejemplo kill-buffer en stackoverflow.

Melioratus
fuente
@dgtized ¿Te ayudó esta respuesta?
Melioratus
2
No sabía que podía incrustar elisp en la sesión, así que gracias por eso. Dicho esto, como mencioné en la pregunta original, sabía que podía automatizar kill-bufferpara forzar una nueva sesión, pero estaba más interesado en aprender si había un argumento de bloque incorporado en el modo org, o alguna otra convención establecida para hacerlo. de lo que no estaba al tanto. Su enfoque es una buena solución, pero espero que haya un enfoque canónico para esto.
Dgtized
@dgtized - ¿Estás buscando una respuesta como esta? :session one :session-reset yes?
Melioratus
Algo así seguro. Nuevamente, se trata tanto de cuál es la práctica recomendada para este ejemplo. Seguramente otras personas tienen sesiones que necesitan reiniciarse, y si simplemente eliminan el búfer, está bien, pero quiero saber cuál es la práctica estándar.
Dgtized
@dgtized - ¡Gracias por aclarar! Esta es una gran pregunta! No he encontrado una práctica estándar documentada pero seguiré buscando .
Melioratus
2

Inspirado por @Melioratus.

Actualmente, org-babel proporciona un gancho llamado org-babel-after-execute-hook. Extendí los argumentos admitidos del bloque org-babel src al usarlo:

(Estoy usando org-babel para elixir. Si desea soporte de otros idiomas, extiéndalo condusted mismo).

(add-hook 'org-babel-after-execute-hook 'semacs/ob-args-ext-session-reset)

(defun semacs/ob-args-ext-session-reset()
  (let* ((src-block-info (org-babel-get-src-block-info 'light))
         (language (nth 0 src-block-info))
         (arguments (nth 2 src-block-info))
         (should-reset (member '(:session-reset . "yes") arguments))
         (session (cdr (assoc :session arguments)))
         (session-process
          (cond ((equal language "elixir") (format "*elixir-%s*" session))
                (t nil))))
    (if (and should-reset (get-process session-process))
        (kill-process session-process))))

Después de evaluar el código anterior, puede escribir un bloque src como este:

#+begin_src elixir :session-reset yes
  IO.puts("HELLO WORLD")
#+end_src

Después de evaluar el bloque src, org-babel limpiará la sesión correspondiente.


fuente