10

I am trying to write a console application in Python3.

The problem is I would like all output messages EG: print("Status message") to be above the input line at the bottom.

Status message 1
Status message 2
Status message 3
Console:> I want to type here while the output messages displayed

at the moment it looks more like this

Console:>  want to type here while the outStatus message 1
put messages displayed

Is there anyway to do this without using curses?

Sean Wilkinson
  • 111
  • 2
  • 7

2 Answers2

4

This can be done using ANSI escape sequences that provide in-band control of the console. This is how the curses library works on the backend.

This sequence should work for what you want, split apart for clarity:

print("\u001B[s", end="")     # Save current cursor position
print("\u001B[A", end="")     # Move cursor up one line
print("\u001B[999D", end="")  # Move cursor to beginning of line
print("\u001B[S", end="")     # Scroll up/pan window down 1 line
print("\u001B[L", end="")     # Insert new line
print(status_msg, end="")     # Print output status msg
print("\u001B[u", end="")     # Jump back to saved cursor position

Note this is not specific to python and works on most consoles.

References:

http://xn--rpa.cc/irl/term.html - Great for TUI programming without curses, includes info on using a separate buffer for vim like screen switching

https://invisible-island.net/xterm/ctlseqs/ctlseqs.html - Full ANSI escape standard, the Wikipedia one excludes critical sequences

  • Just in case it helps someone else: in my program on my system, using `print` with `end=""` was causing nothing to be printed. I fixed this by forcing print to flush the output by passing `flush=True`: `print(f"\u001B[s\u001B[A\u001B[999D\u001B[S\u001B[L{msg}\u001B[u", end="", flush=True)`. – Matthias Feb 09 '23 at 16:15
3

Try this:

print chr(27)+'[2AOutput'

Hope this is what you are asking for.

Sorry the above is for Python 2.7. I am not sure whether the Python 3 version

print(chr(27)+'[2AOutput')

will work or not.

Ref: http://en.wikipedia.org/wiki/ANSI_escape_code

FJDU
  • 1,425
  • 2
  • 15
  • 21
  • This would remove the functionality of having a backlog of the output. If you wish to keep that functionality you could do something like this: print('\e[A\e[kOutput\nCurrent state of the prompt', end='') `\e[A` moves the cursor to the last printed string (should be the `Console:>...`). `\e[k` clears the line and then replaces it with the new output and then reprint the `Console:>...` and get ready to recieve more values from the input. It's possible that the `\e[A` should be skipped. – Hobblin Jan 07 '14 at 15:13