Skip to content

Commit d27fe8c

Browse files
Update VS Code shell integration script (#1982)
1 parent c1733a1 commit d27fe8c

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs

+21-5
Original file line numberDiff line numberDiff line change
@@ -503,11 +503,10 @@ internal Task LoadHostProfilesAsync(CancellationToken cancellationToken)
503503

504504
private Task EnableShellIntegrationAsync(CancellationToken cancellationToken)
505505
{
506-
// Imported on 11/17/22 from
506+
// Imported on 01/03/23 from
507507
// https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/terminal/browser/media/shellIntegration.ps1
508508
// with quotes escaped, `__VSCodeOriginalPSConsoleHostReadLine` removed (as it's done
509509
// in our own ReadLine function), and `[Console]::Write` replaced with `Write-Host`.
510-
// TODO: We can probably clean some of this up.
511510
const string shellIntegrationScript = @"
512511
# Prevent installing more than once per session
513512
if (Test-Path variable:global:__VSCodeOriginalPrompt) {
@@ -523,8 +522,21 @@ private Task EnableShellIntegrationAsync(CancellationToken cancellationToken)
523522
524523
$Global:__LastHistoryId = -1
525524
525+
function Global:__VSCode-Escape-Value([string]$value) {
526+
# NOTE: In PowerShell v6.1+, this can be written `$value -replace '…', { … }` instead of `[regex]::Replace`.
527+
# Replace any non-alphanumeric characters.
528+
[regex]::Replace($value, '[\\\n;]', { param($match)
529+
# Encode the (ascii) matches as `\x<hex>`
530+
-Join (
531+
[System.Text.Encoding]::UTF8.GetBytes($match.Value) | ForEach-Object { '\x{0:x2}' -f $_ }
532+
)
533+
})
534+
}
526535
527536
function Global:Prompt() {
537+
# NOTE: We disable strict mode for the scope of this function because it unhelpfully throws an
538+
# error when $LastHistoryEntry is null, and is not otherwise useful.
539+
Set-StrictMode -Off
528540
$FakeCode = [int]!$global:?
529541
$LastHistoryEntry = Get-History -Count 1
530542
# Skip finishing the command if the first command has not yet started
@@ -545,7 +557,7 @@ private Task EnableShellIntegrationAsync(CancellationToken cancellationToken)
545557
} else {
546558
$CommandLine = """"
547559
}
548-
$Result += $CommandLine.Replace(""\"", ""\\"").Replace(""`n"", ""\x0a"").Replace("";"", ""\x3b"")
560+
$Result += $(__VSCode-Escape-Value $CommandLine)
549561
$Result += ""`a""
550562
# Command finished exit code
551563
# OSC 633 ; D [; <ExitCode>] ST
@@ -557,9 +569,11 @@ private Task EnableShellIntegrationAsync(CancellationToken cancellationToken)
557569
$Result += ""$([char]0x1b)]633;A`a""
558570
# Current working directory
559571
# OSC 633 ; <Property>=<Value> ST
560-
$Result += if($pwd.Provider.Name -eq 'FileSystem'){""$([char]0x1b)]633;P;Cwd=$($pwd.ProviderPath)`a""}
572+
$Result += if($pwd.Provider.Name -eq 'FileSystem'){""$([char]0x1b)]633;P;Cwd=$(__VSCode-Escape-Value $pwd.ProviderPath)`a""}
561573
# Before running the original prompt, put $? back to what it was:
562-
if ($FakeCode -ne 0) { Write-Error ""failure"" -ea ignore }
574+
if ($FakeCode -ne 0) {
575+
Write-Error ""failure"" -ea ignore
576+
}
563577
# Run the original prompt
564578
$Result += $Global:__VSCodeOriginalPrompt.Invoke()
565579
# Write command started
@@ -579,12 +593,14 @@ function Set-MappedKeyHandler {
579593
Set-PSReadLineKeyHandler -Chord $Sequence -Function $Handler.Function
580594
}
581595
}
596+
582597
function Set-MappedKeyHandlers {
583598
Set-MappedKeyHandler -Chord Ctrl+Spacebar -Sequence 'F12,a'
584599
Set-MappedKeyHandler -Chord Alt+Spacebar -Sequence 'F12,b'
585600
Set-MappedKeyHandler -Chord Shift+Enter -Sequence 'F12,c'
586601
Set-MappedKeyHandler -Chord Shift+End -Sequence 'F12,d'
587602
}
603+
588604
Set-MappedKeyHandlers
589605
";
590606

0 commit comments

Comments
 (0)