dalance / termbg

A Rust library for terminal background color detection
Apache License 2.0
87 stars 8 forks source link

Stdin is blocked on Windows #25

Open Etto48 opened 2 months ago

Etto48 commented 2 months ago

When using the library on Windows (both WindowsTerminal and VSCode integrated terminal) the program fails to detect the color and also blocks the Stdin until the next character is received. This is a significant problem when included in a TUI program because this behavior disables a lot of crossterm events. A possible workaround would be to identify the terminal as Windows instead of XtermCompatible when VSCode or WT are detected on Windows even if this could provide some wrong results. Another solution could be to mark the terminal as Unsupported and return an error. I can create a PR with one of these solutions if it's needed.

dalance commented 2 months ago

I had recognized unexpected char consuming of stdin, but I couldn't fix it. Now I found the way to use non-blocking stdin, and implemented it. Could you try non_blocking_stdin branch?

Etto48 commented 2 months ago

Thank you @dalance for looking into it! Unfortunately this does not compile on windows I think it's because you use some functions and modules that are exclusive to unix-like systems Here is the log


error[E0432]: unresolved import `std::os::fd`
   --> src\stdin.rs:7:9
    |
7   |     os::fd::{FromRawFd, RawFd},
    |         ^^ could not find `fd` in `os`
    |
note: found an item that was configured out
   --> C:\Users\the_E\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\os\mod.rs:164:9
    |
164 | pub mod fd;
    |         ^^

error[E0432]: unresolved import `tokio::io::unix`
   --> src\stdin.rs:11:17
    |
11  | use tokio::io::{unix::AsyncFd, AsyncRead, ReadBuf};
    |                 ^^^^ could not find `unix` in `io`
    |
note: found an item that was configured out
   --> C:\Users\the_E\.cargo\registry\src\index.crates.io-6f17d22bba15001f\tokio-1.39.3\src\io\mod.rs:246:13
    |
246 |     pub mod unix {
    |             ^^^^

error[E0432]: unresolved imports `libc::fcntl`, `libc::F_GETFL`, `libc::F_SETFL`, `libc::O_NONBLOCK`
  --> src\stdin.rs:15:16
   |
15 |     use libc::{fcntl, F_GETFL, F_SETFL, O_NONBLOCK};
   |                ^^^^^  ^^^^^^^  ^^^^^^^  ^^^^^^^^^^ no `O_NONBLOCK` in the root
   |                |      |        |
   |                |      |        no `F_SETFL` in the root
   |                |      no `F_GETFL` in the root
   |                no `fcntl` in the root

error[E0599]: no function or associated item named `from_raw_fd` found for struct `File` in the current scope
   --> src\stdin.rs:72:35
    |
72  |     let stdin_fd = unsafe { File::from_raw_fd(0) };
    |                                   ^^^^^^^^^^^ function or associated item not found in `File`
    |
note: if you're trying to build a new `File` consider using one of the following associated functions:
      File::open
      File::create
      File::create_new
   --> C:\Users\the_E\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\fs.rs:374:5  
    |
374 |     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
403 |     pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
437 |     pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: there is an associated function `from_raw_handle` with a similar name
    |
72  |     let stdin_fd = unsafe { File::from_raw_handle(0) };
    |                                   ~~~~~~~~~~~~~~~

warning: unused import: `Read`
 --> src\stdin.rs:6:16
  |
6 |     io::{self, Read},
  |                ^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

Some errors have detailed explanations: E0432, E0599.
For more information about an error, try `rustc --explain E0432`.
warning: `termbg` (lib) generated 1 warning
error: could not compile `termbg` (lib) due to 4 previous errors; 1 warning emitted```
dalance commented 2 months ago

OK. I'll investigate about Windows API for non-blocking stdin.

durbanlegend commented 3 weeks ago

For some reason I only found this issue after going down the Windows rabbit hole myself. I have been preparing a PR for this issue, with a non-blocking solution based on crossterm's event::read. I'm still trying to figure out an automated test for it, otherwise I'm ready to go. The PR is based on a customisation I did for my own project, so it contains a few other changes, including a scopeguard to ensure state is restored and additional comments further explaining the issues with Windows. It also replaces the use of async_std with a simple synchronous loop, as I didn't want to incorporate the 216kB async_std as a dependency and don't consider it necessary. You may or may not choose to accept all these changes, but crucially it does contain a version of fn from_xterm that fixes the problem in all the testing I've done. A piece of good news is that xterm is part of MS's strategic roadmap for Windows Terminal, and as of the currently available Windows Terminal (WT) 1.22 Preview, WT finally supports OSC10 and 11 colour queries, which up to now have not been part of its xterm compatibility. I've tested this too, and it works. Regards, Don