terminal: `cls` in PowerShell and cmd.exe doesn't fully clear the Terminal scroll-back history

I feel like this problem should have been reported already, but I couldn’t find it in GitHub issue search.

Environment

Windows build number: Microsoft Windows [Version 10.0.18362.205] - Win10 ver. 1903 with Microsoft-internal test build for monthly quality update Windows Terminal version: 8dd2e795abb5ef7288ad8f08aece6ff581ec1609 - Azure DevOps CI build for AMD64

Steps to reproduce

  1. Start Terminal, with either a Command Prompt (cmd.exe) tab or a PowerShell tab.
  2. Run this command: type C:\Windows\System32\OEMDefaultAssociations.xml
  3. Observe a long XML file appear on screen.
  4. Run this command: cls

Expected behavior

The visible area of the window is cleared of everything except the cmd/PS prompt, and you can no longer scroll the window view to see any part of the file you displayed. This is what happens in the old console window (conhost.exe).

Actual behavior

The visible area is cleared, but the window scrollbar remains active. When you scroll up, you see that most of the file you displayed remains; only the end of the file is erased up to a length determined by your visible window height.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 27
  • Comments: 29 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@DHowett In the most recent update of the Terminal from the Store, it still doesn’t quite do the right thing - it clears the scrollback, but it doesn’t always seem to be clearing the screen. For example, try this in PowerShell:

ls c:\windows; echo "$([char]27)[3J"

and try scrolling up. Conversely, if you do cls, then the screen gets cleared, but not the scrollback:

ls c:\windows; cls"

What does work is combining them!

ls c:\windows; cls; echo "$([char]27)[3J"

Well, almost. For some reason, it doesn’t clear the last line of the scrollback. But this only happens if you do it all in one command - if you clear the screen separately, it does the right thing:

ls c:\windows
cls; echo "$([char]27)[3J"

After carefully reading the requisite behavior for this escape sequence, I believe this all is actually correct - Unix terminals behave the same, they don’t clear the scrollback for it.

However, there’s one other thing. I thought that cls issues the “Reset Device” VT100 escape sequence, ␛c. But this doesn’t seem to be the case - if I use that sequence manually, it is ignored altogether by Terminal - it doesn’t affect either the screen or the scrollback:

echo "$([char]27)c"

On the other hand, pretty much any Unix terminal I can test handles this by clearing everything. So I think the only real bug here is the handling of this one.

In the meantime, the workaround is to redefine the cls alias in PowerShell to be a combo of clear-host and the escape sequence.

Ahh, I must have mixed it up at some point! Thank you for clarifying.

Anyway, for anybody else who runs into this issue, here’s a workaround recipe for your Profile.ps1:

remove-alias cls
function cls {
    clear-host
    echo "$([char]27)[2J$([char]27)[3J"
}

Side note: I’m not sure I fully understand why this needs [2J in it. If it’s omitted, and you use it to prefix another command (i.e. cls; ls c:\windows), then this exhibits the aforementioned issue where the final line of scrollback remains, and can be seen if you scroll up. I would expect clear-host to fully clear the screen, and then [3J to fully clear scrollback, so [2J should be redundant?

🎉This issue was addressed in #5627, which has now been successfully released as Windows Terminal Release Candidate v0.11.1251.0 (1.0rc1).🎉

Handy links:

I am thankful to have stumbled upon this issue while looking for something else as I couldn’t quite figure out why prior history would come back after I would run a new command following a clear. Until now, I didn’t scroll up to notice the root of the problem.

I am using Version 0.7.3382.0 of Windows Terminal Preview where the published work-around has no effect.

I see the same issue in VSCode 1.40.2 using the Powershell Extension v2019.11.0, however I am happy to confirm that the given work-around achieves clearing the entire window buffer.

clear-host; echo "$([char]27)[2J$([char]27)[3J"

To make this work in my Microsoft.VSCode_profile.ps1 file I had to use the following. Note that rather than overwrite the existing alias, I just used ‘cl’ since it wasn’t an existing command on my machine.

function ClsWorkaround {
    clear-host
    Write-Output "$([char]27)[2J$([char]27)[3J"
}
Set-Alias -Name cl -Value ClsWorkaround -Scope "Local"

I am using the latest version (0.6.2951.0 ) of the terminal from the store and the workaround does not seem to work.

The command

echo "$([char]27)[3J"

seems to simply print an empty line. The full

echo "$([char]27)[2J$([char]27)[3J"

seems to act the same as

echo "$([char]27)[2J"

which just clears the visible part of the terminal and not the scrollback. And this acts weird with powershell, since it clears the screen, but if the the input cursor was at the bottom, after clearing the screen the cursor is at the bottom of the screen: grafik

Calling cls in cmd, or clear-host in powershell, or clear in bash on WLS will all simply clear the visible part of the terminal and not the scrollback. At least in powershell it does not have the weird behavior described above. Pressing Ctrl+L in powershell or bash will do the same.

To me it looks like there is currently no way to clean the scrollback.

So if this problem originates from the console app and not Terminal, what about PowerShell?

@mixmastamyk the actual issue tracking \e[3J not working in the Windows Terminal is #2715, which is still very open 😉

I’ll second @Boereck’s comment for the latest release (Version 0.7.3291.0). Nothing seems to clear the scrollback for me, from clear, printf "\e[3J", reset or tput reset under WSL (Ubuntu 18.04, with TERM variable is set to xterm-256color), cls under cmd.exe or echo "$([char]27)[3J" with Powershell.

(I just tested locally: Emitting CSI 3 J through conpty does work, and does clear the scrollback.)

Here’s the relevant pwsh issue: https://github.com/PowerShell/PowerShell/issues/8606

There’s also a related corefx issue for Console.Clear(): https://github.com/dotnet/corefx/issues/34463

However, it is not clear to me whether they’re taking the new terminal into account. Of note, the corefx issue relies on the ANSI escape sequence that, if supported, is meant to clear the entire buffer: ␛[3J However, it does not appear to be respected by the new terminal:

PS> python3 -c "print('\x1b[3J')"

PS>  

Thus, their fix will not work in this case. You need to implement it on your end, as well.

Furthermore, if you do implement it, then it will also provide an immediate workaround for users, since we can then create aliases that simply echo the above sequence (this is already common on Unix-likes, where most terminals do respect this sequence, but clear doesn’t use it).

@nelson6e65 Yes, but what are you using?

  • DOS/Windows cls traditionally cleared everything.
  • Unix clear traditionally scrolled to a new screen, in effect leaving scrollback. Think form-feed.
  • Recent clear on Linux defaults to clearing the scrollback also, but you can pass -x to avoid that.
  • cmd doesn’t support any other way, to my knowledge. All or nothing. This team has said they won’t add anything to it either. It’s done.
  • Maybe you could write your own utility to do it under cmd ?

However,

  • Unix shells support Ctrl-L (i.e. form-feed) for clearing just the current “screen.”
  • Powershell supports it too.
  • cmd doesn’t support it, but the yori shell does!
    I recommend it if you’d like a simple everyday but more modern DOS-like shell.

@nelson6e65 , I believe the terminal supports it, since it supports Unixy behavior. Sounds like it needs to be implemented in your shell. Perhaps make an alias that prints the ansi escapes to do the scroll yourself in the meantime.

as per bot, I just updated Terminal app from store. running cls cmd worked. also I’m not completely sure its the update or the fix mentioned by @jtbrower so far it works for me.

So I don’t believe this is something we can change about cmd.exe.

cls is a cmd-intrinsic, something that’s directly built into cmd.exe. It uses the Console API to clear the screen buffer. This works as expected in conhost, but it won’t in any conpty session. In conpty, the only part of the buffer that exists to the commandline application is the actual viewport. So when cls runs in conpty, it clears the entire viewport, but there’s no scrollback to clear, so that has no affect. Because there’s no way for conpty to magically figure out that the commandline application wanted the scrollback cleared as well, all conpty does in this case is render a “clear viewport” command to the terminal.

In a different world, we’d update cls to use VT to clear the buffer instead of the API. Then, cls would specifically tell conpty that it wants both the viewport and the scrollback cleared. Because the “clear scrollback” VT sequence doesn’t really do anything in conpty mode, we forward it to the terminal. In that world, cls would work exactly as it does in conhost.

Unfortunately, we don’t live in that world. We live in the universe where cmd.exe is parked indefinitely, and we can’t make any changes to it. 100% of the time we think we have a trivial change we could make to cmd.exe, it results in a nightmare of back-compat bugs (for whatever reason). So while this does have a technically feasible solution, it has a bureaucratically impossible solution.