Como ativar a entrada tty mesmo com pipe?

0

Eu preciso modificar a saída de um programa que pede entrada tty. Quando canalizo a saída do programa para um utilitário como sed , linhas de entrada não são exibidas.

Como um exemplo específico se trivial: gostaria de receber a entrada Scala normal, que inclui um prompt REPL:

$ scala
Welcome to Scala 2.12.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala>

E altere todas as ocorrências de Java para Mocha :

$ scala | sed 's/Java/Mocha/g'
Welcome to Scala 2.12.3 (Mocha HotSpot(TM) 64-Bit Server VM, Mocha 1.8.0_60).
Type in expressions for evaluation. Or try :help.

O problema é que nem a última linha ( scala> ) nem nenhuma entrada de teclado digitada é mostrada até que [Enter] seja pressionado. Eu gostaria que a segunda versão se comportasse como a primeira, apenas com a substituição sed (e não a substituição da entrada do teclado, é claro). Isso é possível?

(Uma solução portátil é melhor, é claro, mas no caso de a única solução ser específica para shell ou distribuição, eu gostaria de ter o Zsh e o BSD. Obrigado.)

    
por Daniel Li 25.08.2017 / 10:09

1 resposta

0

O armazenamento em buffer será um problema, pois scala pode usar o buffer baseado em blocos por causa do pipe (em vez do buffer padrão baseado em linha de terminal, veja setvbuf(3) ) e também buffering feito por sed (ou qualquer outra coisa no pipeline). Você poderia tentar colocar stdbuf em tudo, lançar portabilidade e rezar para que esses LD_PRELOAD monkey patches funcionem; outra opção seria executar o REPL sob um PTY, alimentar a entrada do usuário para isso e substituir a saída antes de enviá-la. Isso aqui mostra a SBCL como scala estava deliciosamente não funcional na minha máquina.

$ ./mochanichize sbcl 
This is SBCL 1.3.20, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (print "Java")

"Mocha" 
"Mocha"
* (exit)
$ 

E o código para mochanichize .

#!/usr/bin/env expect

package require Tcl 8.5

proc mochanichize {fh} {
   global godot
   set somedata [read $fh]
   if {[eof $fh]} { close $fh; set godot 1; return; }
   regsub -all {\mJava\M} $somedata {Mocha} somedata
   puts -nonewline $somedata
}

proc sendtoprog {from to} {
   # TODO support ^D but that's more complicated
   puts -nonewline $to [read $from]
}

# no echo on PTY command we're running (soas not to duplicate what is
# echo'd back to the user via the user tty)
set stty_init -echo

if {[catch {spawn -noecho {*}$argv} err]} { puts stderr $err; exit 1 }

chan configure $spawn_id -blocking 0 -buffersize 1
chan event $spawn_id readable [list mochanichize $spawn_id]

chan configure stdin -blocking 0 -buffersize 1
chan configure stdout -blocking 0 -buffersize 1
chan event stdin readable [list sendtoprog stdin $spawn_id]

# TODO better handle ^Z this goes all meh on it
trap SIG_IGN SIGTSTP

vwait godot
    
por 25.08.2017 / 18:43

Tags