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

When stdin is a terminal, for_byte_record_with_terminator() does not exit immediately on Control-D #180

Closed
zhitkoff opened this issue Feb 24, 2024 · 4 comments

Comments

@zhitkoff
Copy link

if stdin().is_terminal() {
        let mut buf_in = BufReader::new(stdin());
        let separator = b'\n';

        println!("Start terminal input for bstr for_byte_record_with_terminator\nTry ^D - it will not exit right away on the first ^D");
        let _result_bstr = buf_in.for_byte_record_with_terminator(separator, |_line| {
            // do something with each line
            Ok(true)
        })?;
        println!("Done");

        println!("Start terminal input for std io, like split, read_until, etc\nTry ^D");
        let _result_std = buf_in.split(separator).for_each(|_line| {
            // do something with each line
        });
        println!("Done");
    }

Comparing to similar functions from std::io, which do exit on the first Control-D right away in the terminal.
This limits usefulness of bstr crate for developing command line utilities that need to process all stdin variants (piped, redirected from file, terminal)

@BurntSushi
Copy link
Owner

Please provide a full program and an example invocation on the CLI that reproduces the problem. Please include actual output and expected output.

@zhitkoff
Copy link
Author

zhitkoff commented Feb 24, 2024

Full program for bstr use case:

use bstr::io::BufReadExt;
use std::io::{self, stdin, BufReader, IsTerminal};

fn main() -> io::Result<()> {
    if stdin().is_terminal() {
        let mut buf_in = BufReader::new(stdin());
        let separator = b'\n';

        println!("Start terminal input for bstr for_byte_record_with_terminator\nTry ^D - it will not exit right away on the first ^D");
        let _result_bstr = buf_in.for_byte_record_with_terminator(separator, |_line| {
            // do something with line
            Ok(true)
        })?;
        println!("Done");
    }
    Ok(())
}

Run with cargo run and it will wait for user input in the terminal. Try ^D (Control-D) and notice that it does not exit, still accepting input in the terminal. Try ^D twice - it should exit to command prompt

@zhitkoff
Copy link
Author

zhitkoff commented Feb 24, 2024

Full program to illustrate that using std::io functions in the same scenario does exit on the first ^D:

use std::io::{self, stdin, BufRead, BufReader, IsTerminal};

fn main() -> io::Result<()> {
    if stdin().is_terminal() {
        let buf_in = BufReader::new(stdin());
        let separator = b'\n';

        println!("Start terminal input for std io, like split, read_until, etc\nTry ^D");
        let _result_std = buf_in.split(separator).for_each(|_line| {
            // do something with line
        });
        println!("Done");
    }
    Ok(())
}

Run with cargo run and it will wait for user input in the terminal. Try ^D (Control-D) once and notice that it does exit into command prompt right away.

@BurntSushi
Copy link
Owner

Nice find. This is fixed in bstr 1.9.1.

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

2 participants