Skip to content

Experimental Shell Completion Menu

Mike Griese edited this page Sep 26, 2023 · 3 revisions

In Terminal 1.19 Preview, we began shipping support for an experimental new "shell completion protocol". This protocol allows shells to provide completions to the terminal, and the terminal to display those completions as the user types.

gh-3121-for-pr

This is a highly experimental feature currently, and is not enabled by default. To enable it, you must both configure the Terminal to enable this feature, AND your shell. Do note that the syntax of this sequence is subject to change, and WILL break in future versions of the Terminal.

To enable this feature in the Terminal, set the experimental.enableShellCompletion setting to true in your settings.json file. You'll also need to set a keybinding in the Terminal's actions to trigger the shell to send completions. The following example binds the Ctrl+Space key:

{
    "experimental.enableShellCompletionMenu": true,
    "actions": [
        { "command": { "action": "sendInput", "input": "\u001b[24~b" }, "keys": "ctrl+space", "name": "Trigger shell completions" }
    ]
}

As for your shell, you must configure it to send the correct sequence to the terminal. To enable this feature in PowerShell, you must add the following to your PowerShell profile:

function Send-Completions {
  $commandLine = ""
  $cursorIndex = 0
  [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex)
  $completionPrefix = $commandLine

  $result = "`e]633;Completions"
  if ($completionPrefix.Length -gt 0) {
    $completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $cursorIndex
    if ($null -ne $completions.CompletionMatches) {
      $result += ";$($completions.ReplacementIndex);$($completions.ReplacementLength);$($cursorIndex);"
      $result += $completions.CompletionMatches | ConvertTo-Json -Compress
    }
  }
  $result += "`a"

  Write-Host -NoNewLine $result
}

function Set-MappedKeyHandlers {
  # Terminal suggest - always on keybindings
  Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock {
    Send-Completions
  }
}

# Register key handlers if PSReadLine is available
if (Get-Module -Name PSReadLine) {
  Set-MappedKeyHandlers
}
else {
  Write-Host "PsReadline was disabled. Shell Completion was not enabled."
}

(the \u001b[24~b in the keybinding above is the sequence corresponding to F12,b that the above PowerShell profile is looking for)

Currently, this is only supported for PowerShell.

Over the coming months, we'll iterate on the design of this protocol more, to create something more broadly suitable for other shells and applications. To follow updates, head on over to #3121.