Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
cchexcode opened this issue Nov 6, 2020 · 5 comments
Open

Comments

@cchexcode
Copy link

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
Copy link
Collaborator

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

@pksunkara pksunkara transferred this issue from console-rs/dialoguer Nov 6, 2020
@cchexcode
Copy link
Author

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
Copy link
Collaborator

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
Copy link
Author

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
Copy link
Collaborator

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.

dtolnay pushed a commit to dtolnay-contrib/console that referenced this issue Feb 4, 2022
Currently, the `console_subscriber::build()` and
`console_subscriber::init()` functions configure an `EnvFilter` that
enables the `tokio` and `runtime` targets, plus any targets configured
by `RUST_LOG`. This means that the `tokio` spans used by the console
will always be enabled at the `TRACE` level for all layers. This
includes the `fmt` layer we previously added in `init`.

Since this resulted in the `fmt` layer logs being cluttered with a bunch
of `tokio=trace` spans and events even when only high-level application
logs are enabled by `RUST_LOG`, we removed the `fmt` layer in PR console-rs#64.

However, tokio-rs/tracing#1523 was recently merged and [released][1],
adding support for [per-layer filtering][2] to `tracing-subscriber`. We
can now use the per-layer filtering API to selectively enable the
`tokio`/`runtime` spans and events at the `TRACE` level _only_ for the
`TasksLayer`, and add a filter to the `fmt` layer based on `RUST_LOG`.
This allows us to put back the `fmt` layer in
`console_subscriber::init`.

Now, if we run the example app (which uses `init`) with a `RUST_LOG`
value that enables only the app's logs, we get nice output:

![image](https://user-images.githubusercontent.com/2796466/133124582-608c2b72-db2f-4588-bb75-585312ac8d66.png)

However, we can also enable the `console-subscriber` crate's internal
logging:

![image](https://user-images.githubusercontent.com/2796466/133124746-7df10f14-cf8c-40ef-96f3-5046039a8577.png)

And, we can still enable `tokio=trace` ourselves, if we actually _want_
to see all the task spans and waker events:

![image](https://user-images.githubusercontent.com/2796466/133124851-3e4af25a-06a4-4912-9950-bfbab6dba4c7.png)

I also added some `trace!` and `debug!` macros in `examples/app.rs` to
demo that `console_subscriber::init()` also enables logging.

Closes console-rs#76
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants