summaryrefslogtreecommitdiffstats
path: root/src/init
diff options
context:
space:
mode:
authorJoshua Poehls <joshua@poehls.me>2020-09-09 10:52:30 -0500
committerGitHub <noreply@github.com>2020-09-09 11:52:30 -0400
commit2996220568d5dcc437b09dcfa2654a90c3ed9809 (patch)
treeb21585a313bd63ea42100af6d99ead7d27aa073f /src/init
parentd3100c5c822b4ee38d18cad8cb1df31e3a1f2fbc (diff)
fix(pwsh): update init script to propagate $LASTEXITCODE and $?
Previously the prompt function used in PowerShell would overwrite the $LASTEXITCODE and $? automatic variables that were set by the previous command run the user in the shell. This results in surprising behavior for the user if they inspect those variables looking for the result of the command they last ran. This fixes the bug reported here: https://github.com/starship/starship/issues/1051 And goes further to also propagate the $? automatic variable which is not mentioned in that bug.
Diffstat (limited to 'src/init')
-rw-r--r--src/init/starship.ps134
1 files changed, 32 insertions, 2 deletions
diff --git a/src/init/starship.ps1 b/src/init/starship.ps1
index 87cef7c6b..558d9c5ca 100644
--- a/src/init/starship.ps1
+++ b/src/init/starship.ps1
@@ -3,24 +3,54 @@
# Starship assumes UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
function global:prompt {
+ $origDollarQuestion = $global:?
+ $origLastExitCode = $global:LASTEXITCODE
+
$out = $null
# @ makes sure the result is an array even if single or no values are returned
$jobs = @(Get-Job | Where-Object { $_.State -eq 'Running' }).Count
$env:PWD = $PWD
$current_directory = (Convert-Path -LiteralPath $PWD)
+
+ # If an external command has not been executed, then the $LASTEXITCODE will be $null.
+ # For the purposes of the prompt, replace this with a 0 exit code so that the prompt
+ # doesn't show the last command as a failure (because it had a non-zero exit code).
+ $lastExitCodeForPrompt = if ($origLastExitCode) { $origLastExitCode } else { 0 }
if ($lastCmd = Get-History -Count 1) {
$duration = [math]::Round(($lastCmd.EndExecutionTime - $lastCmd.StartExecutionTime).TotalMilliseconds)
# & ensures the path is interpreted as something to execute
- $out = @(&::STARSHIP:: prompt "--path=$current_directory" --status=$lastexitcode --jobs=$jobs --cmd-duration=$duration)
+ $out = @(&::STARSHIP:: prompt "--path=$current_directory" --status=$lastExitCodeForPrompt --jobs=$jobs --cmd-duration=$duration)
} else {
- $out = @(&::STARSHIP:: prompt "--path=$current_directory" --status=$lastexitcode --jobs=$jobs)
+ $out = @(&::STARSHIP:: prompt "--path=$current_directory" --status=$lastExitCodeForPrompt --jobs=$jobs)
}
# Convert stdout (array of lines) to expected return type string
# `n is an escaped newline
$out -join "`n"
+
+ # Propagate the original $LASTEXITCODE from before the prompt function was invoked.
+ $global:LASTEXITCODE = $origLastExitCode
+
+ # Propagate the original $? automatic variable value from before the prompt function was invoked.
+ #
+ # $? is a read-only or constant variable so we can't directly override it.
+ # In order to propagate up its original boolean value we will take an action
+ # which will produce the desired value.
+ #
+ # This has to be the very last thing that happens in the prompt function
+ # since every PowerShell command sets the $? variable.
+ if ($global:? -ne $origDollarQuestion) {
+ if ($origDollarQuestion) {
+ # Simple command which will execute successfully and set $? = True without any other side affects.
+ 1+1
+ } else {
+ # Write-Error will set $? to False.
+ # ErrorAction Ignore will prevent the error from being added to the $Error collection.
+ Write-Error '' -ErrorAction 'Ignore'
+ }
+ }
}
$ENV:STARSHIP_SHELL = "powershell"