Wie erzwinge ich das Zurücksetzen oder Initialisieren einer org-babel-Sitzung?

8

Wenn ich die folgenden Babel-Shell-Blöcke ausführe

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

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

Org erstellt einen Shell-Puffer namens one, wird ausgeführt ssh stagingund nach dem Verbinden hostnamebeim Staging ausgeführt. Wenn ich jedoch den Befehl ssh optimiere und erneut ausführe, wird versucht, ihn innerhalb der ersten Sitzung vom Staging-Host aus auszuführen. Wenn ich den Puffer schließe one, wird die Sitzung zurückgesetzt, wenn ein Befehl das nächste Mal mit diesem Sitzungsnamen ausgeführt wird, wird er neu erstellt. Was ich nicht finden konnte, ist eine Methode, um einen bestimmten Babel-Block zu zwingen, immer eine neue Sitzung zu initialisieren.

Mir ist bewusst, dass dies für einige Sprachen (insbesondere Elisp) nicht möglich wäre. Ich nehme an, ich könnte der Sitzung einen Elisp-Block voranstellen, der enthält (kill-buffer "one"), aber dies wäre, wenn möglich, eher ein Header-Argument. Mir ist auch bewusst, dass ich für dieses Beispiel die beiden einfach ohne Sitzung zu einem einzigen Block kombinieren könnte, aber ich bin an komplizierteren Sequenzen interessiert.

Gibt es einen :prologueBefehl oder ein anderes spezielles Argument, :sessiondas diesen Block zwingt, bei jedem Aufruf eine neue Shell zu initialisieren?

dgtized
quelle
In Org 8.2.10 gibt es keine solche Option (oder keinen Quellcode-Blockparameter), aber das Hinzufügen sollte ziemlich einfach sein. Ich würde mit dem Hacken beginnen org-babel-initiate-session.
Constantine

Antworten:

5

Versuche dies

Erzwingen Sie das Zurücksetzen oder Initialisieren einer org-babel-Sitzung mithilfe einer elisp-bedingten Anweisung , um den Wert des : session- Headers im ersten Codeblock dynamisch festzulegen .

z.B :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

Im obigen Code prüft die Funktion get-buffer , ob ein Puffer mit dem Namen one vorhanden ist. Wenn true, löscht die Kill-Buffer- Funktion den einen Puffer und gibt dann einen Wert von oder zurück, der an die Anweisung übergeben wird. In diesem speziellen Beispiel gibt die verschachtelte Anweisung immer den Wert Eins zurück . Bitte beachte, ich lerne immer noch Elisp.tnilifif

Unten finden Sie den aktualisierten Beispielcode:

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

Jedes Mal, wenn der erste Codeblock ausgeführt wird, fordert emacs Sie auf, den einen Puffer zu beenden , damit Sie die Sitzung zurücksetzen können, wenn Sie dies wünschen.

BEARBEITEN

Hoppla , ich habe einen Teil verpasst, von dem Sie immer wollten, dass der Puffer getötet wird, dh keine Aufforderung . Führen Sie diesen Block zuerst aus, um die Aufforderung zum Beenden des Puffers vorübergehend auszuschalten.

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

Hoffe das hat geholfen!

Hinweis: Dieser Code wurde mit den folgenden Versionen von Emacs und Org-Mode getestet.

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)

Zusammenfassend fand ich technische Inspiration für diese Antwort auf der org-scraps- Website und diesen Kill-Buffer-Beispielcode für Stackoverflow.

Melioratus
quelle
@dgtized hat diese Antwort geholfen?
Melioratus
2
Mir war nicht bewusst, dass Sie elisp in den Sitzungsaufruf einbetten können. Vielen Dank dafür. Wie ich in der ursprünglichen Frage erwähnt habe, war mir jedoch bewusst, dass ich automatisieren kann kill-buffer, um eine neue Sitzung zu erzwingen, aber ich war mehr daran interessiert zu erfahren, ob ein Blockargument in den Organisationsmodus eingebaut ist oder eine andere etablierte Konvention, um dies zu tun das war mir nicht bewusst. Ihr Ansatz ist eine gute Lösung, aber ich hoffe, dass es dafür einen kanonischen Ansatz gibt.
Dgtized
@dgtized - Suchen Sie eine Antwort wie diese? :session one :session-reset yes?
Melioratus
So etwas sicher. Auch hier geht es um die empfohlene Vorgehensweise für dieses Beispiel. Sicherlich haben andere Leute Sitzungen, die zurückgesetzt werden müssen, und wenn sie nur den Puffer töten, ist das in Ordnung, aber ich möchte wissen, was die Standardpraxis ist.
Dgtized
@dgtized - Danke für die Klarstellung! Das ist eine gute Frage! Ich habe keine dokumentierte Standardpraxis gefunden, werde aber weiter suchen .
Melioratus
2

Inspiriert von @Melioratus.

Derzeit bietet org-babel einen Hook namens org-babel-after-execute-hook. Ich habe die unterstützten Argumente des org-babel src-Blocks damit erweitert:

(Ich verwende org-babel als Elixier. Wenn Sie Unterstützung für andere Sprachen wünschen, erweitern Sie diese condselbst.)

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

Nachdem Sie den obigen Code ausgewertet haben, können Sie den src-Block wie folgt schreiben:

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

Nach dem Auswerten des src-Blocks bereinigt org-babel die entsprechende Sitzung.


quelle