How to prevent the delete key from acting like backspace

keyboard shortcutspowershell

In PowerShell 6.0.1, the out-of-the-box behavior is that when I press Delete while my caret is not at the end of the line, it deletes the character above the caret, as expected. However, once I delete the last character on the line, it moves the caret back a position. I find this very annoying, because I can no longer just hold Delete to delete until the end of the line. Is there a way to change it so that it behaves the same as when I press EndDelete – i.e. it does nothing?

delete key

Research undertaken:

I saw Disable PowerShell beep on backspace, and thought perhaps there is also a setting for what I want, but after reading the docs on the PSReadLine cmdlet, I saw that there isn't.

I then looked into keybindings, and ran Get-PSReadLineKeyHandler to check what Delete is currently assigned to, and then searched for DeleteChar in the PSReadLine codebase, to see the definition for that function, and to browse around for something similar. I found DeleteCharOrExit, and ran Set-PSReadLineKeyHandler -Key Delete -Function DeleteCharOrExit which doesn't exit the "delete" process – as I assumed from the unclear doc comment – it exits the PowerShell console process…

I also found https://github.com/lzybkr/PSReadLine/issues/486, which suggests it has been fixed, but clearly not…

Maybe I need to inject some custom keybinding code like https://github.com/lzybkr/PSReadLine/blob/46d232c22ac3f24a95e32d773c594ad306dfc327/PSReadLine/SamplePSReadLineProfile.ps1#L257-L291?

Best Answer

It turns out that PowerShell Core 6.0.1 ships with version 1.2 of the PSReadLine module, as seen by Get-Module PSReadLine, but the fix was in https://github.com/lzybkr/PSReadLine/releases/tag/v2.0.0-beta1. Seeing as that release says:

This is the first release from the repo supporting both PowerShell Core (all platforms) and Windows PowerShell.

I assumed I had that version and didn't check originally.

To get it working with that version, one can use:

Set-PSReadLineKeyHandler -Key Delete `
                             -BriefDescription Delete `
                             -LongDescription "Delete character over the caret" `
                             -ScriptBlock {
        param($key, $arg)

        $line = $null
        $cursor = $null
        [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

        if ($cursor -lt $line.Length)
        {
            [Microsoft.PowerShell.PSConsoleReadLine]::Delete($cursor, 1)
        }
    }

(ideally by placing it in the appropriate profile file so that it is auto-run when PowerShell starts.)

This can also be fixed by upgrading the PSReadLine module, using the instructions at https://github.com/lzybkr/PSReadLine/issues/612, which are:

Install-Module PSReadLine -RequiredVersion 2.0.0-beta1 -AllowPrerelease -Scope CurrentUser -SkipPublisherCheck

Presumably a future release of PowerShell Core will include a fixed version of the PSReadLine module.

Related Question