Ist es möglich, Benutzereingaben von STDIN zu lesen, während ein Quellblock verwickelt wird?

10

Ist es möglich, Benutzereingaben von STDIN zu lesen, während ein Quellblock mit verwirrt wird org-babel-tangle?

Mir ist dies bewusst: Org Mode Babel - Interaktive Codeblockauswertung .

Dies hilft nicht, diesen speziellen Anwendungsfall zu lösen, da es immer noch keine ordnungsgemäße STDIN-Eingabe von der Shell zulässt, sondern nur eine begrenzte interne Eingabe für Emacs simuliert .

Hintergrund

Ich möchte Orgs Babel verwenden, um neue Programmiersprachen (Perl und Bash) zu lernen, indem ich einige Tutorials aus einer Organisationsdatei ausführe.

Das Problem ist, dass viele Tutorials auf STDIN basieren. Zum Beispiel, wenn man den folgenden Perl-Leckerbissen ausführt:

#+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 wartet nicht darauf, dass die Interaktion des Benutzers einen Namen in STDIN richtig eingibt, und gibt sofort Folgendes aus:

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

Gleiches anhand eines Bash-Beispiels. Diese:

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

Wartet nicht auf Benutzereingaben und Emacs gibt dies sofort zurück:

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

Gibt es eine native Möglichkeit für Emacs, auf Eingaben in einem ausgeführten Block zu warten?

Wenn nicht, geben Sie bitte einige Hinweise, wie Sie so etwas wie eine tangle-and-run-via-shell-bufferFunktion schreiben können, die:

  • Verwickeln Sie den Codeblock an der Stelle und speichern Sie ihn mit dem angegebenen Dateinamen.
  • Führen Sie die entsprechende Datei in einem sichtbaren shellPuffer aus.
  • möglicherweise Eingaben des Benutzers akzeptieren,
  • und schließlich STDOUT, wenn überhaupt, zu melden #+RESULTS:?

Wenn eine solche Funktion (noch) nicht in Org implementiert ist, wie könnte man sie mit elisp implementieren?


Update: Nachdem Sie die Emacs- und Elisp-Handbücher genauer durchgesehen und studiert haben, scheint es so, als würde man Comint nutzen , wie vielleicht make-comint-in-buffer.

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

Leider geht mir das gerade über den Kopf 😣

gsl
quelle

Antworten:

4

Versuche dies

Hinweis : Folgende geringfügige Änderungen an Ihrem Codeblock wurden vorgenommen:

  • #!/bin/bashIn den Codeblock-Header verschoben, :shebang #!/bin/bashum automatisch ausführbare Dateiberechtigungen festzulegen, wenn der Block verwickelt ist dir-input.sh.

  • Der hinzugefügte Debug-Code $TEST_DIRwurde korrekt von zugewiesen 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   

Dann wurde ein neuer Codeblock erstellt, um eine verworrene Datei aufzurufen ./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

Kopfzeile beachten :var USER_INPUT=(read-string "Test Dir: ")

Dieser Header zeigt eine Test Dir:Eingabeaufforderung im minibufferFenster an, wenn der Codeblock mit a ausgeführt wird C-c C-c.

Geben Sie den Pfad ein, z. B. / path / to / test / dir enter

und der Block leitet die Eingabe an die ./dir-input.shVia weiter STDIN. Sie sollten Folgendes sehen#+RESULTS:

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

Hoffe das hat geholfen!


Code getestet mit:
GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) der
Version 2014-12-25 org-mode: 8.3.2

Melioratus
quelle
Das hilft ziemlich viel, danke. Eine kreative Art, Vars zu verwenden, sehr lehrreich. Ich frage mich, wie ich STDIN "ganz" einfangen soll, sozusagen, wie man es von einer einheimischen Shell könnte? Zum Beispiel, um neue Zeilen lesen und Zeichen steuern zu können (neben STRG-D)?
gsl
1
@gsl - Übrigens - Ich arbeite immer noch an einer neuen Antwort auf Fragen zu mehreren Zeilen und Steuerzeichen. Wenn Sie es vor mir herausfinden, posten Sie bitte Ihre Antwort.
Melioratus
Vielen Dank für die Vorbereitung einer neuen Antwort. Ich suche immer noch nach einer funktionierenden Lösung. Ich kann es nicht selbst herausfinden, immer noch über meinem Kopf. Ich wähle Ihre Antwort und wenn Ihre neue erscheint, wählen Sie sie später aus.
gsl
Hallo @melioratus - konnten Sie einen Weg finden, mit mehreren Zeilen und Steuerzeichen umzugehen? Das wäre in vielen Fällen sehr nützlich.
gsl
1
@gsl - Danke fürs Follow-up! Sie sind richtig lesen von stdin wäre wirklich nützlich und ich suche immer noch! Ich habe Fortschritte beim Lesen von stdin in den benannten Puffer über die Befehlszeile gemacht und dann elisp aufgerufen, um den mehrzeiligen Puffer in die Variable zu lesen. Dies funktioniert beim Lesen aus einer Pipe, aber leider noch nicht für das Streaming von stdin, dh tail file |funktioniert aber nicht tail -f file |. Ich werde meine Notizen durchsehen und mein teilweise funktionierendes mehrzeiliges Beispiel als neue Antwort hinzufügen. Danke für die Erinnerung!
Melioratus