Comment forcer une session org-babel à se réinitialiser ou à s'initialiser?

8

Si je lance les blocs shell babel suivants

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

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

Org crée un tampon shell appelé one, s'exécute ssh stagingpuis, après la connexion, s'exécute hostnamelors du transfert. Cependant, si je modifie la commande ssh et l'exécute à nouveau, elle tente de l'exécuter à partir de la première session, à partir de l'hôte intermédiaire. Si je ferme le tampon, oneil réinitialise la session car la prochaine fois qu'une commande est exécutée avec ce nom de session, il la recrée. Ce que je n'ai pas pu trouver, c'est une méthode pour forcer un bloc babel particulier à toujours initialiser une nouvelle session.

Je suis conscient que pour certaines langues (elisp en particulier), cela ne serait pas possible. Je suppose que je pourrais ajouter la session à un bloc elisp contenant (kill-buffer "one"), mais je préfère que ce soit un argument d'en-tête si possible. Je suis également conscient que pour cet exemple, je pourrais simplement combiner les deux en un seul bloc sans session, mais je suis intéressé par des séquences plus compliquées.

Existe-t-il une :prologuecommande ou un autre argument spécial :sessionqui force ce bloc à initialiser un nouveau shell à chaque appel?

dgtized
la source
Il n'y a pas une telle option (ou un paramètre de bloc de code source) dans Org 8.2.10, mais il devrait être assez facile à ajouter. Je commencerais par pirater org-babel-initiate-session.
Constantine

Réponses:

5

Essaye ça

Forcer une session org-babel à se réinitialiser ou à s'initialiser à l'aide d'une instruction conditionnelle elisp pour définir dynamiquement la valeur de l'en - tête : session sur le premier bloc de code.

par exemple :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

Dans le code ci-dessus, la fonction get-buffer vérifie si un tampon nommé un existe. Si cela est vrai, le kill-buffer fonction tue l' un tampon retourne une valeur d'alors tou nilqui est passé à la ifdéclaration. Dans cet exemple spécifique, l' ifinstruction imbriquée renvoie toujours une valeur de un . Veuillez noter que j'apprends encore elisp.

Voici l'exemple de code mis à jour:

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

Chaque fois que le premier bloc de code est exécuté, emacs demandera de tuer le seul tampon , afin que vous puissiez réinitialiser la session quand vous le souhaitez.

ÉDITER

Oups, vous avez manqué la partie que vous avez toujours voulu tuer, c'est-à-dire sans invite . Exécutez d'abord ce bloc pour désactiver temporairement l'invite à tuer le tampon.

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

J'espère que cela a aidé!

Remarque: Ce code a été testé à l'aide des versions suivantes d'emacs et du mode org.

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 conclusion, j'ai trouvé l'inspiration technique pour cette réponse sur le site Web org-scraps et cet exemple de code kill-buffer sur stackoverflow.

Melioratus
la source
@dgtized cette réponse vous a-t-elle aidé?
Melioratus
2
Je ne savais pas que vous pouviez intégrer elisp dans l'appel de session, alors merci pour cela. Cela dit, comme je l'ai mentionné dans la question d'origine, je savais que je pouvais automatiser kill-bufferpour forcer une nouvelle session, mais j'étais plus intéressé à savoir s'il y avait un argument de bloc intégré au mode org, ou une autre convention établie pour le faire. que je n'étais pas au courant. Votre approche est une bonne solution de contournement, mais j'espère qu'il existe une approche canonique pour cela.
organisé le
@dgtized - Recherchez-vous une réponse comme celle-ci? :session one :session-reset yes?
Melioratus
Quelque chose comme ça bien sûr. Encore une fois, il s'agit tout autant de savoir quelle est la pratique recommandée pour cet exemple. Certes, d'autres personnes ont des sessions qui doivent être réinitialisées, et si elles tuent simplement le tampon, c'est bien, mais je veux savoir quelle est la pratique standard.
dgtized
@dgtized - Merci d'avoir clarifié! C'est une excellente question! Je n'ai pas trouvé de pratique standard documentée mais je continuerai à chercher .
Melioratus
2

Inspiré par @Melioratus.

Actuellement, org-babel fournit un crochet appelé org-babel-after-execute-hook. J'ai étendu les arguments pris en charge du bloc org-babel src en l'utilisant:

(J'utilise org-babel pour élixir. Si vous voulez des supports d'autres langues, développez condvous-même.)

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

Après avoir évalué le code ci-dessus, vous pouvez écrire un bloc src comme ceci:

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

Après avoir évalué le bloc src, org-babel nettoiera la session correspondante.


la source