summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSegev Finer <segev208@gmail.com>2022-01-14 22:54:29 +0200
committerGitHub <noreply@github.com>2022-01-14 21:54:29 +0100
commit0b6ffca35d7a129bb629a192b51cdfc637b6a4a8 (patch)
treeb1066ff49f81b1bc96249ed7c49b76c876aa76d8
parenta53a99b12aab046f1f5935d4d918d7f0d0ae012d (diff)
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
-rwxr-xr-xsrc/init/starship.ps1241
1 files changed, 120 insertions, 121 deletions
diff --git a/src/init/starship.ps1 b/src/init/starship.ps1
index 266ad2c65..2ae5158ba 100755
--- a/src/init/starship.ps1
+++ b/src/init/starship.ps1
@@ -1,6 +1,8 @@
#!/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 {
$cwd = Get-Location
$provider_prefix = "$($cwd.Provider.ModuleName)\$($cwd.Provider.Name)::"
@@ -9,7 +11,7 @@ function Get-Arguments {
# NOTE: ProviderPath is only a physical filesystem path for the "FileSystem" provider
# E.g. `Dev:\` -> `C:\Users\Joe Bloggs\Dev\`
Path = $cwd.ProviderPath;
- # Resolve the provider-logical path
+ # Resolve the provider-logical path
# NOTE: Attempt to trim any "provider prefix" from the path string.
# E.g. `Microsoft.PowerShell.Core\FileSystem::Dev:\` -> `Dev:\`
LogicalPath =
@@ -21,133 +23,130 @@ function Get-Arguments {
}
}
- # @ makes sure the result is an array even if single or no values are returned
- $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 }
+ function Invoke-Native {
+ param($Executable, $Arguments)
+ $startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $Executable -Property @{
+ StandardOutputEncoding = [System.Text.Encoding]::UTF8;
+ RedirectStandardOutput = $true;
+ RedirectStandardError = $true;
+ CreateNoWindow = $true;
+ UseShellExecute = $false;
+ };
+ if ($startInfo.ArgumentList.Add) {
+ # PowerShell 6+ uses .NET 5+ and supports the ArgumentList property
+ # which bypasses the need for manually escaping the argument list into
+ # a command string.
+ foreach ($arg in $Arguments) {
+ $startInfo.ArgumentList.Add($arg);
+ }
+ }
+ else {
+ # Build an arguments string which follows the C++ command-line argument quoting rules
+ # See: https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)?redirectedfrom=MSDN
+ $escaped = $Arguments | ForEach-Object {
+ $s = $_ -Replace '(\\+)"','$1$1"'; # Escape backslash chains immediately preceding quote marks.
+ $s = $s -Replace '(\\+)$','$1$1'; # Escape backslash chains immediately preceding the end of the string.
+ $s = $s -Replace '"','\"'; # Escape quote marks.
+ "`"$s`"" # Quote the argument.
+ }
+ $startInfo.Arguments = $escaped -Join ' ';
+ }
+ $process = [System.Diagnostics.Process]::Start($startInfo)
+
+ # stderr isn't displayed with this style of invocation
+ # Manually write it to console
+ $stderr = $process.StandardError.ReadToEnd().Trim()
+ if ($stderr -ne '') {
+ # Write-Error doesn't work here
+ $host.ui.WriteErrorLine($stderr)
}
- $duration = [math]::Round(($lastCmd.EndExecutionTime - $lastCmd.StartExecutionTime).TotalMilliseconds)
-
- $arguments += "--cmd-duration=$($duration)"
- }
-
- $arguments += "--status=$($lastExitCodeForPrompt)"
-
- return $arguments
-}
-
-function Invoke-Native {
- param($Executable, $Arguments)
- $startInfo = New-Object System.Diagnostics.ProcessStartInfo -ArgumentList $Executable -Property @{
- StandardOutputEncoding = [System.Text.Encoding]::UTF8;
- RedirectStandardOutput = $true;
- RedirectStandardError = $true;
- CreateNoWindow = $true;
- UseShellExecute = $false;
- };
- if ($startInfo.ArgumentList.Add) {
- # PowerShell 6+ uses .NET 5+ and supports the ArgumentList property
- # which bypasses the need for manually escaping the argument list into
- # a command string.
- foreach ($arg in $Arguments) {
- $startInfo.ArgumentList.Add($arg);
- }
- }
- else {
- # Build an arguments string which follows the C++ command-line argument quoting rules
- # See: https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)?redirectedfrom=MSDN
- $escaped = $Arguments | ForEach-Object {
- $s = $_ -Replace '(\\+)"','$1$1"'; # Escape backslash chains immediately preceding quote marks.
- $s = $s -Replace '(\\+)$','$1$1'; # Escape backslash chains immediately preceding the end of the string.
- $s = $s -Replace '"','\"'; # Escape quote marks.
- "`"$s`"" # Quote the argument.
- }
- $startInfo.Arguments = $escaped -Join ' ';
- }
- $process = [System.Diagnostics.Process]::Start($startInfo)
-
- # stderr isn't displayed with this style of invocation
- # Manually write it to console
- $stderr = $process.StandardError.ReadToEnd().Trim()
- if ($stderr -ne '') {
- # Write-Error doesn't work here
- $host.ui.WriteErrorLine($stderr)
- }
-
- $process.StandardOutput.ReadToEnd();
-}
-function global:prompt {
- $origDollarQuestion = $global:?
- $origLastExitCode = $global:LASTEXITCODE
+ $process.StandardOutput.ReadToEnd();
+ }
- # Invoke precmd, if specified
- try {
- if (Test-Path function:Invoke-Starship-PreCommand) {
- Invoke-Starship-PreCommand
+ function global:prompt {
+ $origDollarQuestion = $global:?
+ $origLastExitCode = $global:LASTEXITCODE
+
+ # Invoke precmd, if specified
+ try {
+ if (Test-Path function:Invoke-Starship-PreCommand) {
+ Invoke-Starship-PreCommand
+ }
+ } catch {}
+
+ # @ makes sure the result is an array even if single or no values are returned
+ $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)"
}
- } catch {}
-
- # Get arguments for starship prompt
- $arguments = Get-Arguments
-
- # Invoke Starship
- Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments
-
- # 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'
+
+ $arguments += "--status=$($lastExitCodeForPrompt)"
+
+ # Invoke Starship
+ Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments
+
+ # 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'
+ }
}
- }
-}
+ }
-# Get arguments for starship continuation prompt
-$arguments = Get-Arguments
-$arguments += "--continuation"
+ # Disable virtualenv prompt, it breaks starship
+ $ENV:VIRTUAL_ENV_DISABLE_PROMPT=1
-# Invoke Starship and set continuation prompt
-$continuation = Invoke-Native -Executable ::STARSHIP:: -Arguments $arguments
-Set-PSReadLineOption -ContinuationPrompt $continuation
+ $ENV:STARSHIP_SHELL = "powershell"
-# Disable virtualenv prompt, it breaks starship
-$ENV:VIRTUAL_ENV_DISABLE_PROMPT=1
+ # 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]$_ })
-$ENV:STARSHIP_SHELL = "powershell"
+ # Invoke Starship and set continuation prompt
+ Set-PSReadLineOption -ContinuationPrompt (
+ Invoke-Native -Executable ::STARSHIP:: -Arguments @(
+ "prompt",
+ "--continuation"
+ )
+ )
-# 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]$_ })
+ Export-ModuleMember
+}