diff --git a/src/WindowTitle.ps1 b/src/WindowTitle.ps1 new file mode 100644 index 000000000..9fbc00733 --- /dev/null +++ b/src/WindowTitle.ps1 @@ -0,0 +1,60 @@ +$HostSupportsSettingWindowTitle = $null +$OriginalWindowTitle = $null + +function Test-WindowTitleIsWriteable { + if ($null -eq $HostSupportsSettingWindowTitle) { + # Probe $Host.UI.RawUI.WindowTitle to see if it can be set without errors + try { + $script:OriginalWindowTitle = $Host.UI.RawUI.WindowTitle + $newTitle = "${OriginalWindowTitle} " + $Host.UI.RawUI.WindowTitle = $newTitle + $script:HostSupportsSettingWindowTitle = ($Host.UI.RawUI.WindowTitle -eq $newTitle) + $Host.UI.RawUI.WindowTitle = $OriginalWindowTitle + Write-Debug "HostSupportsSettingWindowTitle: $HostSupportsSettingWindowTitle" + Write-Debug "OriginalWindowTitle: $OriginalWindowTitle" + } + catch { + $script:OriginalWindowTitle = $null + $script:HostSupportsSettingWindowTitle = $false + Write-Debug "HostSupportsSettingWindowTitle error: $_" + } + } + return $HostSupportsSettingWindowTitle +} + +function Reset-WindowTitle { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + param() + $settings = $global:GitPromptSettings + + # Revert to original WindowTitle, but only if posh-git is currently configured to set it + if ($HostSupportsSettingWindowTitle -and $OriginalWindowTitle -and $settings.WindowTitle) { + Write-Debug "Resetting WindowTitle: '$OriginalWindowTitle'" + $Host.UI.RawUI.WindowTitle = $OriginalWindowTitle + } +} + +function Set-WindowTitle { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + param($GitStatus, $IsAdmin) + $settings = $global:GitPromptSettings + + # Update the host's WindowTitle if host supports it and user has not disabled $GitPromptSettings.WindowTitle + if ($settings.WindowTitle -and (Test-WindowTitleIsWriteable)) { + try { + if ($settings.WindowTitle -is [scriptblock]) { + # ensure results returned by scriptblock are flattened into a string + $windowTitleText = "$(& $settings.WindowTitle $GitStatus $IsAdmin)" + } + else { + $windowTitleText = $ExecutionContext.SessionState.InvokeCommand.ExpandString("$($settings.WindowTitle)") + } + + Write-Debug "Setting WindowTitle: $windowTitleText" + $Host.UI.RawUI.WindowTitle = "$windowTitleText" + } + catch { + Write-Debug "Error occurred during evaluation of `$GitPromptSettings.WindowTitle: $_" + } + } +} diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index 279171537..2afcce73a 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -5,6 +5,7 @@ param([switch]$NoVersionWarn, [switch]$ForcePoshGitPrompt) . $PSScriptRoot\ConsoleMode.ps1 . $PSScriptRoot\Utils.ps1 . $PSScriptRoot\AnsiUtils.ps1 +. $PSScriptRoot\WindowTitle.ps1 . $PSScriptRoot\PoshGitTypes.ps1 . $PSScriptRoot\GitUtils.ps1 . $PSScriptRoot\GitPrompt.ps1 @@ -17,19 +18,6 @@ if (!$Env:HOME) { $Env:HOME = "$Env:USERPROFILE" } $IsAdmin = Test-Administrator -# Probe $Host.UI.RawUI.WindowTitle to see if it can be set without errors -$WindowTitleSupported = $false -try { - $global:PreviousWindowTitle = $Host.UI.RawUI.WindowTitle - $newTitle = "${global:PreviousWindowTitle} " - $Host.UI.RawUI.WindowTitle = $newTitle - $WindowTitleSupported = ($Host.UI.RawUI.WindowTitle -eq $newTitle) - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle -} -catch { - Write-Debug "Probing for WindowTitleSupported errored: $_" -} - # Get the default prompt definition. $initialSessionState = [Runspace]::DefaultRunspace.InitialSessionState if (!$initialSessionState.Commands -or !$initialSessionState.Commands['prompt']) { @@ -43,10 +31,6 @@ else { $GitPromptScriptBlock = { $settings = $global:GitPromptSettings if (!$settings) { - if ($WindowTitleSupported -and $global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } - return "<`$GitPromptSettings not found> " } @@ -92,36 +76,8 @@ $GitPromptScriptBlock = { $promptSuffix.Text = $promptSuffix.Text.Substring(0, $promptSuffix.Text.Length - 1) } - # Update the host's WindowTitle is host supports it and user has not disabled $GitPromptSettings.WindowTitle # This has to be *after* the call to Write-VcsStatus, which populates $global:GitStatus - if ($WindowTitleSupported) { - $windowTitle = $settings.WindowTitle - if (!$windowTitle) { - if ($global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } - } - else { - try { - if ($windowTitle -is [scriptblock]) { - $windowTitleText = & $windowTitle $global:GitStatus $IsAdmin - } - else { - $windowTitleText = $ExecutionContext.SessionState.InvokeCommand.ExpandString("$windowTitle") - } - - # Put $windowTitleText in a string to ensure results returned by scriptblock are flattened to a string - $Host.UI.RawUI.WindowTitle = "$windowTitleText" - } - catch { - if ($global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } - - Write-Debug "Error occurred during evaluation of `$GitPromptSettings.WindowTitle: $_" - } - } - } + Set-WindowTitle $global:GitStatus $IsAdmin # If prompt timing enabled, write elapsed milliseconds if ($settings.DefaultPromptEnableTiming) { @@ -171,10 +127,7 @@ if ($ForcePoshGitPrompt -or !$currentPromptDef -or ($currentPromptDef -eq $defau $ExecutionContext.SessionState.Module.OnRemove = { $global:VcsPromptStatuses = $global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt } - # Revert original WindowTitle - if ($WindowTitleSupported -and $global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } + Reset-WindowTitle # Check if the posh-git prompt function itself has been replaced. If so, do not restore the prompt function $promptDef = if ($funcInfo = Get-Command prompt -ErrorAction SilentlyContinue) { $funcInfo.Definition }