22

I'd like to be able to clear my scrollback buffer in Windows Terminal using a keyboard shortcut.

In WSL I can hit Ctrl+L and it does a form-feed (equivalent of clear -x command), which clears the screen but only by scrolling the content above up and out of view.

What I'd like to do is, for example, hit Ctrl+K (like macOS Terminal) to be able to clear the screen properly (similar to issuing a plain clear command) in both WSL and PowerShell.

Is this possible?

Update: This is now supported natively in Windows Terminal. I've added my own answer below and self-accepted, but it's a bit buried, so here is a link: https://superuser.com/a/1628815/2924

6
  • Does CLS not do what you expect? I remember it as ClearLaScreen ;) Commented Feb 24, 2021 at 15:44
  • Yeah it does in PowerShell. Both cls and clear are aliases of Clear-Host in PS. So what I really need in Windows Terminal is a way to bind the clear command to a shortcut, which would work in both WSL and PS. Commented Feb 24, 2021 at 18:58
  • What does it matter if it is a "shortcut" or a command? .. that is as long as you can type the same three keys and it works with either system? I do get what you are saying though.. this still does not answer your question. I am using WSL1 and I can bind anything that I want using the Linux alias command.. for instance.. alias start='explorer.exe' .. then I can do start . just like I do from windows. Commented Feb 24, 2021 at 20:28
  • Sometimes I have a command on the prompt and realise I want the screen cleared before I run it. I can hit Ctrl+L and the screen will clear, but leave what I've typed at the prompt in place. I could hit Ctrl+a, Ctrl+k, type clear, Ctrl+y to cut the line, clear the screen, then yank (paste) back the result, but I'm lazy. Plus it's just easier to quickly hit a keyboard shortcut for this task - it's a muscle memory thing :) Commented Feb 24, 2021 at 22:52
  • 1
    Cool :) .. I get it. This does not happen with my own work flow. I don't have an answer but I wish you good luck. Commented Feb 24, 2021 at 22:59

3 Answers 3

21

Update 2021-10-20: This is now natively supported as of version 1.12 (in preview at time of writing).

See PR #10906 for full details.

This adds a new action, clearBuffer. It accepts 3 values for the clear type:

  • "clear": "screen": Clear the terminal viewport content. Leaves the scrollback untouched. Moves the cursor row to the top of the viewport (unmodified).

  • "clear": "scrollback": Clear the scrollback. Leaves the viewport untouched.

  • "clear": "all": (default) Clear the scrollback and the visible viewport. Moves the cursor row to the top of the viewport (unmodified).

  • "Clear Buffer" has also been added to defaults.json.

These actions can be invoked from the command palette or can be bound to keyboard shortcuts via the settings UI, and directly in settings.json as covered in the official documentation.

Binding a shortcut to the Clear buffer action

Clear buffer action in settings.json

Windows Terminal clearBuffer action example


For reference, here's a discussion on the difference between Cmd ⌘+K and Ctrl+L: What is the difference between Ctrl+L and Cmd+K for clearing the terminal screen?

Longer answer

According to Mike Griese (zadjii-msft on GitHub), an engineer working on Windows Terminal:

To clarify for future me - cmd+k is not something that's being handled by bash or the shell. This is the Terminal itself handling the keybinding, and clearing both the buffer and the scrollback.

You've described a user story that makes sense to me, so I'm gonna put this on the backlog.

Dustin Howett (DHowett-MSFT on GitHub) goes on to say:

[T]his issue in particular that's thornier than most. For compatibility with Windows console applications that do not expect a terminal to be connected, we need to maintain a text buffer for them to read. That's all. Because we don't have a way to clear that text buffer (from the terminal side), and we just haven't written one yet, it's only more complex than clearing the local screen. It's not a complexity class issue with all of Terminal.

Reference: https://github.com/microsoft/terminal/issues/1882

2
9

Well this turned into a rabbit-trail-and-a-half ;-) ...

I would have thought this would have been pretty straightforward with the sendInput action introduced in Windows Terminal 1.3, but I keep coming up short using that method. I don't claim to be any expert at keybindings or terminal escape sequences, but I'm trying to muddle through.

First, from man clear, the "clear scrollback" sequence is Esc[3J. This works in Windows Terminal via:

  • Powershell: Write-Output "`e[3J"
  • bash, zsh, or fish: printf '\033[3J' (or equivalent echo)

It, of course, needs to be coupled with the "clear entire screen" sequence (\033[2J) and the "cursor to home position" (\033[H) (obtained from this answer).

Put it together, and printf '\033[2J\033[3J\033[H' gets us the clear (without arguments) behavior.

So I would think, given the sendInput example in the Windows Terminal 1.3 release notes that we could send that escape code via:

{ "command": { "action": "sendInput", "input": "\u001B[3J" }, "keys": "ctrl+shift+l"}

in the "actions" section (formerly "keybindings"). The \u001b[A example (up arrow) works fine for me, but the "clear scrollback" results in an error bell in bash and printing [3J in fish. The same occurs for \u001B[2J for just trying to clear the screen as well. If someone can figure out where I'm going wrong on that, I'd love to know.

But ... we can rebind the keys in the shells. However, they probably won't won't be able to tell the difference between Ctrl+L and Ctrl+Shift+L for this reason. Except for the recent PSReadLine 2.0, which is case-sensitive on key-bindings.

So if you really want to use Ctrl+Shift+l in both PowerShell and Linux shells in WSL, you'll need to do it in two steps:

First, set up a Windows Terminal action to sendInput with an unused keycode:

"actions":
// formerly "keybindings"
    [
      ...
        { "command": { "action": "sendInput", "input": "\uAC12" }, "keys": "ctrl+shift+l"},
      ...
    ]
}

Honestly, I'm not sure what the best way of picking a keycode is. I just went with something from the Hangul character set (\uAC12), since I'm fairly sure I'm never going to run across that in real-life. Note that this comment recommends using the "private use" E000-EFFF range, but it seemed fairly populated on Windows Terminal, and I'd already settled on Hangul, so I've left the examples below using \uAC12.

So then we need to bind \uAC12 in each shell to send the right escape sequences:

  • Bash:

    First, get the key sequence to bind to with printf '\uAC12' | xxd, which results in 00000000: eab0 92.

    Then, using that output, encode the bind command as bind -x '"\xEA\xB0\x92":"printf \\033[2J\\033[3J\\033[H"' (xxd idea from a comment in this answer.)

  • Zsh: It looks to be a bit more involved:

    function clear-scrollback {
      clear && printf '\e[3J'
      zle && zle .reset-prompt && zle -R
    }
    zle -N clear-scrollback
    bindkey '\uAC12' clear-scrollback
    
    

    (with assist from this answer).

  • Fish: bind \uAC12 "printf '\033[2J\033[3J\033[H'; commandline -f repaint"

  • PowerShell: Set-PSReadLineKeyHandler "$([char]0xAC12)" -ScriptBlock { Write-Output "`e[2J`e[3J"; [Microsoft.PowerShell.PSConsoleReadLine]::ClearScreen() }. Assist on the [char] casting from this answer, and dang if it didn't take me a while to find an example of calling a PSReadline function in a ScriptBlock.

  • PowerShell Core: Set-PSReadLineKeyHandler "$([char]0xAC12)" -ScriptBlock { Write-Host "`e[2J`e[3J"; [Microsoft.PowerShell.PSConsoleReadLine]::ClearScreen() }. Not sure why PowerShell and PowerShell Core behave differently here.

Corrections or suggestions for improvement welcome.

0
8

Edit your ~/.bashrc

alias cls='clear && echo -en "\e[3J"'

Now you can type cls to clear the screen and scrollback inside your bash WSL session.

Edit your Windows Terminal JSON file

"actions": 
[
    // Command to reset terminal and scrollback
    { 
        "command": 
        { 
            "action": "sendInput", "input": "cls\r" 
        }, 
        "keys": "ctrl+k"
    },
]

Now pressing CTRL+k will enter the CLS command for you. For PowerShell or a CMD prompt, the CLS command is already supported by default, so no extra config is necessary.

3
  • 1
    Usually I'm not a personal fan of sendInput entering commands, since it can be triggered even when not at the prompt. That said, it's just so much easier than my answer that I'd go with your method in this case. Commented Aug 27, 2021 at 19:43
  • Worked great. Accepted due to the simplicity of the solution and me being a simple person. :) Commented Sep 1, 2021 at 3:59
  • 1
    To not clutter your history, make it "input": " cls\r" (note the leading space) and in your ~/.bashrc set HISTCONTROL to ignorespace or ignoreboth. Commented Sep 23, 2021 at 12:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .