How to Get Position of Cursor in Terminal

How to get the current text cursor position from Python in a Windows Terminal?

The problem was to locate the various Structure definitions. After having experimented significantly, I've got the following working solution.

#!/usr/bin/env python -u
# -*- coding: UTF-8 -*-
#------------------------------------------------------------------------------
from ctypes import windll, wintypes, Structure, c_short, c_ushort, byref, c_ulong
from readline import console

#------------------------------------------------
# Win32 API
#------------------------------------------------
SHORT = c_short
WORD = c_ushort
DWORD = c_ulong

STD_OUTPUT_HANDLE = DWORD(-11) # $CONOUT

# These are already defined, so no need to redefine.
COORD = wintypes._COORD
SMALL_RECT = wintypes.SMALL_RECT
CONSOLE_SCREEN_BUFFER_INFO = console.CONSOLE_SCREEN_BUFFER_INFO

#------------------------------------------------
# Main
#------------------------------------------------
wk32 = windll.kernel32

hSo = wk32.GetStdHandle(STD_OUTPUT_HANDLE)
GetCSBI = wk32.GetConsoleScreenBufferInfo

def cpos():
csbi = CONSOLE_SCREEN_BUFFER_INFO()
GetCSBI(hSo, byref(csbi))
xy = csbi.dwCursorPosition
return '({},{})'.format(xy.X,xy.Y)

cls='\x1b[H'
print('\n'*61)
print(cls+'12345', end='', flush=True); print(' {}'.format(cpos()), flush=True)

# 12345 (5,503)

Is there a way to get the mouse position within the terminal?

I have solved my problem.

To get events, the bash escape load ESC[?100Xh, replacing X with a number. The events will then be logged to the console.

How can I get the cursor's position in an ANSI terminal?

You can simply read sys.stdin yourself to get the value.
I found the answer in a question just like yours, but for one trying to do that from a C program:

http://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/

So, when I tried something along that from the Python interactive terminal:

>>> import sys
>>> sys.stdout.write("\x1b[6n");a=sys.stdin.read(10)
]^[[46;1R
>>>
>>> a
'\x1b[46;1R'
>>> sys.stdin.isatty()
True

You will have to use other ANSI tricks/position/reprint to avoid the output actually showing up on the terminal, and prevent blocking on stdin read - but I think it can be done with some trial and error.

get terminal cursor position

Have you tried getyx()?

Or, if you prefer legacy curses functions, getcurx() and getcury()?

Determine the terminal cursor position with an ANSI sequence in Python 3

Here is a POC snippet, how to read the current cursor position via an ansi/vt100 controll sequence.

curpos.py

import os, re, sys, termios, tty

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]))

if __name__ == "__main__":
print(getpos())

example output

$ python ./curpos.py
(2, 1)

warning

This is not perfect. To make it more robust, a routine which sorts out keystrokes from the user while reading from stdin would be nice.



Related Topics



Leave a reply



Submit