crossterm
crossterm copied to clipboard
Always read user input from /dev/tty
Is your feature request related to a problem? Please describe. I'm trying to port my CLI util skim to crossterm for windows support. And one of the use cases of skim is to accept piped input:
echo "input" | sk
In this case the stdin
do not generate user inputs while I still hope the user inputs are handled correctly.
Describe the solution you'd like
When creating file descriptor, use /dev/tty
all the time.
We already use /dev/tty, this one is not supported for windows of course. There we use winapi. Crossterm can be used through a pipe, please see this example for a demo.
@TimonPost Not sure if I understand correctly. I believe the example shows how to write to stderr
instead of stdout
. While I am trying to do is to read piped input(stdin).
For example, expecting the following example to work:
$ echo "abc"| cargo run --example event-read
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/examples/event-read`
Blocking read()
- Keyboard, mouse and terminal resize events enabled
- Hit "c" to print current cursor position
- Use Esc to quit
Error: IoError(Os { code: 25, kind: Other, message: "Inappropriate ioctl for device" })
I've tried to always use /dev/tty here:
/// Creates a file descriptor pointing to the standard input or `/dev/tty`.
pub fn tty_fd() -> Result<FileDesc> {
let (fd, close_on_drop) = (
fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/tty")?
.into_raw_fd(),
true,
);
Ok(FileDesc::new(fd, close_on_drop))
}
But doesn't seem to fix the issue. Any idea why it might not detect an IOCTL device while using a pipe ?
In fact, this resulted in an error for ITerm terminals. #404. On Linux, it seems to behave just fine, but on macos no input can be read anymore.
@TimonPost Just to make sure, were tcgetattr
and tcsetattr
operated on /dev/tty
as well?
(Disclaimer: I haven't checked the solution)
- https://github.com/crossterm-rs/crossterm/blob/master/src/terminal/sys/unix.rs#L121
- https://github.com/crossterm-rs/crossterm/blob/master/src/terminal/sys/unix.rs#L127
Ah, no they did not, I will open a branch with those changes. If someone can validate the working on mac os we can merge it.
@TimonPost I can test it on Mac, let me know
Can someone try this branch on mac os: https://github.com/crossterm-rs/crossterm/pull/407
@TimonPost - I can give it a try. Is there something in particular that needs testing?
You could run the interactive example in the examples folder. And in there run the input demo. It should work. Though on the PR #407 and #406 there are people who did the testing already. They reported invalid input. I left a comment with some ideas on there.
@TimonPost I noticed with the latest master that #406 is fixed but I do still see the issue that @lotabout mentions in the comment above:
% echo "abc" | cargo run --example event-read
Compiling crossterm v0.17.3 (/Users/test/Source/crossterm)
Finished dev [unoptimized + debuginfo] target(s) in 3.42s
Running `target/debug/examples/event-read`
Blocking read()
- Keyboard, mouse and terminal resize events enabled
- Hit "c" to print current cursor position
- Use Esc to quit
Error: IoError(Os { code: 25, kind: Other, message: "Inappropriate ioctl for device" })
Yea, there is someplace some argument is given, I supposed to libc, which is invalid. I haven't found that place yet. Regarding @Iotabout his comment, his ideas are implemented by this PR.
I ran into this issue in the tab terminal multiplexer. I was trying to add support for stdin input in a raw mode app:
echo query | tab
I hit the same error as described above.