How can I read non-blocking from stdin?

Is there a way to check if data is available stdin

in Rust, or to perform a read that returns immediately with the currently available data?

My goal is to read the input generated by, for example, the cursor keys in a shell that is configured to return all read data immediately. For example, with the equivalent of: stty -echo -echok -icanon min 1 time 0


I suppose one solution would be to use ncurses or similar libraries, but I would like to avoid any big dependencies.

So far, I've only gotten input locking, which is what I don't want:

let mut reader = stdin();
let mut s = String::new();

match reader.read_to_string(&mut s) {...} // this blocks :(



source to share

2 answers

Most operating systems work with standard input and output in a blocked way by default. Unsurprisingly, the Rust library appears instead.

To read from a blocking thread in a non-blocking way, you can create a separate thread to allow additional blocks of threads instead of the main one. Checking that the blocking file descriptor has produced some input is similar: create a stream, force it to read data, check if it has produced any data so far.

Here is a code snippet that I am using for a similar purpose of handling the output of a pipe interactively and hopefully can serve as an example. It sends data through a channel that supports try_recv - allows you to check if data is available or not.

Someone told me that mio can use to read from a pipe in a non-blocking way, so you might want to test it as well. I suspect passing the stdin (0) file descriptor to PipeReader :: from_fd should work.



You can also look at ncurses (also at ) which will allow you to read in raw mode. There are several examples on the Github repository that show you how to do this.



All Articles