Чи можливо зчитувати введення користувача зі STDIN під час переплутання джерельного блоку?


10

Чи можливо зчитувати введення користувача зі STDIN під час переплутання блоку джерела org-babel-tangle?

Мені це відомо: Org Mode Babel - оцінка інтерактивного кодового блоку .

Це не допомагає вирішити конкретний випадок використання, оскільки він все ще не дозволяє належним чином вводити STDIN з оболонки, а лише імітує обмежений вхід внутрішньо до Emacs.

Фон

Я хотів би скористатися Org's Babel для вивчення нових мов програмування (Perl і Bash), виконавши кілька навчальних посібників з одного файлу org.

Проблема полягає в тому, що багато навчальних посібників покладаються на STDIN. Наприклад, якщо один запускає такий підказки perl:

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

Те саме, використовуючи приклад баша. Це:

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

Сподіваюся, що допомогло!


Код протестовано за допомогою:
GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) 2014-12-25
org-mode версія: 8.3.2


Це дуже допомагає, дякую. Творчий спосіб використання vars, дуже повчальний. Мені цікаво, як би я пішов на захоплення STDIN "цілком", начебто говорити, тобто як можна було б із рідної оболонки? Наприклад, щоб мати можливість читати нові рядки та керувати символами (поруч із CTRL-D)?
gsl

1
@gsl - BTW - Я все ще працюю над новою відповіддю на запитання про кілька рядків та контрольних символів. Якщо ви це зрозумієте, перш ніж я, будь ласка, опублікуйте свою відповідь.
Меліорат

Дуже дякую за підготовку нової відповіді. Я все ще дивлюсь на робоче рішення. Я не можу це зрозуміти сам, все ще над головою. Я вибираю вашу відповідь, і коли з’явиться нова, виберіть її пізніше.
gsl

Привіт @melioratus - чи змогли ти знайти спосіб розібратися з кількома рядками та контрольними символами? Це було б досить корисно у багатьох випадках.
gsl

1
@gsl - Дякую за продовження! Ви правильне читання з stdin було б дуже корисно, і я все ще шукаю! Я домігся прочитання stdin у названому буфері з командного рядка, а потім викликав elisp для читання багаторядного буфера в змінну. Це працює при зчитуванні з труби, але, на жаль, ще не для потокового stdin, тобто tail file |працює, але ні tail -f file |. Я перегляну свої замітки та додаю свій частково працюючий багаторядковий приклад як нову відповідь. Дякуємо за нагадування!
Меліорат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.