console-rs / console

A rust console and terminal abstraction
MIT License
963 stars 114 forks source link

Piping data via STDIN into executable makes text prompts not work #76

Open cchexcode opened 4 years ago

cchexcode commented 4 years ago

Issue As soon as I populate the STDIN pipe to my program with any data, the text prompts won't work properly.

Context I have a binary that does text processing (https://github.com/replicadse/complate). In the past, the configuration for the template was loaded via a configuration file. I have added a feature with which one should be able to pipe the configuration string directly into the print command.

Behaviour

dialoguer::Input::new().allow_empty(false).with_prompt("some text").interact()

When specifying allow_empty(false), the terminal flickers and shows weird behaviour. I can not enter text nor can I do anything else than Ctrl+C exit. When specifying allow_empty(true), the data result string is empty.

References Here you can see me reading the data from STDIN: https://github.com/replicadse/complate/pull/10/files#diff-c5354523dab7ee14c84278715c952cb7e302af46f5c8372b94375b36f003b93eR138 Here you can see me using dialoguer: https://github.com/replicadse/complate/blob/master/src/render/mod.rs#L174

pksunkara commented 4 years ago

We don't support reading data from STDIN currently. If you want to add support, please go ahead.

cchexcode commented 4 years ago

I think you might have misunderstood me. In fact I am not piping anything into the dialoguer interaction command itself (or similar). I am reading the data from STDIN myself before essentially doing anything with the crate. So there is no need for the prompt to support STDIN, just to not be confused when there was something in it which was read way before the creation and interaction.

pksunkara commented 4 years ago

I am not still sure what exactly the issue is. Can you please produce a minimal reproducible example code? Hopefully using console read character logic instead of dialoguer.

cchexcode commented 4 years ago

Sure, please find the example below:

use std::io::{Read, Result};

use dialoguer::Input;

fn main() {
    // read data from stdin
    let mut buffer= String::new();
    std::io::stdin().lock().read_to_string(&mut buffer).unwrap();

    let input: Result<String> = Input::new()
        .allow_empty(false)
        .with_prompt(&buffer)
        .interact();

    println!("{}", input.unwrap());
}

execute the example via:

cargo build && printf "hey" | ./target/debug/$program

Remark: I was noticing that I originally used v. 0.5.0 in my crate. After updating it to 0.7.1, it actually now gives me a buffer overflow exception. But in this minimal example, the behaviour is the same as it was in 0.5.0 on my original use-case.

mitsuhiko commented 3 years ago

The issue is mostly that we actually do read from stdin for prompts. It would be a nice thing to provide an option to alternatively read from tty directly.