1

How do I save the cursor position into a variable in TCL ?

The best I can come up with is:

set tty [open /dev/tty w]
puts $tty "\033\[6n"
close $tty

set position [read stdin]
puts $position

but I cannot capture the output.

I have also tried using ::term::ansi::send::qcp from Tcllib but get the same problem.

(FYI I tried to model the above TCL on a PHP answer from How to get cursor position with PHP-CLI?).

mvanle
  • 1,847
  • 23
  • 19

1 Answers1

1

It's tricky to get this right, as we need to read a partial line and it's not yielded by the terminal implementation immediately. After experimenting a bit, the most reliable approach that I found was this:

proc readbits {{chan stdin}} {
    set s ""
    while {![eof $chan]} {
        set c [read $chan 1]
        append s $c
        if {$c eq "R"} break
    }
    return $s
}

proc getcur {} {
    puts -nonewline "\u001b\[6n"
    flush stdout
    scan [readbits] "\u001b\[%d;%dR"
}

# Must be in raw+noecho mode for this to work!
exec stty raw -echo
puts [getcur]
# Restore normal mode
exec stty -raw echo

In Tcl 8.7, you can use: fconfigure stdin -mode raw and fconfigure stdin -mode normal in place of those exec stty calls.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • The escape sequence to request the information was from https://stackoverflow.com/questions/34746634/termcaps-get-cursor-position and I've tested this on macOS, but it should also work on Linux and other POSIX. – Donal Fellows Aug 23 '21 at 14:31