crossterm icon indicating copy to clipboard operation
crossterm copied to clipboard

Feature Request: A method for Unix systems to get the position of the cursor in stderr

Open Vonr opened this issue 3 years ago • 4 comments

Is your feature request related to a problem? Please describe. I am trying to create a simple command line utility to draw a box with contents and questions in it which the user can directly input into.

However, in an attempt to not let the box be redirected, I have decided to use eprintln!() to print out the box and its contents. This works fine when redirecting to some programs, such as cat, but on others, such as rev, crossterm::cursor::position() fails as the written characters used to find the cursor position are also redirected to the program.

This effectively renders my utility is unusable or extremely tedious to use for scripting.

Describe the solution you'd like I would like to be able to get the position of the cursor in stderr, currently I have implemented a hackfix in my fork of crossterm here where I changed line 32 of src/cursor/sys/unix.rs from

let mut stdout = io::stdout();

to

let mut stdout = io::stderr();

However, this is far from ideal as this breaks normal behavior and I am unable to come up with a solution that is cross-platform.

That said, I also have no intention of supporting Windows in my utility as I am deeply unfamiliar with their scripting.

Describe alternatives you've considered in any I have created a fork of crossterm for personal use with a hackfix and used it in my Cargo.toml as a temporary workaround until a proper solution is implemented or found.

Vonr avatar Apr 11 '22 00:04 Vonr

Hi I just stumbled on this accidentally while checking out reedline. I noticed two surprising things.

  1. reedline uses crossterm over stderr.
  2. reedline calls crossterm::cursor::position(), which fails if stdout is redirected to a file.

So programs using reedline can't have stdout go to a file even though most of the terminal stuff happens over stderr because crossterm::cursor::position() uses stdout.

Most of the crossterm API clearly intends to support stdout and stderr via the Write trait. The expectation that a user of crossterm using stderr should then also use crossterm::cursor::position() over stdout doesn't really make sense or seem to be coherent with the point of abstracting over Write everywhere else in the API. For that reason, I think this should be a bug, not a feature request.

sqwishy avatar Jun 01 '22 01:06 sqwishy

I created a fix here https://github.com/crossterm-rs/crossterm/compare/master...sigmaSd:cursor_pos_new?expand=1 and here https://github.com/crossterm-rs/crossterm-winapi/compare/master...sigmaSd:cursor_pos_new?expand=1

If someone can validate my assumptions and test it on linux and windows I can pr it

couple of points:

  • on windows you can't get a handle to random writer, so the api has to be a bit different
  • on windows there is no equivalent to CONOUT$ for stderr, so I just use STD_ERROR_HANDLE

sigmaSd avatar Jun 01 '22 06:06 sigmaSd

I think accepting any writer is unneeded, is there any use case other then stdout and stderr?

I probably should just unify the api to cursor::position_in_stderr()

sigmaSd avatar Jun 01 '22 14:06 sigmaSd

Sorry for not noticing this earlier, I was in the midst of switching email providers. I believe there may be some use in accepting a Writer in the form of writing to /dev/tty{,{0..63}} in order to write directly to a tty.

Vonr avatar Jun 01 '22 14:06 Vonr