Можно ли прочитать пользовательский ввод из STDIN при запутывании исходного блока?

10

Можно ли прочитать пользовательский ввод из STDIN при запутывании исходного блока с org-babel-tangle?

Мне известно об этом: Org Mode Babel - Интерактивная оценка кода блока .

Это не помогает решить этот конкретный вариант использования, так как он по-прежнему не позволяет вводить STDIN из оболочки, а только имитирует ограниченный ввод внутри Emacs.

Фон

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

Проблема в том, что многие учебные пособия опираются на STDIN. Например, если запустить следующий tidbit 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?

То же самое, используя пример bash. Эта:

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

К сожалению, это сейчас над моей головой

GSL
источник

Ответы:

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.shканал 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 в орг-режиме: 8.3.2

Melioratus
источник
Это очень помогает, спасибо. Творческий способ использования Vars, очень поучительно. Мне интересно, как бы я поймал STDIN "целиком", вроде как, то есть, как можно было бы из родной оболочки? Например, чтобы иметь возможность читать новые строки и управлять символами (кроме CTRL-D)?
GSL
1
@gsl - Кстати - я все еще работаю над новым ответом на вопрос о нескольких строках и управляющих символах. Если вы поймете это раньше, пожалуйста, напишите свой ответ.
Мелиоратус
Большое спасибо за подготовку нового ответа. Я все еще ищу рабочее решение. Я не могу понять это сам, все еще над моей головой прямо сейчас. Я выбираю ваш ответ, и когда появится новый, выберите его позже.
Gsl
Привет @melioratus - ты смог найти способ справиться с несколькими строками и управляющими персонажами? Это было бы весьма полезно во многих случаях.
GSL
1
@gsl - Спасибо за продолжение! Вы правильно читаете из stdin, было бы очень полезно, а я все еще смотрю! Я добился прогресса, читая stdin в именованный буфер из командной строки и затем вызывая elisp для чтения многострочного буфера в переменную. Это работает при чтении из канала, но, к сожалению, пока не для потокового ввода, т.е. tail file |работает, но не работает tail -f file |. Я посмотрю свои заметки и добавлю частично работающий многострочный пример в качестве нового ответа. Спасибо за напоминание!
Мелиоратус