È possibile leggere l'input dell'utente da STDIN mentre si aggroviglia un blocco sorgente?


10

È possibile leggere l'input dell'utente da STDIN mentre si aggroviglia un blocco sorgente con org-babel-tangle?

Sono consapevole di questo: Org Mode Babel - Valutazione interattiva del blocco di codice .

Ciò non aiuta a risolvere questo particolare caso d'uso, poiché non consente ancora l'input STDIN corretto dalla shell, ma simula solo un input limitato internamente a Emacs.

sfondo

Vorrei usare Org's Babel per imparare nuovi linguaggi di programmazione (Perl e Bash) eseguendo alcuni tutorial da un unico file dell'organizzazione.

Il problema è che molti tutorial si basano su STDIN. Ad esempio, se si esegue il seguente perl tidbit:

#+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 non attenderà che l'interazione dell'utente digiti correttamente un nome su STDIN e produrrà immediatamente:

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

Stessa cosa usando un esempio bash. Questo:

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

Non attenderà l'input dell'utente ed Emacs restituirà immediatamente questo:

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

Esiste un modo nativo per Emacs di attendere l'input su un blocco aggrovigliato in esecuzione?

In caso contrario, potresti fornire alcuni suggerimenti su come scrivere qualcosa come una tangle-and-run-via-shell-bufferfunzione che:

  • Aggroviglia il blocco di codice in quel punto, salvandolo con il nome file specificato,
  • eseguire il file corrispondente in un shellbuffer visibile ,
  • eventualmente accettare input da parte dell'utente,
  • e infine riferire STDOUT, se del caso, a #+RESULTS:?

Se tale funzionalità non è implementata (ancora) in Org, come è possibile implementarla con elisp?


Aggiornamento: dopo aver cercato e studiato più Emacs e manuali elisp, sembra che il modo per farlo sarebbe sfruttare Comint , come forse make-comint-in-buffer.

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

Sfortunatamente, questo è il mio problema in questo momento 😣

Risposte:


4

Prova questo

Nota : apportate le seguenti modifiche minori al blocco di codice:

  • Spostato #!/bin/bashnell'intestazione del blocco di codice :shebang #!/bin/bashper impostare automaticamente le autorizzazioni del file eseguibile quando il blocco è aggrovigliato dir-input.sh.

  • Aggiunto codice di debug per mostrare è $TEST_DIRstato assegnato correttamente da 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   

Quindi ha creato un nuovo blocco di codice per chiamare il file aggrovigliato ./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

Avviso intestazione :var USER_INPUT=(read-string "Test Dir: ")

Questa intestazione mostrerà un Test Dir:prompt nella minibufferfinestra quando il blocco di codice viene eseguito usando a C-c C-c.

Immettere il percorso, ad es. / Path / to / test / dir enter

e il blocco passerà l'ingresso alla ./dir-input.shvia STDIN. Dovresti vedere quanto segue#+RESULTS:

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

Spero che abbia aiutato!


Codice testato con:
GNU Emacs 24.4.1 (x86_64-apple-darwin14.0.0, NS apple-appkit-1343.14) della versione 2014-12-25
org-mode: 8.3.2


Questo aiuta parecchio, grazie. Un modo creativo di usare i var, molto istruttivo. Mi chiedo come farei a catturare STDIN "del tutto", in un certo senso, cioè come si potrebbe fare dalla shell nativa? Ad esempio, per poter leggere nuove righe e controllare i caratteri (accanto a CTRL-D)?
gsl

1
@gsl - A proposito - Sto ancora lavorando a una nuova risposta alla domanda su più righe e caratteri di controllo. Se lo capisci prima di me, per favore pubblica la tua risposta.
Melioratus,

Grazie mille per aver preparato una nuova risposta. Sto ancora cercando una soluzione funzionante. Non riesco a capirlo da solo, ancora sopra la mia testa in questo momento. Sto scegliendo la tua risposta e quando verrà visualizzata la tua nuova, selezionala in seguito.
gsl

Ciao @melioratus - sei riuscito a trovare un modo per gestire più righe e controllare i personaggi? Sarebbe abbastanza utile in molti casi.
gsl

1
@gsl - Grazie per il follow-up! La tua lettura corretta da Stdin sarebbe davvero utile e sto ancora cercando! Ho fatto progressi leggendo stdin nel buffer denominato dalla riga di comando e quindi chiamando elisp per leggere il buffer multilinea in variabile. Questo funziona quando si legge da una pipe ma purtroppo non è ancora per lo streaming di stdin, cioè tail file |funziona ma non tail -f file |. Esaminerò le mie note e aggiungerò il mio esempio multilinea parzialmente funzionante come nuova risposta. Grazie per il promemoria!
Melioratus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.