powershellvimpsreadline

Different cursor for different Vim modes in Powershell


I added Vim bindings to my Powershell using PSReadline module as shown in this Server Fault post. The problem after this was that there wasn't any visual indicator for the different modes of Vim.

I just wanted different cursors for the 'command' and the other modes. Block cursor for command mode and line cursor for other modes. So I searched around and found this in the official Microsoft docs: Use ViModeChangeHandler to display Vi mode changes

# This example emits a cursor change VT escape in response to a Vi mode change.

function OnViModeChange {
    if ($args[0] -eq 'Command') {
        # Set the cursor to a blinking block.
        Write-Host -NoNewLine "`e[1 q"
    } else {
        # Set the cursor to a blinking line.
        Write-Host -NoNewLine "`e[5 q"
    }
}
Set-PSReadLineOption -ViModeIndicator Script -ViModeChangeHandler $Function:OnViModeChange

I simply copy-pasted this at the bottom of my $PROFILE file after running ise $PROFILE.

Surprisingly, I got an error when I tried to source my $PROFILE:

> & $PROFILE
Set-PSReadLineOption : Cannot bind parameter 'ViModeIndicator'. Cannot convert value "Script" to type
"Microsoft.PowerShell.ViModeStyle". Error: "Unable to match the identifier name Script to a valid enumerator name. Specify one of
the following enumerator names and try again:
None, Prompt, Cursor"
At C:\Users\user\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1:27 char:39
+ Set-PSReadLineOption -ViModeIndicator Script -ViModeChangeHandler $Fu ...
+                                       ~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-PSReadLineOption], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.SetPSReadLineOption

Googling "Set-PSReadLineOption : Cannot bind parameter 'ViModeIndicator'. Cannot convert value "Script" to type "Microsoft.PowerShell.ViModeStyle"." doesn't result in any useful results (just 2 results actually).

How can I fix this?


Solution

  • When I was following the instructions given in the Server Fault post I ran:

    Install-Module PsReadline -Scope CurrentUser
    

    And was notified that PsReadline was already installed on my system. It asked me to append -Force at the end of the command to force it to update. At the time, I didn't append -Force and went along with the preinstalled version.

    Thanks to Mathias R. Jessen's comment:

    The error tells you what to do: "Specify one of the following enumerator names and try again: None, Prompt, Cursor"

    I figured out the problem. I went back to the documentation and checked the docs for -ViModeIndicator and found:

    -ViModeIndicator

    This option sets the visual indication for the current Vi mode. Either insert mode or command mode.

    The valid values are as follows:

    None: There`s no indication.
    Prompt: The prompt changes color.
    Cursor: The cursor changes size.
    Script: User-specified text is printed.
    

    This contradicted the output I was getting in my Powershell, saying, "[...] one of the following enumerator names and try again: None, Prompt, Cursor". (Notice that Script is not mentioned).

    So I understood that I must be using the wrong version of PsReadline, as stated in the documentation (emphasis mine):

    The PSReadLine module contains cmdlets that let you customize the command-line editing environment in PowerShell. PowerShell 7.1 shipped with PSReadLine v2.1. These articles document PSReadLine v2.1.

    Hence to solve this use:

    Install-Module PsReadline -Scope CurrentUser -Force
    

    while installing PsReadline.