4

Saving and restoring the cursor position should be possible with simple ANSI escape sequences

ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:

  • [...]
  • Save cursor position: \033[s
  • Restore cursor position: \033[u

Source: Bash Prompt HOWTO: Cursor movement

However, it seems that this ANSI sequences restore only the horizontal position of the cursor. For example:

$ printf 'Doing some task...\e[s\n\nMore text\n\e[udone!\n\n\n'
Doing some task...

More text
                  done!


$

where the done! is horizontally at the correct position but not vertically (correct in the sense of restored).

  1. Am I missing something, i.e. can you reproduce this?!
  2. Is this the intended desired behaviour? If so, how would I get the done! printed after the task...?
  3. If this should not happen, might this behaviour be triggered indirectly by something in my environment?

I searched and read the many questions about, but I did not find anything about this behaviour I experienced. Actually, the same occur with tput via

$ printf 'Doing some task...'; tput sc; printf '\n\nMore text\n'; tput rc; printf 'done!\n\n\n'
6

2 Answers 2

7

Am I missing something, i.e. can you reproduce this?!

I can, if I'm at the bottom of the terminal and the next line makes the content move up. But repeat the test in a terminal that doesn't scroll in the meantime. Hit Ctrl+L (or invoke clear) and start from the top. Then it behaves as you wish.

Is this the intended desired behaviour?

I think so. Cursor position is relative to the screen, not to its content.

How would I get the done! printed after the task...?

Possible approach: If you know you're going to print no more than 6 lines and the terminal is big enough, print 6 empty lines first so it scrolls first, then move the cursor up and only then print the meaningful text:

printf '\n\n\n\n\n\n'; printf '\033[6A'; printf 'Doing some task...\e[s\n\nMore text\n\e[udone!\n\n\n'

I used three separate printfs to show the logic, but it could be one.

1
  • Nice catch with the scrolling down of the terminal, I had not thought about that. If this is an intended behaviour, and what you write makes sense, then your idea to avoid the scrolling down is easy and smart. Commented Feb 4, 2020 at 9:53
-1

Works for me. I prefer to use the terminfo database (man 5 terminfo) rather than hardcode escape sequences.

sc=$(tput sc) rc=$(tput rc) el=$(tput el)
clear; printf 'Doing some task...%s\n' "$sc"; sleep 1; printf '%sDONE%s\n' "$rc" "$el"

You can also move the cursor to an absolute position ({0,0} is top left), in case that's a better option than saving/restoring the current cursor position.

tput cup 4 40; sleep 1; printf "%s\n" 'This is row 4 column 40'
4
  • Doesn't work. The same issue if a terminal scrolled.
    – Artfaith
    Commented Feb 28, 2021 at 8:24
  • 1
    @F8ER this answer, like all the others, saves an absolute position on the screen. The absolute position doesn't change just because the text scrolled. Commented Feb 28, 2021 at 8:44
  • Of course, and that's why -1, sorry. This particular answer doesn't include anything explaining it and doesn't resolve the issue of the question.
    – Artfaith
    Commented Feb 28, 2021 at 8:56
  • Look at the edit histories. This answer offers clean terminfo rather then messy escape sequences. Both answers address the question, which (still) doesn't mention anything about tracking a position relative to scrolled text Commented Feb 28, 2021 at 9:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .