15

In using the clear command, the screen clears. Totally. I no longer have access to any of the stuff that was previously on the screen at all.

Is there a way to "clear" the screen (i.e. make the prompt go to the top of the screen) without erasing everything that was on the screen? Ideally I'd like to "clear" the screen but be able to scroll up to see everything else.

I'm using the Windows Terminal program and the PowerShell shell, but I'd like to know the answer for the Windows Command line, too.

I put that I wanted to maintain the ability to scroll up -- by this I mean I want to be able to see everything that came before I hit the "clear" command, so... yes, I want to maintain everything that came before, not the command history.

random
  • 15,201
Bob
  • 183
  • 1
  • 2
  • 6

5 Answers5

16

PSReadline (PowerShell's standard input handler) has the CtrlL hotkey found in most Unix shells, which clears the screen as if you forced all text to scroll out (like the ASCII "Form Feed" character would).

In PS5 though it still erases the displayed text fully – but everything that has already gone to the scrollback will remain in the scrollback.

As a workaround, you can output enough empty lines to push everything into scrollback:

echo ("`n" * $Host.UI.RawUI.WindowSize.Height)

...and then bring the cursor to top:

$e = [char]27
echo "$e[H" # Move cursor to 0;0
echo "$e[J" # Erase down/right

This could also be bound to a key using Set-PSReadlineKeyHandler -ScriptBlock.

Cmd doesn't have an equivalent – it reads input in line-mode, with only a few shortcuts provided by Conhost instead. However, you can still create a batch script (or even a Conhost DOSKEY alias) which would output the same VT sequences.

grawity
  • 501,077
10

While clearing the screen is a terminal function (via ANSI terminal control codes), the way that you get those codes sent can be different depending on the shell. The general idea is that:

  • ESC[H moves the cursor to the Home position
  • ESC[2J clears the screen, but leaves the scrollback
  • ESC[3J clears the scrollback

... where ESC represents the ASCII character code 27.

According to man clear on Linux, the 3J code was originally (in 1999) an extension to Xterm (see Xterm Control Sequences), which was picked up by the Linux kernel in 2011 for the console driver. Sometime later, Windows Console Host picked it up, and it's been in Windows Terminal probably since its inception.

Windows Terminal (for all shells)

Windows Terminal includes the clearBuffer action which can be bound to any hotkey. However, it impacts all shells regardless of what application may be running inside it. For that reason, I recommend against using it unless you are sure you won't accidentally press the hotkey when in something like vi (or worse).

That said, it's definitely the easiest way to get this functionality in CMD.

If you do want to use it, the clearBuffer action allows you to specify a clear target of:

  • screen
  • scrollback
  • all

Using the screen option will clear the current contents of the screen but leave the scrollback in place.

You'll need to edit your Windows Terminal settings.json directly since the UI doesn't have a way to set the clear target:

        {
            "command": 
            {
                "action": "clearBuffer",
                "clear": "screen"
            },
            "keys": ""
        }
PowerShell

For PowerShell, as user1684 beat me to it Ctrl+L sends the proper escape sequence.

On the other hand, Clear-Host (alias clear) on PowerShell sends an ESC[3J (clearing the scrollback as well).

If you have muscle memory in typing clear in PowerShell, you could simply change its definition:

Remove-Item Alias:clear
function clear {
    Write-Output "$([char]27)[H$([char]27)[2J"
}

Place this in your PowerShell profile if you want it to be permanent.

CMD

It's possible, but tricky to do this in CMD as well.

The biggest problem in CMD is actually getting the ESC character (ASCII 27) printed. I had the actual "character" pasted in here which would transfer via copy/paste to CMD, but it was erased the first time I made another edit to this post. The character is still there in the (source) edit history for this answer, but let's find a better way to do this.

From PowerShell, use this to create a CMD batch file:

@"
@echo off
echo $([char]27)[H$([char]27)[2J
"@ | Out-File -FilePath .\clear.cmd -Encoding ASCII

Executing the resulting clear.cmd batch file in CMD should clear the screen (but not the scrollback).

If you have problems with that, any way you can print an ASCII 27 followed by [2J should work. If you have PowerShell Core installed, for instance:

pwsh -c "Write-Output "`e[H`e[2J""

And just to provide some additional detail on one of your comments:

That seems like either the world's largest design failure or... I dunno. I maintain that there is probably a workaround at the very least.

So yes, we've come up with a workaround, but it honestly wouldn't surprise me if we hadn't. Remember, Windows Console Host (in which CMD used to run by default) dates back to Windows 95 (so 27 years now), well before XTerm even added those codes.

And while Windows Terminal is much more modern, I don't think CMD (which needs to generate the codes) has seen any substantial update since before PowerShell was released in 2006.

Really, I count ourselves lucky we've got a workaround ;-).

Windows Subsystem for Linux
  • Ctrl+L also works from many Linux shells to send a ESC[2J (leave scrollback).
  • clear will act like on PowerShell, clearing the screen and scrollback (ESC[H+ESC[2J+ESC[3J).
  • clear -x will leave the scrollback (ESC[H+ESC[2J)
NotTheDr01ds
  • 28,025
3

As a workaround, in CMD you can hold down Ctrl↓ (Down arrow) until screen is empty. It will scroll down fairly fast, so it is possible to scroll too much. In that case you can press Ctrl→ (Right arrow) or start typing, and the prompt line pops back into view. Anything that moves cursor will do.

This doesn't seem to work in Powershell unfortunately.

1

Clear PowerShell and preserve scrollback

PowerShell

I used Get-Command to look for cmdlets like Write-Host or Write-Output because it seems REALLY odd that this isn't a feature of powershell.

Get-Command -CommandType Cmdlet

There isn't one , but I noticed Clear-Host was absent from the output. In PowerShell, both clear and cls alias Clear-Host. I verified:

(Get-Command Clear-Host).CmdletBinding
 # False

Get-Command Clear-Host

CommandType Name

----------- ----

Function Clear-Host

So I checked the Definition and ScriptBlock properties, and they're populated with source code. It might be useful to understand how Clear-Host works and what we don't like about its implementation.

((Get-Command Clear-Host).Definition)
 # $RawUI = $Host.UI.RawUI
 # $RawUI.CursorPosition = @{X=0;Y=0}
 # $RawUI.SetBufferContents(
 #    @{Top = -1; Bottom = -1; Right = -1; Left = -1},
 #    @{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor})
 # # .Link
 # # https://go.microsoft.com/fwlink/?LinkID=<7_dot_3_DOC_LINK>
 # # .ExternalHelp System.Management.Automation.dll-help.xml

Clear-Host moves the cursor and replaces the buffer contents. It does not write to standard output. Knowing its scope, I feel confident replacing the function.

Use Write-Host to avoid mutating standard output streams.

  • Write-Host appears only to developer, cannot be captured.
  • Write-Output - appears to everyone and their logger.
  • echo - not even PowerShell; alias of Write-Output
function Invoke-Clear () {
  $e = [char]27
  . Write-Host "$e[2J$e[H" -NoNewline
}
Remove-Alias -Name clear && Set-Alias -Name clear -Value Invoke-Clear

The . before Write-Host is critical.

I'd recommend aliasing clear over cls because clear is a unix standard and it should give you better interop with non-windows programs/machines. Keep cls as a windows-only "hard" clear.

Persist the custom script

You can save the above script to your $PROFILE. You can modify it in any text editor.

#> code $PROFILE -n
notepad $PROFILE

$PROFILE points to your current shell's PowerShell profile script.

dubble
  • 11
0

Use for both CMD and PowerShell the clear screen command.

Enter : cls

harrymc
  • 498,455