Come forzare una sessione org-babel a ripristinare o inizializzare?


8

Se eseguo i seguenti blocchi di shell babele

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

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

Org crea un buffer di shell chiamato one, viene eseguito ssh staginge quindi, dopo la connessione, viene eseguito hostnamein gestione temporanea . Tuttavia, se modifico il comando ssh ed eseguo di nuovo, tenta di eseguirlo dall'interno della sessione uno, dall'host di gestione temporanea. Se chiudo il buffer onereimposta la sessione come la prossima volta che viene eseguito qualsiasi comando con quel nome di sessione lo ricrea. Quello che non sono riuscito a trovare è un metodo per forzare un particolare blocco babel a inizializzare sempre una nuova sessione.

Sono consapevole che per alcune lingue (in particolare elisp) ciò non sarebbe possibile. Suppongo che potrei anteporre la sessione con un blocco elisp contenente (kill-buffer "one"), ma preferirei che fosse un argomento di intestazione, se possibile. Sono anche consapevole che per questo esempio potrei semplicemente combinare i due in un singolo blocco senza sessione, ma sono interessato a sequenze più complicate.

Esiste un :prologuecomando o qualche altro argomento speciale per :sessionforzare quel blocco a inizializzare una nuova shell su ogni invocazione?


Non esiste tale opzione (o un parametro di blocco del codice sorgente) in Org 8.2.10, ma dovrebbe essere abbastanza facile da aggiungere. Vorrei iniziare hackerando org-babel-initiate-session.
Costantino,

Risposte:


5

Prova questo

Forzare o inizializzare una sessione org-babel usando un'istruzione condizionale elisp per impostare dinamicamente il valore dell'intestazione : session sul primo blocco di codice.

per esempio :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

Nel codice sopra, la funzione get-buffer controlla se esiste un buffer di nome uno . Se fosse vero, il kill-buffer di funzione uccide l' uno tampone poi restituisce un valore di to nil, che è passato al ifcomunicato. In questo esempio specifico, l' ifistruzione nidificata restituirà sempre un valore di uno . Si prega di notare, sto ancora imparando elisp.

Di seguito è riportato il codice di esempio aggiornato:

#+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

Ogni volta che viene eseguito il primo blocco di codice, emacs chiederà di eliminare un buffer , in modo da poter ripristinare la sessione quando lo desideri.

MODIFICARE

Oops mancava la parte che hai sempre voluto che il buffer venisse ucciso, cioè nessun suggerimento . Eseguire prima questo blocco per disattivare temporaneamente la richiesta di blocco del buffer.

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

Spero che abbia aiutato!

Nota: questo codice è stato testato utilizzando le seguenti versioni di emacs e 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)

In conclusione, ho trovato l'ispirazione tecnica per questa risposta sul sito Web org-scraps e questo codice di esempio kill-buffer su stackoverflow.


@dgtized questa risposta ha aiutato?
Melioratus,

2
Non sapevo che avresti potuto inserire elisp nella sessione di sessione, quindi grazie per quello. Detto questo, come ho detto nella domanda originale, ero consapevole che avrei potuto automatizzare kill-bufferper forzare una nuova sessione, ma ero più interessato a sapere se esisteva un argomento a blocchi incorporato in modalità org, o qualche altra convenzione stabilita per farlo di cui non ero a conoscenza. Il tuo approccio è un bel rimedio, ma spero che ci sia un approccio canonico per questo.
dgtized

@dgtized - Stai cercando una risposta come questa? :session one :session-reset yes?
Melioratus,

Qualcosa del genere certo. Ancora una volta, è tanto una questione di quale sia la pratica raccomandata per questo esempio. Sicuramente altre persone hanno sessioni che devono essere ripristinate, e se uccidono il buffer va bene, ma voglio sapere qual è la pratica standard.
dgtized

@dgtized - Grazie per il chiarimento! Questa è un'ottima domanda! Non ho trovato una pratica standard documentata ma continuerò a cercare .
Melioratus,

2

Ispirato da @Melioratus.

Attualmente org-babel fornisce un hook chiamato org-babel-after-execute-hook. Ho esteso gli argomenti supportati del blocco org-babel src usando:

(Sto usando org-babel per l'elisir. Se vuoi il supporto di altre lingue, estendi condda solo.)

(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))))

Dopo aver valutato il codice sopra, puoi scrivere il blocco src in questo modo:

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

Dopo aver valutato il blocco src, org-babel pulirà la sessione corrispondente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.