console-rs / console

A rust console and terminal abstraction
MIT License
961 stars 113 forks source link

How can I get the cursor position #201

Open ShadowySpirits opened 10 months ago

ShadowySpirits commented 10 months ago

I found issue #38, but it only adds the function to move the cursor. Could someone help me with this?

Joedang commented 5 months ago

Well, I have a partial solution. Maybe someone who's more familiar with this library can get it across the finish line.

Partial solution

use console::Term;

fn main() {
    let term = Term::stdout();
    print!("\nsome filler text... please hit enter \x1b[6n");
    let response = term.read_line().expect("failed to read response");
    assert_eq!(response, ";38R"); // should be something like "\x1b[10;38R"
                                  // not sure why row info is being cut off

    term.clear_screen().expect("failed to clear screen");
    print!("\nsome filler text... please hit enter \x1b[6n");
    let response = term.read_line().expect("failed to read response");
    assert_eq!(response, "38R"); // not sure why clearing the screen matters
}

Explanation

Printing the escape sequence \x1b[6n requests the cursor position, and the terminal should respond by writing \x1b[Y;XR, where Y and X are the row and column.

As stated in man 4 console_codes:

ESC [ 6 n
       Cursor position report (CPR): Answer is ESC [ y ; x R, where x,y is the cursor location.

So, I would expect my partial solution to get a response like \x1b[10;38R. (Of course, the row would depend on the cursor position when print!() was called.) The row info is getting cut off and I'm not sure why. It also cuts off the ; if the screen is cleared before-hand, which is very confusing. (I tried throwing in some calls to term.flush(), figuring there was some race-condition going on between the terminal and the Rust program, but it didn't make a difference.)

nicolasbauw commented 2 months ago

I'd love to see a Term method like pub fn get_cursor_pos(&self) -> (u16, u16)