Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3: Capture return of `\x1b[6n` (`\033[6n`, `\e[6n`) ansi sequence

Im writing a "libansi". I want to capture the return code of the ansi sequence \x1b[6n I tried some work-around but nothing to do.

exemple :

#!/usr/bin/python3.4
rep = os.popen("""a=$(echo "\033[6n") && echo $a""").read()

rep return "\033[6n"...

Anyone have an idea ?

Thanks for help.

Edit : I have a partial solution :

a=input(print("\033[6n", end='')

But this need that i press 'enter' on input to get cursor position.

like image 635
Daudré-Vignier Charles Avatar asked Oct 22 '25 04:10

Daudré-Vignier Charles


1 Answers

The problem is

  1. that by default stdin is buffered and
  2. after writing the sequence to stdout, the terminal will sent it's response to stdin, rather then to stdout. So the terminal act like pressing the actual keys without a return.

The trick is to use tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW) and before that store the terminal attributes via termios.getattr in variable to restore the default behavior. With cbreak set, os.read(sys.stdin.fileno(), 1) you can read from stdin immediately. This also suppress the ansi controll code response from the terminal.

def getpos():

    buf = ""
    stdin = sys.stdin.fileno()
    tattr = termios.tcgetattr(stdin)

    try:
        tty.setcbreak(stdin, termios.TCSANOW)
        sys.stdout.write("\x1b[6n")
        sys.stdout.flush()

        while True:
            buf += sys.stdin.read(1)
            if buf[-1] == "R":
                break

    finally:
        termios.tcsetattr(stdin, termios.TCSANOW, tattr)

    # reading the actual values, but what if a keystroke appears while reading
    # from stdin? As dirty work around, getpos() returns if this fails: None
    try:
        matches = re.match(r"^\x1b\[(\d*);(\d*)R", buf)
        groups = matches.groups()
    except AttributeError:
        return None

    return (int(groups[0]), int(groups[1]))
like image 182
netzego Avatar answered Oct 23 '25 19:10

netzego



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!