powershellcommand-line-interfaceeditorpsreadline

How do you edit the command line in an external editor?


tl;dr

I want to find a Powershell version of the bash edit-and-execute-command widget or the zsh edit-command-line widget.

Background

Short commands get executed directly on the command-line, long complicated commands get executed from scripts. However, before they become "long", it helps to be able to test medium length commands on the command-line. To assist in this effort, editing the command in an external editor becomes very helpful. AFAIK Powershell does not support this natively as e.g. bash and zsh do.

My current attempt

I am new to Powershell, so I'm bound to make many mistakes, but I have come up with a working solution using the features of the [Microsoft.Powershell.PSConsoleReadLine] class. I am able to copy the current command-line to a file, edit the file, and then re-inject the edited version back into the command-line:

Set-PSReadLineKeyHandler -Chord "Alt+e" -ScriptBlock {
  $CurrentInput = $null

  # Copy current command-line input, save it to a file and clear it
  [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref] $CurrentInput, [ref] $null)
  Set-Content -Path "C:\Temp\ps_${PID}.txt" -Value "$CurrentInput"
  [Microsoft.PowerShell.PSConsoleReadLine]::KillRegion()

  # Edit the command with gvim
  Start-Job -Name EditCMD -ScriptBlock { gvim "C:\Temp\ps_${Using:PID}.txt" }
  Wait-Job  -Name EditCMD

  # Get command back from file the temporary file and insert it into the command-line
  $NewInput  = (Get-Content -Path "C:\Temp\ps_${PID}.txt") -join "`n"
  [Microsoft.PowerShell.PSConsoleReadLine]::Insert($NewInput)
}

Questions

My current solution feels clunky and a somewhat fragile. Are there other solutions? Can the current solution be improved?

Environment

The solution I went with

Create a "baked" executable similar to what mklement0 showed. I prefer vim for this instead of `gvim, as it runs directly in the console:

'@vim -f %*' > psvim.cmd
$env:EDITOR = "psvim"
Set-PSReadLineKeyHandler -Chord "Alt+e" -Function ViEditVisually

Solution

  • tl;dr

    Details below.



    Example configuration with a helper executable for code (Visual Studio Code):

    $env:VISUAL = "$HOME/codewait"
    
    # Custom key binding
    Set-PSReadLineKeyHandler -Chord Alt+e -Function ViEditVisually