org-babelセッションを強制的にリセットまたは初期化するにはどうすればよいですか?


8

次のバベルシェルブロックを実行すると

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

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

ORGと呼ばれるシェルバッファを作成しone実行、ssh stagingおよびその後接続した後、実行hostnameステージに。ただし、sshコマンドを微調整して再度実行すると、ステージングホストからセッション1内から実行しようとします。バッファを閉じるoneと、次回そのセッション名でコマンドが実行されるときにセッションがリセットされ、再作成されます。私が見つけることができなかったのは、特定のバベルブロックに常に新しいセッションを初期化させる方法です。

一部の言語(特にelsp)では、これが不可能であることを認識しています。セッションの先頭にを含むelispブロックを付加できると思い(kill-buffer "one")ますが、可能であればこれをヘッダー引数にしたいと思います。この例では、セッションなしで2つを1つのブロックに単純に結合できることも知っていますが、もっと複雑なシーケンスに興味があります。

すべての呼び出しでそのブロックに新しいシェルを初期化させる:prologueコマンドまたは他の特別な引数はあり:sessionますか?


Org 8.2.10にはそのようなオプション(またはソースコードブロックパラメーター)はありませんが、追加は非常に簡単です。ハッキングから始めorg-babel-initiate-sessionます。
コンスタンティン

回答:


5

これを試して

最初のコードブロックで:sessionヘッダーの値を動的に設定するelisp条件ステートメントを使用して、org-babelセッションを強制的にリセットまたは初期化します。

例えば :session (if (get-buffer "one") (if (kill-buffer "one") (print "one") (print "one")) (print "one"))

上記のコードで、get-buffer関数は、1という名前のバッファーが存在するかどうかを確認します。trueの場合、kill-buffer関数は1つのバッファーを強制終了してから、ステートメントに渡されるまたはの値を返します。この特定の例では、ネストされたステートメントは常に1の値を返します。注意してください、私はまだelispを学んでいます。tnilifif

以下は更新されたサンプルコードです:

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

最初のコードブロックが実行されるたびに、emacsは1つのバッファを強制終了するように要求するため、必要に応じてセッションをリセットできます。

編集

おっと、あなたはいつもあなたが常にバッファを殺したかった、つまりプロンプトを出さない部分を逃しました。最初にこのブロックを実行して、バッファを強制終了するプロンプトを一時的にオフにします。

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

お役に立てば幸いです。

注:このコードは、以下のバージョンのemacsおよび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)

結論として、私はorg-scrapsの Webサイトでこの回答の技術的なインスピレーションと、stackoverflowのこのキルバッファーのサンプルコードを見つけました。


@dgtizedこの回答は役に立ちましたか?
Melioratus、2015年

2
セッションコールにelispを組み込むことができるとは知らなかったので、ありがとうございます。とは言っても、元の質問で述べたように、自動化kill-bufferして新しいセッションを強制できることは知っていましたが、org-modeに組み込まれたブロック引数があるかどうか、またはこれを行うための他の確立された規則があるかどうかを学ぶことにもっと興味を持っていました知らなかった。あなたのアプローチは良い回避策ですが、これには正規のアプローチがあることを願っています。
dgtized

@dgtized-このような答えを探していますか?:session one :session-reset yes
Melioratus、2015年

確かにそのようなもの。繰り返しますが、これはこの例で推奨される方法が何であるかという問題です。確かに他の人はリセットが必要なセッションを持っています、そして彼らがバッファを殺すだけでいいのならそれでいいですが、私は標準的な慣行が何であるか知りたいです。
dgtized '

@dgtized-明確にしてくれてありがとう!これはすばらしい質問です。文書化された標準的なプラクティスは見つかりませんでしたが、今後も検討していきます
Melioratus、2015年

2

@Melioratusに触発されました。

現在、org-babelはというフックを提供していますorg-babel-after-execute-hook。私はそれを使用してorg-babel srcブロックのサポートされている引数を拡張しました:

(私はエリクサーにorg-babelを使用condしています。他の言語のサポートが必要な場合は、自分で拡張してください。)

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

上記のコードを評価した後、次のようにsrcブロックを記述できます。

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

srcブロックを評価した後、org-babelは対応するセッションをクリーンアップします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.