ソースブロックをもつれさせながら、STDINからユーザー入力を読み取ることはできますか?


10

ソースブロックをもつれさせながらSTDINからユーザー入力を読み取ることはできますorg-babel-tangleか?

私はこれを知っています:Org Mode Babel-インタラクティブコードブロックの評価

それは助けには、それはまだシェルから適切なSTDIN入力を許可しないように、この特定のユースケースを解決しますが、限られた入力をシミュレートしていない内部のEmacsに。

バックグラウンド

OrgのBabelを使用して、1つのorgファイルからいくつかのチュートリアルを実行することにより、新しいプログラミング言語(PerlとBash)を学びたいと思います。

問題は、多くのチュートリアルがSTDINに依存していることです。たとえば、次のperl tidbitを実行するとします。

#+BEGIN_SRC perl :tangle hello-name.pl  :results output :export code
use 5.010;
use strict;
use warnings;

say "What is your name?";
my $name=<STDIN>;
say "Hello $name, how are you?";

#+END_SRC

EmacsはユーザーのインタラクションがSTDINに名前を正しく入力するのを待たず、すぐに出力します:

#+RESULTS:
: What is your name?
: Hello , how are you?

bashの例を使用して同じこと。この:

#+BEGIN_SRC sh  :results output :export code :tangle dir-input.sh
#!/bin/bash

if [ -z "$TEST_DIR" ]
then
    echo "TEST_DIR was not set, please enter the path: "
    read input_variable
    export TEST_DIR=$input_variable
fi
#+END_SRC

ユーザー入力を待たず、Emacsはすぐにこれを返します:

#+RESULTS:
: TEST_DIR was not set, please enter the path: 

Emacsが実行中のもつれたブロックの入力を待つネイティブの方法はありますか?

そうでない場合は、次のようなtangle-and-run-via-shell-buffer関数のようなものを書く方法について、いくつかの指針を示してください。

  • ポイントでコードブロックをもつれさせ、与えられたファイル名で保存し、
  • 可視shellバッファーで対応するファイルを実行し、
  • おそらくユーザーからの入力を受け入れる
  • そしてSTDOUT、もしあれば、最後に報告し#+RESULTS:ますか?

そのような機能がOrgで(まだ)実装されていない場合、elispでどのように実装できますか?


更新:Emacsとelispのマニュアルをさらに調べて調べたところ、おそらく、のように、Comintを活用することになるでしょうmake-comint-in-buffer

(make-comint-in-buffer "*cmd-buffer*" nil "perl" nil "hello-name.pl")

残念ながら、それは今私の頭上にあります😣

回答:


4

これを試して

:コードブロックに次の小さな変更を加えました。

  • #!/bin/bashコードブロックヘッダー:shebang #!/bin/bashに移動し、ブロックがに絡まったときに実行可能ファイルの権限を自動的に設定しますdir-input.sh

  • 表示するデバッグコードがから$TEST_DIR正しく割り当てられましたread input_variable

#+BEGIN_SRC sh  :results output :export code :tangle dir-input.sh :shebang #!/bin/bash

if [ -z "$TEST_DIR" ]
then
    echo "TEST_DIR was not set, please enter the path: "
    read input_variable
    export TEST_DIR=$input_variable
    echo "# export TEST_DIR=$TEST_DIR"
fi
#+END_SRC   

次に、もつれたファイルを呼び出す新しいコードブロックを作成しました./dir-input.sh

#+BEGIN_SRC sh :results output :shebang #!/bin/bash  :var USER_INPUT=(read-string "Test Dir: ")
  echo $USER_INPUT | ./dir-input.sh 
#+END_SRC

通知ヘッダー :var USER_INPUT=(read-string "Test Dir: ")

このヘッダーは、を使用してコードブロックが実行されるTest Dir:と、minibufferウィンドウにプロンプトを表示しますC-c C-c

/ path / to / test / dirなどのパスを入力します enter

そして、ブロックは./dir-input.shviaに入力を渡しますSTDIN。次が表示されます#+RESULTS:

#+RESULTS:
: TEST_DIR was not set, please enter the path: 
: # export TEST_DIR=/path/to/test/dir

お役に立てば幸いです。


テスト済みコード:
2014-12-25
組織モードバージョン:8.3.2のGNU Emacs 24.4.1(x86_64-apple-darwin14.0.0、NS apple-appkit-1343.14)


それはかなり役に立ちます、ありがとう。非常に有益な変数を使用する創造的な方法。私はどのようにしてSTDINを「完全に」、つまり話すか、つまりネイティブシェルから取得できるようにキャプチャするのでしょうか。たとえば、新しい行を読み、文字を制御できるようにするには(CTRL-D以外)?
gsl 2016

1
@gsl-ところで-複数の行と制御文字に関する質問への新しい回答をまだ作成中です。私がそれをする前にそれを理解するならば、あなたの答えを投稿してください。
Melioratus

新しい回答をご用意いただき、誠にありがとうございます。私はまだ実用的な解決策を見ています。私は自分でそれを理解することはできません。私はあなたの答えを選んでいます。あなたの新しい答えが出てきたら、後でそれを選択してください。
gsl 2018年

こんにちは@melioratus-複数の行を処理して文字を制御する方法を見つけることができましたか?それは多くの場合非常に役に立ちます。
gsl

1
@gsl-フォローアップありがとうございます!stdinからの正しい読み取りは本当に役立つでしょう。私はまだ探しています!コマンドラインからstdinを名前付きバッファーに読み込んでから、elispを呼び出して複数行バッファーを変数に読み込むようにしました。これはパイプから読み取るときに機能しますが、残念ながらまだstdinをストリーミングするためにはtail file |機能しませんtail -f file |。つまり、機能しますが機能しません。私はノートを調べ、部分的に機能している複数行の例を新しい答えとして追加します。リマインダーをありがとう!
Melioratus
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.