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.