Apakah mungkin untuk membaca input pengguna dari STDIN sambil mengacaukan blok sumber?

10

Apakah mungkin untuk membaca input pengguna dari STDIN sambil mengacaukan blok sumber dengan org-babel-tangle?

Saya mengetahui hal ini: Org Mode Babel - Evaluasi blok kode interaktif .

Itu tidak membantu menyelesaikan kasus penggunaan khusus ini, karena masih tidak memungkinkan input STDIN yang tepat dari shell, tetapi hanya mensimulasikan input terbatas secara internal ke Emacs.

Latar Belakang

Saya ingin menggunakan Org's Babel untuk mempelajari bahasa pemrograman baru (Perl dan Bash) dengan menjalankan beberapa tutorial dari satu file org.

Masalahnya adalah banyak tutorial bergantung pada STDIN. Sebagai contoh, jika seseorang menjalankan perl tidbit berikut:

#+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 tidak akan menunggu interaksi pengguna untuk mengetik nama dengan benar di STDIN, dan itu akan segera menampilkan:

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

Hal yang sama menggunakan contoh bash. Ini:

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

Tidak akan menunggu input pengguna, dan Emacs akan segera mengembalikan ini:

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

Apakah ada cara asli bagi Emacs untuk menunggu input pada blok kusut yang sedang dieksekusi?

Jika tidak, tolong beri beberapa petunjuk tentang cara menulis sesuatu seperti tangle-and-run-via-shell-bufferfungsi yang akan:

  • Kusut blok kode pada titik, simpan dengan nama file yang diberikan,
  • mengeksekusi file yang sesuai dalam shellbuffer yang terlihat ,
  • mungkin menerima input dari pengguna,
  • dan akhirnya melaporkan STDOUT, jika ada, ke #+RESULTS:?

Jika fitur tersebut belum diimplementasikan (belum) di Org, bagaimana mungkin seseorang mengimplementasikannya dengan elisp?


Pembaruan: Setelah mencari dan mempelajari lebih lanjut Emacs dan manual elisp, tampaknya cara untuk melakukannya akan meningkatkan Comint , seperti mungkin make-comint-in-buffer.

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

Sayangnya, itu di atas kepala saya sekarang 😣

gsl
sumber

Jawaban:

4

Coba ini

Catatan : Buat perubahan kecil berikut pada blok kode Anda:

  • Pindah #!/bin/bashke header blok kode :shebang #!/bin/bashuntuk secara otomatis mengatur izin file yang dapat dieksekusi ketika blok dilibatkan dir-input.sh.

  • Menambahkan kode debug untuk ditampilkan $TEST_DIRditugaskan dengan benar dari 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   

Kemudian buat blok kode baru untuk memanggil file kusut ./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

Header pemberitahuan :var USER_INPUT=(read-string "Test Dir: ")

Header ini akan menampilkan Test Dir:prompt di minibufferjendela ketika blok kode dieksekusi menggunakan a C-c C-c.

Masukkan path, misalnya / path / ke / test / dir enter

dan blok akan meneruskan input ke ./dir-input.shvia STDIN. Anda harus melihat yang berikut ini#+RESULTS:

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

Harapan itu membantu!


Kode diuji dengan:
GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) dari 2014-12-25
versi mode org: 8.3.2

Melioratus
sumber
Itu sedikit membantu, terima kasih. Cara kreatif menggunakan vars, sangat instruktif. Saya bertanya-tanya bagaimana saya akan pergi untuk menangkap STDIN "sepenuhnya", semacam berbicara, yaitu seperti seseorang dapat dari shell asli? Misalnya, untuk dapat membaca baris baru dan mengontrol karakter (di samping CTRL-D)?
gsl
1
@gsl - BTW - Saya masih mengerjakan jawaban baru untuk pertanyaan tentang beberapa baris dan karakter kontrol. Jika Anda mengetahuinya sebelum saya lakukan, silakan kirim jawaban Anda.
Melioratus
Terima kasih banyak telah menyiapkan jawaban baru. Saya masih mencari solusi yang berfungsi. Aku tidak bisa memahaminya sendiri, masih di atas kepalaku saat ini. Saya memilih jawaban Anda, dan ketika jawaban baru Anda muncul, pilih nanti.
gsl
Hai @melioratus - apakah Anda dapat menemukan cara untuk menangani beberapa baris dan karakter kontrol? Itu akan sangat berguna dalam banyak kasus.
gsl
1
@gsl - Terima kasih telah menindaklanjuti! Anda benar membaca dari stdin akan sangat berguna dan saya masih mencari! Saya telah membuat kemajuan membaca stdin menjadi buffer bernama dari baris perintah dan kemudian memanggil elisp untuk membaca buffer multiline ke dalam variabel. Ini berfungsi ketika membaca dari sebuah pipa tetapi sayangnya belum untuk streaming stdin, yaitu tail file |bekerja tetapi tidak tail -f file |. Saya akan memeriksa catatan saya dan menambahkan contoh multiline yang berfungsi sebagian sebagai jawaban baru. Terima kasih untuk pengingat!
Melioratus