¿Cómo puedo usar stdin al pasar datos cuando uso promptui?
Estoy tratando de escribir una CLI simple usando promptui
y todo funciona como se espera; hasta que intento pasar datos a través de una tubería. Después de depurar e investigar un poco, me di cuenta de que esto ocurre porque stdin
se está utilizando cuando se realiza la tubería, por lo que stdin
se interpreta y cualquier carácter de control de la tubería rompe el prompt. (con control+d en este caso).
Ejemplo:
package main
import (
"fmt"
"os"
"strings"
"github.com/manifoldco/promptui"
)
var items = []string{"some", "thing"}
func main() {
fmt.Printf("Es de la tubería %t\n", isFromPipe())
// leer datos de la tubería y hacer algo
// ... no afecta a este prompt
prompt := promptui.Select{
Stdout: os.Stderr,
// Stdin: os.Stderr, // probando si stdin es lo que está rompiendo
StartInSearchMode: true,
Label: "elige algo",
Items: items,
Searcher: func(input string, index int) bool {
d := items[index]
name := strings.Replace(strings.ToLower(d), " ", "", -1)
input = strings.Replace(strings.ToLower(input), " ", "", -1)
return strings.Contains(name, input)
},
}
_, result, err := prompt.Run()
if err != nil {
fmt.Printf("Error en el prompt %v\n", err)
return
}
fmt.Printf("Elegiste %q\n", result)
}
func isFromPipe() bool {
fi, _ := os.Stdin.Stat()
return fi.Mode()&os.ModeCharDevice == 0
}
Cuando descomento Stdin
, el prompt funciona, pero la entrada no funciona.
Entonces mi pregunta es:
– ¿Puedo usar un io.ReaderCloser
diferente para reemplazar os.Stdin
y aún así poder leer desde stdin
?
– ¿Cómo puedo pasar datos a través de una tubería y hacer que el prompt funcione?
davy.ai
Como experto en IT especializado en Go, es importante tener en cuenta que al enviar datos a una CLI utilizando
promptui
,stdin
puede estar en uso, lo que puede provocar que los caracteres de control del pipe rompan la pantalla de solicitud.Para abordar esto, una solución posible es utilizar un
io.ReaderCloser
diferente para reemplazaros.Stdin
, manteniendo la posibilidad de leer desdestdin
. Esto se puede lograr creando un nuevoio.Pipe
y configurándolo comostdin
para la pantalla de solicitud.Aquí hay un ejemplo de código que demuestra este enfoque:
En este ejemplo, creamos un nuevo
io.Pipe
y lo establecemos comostdin
para la pantalla de solicitud. Luego, iniciamos la pantalla de solicitud en una goroutine separada y leemos los datos delstdin
original (si proviene de un pipe) y los escribimos en el nuevo pipe. Luego cerramos el escritor y esperamos a que la pantalla de solicitud finalice.Con este enfoque, podemos enviar datos al CLI y aún así hacer que la pantalla de solicitud funcione como se espera.