[PR #14938] [MERGED] Add Suggestions UI & experimental shell completions support #30310

Open
opened 2026-01-31 09:40:00 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/14938
Author: @zadjii-msft
Created: 3/1/2023
Status: ✅ Merged
Merged: 8/14/2023
Merged by: @zadjii-msft

Base: main ← Head: dev/migrie/fhl-2023/pwsh-autocomplete-demo


📝 Commits (10+)

  • c96799c Preview the input via the TSF input control. This is awesome, and should go into main
  • 1449088 bugfixes for the demo
  • d3b5533 fix remaining bugs
  • 0bda66f a comment I missed
  • ccfc834 Migrate spelling-0.0.21 changes from main
  • c97ac66 resart with fresh plumbing
  • 7404dc3 zhu li, do the thing
  • f361b6c lots of removal of dead code from the sxnui
  • b0fa972 make the menu mode compact, and remove the search box
  • 985fcdb better UX for typing

📊 Changes

40 files changed (+2003 additions, -3 deletions)

View changed files

📝 .github/actions/spelling/allow/allow.txt (+1 -0)
📝 .github/actions/spelling/expect/expect.txt (+2 -0)
📝 src/cascadia/LocalTests_TerminalApp/pch.h (+2 -0)
➕ src/cascadia/TerminalApp/SuggestionsControl.cpp (+1103 -0)
➕ src/cascadia/TerminalApp/SuggestionsControl.h (+132 -0)
➕ src/cascadia/TerminalApp/SuggestionsControl.idl (+48 -0)
➕ src/cascadia/TerminalApp/SuggestionsControl.xaml (+214 -0)
📝 src/cascadia/TerminalApp/TerminalAppLib.vcxproj (+13 -0)
📝 src/cascadia/TerminalApp/TerminalPage.cpp (+116 -1)
📝 src/cascadia/TerminalApp/TerminalPage.h (+10 -1)
📝 src/cascadia/TerminalApp/TerminalPage.xaml (+8 -0)
📝 src/cascadia/TerminalApp/pch.h (+2 -0)
📝 src/cascadia/TerminalControl/ControlCore.cpp (+13 -0)
📝 src/cascadia/TerminalControl/ControlCore.h (+5 -0)
📝 src/cascadia/TerminalControl/ControlCore.idl (+3 -0)
📝 src/cascadia/TerminalControl/EventArgs.cpp (+1 -0)
📝 src/cascadia/TerminalControl/EventArgs.h (+14 -0)
📝 src/cascadia/TerminalControl/EventArgs.idl (+6 -0)
📝 src/cascadia/TerminalControl/TermControl.cpp (+30 -1)
📝 src/cascadia/TerminalControl/TermControl.h (+5 -0)

...and 20 more files

📄 Description

There's two parts to this PR that should be considered separately.

  1. The Suggestions UI, a new graphical menu for displaying suggestions / completions to the user in the context of the terminal the user is working in.
  2. The VsCode shell completions protocol. This enables the shell to invoke this UI via a VT sequence.

These are being introduced at the same time, because they both require one another. However, I need to absolutely emphasize:

THE FORMAT OF THE COMPLETION PROTOCOL IS EXPERIMENTAL AND SUBJECT TO CHANGE

This is what we've prototyped with VsCode, but we're still working on how we want to conclusively define that protocol. However, we can also refine the Suggestions UI independently of how the protocol is actually implemented.

This will let us rev the Suggestions UI to support other things like tooltips, recent commands, tasks, INDEPENDENTLY of us rev'ing the completion protocol.

So yes, they're both here, but let's not nitpick that protocol for now.

Checklist

Detailed Description

Suggestions UI

The Suggestions UI is spec'ed over in #14864, so go read that. It's basically a transient Command Palette, that floats by the user's cursor. It's heavily forked from the Command Palette code, with all the business about switching modes removed. The major bit of new code is SuggestionsControl::Anchor. It also supports two "modes":

  • A "palette", which is like the command palette - a list with a text box
  • A "menu", which is more like the intellisense flyout. No text box. This is the mode that the shell completions use

Shell Completions Protocol

I literally cannot say this enough times - this protocol is experimental and subject to change. Build on it at your own peril. It's disabled in Release builds (but available in preview behind globals.experimental.enableShellCompletionMenu), so that when it ships, no one can take a dependency on it accidentally.

Right now we're just taking a blob of JSON, passing that up to the App layer, who asks Command to parse it and build a list of sendInput actions to populate the menu with. It's not a particularly elegant solution, but it's good enough to prototype with.

How do I test this?

I've been testing this in two parts. You'll need a snippet in your powershell profile, and a keybinding in the Terminal settings to trigger it. The work together by binding Ctrl+space to essentially send F12b. Wacky, but it works.

{ "command": { "action": "sendInput","input": "\u001b[24~b" }, "keys": "ctrl+space" },
function Send-Completions2 {
  $commandLine = ""
  $cursorIndex = 0
  # TODO: Since fuzzy matching exists, should completions be provided only for character after the
  #       last space and then filter on the client side? That would let you trigger ctrl+space
  #       anywhere on a word and have full completions available
  [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex)
  $completionPrefix = $commandLine

  # Get completions
  $result = "`e]633;Completions"
  if ($completionPrefix.Length -gt 0) {
    # Get and send completions
    $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 {
  # VS Code send completions request (may override Ctrl+Spacebar)
  Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock {
    Send-Completions2
  }
}

# Register key handlers if PSReadLine is available
if (Get-Module -Name PSReadLine) {
  Set-MappedKeyHandlers
}

TODO

  • (prompt | format-hex).Ctrl+space -> This always throws an exception. Seems like the payload is always clipped to
    {"CompletionText":"Ascii","ListItemText":"Ascii","ResultType":5,"ToolTip":"string Ascii { get
    and that ain't JSON. Investigate on the pwsh side?

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/14938 **Author:** [@zadjii-msft](https://github.com/zadjii-msft) **Created:** 3/1/2023 **Status:** ✅ Merged **Merged:** 8/14/2023 **Merged by:** [@zadjii-msft](https://github.com/zadjii-msft) **Base:** `main` ← **Head:** `dev/migrie/fhl-2023/pwsh-autocomplete-demo` --- ### 📝 Commits (10+) - [`c96799c`](https://github.com/microsoft/terminal/commit/c96799c6e9d84b5968f8841633c6d74480f91d02) Preview the input via the TSF input control. This is awesome, and should go into main - [`1449088`](https://github.com/microsoft/terminal/commit/1449088e80b81d82cbf5456baaf69798ee849d16) bugfixes for the demo - [`d3b5533`](https://github.com/microsoft/terminal/commit/d3b5533a1eef45edbfbae4e68ee7e9507c97406c) fix remaining bugs - [`0bda66f`](https://github.com/microsoft/terminal/commit/0bda66fc2f0f5d6a5e709d8ebc4678256d132fc3) a comment I missed - [`ccfc834`](https://github.com/microsoft/terminal/commit/ccfc83443be754abac5be2200e3df05a8ae6f2ca) Migrate spelling-0.0.21 changes from main - [`c97ac66`](https://github.com/microsoft/terminal/commit/c97ac66d5df89e046bd46c7838269867c9dbb3c1) resart with fresh plumbing - [`7404dc3`](https://github.com/microsoft/terminal/commit/7404dc3d35fa2fe8e73df27caa9fa910b4b86738) zhu li, do the thing - [`f361b6c`](https://github.com/microsoft/terminal/commit/f361b6c8792a9b94b4fb2328b8f23ac1dd7fe100) lots of removal of dead code from the sxnui - [`b0fa972`](https://github.com/microsoft/terminal/commit/b0fa972ec16dd11153ba7dd8bacd5f449af923d3) make the menu mode compact, and remove the search box - [`985fcdb`](https://github.com/microsoft/terminal/commit/985fcdbdb6c6bab444bdfa804325b80358f6dee7) better UX for typing ### 📊 Changes **40 files changed** (+2003 additions, -3 deletions) <details> <summary>View changed files</summary> 📝 `.github/actions/spelling/allow/allow.txt` (+1 -0) 📝 `.github/actions/spelling/expect/expect.txt` (+2 -0) 📝 `src/cascadia/LocalTests_TerminalApp/pch.h` (+2 -0) ➕ `src/cascadia/TerminalApp/SuggestionsControl.cpp` (+1103 -0) ➕ `src/cascadia/TerminalApp/SuggestionsControl.h` (+132 -0) ➕ `src/cascadia/TerminalApp/SuggestionsControl.idl` (+48 -0) ➕ `src/cascadia/TerminalApp/SuggestionsControl.xaml` (+214 -0) 📝 `src/cascadia/TerminalApp/TerminalAppLib.vcxproj` (+13 -0) 📝 `src/cascadia/TerminalApp/TerminalPage.cpp` (+116 -1) 📝 `src/cascadia/TerminalApp/TerminalPage.h` (+10 -1) 📝 `src/cascadia/TerminalApp/TerminalPage.xaml` (+8 -0) 📝 `src/cascadia/TerminalApp/pch.h` (+2 -0) 📝 `src/cascadia/TerminalControl/ControlCore.cpp` (+13 -0) 📝 `src/cascadia/TerminalControl/ControlCore.h` (+5 -0) 📝 `src/cascadia/TerminalControl/ControlCore.idl` (+3 -0) 📝 `src/cascadia/TerminalControl/EventArgs.cpp` (+1 -0) 📝 `src/cascadia/TerminalControl/EventArgs.h` (+14 -0) 📝 `src/cascadia/TerminalControl/EventArgs.idl` (+6 -0) 📝 `src/cascadia/TerminalControl/TermControl.cpp` (+30 -1) 📝 `src/cascadia/TerminalControl/TermControl.h` (+5 -0) _...and 20 more files_ </details> ### 📄 Description There's two parts to this PR that should be considered _separately_. 1. The Suggestions UI, a new graphical menu for displaying suggestions / completions to the user in the context of the terminal the user is working in. 2. The VsCode shell completions protocol. This enables the shell to invoke this UI via a VT sequence. These are being introduced at the same time, because they both require one another. However, I need to absolutely emphasize: ### THE FORMAT OF THE COMPLETION PROTOCOL IS EXPERIMENTAL AND SUBJECT TO CHANGE This is what we've prototyped with VsCode, but we're still working on how we want to conclusively define that protocol. However, we can also refine the Suggestions UI independently of how the protocol is actually implemented. This will let us rev the Suggestions UI to support other things like tooltips, recent commands, tasks, INDEPENDENTLY of us rev'ing the completion protocol. So yes, they're both here, but let's not nitpick that protocol for now. ### Checklist * Doesn't actually close anything * Heavily related to #3121, but I'm not gonna say that's closed till we settle on the protocol * See also: * #1595 * #14779 * https://github.com/microsoft/vscode/pull/171648 ### Detailed Description #### Suggestions UI The Suggestions UI is spec'ed over in #14864, so go read that. It's basically a transient Command Palette, that floats by the user's cursor. It's heavily forked from the Command Palette code, with all the business about switching modes removed. The major bit of new code is `SuggestionsControl::Anchor`. It also supports two "modes": * A "palette", which is like the command palette - a list with a text box * A "menu", which is more like the intellisense flyout. No text box. This is the mode that the shell completions use #### Shell Completions Protocol I literally cannot say this enough times - this protocol is experimental and subject to change. Build on it at your own peril. It's disabled in Release builds (but available in preview behind `globals.experimental.enableShellCompletionMenu`), so that when it ships, no one can take a dependency on it accidentally. Right now we're just taking a blob of JSON, passing that up to the App layer, who asks `Command` to parse it and build a list of `sendInput` actions to populate the menu with. It's not a particularly elegant solution, but it's good enough to prototype with. #### How do I test this? I've been testing this in two parts. You'll need a snippet in your powershell profile, and a keybinding in the Terminal settings to trigger it. The work together by binding <kbd>Ctrl+space</kbd> to _essentially_ send <kbd>F12</kbd><kbd>b</kbd>. Wacky, but it works. ```json { "command": { "action": "sendInput","input": "\u001b[24~b" }, "keys": "ctrl+space" }, ``` ```ps1 function Send-Completions2 { $commandLine = "" $cursorIndex = 0 # TODO: Since fuzzy matching exists, should completions be provided only for character after the # last space and then filter on the client side? That would let you trigger ctrl+space # anywhere on a word and have full completions available [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$cursorIndex) $completionPrefix = $commandLine # Get completions $result = "`e]633;Completions" if ($completionPrefix.Length -gt 0) { # Get and send completions $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 { # VS Code send completions request (may override Ctrl+Spacebar) Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock { Send-Completions2 } } # Register key handlers if PSReadLine is available if (Get-Module -Name PSReadLine) { Set-MappedKeyHandlers } ``` ### TODO * [x] `(prompt | format-hex).`<kbd>Ctrl+space</kbd> -> This always throws an exception. Seems like the payload is always clipped to ```{"CompletionText":"Ascii","ListItemText":"Ascii","ResultType":5,"ToolTip":"string Ascii { get``` and that ain't JSON. Investigate on the pwsh side? --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:40:00 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#30310