title: How to get the current text cursor position from Python in a Windows Terminal?
body: <p>Getting the current mouse pointer position in Python is trivial, through the use of the Windows API <code>ctypes</code> libraries. However, it seem that taking the step from the mouse pointer's screen position position <em>(x,y)</em>, to get the current <em>text cursor</em> position of the current terminal window, seem a huge difficulty.</p>
  <p>In addition it makes it worse that the programmer community keep confusing mouse <em>pointer</em> position with text <em>cursor</em> position. <a href="https://en.wikipedia.org/wiki/Cursor_(user_interface)" rel="nofollow noreferrer">Historically</a> there never was a mouse <em>&quot;cursor&quot;</em> so when people are saying &quot;cursor&quot;, they <em>should</em> mean text cursor, and not the other way around. Because of this error, Stackoverflow is full of questions and answers, relating to &quot;cursor&quot;, but seemingly none relates to getting the terminal shell's current <em>character position</em>. [The cursed cursor!]</p>
  <p>To get the relative <em>mouse pointer position</em>:</p>
  <pre class="lang-py prettyprint-override"><code>from ctypes import windll, wintypes, byref
  def get_cursor_pos():
      cursor = wintypes.POINT()
      windll.user32.GetCursorPos(byref(cursor))
      return (cursor.x, cursor.y)
  
  while(1): print('{}\t\t\r'.format(get_cursor_pos()), end='')
  </code></pre>
  <p>I want to have a function that give me the last position in terms of <strong>character</strong> <em>row</em>
  and <em>column</em>. Perhaps something like this:</p>
  <pre class="lang-py prettyprint-override"><code>def cpos(): 
      xy = here_be_magic()
      return xy
  
  # Clear screen and start from top:
  print('\x1b[H', end=''); 
  print('12345', end='', flush=True); xy=cpos(); print('( {},{})'.format(xy[0],xy[1]),end='', flush=True)
  
  # 12345 (1,5)  # written on top of blank screen
  </code></pre>
  <p><strong>How do I get the <code>text</code> cursor position in (<em>row,column</em>) inside my terminal?</strong><br />
  <sub>(And without making any assumptions and having to write my own window manager?)</sub></p>
  <p>Ultimately I hope to use this to find the last cursor position in any terminal window, (and possibly used by any program?)</p>
  <hr />
  <p>Possibly related (but not useful) SO Questions:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/13427754/get-current-key-cursors-position-text">get current key cursors position text</a> [C#]</li>
  <li><a href="https://stackoverflow.com/questions/3698635/how-to-get-the-text-cursor-position-in-windows">How to get the text cursor position in Windows?</a> [mouse?]</li>
  <li><a href="https://stackoverflow.com/questions/60018367/how-to-get-the-current-cursor-position-in-python-readline">How to get the current cursor position in python readline</a> [mouse?]</li>
  <li><a href="https://stackoverflow.com/questions/48302647/how-to-change-cursor-position-in-powershell-console">How to change cursor position in powershell console</a></li>
  <li><a href="https://stackoverflow.com/questions/30324758/python-ctypes-pass-double-pointer-by-reference">python ctypes, pass double pointer by reference</a></li>
  <li><a href="https://stackoverflow.com/questions/4213095/python-and-ctypes-how-to-correctly-pass-pointer-to-pointer-into-dll">Python and ctypes: how to correctly pass &quot;pointer-to-pointer&quot; into DLL?</a></li>
  </ul>
  <hr />
  <p><strong>UPDATE</strong> (2022-01-17)</p>
  <p>Looking through the MS documentation, I am now convinced it should be possible to get this from the (older, non-VT-based) API call, <a href="https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo" rel="nofollow noreferrer"><code>GetConsoleScreenBufferInfo</code></a> which is given like this.</p>
  <pre><code>BOOL WINAPI GetConsoleScreenBufferInfo(
    _In_  HANDLE                      hConsoleOutput,            # A handle to the console screen buffer. The handle must have the GENERIC_READ access right. 
    _Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo  # A pointer to a CONSOLE_SCREEN_BUFFER_INFO structure that receives the console screen buffer information.
  );
  
  typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
    COORD      dwSize;                # contains the size of the console screen buffer, in character columns and rows.
    COORD      dwCursorPosition;      # contains the column and row coordinates of the cursor in the console screen buffer.
    WORD       wAttributes;           # Character attributes (divided into two classes: color and DBCS)
    SMALL_RECT srWindow;              # A SMALL_RECT structure that contains the console screen buffer coordinates of the upper-left and lower-right corners of the display window.
    COORD      dwMaximumWindowSize;   # A COORD structure that contains the maximum size of the console window, in character columns and rows, given the current screen buffer size and font and the screen size.
  } CONSOLE_SCREEN_BUFFER_INFO;       # 
  
  # Defines the coordinates of a character cell in a console screen buffer. 
  # The origin of the coordinate system (0,0) is at the top, left cell of the buffer.
  
  typedef struct _COORD {
    SHORT X;              # The horizontal coordinate or column value. The units depend on the function call.
    SHORT Y;              # The vertical coordinate or row value. The units depend on the function call.
  } COORD, *PCOORD;
  
  
  typedef struct _SMALL_RECT {
    SHORT Left;
    SHORT Top;
    SHORT Right;
    SHORT Bottom;
  } SMALL_RECT;
  </code></pre>
  <p>So in light of this, I was thinking the following would work.</p>
  <pre class="lang-py prettyprint-override"><code>cls='\x1b[H'
  from ctypes import windll, wintypes, byref
  def cpos():
      cursor = wintypes._COORD(ctypes.c_short)
      windll.kernel32.GetConsoleScreenBufferInfo(byref(cursor))
      return (cursor.X, cursor.Y)
  
  cpos()
  
  # TypeError: '_ctypes.PyCSimpleType' object cannot be interpreted as an integer
  </code></pre>