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

fix: fall back to /dev/tty when stdin/stdin is not a tty #957

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aschey
Copy link
Contributor

@aschey aschey commented Dec 15, 2024

Resolves #919
Resolves #396
Supersedes #743

Previous attempts to read from /dev/tty had issues because of problems with polling /dev/tty on MacOS. This has been solved for a while with the use-dev-tty feature, so now it should be safe to fall back to using /dev/tty if stdin/stdout is not a terminal everywhere except for the mio event reader on MacOS.

This PR standardizes the use of /dev/tty for both input and output by splitting the tty_fd function into tty_fd_in and tty_fd_out so both can handle the appropriate fallback logic for stdin and stdout respectively. The only place that needs special care is the MacOS event reader when use-dev-tty is not enabled.

The mio event reader for MacOS has been modified to return an explicit error message when used with piped input to inform users that use-dev-tty is required for such use cases. The error message was previously getting swallowed, but will now be returned to the caller.

Finally, the logic to read the cursor position was always writing to stdout, causing an error when stdout was not a tty. This has been changed to use the new tty_fd_out function.

This was tested on Mac, Linux, and WSL. Windows should be unaffected.

@aschey aschey requested a review from TimonPost as a code owner December 15, 2024 23:57
@aschey aschey changed the title fix: standardize usage of /dev/tty everywhere fix: standardize usage of /dev/tty where possible Dec 16, 2024
@LoricAndre
Copy link

This might fix an issue I have in skim-rs/skim#653
Any idea when it could be merged ?

@aschey
Copy link
Contributor Author

aschey commented Feb 5, 2025

Hey @LoricAndre, I'm not sure when this will be reviewed. If you want to give this branch a try, it would be helpful to see if it does fix your issue since the original problem that skim was facing (#396) is one of the main reasons I made this change.

@joshka
Copy link
Collaborator

joshka commented Feb 5, 2025

Changing from processing input from stdin to always using dev/tty seems like it would fundamentally change the behavior of apps. I'm not certain that this is desired in all cases. Can you talk a bit about the impact of the change and perhaps discuss where this might not be desired? A good way to think about this is put yourself in the perspective of an app developer who sees this change. What does it mean for their app? What does it mean if they hit a problem caused by this change?

@aschey
Copy link
Contributor Author

aschey commented Feb 5, 2025

Input processing currently uses the tty_fd method which only reads from stdin if it's a tty anyway, so it shouldn't have any noticeable effects.

The only scenario I can think of where explicitly reading from stdin instead of /dev/tty would be preferred is if you wanted to pipe some data into your app and have it parsed as input sequences, which seems odd.

It wouldn't be too difficult to have another method or some conditional logic that prefers stdin over /dev/tty that we only use for input reading, I just couldn't think of a good reason for it. If someone knows of a scenario where this can be problematic then I'm happy to change it.

@joshka
Copy link
Collaborator

joshka commented Feb 5, 2025

My question is not so much about whether the use case is rational, but more about whether by choosing this approach is a one way door. I.e. this change makes it impossible to use stdin instead of tty as the input. An example of where you might want to do this is nesting an inner TUI app inside an outer one and using the stdin / out as the means to control the inner tty from the outer.

@aschey
Copy link
Contributor Author

aschey commented Feb 5, 2025

An example of where you might want to do this is nesting an inner TUI app inside an outer one and using the stdin / out as the means to control the inner tty from the outer.

Fair point. I suppose it doesn't hurt to prefer using stdin/stdout if isatty is true. I'll refactor the tty_fd_in and tty_fd_out methods to work that way and test it out.

@aschey aschey changed the title fix: standardize usage of /dev/tty where possible fix: fall back to /dev/tty when isatty is false Feb 5, 2025
@aschey aschey changed the title fix: fall back to /dev/tty when isatty is false fix: fall back to /dev/tty when stdin/stdin is not a tty Feb 5, 2025
@aschey aschey force-pushed the fix/use-tty branch 2 times, most recently from 4e9fd94 to 74f0826 Compare February 5, 2025 04:23
@aschey
Copy link
Contributor Author

aschey commented Feb 5, 2025

Actually, I don't think it matters here. If you're piping input from a parent process, isatty will be false anyway, so there isn't a good way to determine this automatically. There have been requests to allow customizing the input source (#728, #941) which is probably the way to deal with these kinds of corner cases. That's out of scope for this fix though I think.

@LoricAndre
Copy link

@aschey I can confirm this fixes the issue I'm having (which is somewhat similar to #396, I am rewriting skim to use ratatui and I'm having issue with the zsh widgets.

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

Successfully merging this pull request may close these issues.

cursor::position() fails when piping stdout Always read user input from /dev/tty
3 participants