I am playing with some terminal capabilities to create async prompt output on bash. I want to get something like this: while outputting string in PROMPT_COMMAND, save terminal cursor position, print put ... and go do other stuff (printing other info for example); then some time later go back to memorized position and print something new. PS1 is designed that way that command itself is put on newline, so that async output is just text in terminal.

I found out cup terminfo entry to move cursor to given position, an there are escape codes to get current position (for examble, see this question). But for me, seems like all of them work with cursor position on screen, rather than in terminal buffer. That means that after putting new line my remembered position will be wrong.

Are there any way to work with terminal cursor position to store and restore cursor position based on buffer position? You can assume that the remembered position is still in visible part of the buffer (so you actually can put cursor there), but it might go up several lines up. For now, let's not consider race conditions. If no, I will try to find other tricks.

There is zsh shell which actually has async prompt support, but I don't actually know will it work if before output user will press Enter to go to new line.

  • I saw this approach to async prompt, but my prompt output is 3 lines long, so no PS1... – Lapshin Dmitry Apr 25 '16 at 8:34

Most of the terminals you are likely to use implement escape sequences for saving and restoring the cursor position. Those are the sc (save cursor) and rc (restore cursor) capabilities in the terminal description, which you can use via tput (just like cup):

tput sc
tput cup 50 10
echo some stuff
echo more stuff
tput rc

However, if your program writes enough text to force scrolling, the restored position will still be on the same place on the terminal's screen. It does not move along with the scrolled text.

POSIX, by the way, documents only part of tput because the tool is actually part of another standard, X/Open Curses. That is summarized in the portability section of the manual page.

Back to the question: there are no escape sequences which track the buffer position (accounting for scrolling). To get that, your application would have to keep track of what was sent to the screen. Solving that sort of problem is what the curses library is for. In a plain command-line application, there is not much that you can do.

  • Too bad, I need to record position, then scroll for sure, then go back. Thanks for effort – Lapshin Dmitry Apr 25 '16 at 9:02
  • In nodeJS, github.com/sindresorhus/log-update library simulates that by actually counting emitted lines (accounting for line wrapping, discounting ansi color sequences), then using correct number of Erase Line sequences to go back and replace it. Could use similar code but move up instead of erasing. However, no such approach can work with race condition wrt. to user pressing <kbd>Enter</kbd>, unless managed by the shell/readline itself. – Beni Cherniavsky-Paskin Dec 3 '20 at 9:31
  • That's subject to the same limitation with respect to scrolling (would require the script to know where the cursor is, to use in that computation). – Thomas Dickey Dec 3 '20 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.