refactor(pwsh): unify logic of generating prompts

This commit is contained in:
L. Yeung 2022-07-28 16:07:41 +08:00 committed by Jan De Dobbeleer
parent c22d0d67be
commit 6723cba4b2
2 changed files with 59 additions and 43 deletions

View file

@ -15,13 +15,14 @@ function global:Get-PoshStackCount {
New-Module -Name "oh-my-posh-core" -ScriptBlock { New-Module -Name "oh-my-posh-core" -ScriptBlock {
$script:ErrorCode = 0 $script:ErrorCode = 0
$script:OMPExecutable = '::OMP::' $script:OMPExecutable = "::OMP::"
$script:ShellName = "::SHELL::"
$script:PSVersion = $PSVersionTable.PSVersion.ToString() $script:PSVersion = $PSVersionTable.PSVersion.ToString()
$script:TransientPrompt = $false $script:TransientPrompt = $false
$env:POWERLINE_COMMAND = "oh-my-posh" $env:POWERLINE_COMMAND = "oh-my-posh"
$env:CONDA_PROMPT_MODIFIER = $false $env:CONDA_PROMPT_MODIFIER = $false
if ('::CONFIG::' -ne '' -and (Test-Path '::CONFIG::')) { if (("::CONFIG::" -ne '') -and (Test-Path "::CONFIG::")) {
$env:POSH_THEME = (Resolve-Path -Path '::CONFIG::').ProviderPath $env:POSH_THEME = (Resolve-Path -Path "::CONFIG::").ProviderPath
} }
# specific module support (disabled by default) # specific module support (disabled by default)
if ($null -eq $env:POSH_GIT_ENABLED) { if ($null -eq $env:POSH_GIT_ENABLED) {
@ -106,7 +107,7 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
$cleanPWD, $cleanPSWD = Get-PoshContext $cleanPWD, $cleanPSWD = Get-PoshContext
$command = $null $command = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null) [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
$standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", "tooltip", "--pwd=$cleanPWD", "--shell=::SHELL::", "--pswd=$cleanPSWD", "--config=$env:POSH_THEME", "--command=$command", "--shell-version=$script:PSVersion")) $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", "tooltip", "--pwd=$cleanPWD", "--shell=$script:ShellName", "--pswd=$cleanPSWD", "--config=$env:POSH_THEME", "--command=$command", "--shell-version=$script:PSVersion"))
Write-Host $standardOut -NoNewline Write-Host $standardOut -NoNewline
$host.UI.RawUI.CursorPosition = $position $host.UI.RawUI.CursorPosition = $position
} }
@ -138,8 +139,8 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
} }
function Enable-PoshLineError { function Enable-PoshLineError {
$validLine = @(Start-Utf8Process $script:OMPExecutable @("print", "valid", "--config=$env:POSH_THEME", "--shell=::SHELL::")) -join "`n" $validLine = @(Start-Utf8Process $script:OMPExecutable @("print", "valid", "--config=$env:POSH_THEME", "--shell=$script:ShellName")) -join "`n"
$errorLine = @(Start-Utf8Process $script:OMPExecutable @("print", "error", "--config=$env:POSH_THEME", "--shell=::SHELL::")) -join "`n" $errorLine = @(Start-Utf8Process $script:OMPExecutable @("print", "error", "--config=$env:POSH_THEME", "--shell=$script:ShellName")) -join "`n"
Set-PSReadLineOption -PromptText $validLine, $errorLine Set-PSReadLineOption -PromptText $validLine, $errorLine
} }
@ -245,7 +246,7 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
} else { } else {
$themes | ForEach-Object -Process { $themes | ForEach-Object -Process {
Write-Host "Theme: $(Get-FileHyperlink -uri $_.FullName -Name ($_.BaseName -replace '\.omp$', ''))`n" Write-Host "Theme: $(Get-FileHyperlink -uri $_.FullName -Name ($_.BaseName -replace '\.omp$', ''))`n"
@(Start-Utf8Process $script:OMPExecutable @("print", "primary", "--config=$($_.FullName)", "--pwd=$PWD", "--shell=::SHELL::")) @(Start-Utf8Process $script:OMPExecutable @("print", "primary", "--config=$($_.FullName)", "--pwd=$PWD", "--shell=$script:ShellName"))
Write-Host "`n" Write-Host "`n"
} }
} }
@ -260,33 +261,36 @@ Example:
"@ "@
} }
function prompt { function Set-PoshPromptType {
# store if the last command was successful
$lastCommandSuccess = $?
# store the last exit code for restore
$realLASTEXITCODE = $global:LASTEXITCODE
$cleanPWD, $cleanPSWD = Get-PoshContext
if ($script:TransientPrompt -eq $true) { if ($script:TransientPrompt -eq $true) {
@(Start-Utf8Process $script:OMPExecutable @("print", "transient", "--error=$script:ErrorCode", "--pwd=$cleanPWD", "--pswd=$cleanPSWD", "--execution-time=$script:ExecutionTime", "--config=$env:POSH_THEME", "--shell-version=$script:PSVersion", "--shell=::SHELL::")) -join "`n" $script:PromptType = "transient"
$script:TransientPrompt = $false $script:TransientPrompt = $false
return return
} }
# see https://github.com/JanDeDobbeleer/oh-my-posh/issues/2483#issuecomment-1175761456 # for details about the trick to detect a debugging context, see these comments:
# and https://github.com/JanDeDobbeleer/oh-my-posh/issues/2502#issuecomment-1179968052 # 1) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2483#issuecomment-1175761456
# 2) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2502#issuecomment-1179968052
if (-not ((Get-PSCallStack).Location -join "").StartsWith("<")) { if (-not ((Get-PSCallStack).Location -join "").StartsWith("<")) {
@(Start-Utf8Process $script:OMPExecutable @("print", "debug", "--pwd=$cleanPWD", "--pswd=$cleanPSWD", "--config=$env:POSH_THEME", "--shell=::SHELL::")) -join "`n" $script:PromptType = "debug"
return return
} }
$script:PromptType = "primary"
Initialize-ModuleSupport Initialize-ModuleSupport
}
function Update-PoshErrorCode {
$script:ExecutionTime = -1 $script:ExecutionTime = -1
$lastHistory = Get-History -ErrorAction Ignore -Count 1 $lastHistory = Get-History -ErrorAction Ignore -Count 1
if ($null -ne $lastHistory -and $script:LastHistoryId -ne $lastHistory.Id) { # error code should be updated only when a non-empty command is run
if (($null -eq $lastHistory) -or ($script:LastHistoryId -eq $lastHistory.Id)) {
return
}
$script:LastHistoryId = $lastHistory.Id $script:LastHistoryId = $lastHistory.Id
$script:ExecutionTime = ($lastHistory.EndExecutionTime - $lastHistory.StartExecutionTime).TotalMilliseconds $script:ExecutionTime = ($lastHistory.EndExecutionTime - $lastHistory.StartExecutionTime).TotalMilliseconds
# error code should be changed only when a non-empty command is called if ($script:OriginalLastExecutionStatus) {
$script:ErrorCode = 0 $script:ErrorCode = 0
if (!$lastCommandSuccess) { return
}
$invocationInfo = try { $invocationInfo = try {
# retrieve info of the most recent error # retrieve info of the most recent error
$global:Error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo $global:Error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo
@ -294,13 +298,25 @@ Example:
# check if the last command caused the last error # check if the last command caused the last error
if ($null -ne $invocationInfo -and $lastHistory.CommandLine -eq $invocationInfo.Line) { if ($null -ne $invocationInfo -and $lastHistory.CommandLine -eq $invocationInfo.Line) {
$script:ErrorCode = 1 $script:ErrorCode = 1
} elseif ($realLASTEXITCODE -is [int] -and $realLASTEXITCODE -ne 0) { return
# native app exit code
$script:ErrorCode = $realLASTEXITCODE
} }
if ($script:OriginalLastExitCode -is [int] -and $script:OriginalLastExitCode -ne 0) {
# native app exit code
$script:ErrorCode = $script:OriginalLastExitCode
return
} }
} }
function prompt {
# store the orignal last command execution status and last exit code
$script:OriginalLastExecutionStatus = $?
$script:OriginalLastExitCode = $global:LASTEXITCODE
Set-PoshPromptType
if ($script:PromptType -ne 'transient') {
Update-PoshErrorCode
}
$cleanPWD, $cleanPSWD = Get-PoshContext
$stackCount = global:Get-PoshStackCount $stackCount = global:Get-PoshStackCount
Set-PoshContext Set-PoshContext
$terminalWidth = $Host.UI.RawUI.WindowSize.Width $terminalWidth = $Host.UI.RawUI.WindowSize.Width
@ -308,19 +324,18 @@ Example:
if (-not $terminalWidth) { if (-not $terminalWidth) {
$terminalWidth = 0 $terminalWidth = 0
} }
$standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", "primary", "--error=$script:ErrorCode", "--pwd=$cleanPWD", "--pswd=$cleanPSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--config=$env:POSH_THEME", "--shell-version=$script:PSVersion", "--terminal-width=$terminalWidth", "--shell=::SHELL::")) $standardOut = @(Start-Utf8Process $script:OMPExecutable @("print", $script:PromptType, "--error=$script:ErrorCode", "--pwd=$cleanPWD", "--pswd=$cleanPSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--config=$env:POSH_THEME", "--shell-version=$script:PSVersion", "--terminal-width=$terminalWidth", "--shell=$script:ShellName"))
# make sure PSReadLine knows we have a multiline prompt # make sure PSReadLine knows if we have a multiline prompt
$extraLines = ($standardOut | Measure-Object -Line).Lines - 1 Set-PSReadLineOption -ExtraPromptLineCount (($standardOut | Measure-Object -Line).Lines - 1)
if ($extraLines -gt 0) {
Set-PSReadLineOption -ExtraPromptLineCount $extraLines
}
# the output can be multiline, joining these ensures proper rendering by adding line breaks with `n # the output can be multiline, joining these ensures proper rendering by adding line breaks with `n
$standardOut -join "`n" $standardOut -join "`n"
$global:LASTEXITCODE = $realLASTEXITCODE
# restore the orignal last exit code
$global:LASTEXITCODE = $script:OriginalLastExitCode
} }
# set secondary prompt # set secondary prompt
Set-PSReadLineOption -ContinuationPrompt (@(Start-Utf8Process $script:OMPExecutable @("print", "secondary", "--config=$env:POSH_THEME", "--shell=::SHELL::")) -join "`n") Set-PSReadLineOption -ContinuationPrompt (@(Start-Utf8Process $script:OMPExecutable @("print", "secondary", "--config=$env:POSH_THEME", "--shell=$script:ShellName")) -join "`n")
Export-ModuleMember -Function @( Export-ModuleMember -Function @(
"Set-PoshContext" "Set-PoshContext"

View file

@ -49,6 +49,7 @@ properties below - defaults to `[DBG]: `
- `.Shell`: `string` - the current shell name - `.Shell`: `string` - the current shell name
- `.UserName`: `string` - the current user name - `.UserName`: `string` - the current user name
- `.HostName`: `string` - the host name - `.HostName`: `string` - the host name
- `.Code`: `int` - the last exit code
- `.Env.VarName`: `string` - Any environment variable where `VarName` is the environment variable name - `.Env.VarName`: `string` - Any environment variable where `VarName` is the environment variable name
[go-text-template]: https://golang.org/pkg/text/template/ [go-text-template]: https://golang.org/pkg/text/template/