Is SU (ESC[<n>S) supposed to erase text? #21767

Closed
opened 2026-01-31 07:54:20 +00:00 by claunia · 9 comments
Owner

Originally created by @vefatica on GitHub (May 24, 2024).

I ultimately want to scroll so that the current command line is at the top of the viewport. I thought I could do that with some combination of SU and cursor placement. Not worrying about cursor placement, I noticed this.

Having just executed DIR I'm at the bottom (line 42) of the viewport.

image

If I issue echo ^e[37S 37 lines of the history (now out of the viewport) are erased. And it's NOT the last 37 lines that were erased! Here's the tail end of what's now in the history.

image

In contrast, if, in the same situation, I issue echo ^e[35S nothing is erased.

What's going on there? The docs don't mention SU erasing anything (especially in such an odd way). And it would be useful to scroll without losing any recent history.

Is there another strategy for scrolling, without losing anything, so the current command line is at the top.

Originally created by @vefatica on GitHub (May 24, 2024). I ultimately want to scroll so that the current command line is at the top of the viewport. I thought I could do that with some combination of SU and cursor placement. Not worrying about cursor placement, I noticed this. Having just executed DIR I'm at the bottom (line 42) of the viewport. ![image](https://github.com/microsoft/terminal/assets/61856645/485cc3f5-ea9c-437c-bd8f-aa16895640e5) If I issue `echo ^e[37S` 37 lines of the history (now out of the viewport) are erased. And it's **NOT** the last 37 lines that were erased! Here's the tail end of what's now in the history. ![image](https://github.com/microsoft/terminal/assets/61856645/5603c8fa-e213-4e82-b022-5cae1116ac29) In contrast, if, in the same situation, I issue `echo ^e[35S` nothing is erased. What's going on there? The docs don't mention SU erasing anything (especially in such an odd way). And it would be useful to scroll without losing any recent history. Is there another strategy for scrolling, without losing anything, so the current command line is at the top.
claunia added the Needs-TriageNeeds-Tag-Fix labels 2026-01-31 07:54:20 +00:00
Author
Owner

@j4james commented on GitHub (May 25, 2024):

What you're trying to do should ideally work, and we've already got an issue tracking that (#11078). But even if it were fixed on Windows Terminal, using SU this way is not generally reliable, so it's not something I would recommend.

Is there another strategy for scrolling, without losing anything, so the current command line is at the top.

The most reliable solution is just writing out a bunch of LF characters at the bottom of the screen.

@j4james commented on GitHub (May 25, 2024): What you're trying to do should ideally work, and we've already got an issue tracking that (#11078). But even if it were fixed on Windows Terminal, using `SU` this way is not generally reliable, so it's not something I would recommend. > Is there another strategy for scrolling, without losing anything, so the current command line is at the top. The most reliable solution is just writing out a bunch of `LF` characters at the bottom of the screen.
Author
Owner

@vefatica commented on GitHub (May 25, 2024):

I see. Thanks for the suggestion, @j4james. It works nicely. I should have thought of it. :-)

@vefatica commented on GitHub (May 25, 2024): I see. Thanks for the suggestion, @j4james. It works nicely. I should have thought of it. :-)
Author
Owner

@vefatica commented on GitHub (Mar 27, 2025):

@j4james:

The most reliable solution is just writing out a bunch of LF characters at the bottom of the screen.

That fails if you've set the scrolling region (DECSTBM) and the scrolling region doesn't include the bottom. Is there a way to get the scrolling region?

@vefatica commented on GitHub (Mar 27, 2025): @j4james: > The most reliable solution is just writing out a bunch of LF characters at the bottom of the screen. That fails if you've set the scrolling region (DECSTBM) and the scrolling region doesn't include the bottom. Is there a way to get the scrolling region?
Author
Owner

@j4james commented on GitHub (Mar 27, 2025):

If you've got a scrolling region, you've got to position the cursor on the last row of that region before writing out the LF characters. The area outside the scrolling region cannot be scrolled.

For example, something like this will scroll rows 1 to 10 up by 3 lines (this is a bash example):

printf "\e[1;10r\e[10H\n\n\n"

And note that the scrolled area will only be moved into the scrollback buffer if the scrolling region starts on line 1.

If you don't know the scrolling region, you can query it with a DECRQSS sequence, but that shouldn't be necessary if you just want to get to the last row. You can simply move to the top of the screen with absolute cursor positioning (i.e. \e[H), and then move down a large amount with relative cursor movement (i.e. something like \e[9999B). The relative movement will be clamped by the margin boundaries, so the cursor will be left on the bottom margin.

@j4james commented on GitHub (Mar 27, 2025): If you've got a scrolling region, you've got to position the cursor on the last row of that region before writing out the `LF` characters. The area outside the scrolling region cannot be scrolled. For example, something like this will scroll rows 1 to 10 up by 3 lines (this is a bash example): ```bash printf "\e[1;10r\e[10H\n\n\n" ``` And note that the scrolled area will only be moved into the scrollback buffer if the scrolling region starts on line 1. If you don't know the scrolling region, you can query it with a [`DECRQSS`](https://vt100.net/docs/vt510-rm/DECRQSS.html) sequence, but that shouldn't be necessary if you just want to get to the last row. You can simply move to the top of the screen with absolute cursor positioning (i.e. `\e[H`), and then move down a large amount with relative cursor movement (i.e. something like `\e[9999B`). The relative movement will be clamped by the margin boundaries, so the cursor will be left on the bottom margin.
Author
Owner

@vefatica commented on GitHub (Mar 27, 2025):

Can you show me exactly how to query the scrolling region with DECRQSS (i.e., what sequence to send). Stuff like this is gibberish to me.

Format
DCS
9/0 $
2/4 q
7/1 D . . . D
... ST
9/12

@vefatica commented on GitHub (Mar 27, 2025): Can you show me exactly how to query the scrolling region with DECRQSS (i.e., what sequence to send). Stuff like this is gibberish to me. Format DCS 9/0 $ 2/4 q 7/1 D . . . D ... ST 9/12
Author
Owner

@j4james commented on GitHub (Mar 27, 2025):

To query the DECSTBM state, the sequence you need to send is \eP$qr\e\\. The terminal will respond with a sequence looking something like \eP1$r1;24r\e\\, where 1 and 24 are the top and bottom rows of the margin area.

@j4james commented on GitHub (Mar 27, 2025): To query the `DECSTBM` state, the sequence you need to send is `\eP$qr\e\\`. The terminal will respond with a sequence looking something like `\eP1$r1;24r\e\\`, where 1 and 24 are the top and bottom rows of the margin area.
Author
Owner

@vefatica commented on GitHub (Mar 27, 2025):

What is it in C? L"\x1bP$qr\x1b\\" doesn't do it.

@vefatica commented on GitHub (Mar 27, 2025): What is it in C? `L"\x1bP$qr\x1b\\"` doesn't do it.
Author
Owner

@DHowett commented on GitHub (Mar 27, 2025):

@vefatica I know you're looking for the hardest possible solution to your problem, but... is there something wrong with the other suggestion to send the cursor home and then move it down by an arbitrary amount?

Every query you introduce between the client and the terminal adds--avoidable in this case!--latency.

@DHowett commented on GitHub (Mar 27, 2025): @vefatica I know you're looking for the hardest possible solution to your problem, but... is there something wrong with the other suggestion to send the cursor home and then move it down by an arbitrary amount? Every query you introduce between the client and the terminal adds--avoidable in this case!--latency.
Author
Owner

@vefatica commented on GitHub (Mar 27, 2025):

I got the C sequence working. I forgot that my shell monkeys with the console input mode. In CMD, a command line version works as advertized.

Image

All I wanted was to scroll to a clean viewport. Thanks to @j4james's original solution, that was easy as long as the scrolling region was the default. I'm not sure whether (or how) to make that work with a non-default scrolling region. I have the query working and I could also keep track of the scrolling region myself. I'll figure something out. Thanks for your help.

@vefatica commented on GitHub (Mar 27, 2025): I got the C sequence working. I forgot that my shell monkeys with the console input mode. In CMD, a command line version works as advertized. ![Image](https://github.com/user-attachments/assets/e6c236d5-600a-4d5b-bb33-8234475e1788) All I wanted was to scroll to a clean viewport. Thanks to @j4james's original solution, that was easy as long as the scrolling region was the default. I'm not sure whether (or how) to make that work with a non-default scrolling region. I have the query working and I could also keep track of the scrolling region myself. I'll figure something out. Thanks for your help.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21767