Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cls in PowerShell and cmd.exe doesn't fully clear the Terminal scroll-back history #1305

Closed
metathinker opened this issue Jun 18, 2019 · 29 comments · Fixed by #5627
Closed
Labels
Issue-Question For questions or discussion Needs-Tag-Fix Doesn't match tag requirements Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe. Resolution-Answered Related to questions that have been answered Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.

Comments

@metathinker
Copy link
Contributor

metathinker commented Jun 18, 2019

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: 8dd2e79 - 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.

@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jun 18, 2019
@zadjii-msft
Copy link
Member

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.

@zadjii-msft zadjii-msft added Issue-Question For questions or discussion Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe. Resolution-Answered Related to questions that have been answered labels Jun 18, 2019
@metathinker
Copy link
Contributor Author

metathinker commented Jun 18, 2019

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

@zadjii-msft
Copy link
Member

That's a good question. I'd imagine that they're in the same situation as cmd.exe probably. I don't know the most about powershell core, but perhaps they could take the opportunity to update their cls command to use VT on both Windows and *nix.

@int19h
Copy link

int19h commented Jul 20, 2019

@zadjii-msft
Could you then provide some shortcut that would have the same effect that cls used to have? E.g. since Ctrl+L is basically the same (clear visible screen), how about something like Ctrl+Shift+L to clear the entire buffer?

Also, while this applies to cmd.exe, in PowerShell, cls is just an alias for Clear-Host, so they should be able to update it. But does Terminal provide a way for them to clear the entire buffer?

@int19h
Copy link

int19h commented Jul 20, 2019

Here's the relevant pwsh issue:
PowerShell/PowerShell#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).

@int19h
Copy link

int19h commented Jul 20, 2019

Also possibly related to #1193

@JeremyTBradshaw
Copy link

Add me to the list that has this issue. I don't think PowerShell 5.1 or CMD.exe are going to get updated to make Windows Terminal able to do clear host. Wouldn't this tool that is still in Preview be the candidate to band-aid these also-Microsoft-owned unlikely-going-to-change apps (i.e. PowerShell 5.1 and cmd.exe .)

@DHowett-MSFT
Copy link
Contributor

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

@metathinker
Copy link
Contributor Author

metathinker commented Aug 8, 2019

CSI 3 J (escape [ 3 J / \x1B[3J]) does clear the terminal scrollback, but there is some inconsistency about whether it also clears what is already visible. (xterm and WinTerm do not clear the visible area, but the Linux built-in console is documented to do so.) You have to also issue CSI 2 J to ensure that the visible area is also cleared.

Coming back to this issue @int19h @JeremyTBradshaw - if it's really impossible to solve this problem without changing cmd.exe (and having just looked at the cmd.exe cls command sources, I'm convinced that that is true), I'm not sure there's anything to be done under this issue. However, implementing screen and scrollback clearing at the WinTerm level (issue #1882) is a promising workaround...

@int19h
Copy link

int19h commented Aug 8, 2019

@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.

@int19h
Copy link

int19h commented Aug 8, 2019

Note that the above was about PowerShell tho, where cls is an alias for Clear-Host. I'm not sure what exactly this translates to in the end when it gets to the Terminal - and it's probably different from cmd.exe cls built-in. And unlike PowerShell, you can't override that with an alias.

But most people probably care more about PowerShell at this point, and cmd.exe users can always define an alternate command (as a batch file), and use that.

@DHowett-MSFT
Copy link
Contributor

\ec is #2307; \e[3J not clearing the screen is, as you noted, by design. \e[2J is required to clear the screen.

CSI Ps J  Erase in Display (ED), VT100.
            Ps = 0  -> Erase Below (default).
            Ps = 1  -> Erase Above.
            Ps = 2  -> Erase All.
            Ps = 3  -> Erase Saved Lines (xterm).

@int19h
Copy link

int19h commented Aug 8, 2019

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?

@Boereck
Copy link

Boereck commented Nov 18, 2019

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.

@studoot
Copy link

studoot commented Nov 29, 2019

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.

@jtbrower
Copy link

jtbrower commented Dec 7, 2019

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"

@shrinktofit
Copy link

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

Does not work.

@zadjii-msft
Copy link
Member

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

@jgarza9788
Copy link

yup, this is still an issue

@Halkcyon
Copy link

@jgarza9788 The PR was just merged into the preview build today, so hopefully a release is coming up soon that actually fixes this issue.

@metathinker metathinker changed the title Terminal bug report: cls in PowerShell and cmd.exe doesn't fully clear the history cls in PowerShell and cmd.exe doesn't fully clear the Terminal scroll-back history Apr 29, 2020
@metathinker
Copy link
Contributor Author

metathinker commented Apr 29, 2020

PR #5627 might suffice to fix the problem with an app compat hack within Terminal (well, within Terminal's headless private conhost.exe), without having to go back and change cmd.exe or Windows' in-box PowerShell to issue the correct VT clear screen sequences that we've discussed further up in this thread.

@ghost ghost added the In-PR This issue has a related PR label Apr 29, 2020
ghost pushed a commit that referenced this issue Apr 30, 2020
## Summary of the Pull Request

This PR implements a pair of shims for `cmd` and `powershell`, so that their `cls` and `Clear-Host` functions will clear the entire terminal buffer (like they do in conhost), instead of just the viewport. With the conpty viewport and buffer being the same size, there's effectively no way to know if an application is calling these API's in this way with the intention of clearing the buffer or the viewport. We absolutely have to guess. 

Each of these shims checks to see if the way that the API is being called exactly matches the way `cmd` or `powershell` would call these APIs. If it does, we manually write a `^[[3J` to the connected terminal, to get he Terminal to clear it's own scrollback.

~~_⚠️ If another application were trying to clear the **viewport** with an exactly similar API call, this would also cause the terminal scrollback to get cleared ⚠️_~~

* [x] Should these shims be restricted to when the process that's calling them is actually `cmd.exe` or `powershell.exe`? Can I even do this? I think we've done such a good job of isolating the client process information from the rest of the host code that I can't figure out how to do this.
  - YES, this can be done, and I did it.
* [ ] **TODO**: _While I'm here_, should I have `DoSrvPrivateEraseAll` (the implementation for `^[[2J`, in `getset.cpp`) also manually trigger a EraseAll in the terminal in conpty mode?

## PR Checklist
* [x] Closes #3126
* [x] Actually closes #1305 too, which is really the same thing, but probably deserves a callout
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

## Validation Steps Performed
* ran tests
* checked `cls` in the Terminal
* checked `Clear-Host` in the Terminal
* Checked running `powershell clear-host` from `cmd.exe`
@ghost ghost added Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed In-PR This issue has a related PR labels Apr 30, 2020
@ghost
Copy link

ghost commented May 5, 2020

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

Handy links:

@steelx
Copy link

steelx commented May 6, 2020

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.

@nelson6e65
Copy link

There is a way to do not clear all, but allow scroll back after clear or cls?

@mixmastamyk
Copy link

mixmastamyk commented Apr 23, 2021

@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
Copy link

nelson6e65 commented Apr 23, 2021

@mixmastamyk I'm using cmd/PowerShell. But I want the Unix behavior.

By using Ctrl-L is kind of similar, but it replaces the text instead of "move" previous text outside the window view.

I think that more than "clearing" the text, I want to scroll all content up and have a new "clean" window, with the cursor in the first line of terminal, but keeping the previous terminal outputs.

@mixmastamyk
Copy link

@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.

@nelson6e65
Copy link

Thanks. I'll try it.

@sam0ed
Copy link

sam0ed commented Jan 10, 2024

Issue persists on integrated terminal in vs code 1.85.1
Issue: cls command clears only the visible part of the screen and only the first time you run it
Steps to reproduce:

  1. open vs code settings, set terminal.integrated.defaultProfile.windows to null
  2. open the terminal via ctrl+`
  3. run command type C:\Windows\System32\OEMDefaultAssociations.xml (outputs a lot of text)
  4. run cls

the workarounds proposed above do not work:
function ClsWorkaround { clear-host Write-Output "$([char]27)[2J$([char]27)[3J" } Set-Alias -Name cl -Value ClsWorkaround -Scope "Local"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question For questions or discussion Needs-Tag-Fix Doesn't match tag requirements Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Product-Cmd.exe The issue is related to the legacy command interpreter, CMD.exe. Resolution-Answered Related to questions that have been answered Resolution-Fix-Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
None yet
Development

Successfully merging a pull request may close this issue.