Чи можливо зчитувати введення користувача зі 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.