1

I'm writing an interactive bash script, which needs to keep editing its own output. For the sake of example let's say it looks like this:

tput sc     # Store the cursor position.

while true; do
    tput rc # Restore the cursor position.
    tput ed # Delete everything from cursor position to the end.
    seq 10  # Output whatever.
    sleep 1 # Repeat after some time.
done

I expect to only ever see the output of seq 10 once on my screen, constantly being erased and re-written. If I run this on a fresh terminal, it works. But if my terminal already has enough output in it from previous commands for the scrollbar to appear, it does not work. I just get the output of seq 10 multiple times on my screen, as if my loop was just:

while true; do
    seq 10
    sleep 1
done

This happens in both Windows Terminal and MinTTY. Anything I can do? Thanks.

EDIT: Here is the output of stty -a:

speed 38400 baud; rows 43; columns 171; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = ^Z; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -tostop echoctl echoke -flusho
Verpous
  • 588
  • 3
  • 7
  • @Philippe I don't want to delete all prior output in the terminal, and this doesn't work anyway if my own command outputs more than the terminal height can hold (which it might) – Verpous Jun 03 '23 at 20:06
  • 1
    Instead of clearing the terminal permanently, would it be ok to switch to an *alternate screen buffer* (output from previous programs is hidden while your program runs and restored later) like `less`, `nano`, `htop`, ... do? See [How to save/restore terminal output](https://unix.stackexchange.com/q/243237/187122) for more information. – Socowi Jun 03 '23 at 20:36
  • @Socowi Looks interesting, I will have to do some research on this one. – Verpous Jun 03 '23 at 22:42
  • Edit your Q to show output of `stty` . I may help a guru spot your problem. Good luck. – shellter Jun 04 '23 at 04:51
  • I don't know.. have you tried different terminals, with different TERM settings? xterm, ansi etc ? Maybe it's a bug in that terminal. – xpusostomos Jun 04 '23 at 06:29
  • it scrools because you command outputs too much. if it does not scroll, your output will not be fully visible. how many lines of output in your real usecase? – pynexj Jun 04 '23 at 07:47
  • @shellter Done. – Verpous Jun 04 '23 at 08:11
  • @pynexj It forwards input from stdin so there's no limit. – Verpous Jun 04 '23 at 08:15
  • Consider just `watch n1 seq 10`. `tput sc # Store the cursor position.` were was the cursor position when you started? On top? If your cursor position is on the last line, then you are jumping to the last line. – KamilCuk Jun 04 '23 at 08:23
  • @KamilCuk I didn't touch it so I assume it was where the command was called. – Verpous Jun 04 '23 at 08:24
  • I do not understand. Please post for example a GIF of example execution of the command. If the cursor at the time of execution `tput sc` is on the last line of the screen, you are clearing only the last line of the screen, effectively nothing. Command works fine with `clear` before `tput sc` for me. Please post the output of `(tput ed; tput rc; tput sc) | hexdump -C`. – KamilCuk Jun 04 '23 at 08:25
  • 1
    Try this: `clear;for ((i=LINES;--i;)){ printf '\e[%dHStart at %d from bottom: ' $((LINES-i)) $i;tput sc;for l in {1..3}; do tput -S - <<< $'rc\ned';seq -f $l-%g 1 10;sleep .5;done;}` – F. Hauri - Give Up GitHub Jun 04 '23 at 16:52

1 Answers1

1

You can save screen with smcup and restore with rmcup :

#!/usr/bin/env bash

tput smcup
clear
tput sc     # Store the cursor position.

for c in {1..10} ; do
    tput rc # Restore the cursor position.
    tput ed # Delete everything from cursor position to the end.
    date
    seq 10  # Output whatever.
    sleep 1 # Repeat after some time.
done

tput rmcup
Philippe
  • 20,025
  • 2
  • 23
  • 32
  • This isn't perfect, the scrollbar feature disappears completely from the terminal when using smcup, which means my script won't be allowed to output more than what can fit in the window. But I've researched all my options and I think this is the best solution available. I'll use this, thanks. – Verpous Jun 04 '23 at 19:41