fix(pwsh): Avoid polluting the global function namespace (#3424)

* fix(pwsh): Avoid polluting the global function namespace

This is an alternative to #3386

* Review changes

* Move continuation prompt after setting starship env
This commit is contained in:
Segev Finer 2022-01-14 22:54:29 +02:00 committed by GitHub
parent a53a99b12a
commit 0b6ffca35d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,8 @@
#!/usr/bin/env pwsh #!/usr/bin/env pwsh
function Get-Arguments { # Create a new dynamic module so we don't pollute the global namespace with our functions and
# variables
$null = New-Module starship {
function Get-Cwd { function Get-Cwd {
$cwd = Get-Location $cwd = Get-Location
$provider_prefix = "$($cwd.Provider.ModuleName)\$($cwd.Provider.Name)::" $provider_prefix = "$($cwd.Provider.ModuleName)\$($cwd.Provider.Name)::"
@ -21,40 +23,7 @@ function Get-Arguments {
} }
} }
# @ makes sure the result is an array even if single or no values are returned function Invoke-Native {
$jobs = @(Get-Job | Where-Object { $_.State -eq 'Running' }).Count
$cwd = Get-Cwd
$arguments = @(
"prompt"
"--path=$($cwd.Path)",
"--logical-path=$($cwd.LogicalPath)",
"--terminal-width=$($Host.UI.RawUI.WindowSize.Width)",
"--jobs=$($jobs)"
)
# Whe start from the premise that the command executed correctly, which covers also the fresh console.
$lastExitCodeForPrompt = 0
if ($lastCmd = Get-History -Count 1) {
# In case we have a False on the Dollar hook, we know there's an error.
if (-not $origDollarQuestion) {
# We retrieve the InvocationInfo from the most recent error using $error[0]
$lastCmdletError = try { $error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo } catch { $null }
# We check if the last command executed matches the line that caused the last error, in which case we know
# it was an internal Powershell command, otherwise, there MUST be an error code.
$lastExitCodeForPrompt = if ($null -ne $lastCmdletError -and $lastCmd.CommandLine -eq $lastCmdletError.Line) { 1 } else { $origLastExitCode }
}
$duration = [math]::Round(($lastCmd.EndExecutionTime - $lastCmd.StartExecutionTime).TotalMilliseconds)
$arguments += "--cmd-duration=$($duration)"
}
$arguments += "--status=$($lastExitCodeForPrompt)"
return $arguments
}
function Invoke-Native {
param($Executable, $Arguments) param($Executable, $Arguments)
$startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $Executable -Property @{ $startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $Executable -Property @{
StandardOutputEncoding = [System.Text.Encoding]::UTF8; StandardOutputEncoding = [System.Text.Encoding]::UTF8;
@ -93,9 +62,9 @@ function Invoke-Native {
} }
$process.StandardOutput.ReadToEnd(); $process.StandardOutput.ReadToEnd();
} }
function global:prompt { function global:prompt {
$origDollarQuestion = $global:? $origDollarQuestion = $global:?
$origLastExitCode = $global:LASTEXITCODE $origLastExitCode = $global:LASTEXITCODE
@ -106,8 +75,35 @@ function global:prompt {
} }
} catch {} } catch {}
# Get arguments for starship prompt # @ makes sure the result is an array even if single or no values are returned
$arguments = Get-Arguments $jobs = @(Get-Job | Where-Object { $_.State -eq 'Running' }).Count
$cwd = Get-Cwd
$arguments = @(
"prompt"
"--path=$($cwd.Path)",
"--logical-path=$($cwd.LogicalPath)",
"--terminal-width=$($Host.UI.RawUI.WindowSize.Width)",
"--jobs=$($jobs)"
)
# Whe start from the premise that the command executed correctly, which covers also the fresh console.
$lastExitCodeForPrompt = 0
if ($lastCmd = Get-History -Count 1) {
# In case we have a False on the Dollar hook, we know there's an error.
if (-not $origDollarQuestion) {
# We retrieve the InvocationInfo from the most recent error using $error[0]
$lastCmdletError = try { $error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo } catch { $null }
# We check if the last command executed matches the line that caused the last error, in which case we know
# it was an internal Powershell command, otherwise, there MUST be an error code.
$lastExitCodeForPrompt = if ($null -ne $lastCmdletError -and $lastCmd.CommandLine -eq $lastCmdletError.Line) { 1 } else { $origLastExitCode }
}
$duration = [math]::Round(($lastCmd.EndExecutionTime - $lastCmd.StartExecutionTime).TotalMilliseconds)
$arguments += "--cmd-duration=$($duration)"
}
$arguments += "--status=$($lastExitCodeForPrompt)"
# Invoke Starship # Invoke Starship
Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments
@ -134,20 +130,23 @@ function global:prompt {
} }
} }
}
# Disable virtualenv prompt, it breaks starship
$ENV:VIRTUAL_ENV_DISABLE_PROMPT=1
$ENV:STARSHIP_SHELL = "powershell"
# Set up the session key that will be used to store logs
$ENV:STARSHIP_SESSION_KEY = -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 16 | ForEach-Object { [char]$_ })
# Invoke Starship and set continuation prompt
Set-PSReadLineOption -ContinuationPrompt (
Invoke-Native -Executable ::STARSHIP:: -Arguments @(
"prompt",
"--continuation"
)
)
Export-ModuleMember
} }
# Get arguments for starship continuation prompt
$arguments = Get-Arguments
$arguments += "--continuation"
# Invoke Starship and set continuation prompt
$continuation = Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments
Set-PSReadLineOption -ContinuationPrompt $continuation
# Disable virtualenv prompt, it breaks starship
$ENV:VIRTUAL_ENV_DISABLE_PROMPT=1
$ENV:STARSHIP_SHELL = "powershell"
# Set up the session key that will be used to store logs
$ENV:STARSHIP_SESSION_KEY = -join ((48..57) + (65..90) + (97..122) | Get-Random -Count 16 | ForEach-Object { [char]$_ })