Czy możliwe jest odczytanie danych wejściowych użytkownika ze STDIN podczas splątania bloku źródłowego?


10

Czy możliwe jest odczytanie danych wejściowych użytkownika ze STDIN podczas splątania bloku źródłowego org-babel-tangle?

Mam tego świadomość: Babel Mode Org - Interaktywna ocena bloku kodu .

To nie pomaga rozwiązać tego konkretnego przypadku użycia, ponieważ nadal nie pozwala na prawidłowe wejście STDIN z powłoki, ale tylko symuluje ograniczone wejście wewnętrznie do Emacsa.

tło

Chciałbym użyć Babel Orga do nauki nowych języków programowania (Perl i Bash), wykonując niektóre samouczki z jednego pliku org.

Problem polega na tym, że wiele samouczków opiera się na STDIN. Na przykład, jeśli uruchomimy następujący perl smakołyk:

#+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 nie będzie czekać na interakcję użytkownika, aby poprawnie wpisać nazwę na STDIN i natychmiast wyświetli:

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

To samo na przykładzie bash. To:

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

Nie będzie czekać na dane wprowadzone przez użytkownika, a Emacs natychmiast zwróci to:

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

Czy istnieje natywny sposób, aby Emacs czekał na dane wejściowe w wykonywanym splątanym bloku?

Jeśli nie, proszę podać kilka wskazówek, jak napisać coś w rodzaju tangle-and-run-via-shell-bufferfunkcji, która:

  • Zaplątaj blok kodu w punkcie, zapisując podaną nazwę pliku,
  • uruchom odpowiedni plik w widocznym shellbuforze,
  • ewentualnie przyjmowanie danych wejściowych od użytkownika,
  • i wreszcie STDOUT, jeśli w ogóle, zgłaszanie się do #+RESULTS:?

Jeśli taka funkcja nie jest (jeszcze) zaimplementowana w organizacji, jak można ją zaimplementować za pomocą elisp?


Aktualizacja: po przeszukaniu i przestudiowaniu podręczników Emacsa i elisp wydaje się, że można to zrobić, wykorzystując Comint , na przykład make-comint-in-buffer.

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

Niestety, to jest teraz nad moją głową 😣

Odpowiedzi:


4

Spróbuj tego

Uwaga : Wprowadzono następujące niewielkie zmiany w bloku kodu:

  • Przeniesiono #!/bin/bashdo nagłówka bloku kodu, :shebang #!/bin/bashaby automatycznie ustawić uprawnienia do pliku wykonywalnego, gdy blok jest zaplątany dir-input.sh.

  • Dodano kod debugowania do pokazania $TEST_DIRzostał poprawnie przypisany 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   

Następnie utworzono nowy blok kodu, aby wywołać plik splątany ./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

Uwaga nagłówek :var USER_INPUT=(read-string "Test Dir: ")

Nagłówek ten wyświetli Test Dir:monit w minibufferoknie, gdy blok kodu jest wykonywany za pomocą C-c C-c.

Wpisz ścieżkę, np. / Path / to / test / dir enter

a blok przekaże dane wejściowe do ./dir-input.shvia STDIN. Powinieneś zobaczyć następujące#+RESULTS:

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

Mam nadzieję, że to pomogło!


Kod testowany z:
GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) wersji
org-mode 2014-12-25 : 8.3.2


To bardzo pomaga, dziękuję. Kreatywny sposób korzystania z Vars, bardzo pouczający. Zastanawiam się, jak przejść do przechwytywania STDIN „całkowicie”, w pewnym sensie mówić, tzn. Jak można to zrobić z natywnej powłoki? Na przykład, aby móc czytać nowe linie i znaki kontrolne (oprócz CTRL-D)?
gsl

1
@gsl - BTW - Nadal pracuję nad nową odpowiedzią na pytanie dotyczące wielu linii i znaków kontrolnych. Jeśli wymyślisz to zanim to zrobię, opublikuj swoją odpowiedź.
Melioratus

Dziękuję bardzo za przygotowanie nowej odpowiedzi. Nadal szukam działającego rozwiązania. Sam nie potrafię tego rozgryźć, wciąż nad głową. Wybieram twoją odpowiedź, a kiedy pojawi się twoja nowa, wybierz ją później.
gsl

Cześć @melioratus - czy udało ci się znaleźć sposób na radzenie sobie z wieloma liniami i kontrolowaniem postaci? Byłoby to przydatne w wielu przypadkach.
gsl

1
@gsl - Dziękujemy za informację! Prawidłowy odczyt ze standardu byłby naprawdę przydatny, a ja wciąż szukam! Poczyniłem postępy w czytaniu stdin do nazwanego bufora z wiersza poleceń, a następnie wywołanie elisp w celu odczytania bufora wielowierszowego do zmiennej. Działa to podczas odczytu z potoku, ale niestety jeszcze nie do przesyłania strumieniowego standardowego, tzn. tail file |Działa, ale nie tail -f file |. Przejrzę moje notatki i dodam mój częściowo działający przykład multilinii jako nową odpowiedź. Dziękuję za przypomnienie!
Melioratus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.