È 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.