Intercept stdin to capture output from ANSI code

I am informed by this post: linux - How can I get position of cursor in terminal? - Stack Overflow

When I run print("\x1b[6n"), the current cursor position is written into stdin. However, the start is an escape sequence, and does not get captured. Furthermore, I want the output in a variable in a string, not as written text in the terminal.

I tried running stuff like

Base.redirect_stdin(()->print("\x1b[6n"), stdout)

, but I was unable to get the desired behaviour. The closest I could get was by running

julia> print("\x1b[6n"); readline()
^[[24;1R    # this is written from running the print command
"\e[24;1R"  # Pressing enter captures the input, and returnes this string

Is there a way to avoid this final step, of having to press enter? I am looking to use this in REPL.Terminals, where I want to implement getX, getY and pos for unix terminals, and I therefore need this to be non-interactive.

By default the terminal will wait for a newline before sending its input (see “canonical mode” in the termios manpage and libc manual). You can temporarily disable that and also disable echoing of the input by manipulating the terminal:

using REPL

function withrawterm(f)
    t = REPL.TerminalMenus.terminal
    REPL.Terminals.raw!(t, true)
    f()
    REPL.Terminals.raw!(t, false)
    return nothing
end

julia> withrawterm() do
           print("\x1b[6n")
           x = readavailable(stdin)
           println("Read: $x.")
       end
Read: UInt8[0x1b, 0x5b, 0x35, 0x32, 0x3b, 0x31, 0x52].

Maybe you can use REPL.Terminals.raw! for your purpose? Although it looks like currently it’s implemented through an external call to stty. Maybe it would be better to call directly into the C library, something like this:

using TERMIOS

function withrawterm(f)
    T = TERMIOS
    s = T.termios()
    T.tcgetattr(stdin, s)
    sraw = deepcopy(s)
    T.cfmakeraw(sraw)
    T.tcsetattr(stdin, T.TCSANOW, sraw)
    f()
    T.tcsetattr(stdin, T.TCSANOW, s)
end

(See here for the flags changed by cfmakeraw.)

2 Likes