Skip to content

Instantly share code, notes, and snippets.

@zadjii-msft
Last active March 27, 2023 18:19
Show Gist options
  • Save zadjii-msft/eddb07cd490f5ee78193fea21a74e6f8 to your computer and use it in GitHub Desktop.
Save zadjii-msft/eddb07cd490f5ee78193fea21a74e6f8 to your computer and use it in GitHub Desktop.
Terminal 1.18 Selfhost Settings

Terminal 1.18 Selfhost Settings

Collection of settings for our 1.18 bug bash. Last updated for 1.18.833

There's also a collection of files for your shell config as well. I made them all separate, especially the pwsh ones, so people could combine as needed. I know folks have complicated shell prompts already. The one I have there is fairly trivial, but should include all the marks you need to get started. Wrap your own prompt as needed.

Shell-completion integration

Make sure that the key in Set-MappedKeyHandlers matches the contents of the sendInput command bound in the actions. In this sample, the Terminal internally passes F12b to pwsh to drive the menu.

Shell integration prompts

These are snippets for:

both rely on the "experimental.autoMarkPrompts": true, setting being enabled.

PRs

{
"actions":
[
// Add the ability to select a whole command (or its output) #14807
{ "keys": "ctrl+shift+w", "command": { "action": "selectOutput", "direction": "prev" }, },
{ "keys": "ctrl+shift+s", "command": { "action": "selectOutput", "direction": "next" }, },
{ "keys": "ctrl+alt+shift+w", "command": { "action": "selectCommand", "direction": "prev" }, },
{ "keys": "ctrl+alt+shift+s", "command": { "action": "selectCommand", "direction": "next" }, },
// Enable tearing out tabs to create new windows #14935
{ "keys": "f1", "command": { "action": "moveTab", "window": "1" }, },
{ "keys": "f2", "command": { "action": "moveTab", "window": "2" }, },
{ "keys": "f3", "command": { "action": "movePane", "window": "1" }, },
{ "keys": "f4", "command": { "action": "movePane", "window": "2" }, },
// Add Suggestions UI & experimental shell completions support #14938
// (Also required pwsh shell integration)
{
"command": { "action": "sendInput", "input": "\u001b[24~b" },
"keys": "ctrl+space",
"name": "magic",
"description": "not for real use - helper for autocomplete."
},
// Add support for opening the Suggestions UI with recent commands #14943
// (Also required ANY shell integration)
{
"keys": "ctrl+shift+h", "command": { "action": "suggestions", "source": "commandHistory", "useCommandline":true },
},
{
"keys": "ctrl+shift+y", "command": { "action": "suggestions", "source": "commandHistory", "useCommandline":false },
},
],
// Add support for running the Terminal without _any_ windows #14944
// (you probably also want at least `quakeMode` or a `globalSummon`)
"compatibility.allowHeadless": true,
// This isn't expected to work well at all right now, but included for completion's sake
"compatibility.isolatedMode": true,
// For shell completions to be enabled.
"experimental.enableShellCompletionMenu": true,
"profiles":
{
"defaults":
{
// Marks in general
"experimental.showMarksOnScrollbar": true,
// NEEDED for both pwsh and CMD shell integration
"experimental.autoMarkPrompts": true,
// Add support for a right-click context menu #14775
"experimental.rightClickContextMenu": true,
"useAtlasEngine": true
},
}
}
# Send tab completion to terminal
function Send-Completions {
# Get current command line
$commandLine = ""
# TODO: Take cursor into account
$cursor = 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]$cursor)
# Get and send completions
$completionPrefix = $commandLine
if ($completionPrefix.Length -eq 0) {
# TODO: Send bell instead?
$result = "`e]633;Completions`a"
Write-Host -NoNewLine $result
return
}
$completions = TabExpansion2 -inputScript $completionPrefix -cursorColumn $completionPrefix.Length
if ($null -eq $completions.CompletionMatches) {
$result = "`e]633;Completions`a"
} else {
$result = "`e]633;Completions;$($completions.ReplacementIndex);$($completions.ReplacementLength);"
$serialized = $completions.CompletionMatches | ConvertTo-Json -Compress
$result += $serialized
$result += "`a"
}
Write-Host -NoNewLine $result
}
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 {
# # Conditionally enable suggestions
# if ($env:VSCODE_SUGGEST -eq '1') {
# Remove-Item Env:VSCODE_SUGGEST
# VS Code send completions request (may override Ctrl+Spacebar)
Set-PSReadLineKeyHandler -Chord 'F12,b' -ScriptBlock {
Send-Completions2
}
# MIKE TODO! This is awesome but doesn't work now, because we backspace and
# retype the command, re-triggering the '-' to get sent. Dumb.
# # Suggest trigger characters
# Set-PSReadLineKeyHandler -Chord "-" -ScriptBlock {
# [Microsoft.PowerShell.PSConsoleReadLine]::Insert("-")
# Send-Completions2
# }
# }
}
# Register key handlers if PSReadLine is available
if (Get-Module -Name PSReadLine) {
Set-MappedKeyHandlers
}
@echo off
PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$e[107;30m$T]$e[97;46m$G$P$e[36;49m$G$e[0m$_$e[0m$e[94m%username%$e[0m@$e[32m%computername%$e[0m$G$e]133;B$e
$Global:__LastHistoryId = -1
function Global:__Terminal-Get-LastExitCode {
if ($? -eq $True) {
return 0
}
# TODO: Should we just return a string instead?
# return -1
if ("$LastExitCode" -ne "") { return $LastExitCode }
return -1
}
function prompt {
$gle = $(__Terminal-Get-LastExitCode);
$LastHistoryEntry = $(Get-History -Count 1)
# Skip finishing the command if the first command has not yet started
if ($Global:__LastHistoryId -ne -1) {
if ($LastHistoryEntry.Id -eq $Global:__LastHistoryId) {
# Don't provide a command line or exit code if there was no history entry (eg. ctrl+c, enter on no command)
$out += "`e]133;D`a"
} else {
# Command finished exit code
# OSC 133 ; D [; <ExitCode>] ST
$out += "`e]133;D;$gle`a"
}
}
$loc = $($executionContext.SessionState.Path.CurrentLocation);
# IMPORTANT: Make sure there's a printable charater _last_ in the prompt.
# Otherwise, PSReadline is gonna use the terminating `\` here and colorize
# that if it detects a syntax error
$out += "`e]133;A$([char]07)"; # Prompt started
$out += "`e]9;9;`"$loc`"$([char]07)"; # CWD
$out += "PWSH $loc$('>' * ($nestedPromptLevel + 1)) "; # { your prompt here }
$out += "`e]133;B$([char]07)"; # Prompt ended == Command started
$Global:__LastHistoryId = $LastHistoryEntry.Id
return $out
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment