From e0ceaba24349f5d882d380561bf966d974dbe196 Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Wed, 24 Jan 2018 23:03:12 -0700 Subject: [PATCH 1/7] WIP - initial, working commit Needs more Pester tests. --- src/GitPrompt.ps1 | 50 +++++++++++++++++++---------- src/GitUtils.ps1 | 1 + src/PoshGitTypes.ps1 | 7 ++-- test/DefaultPrompt.Tests.ps1 | 62 ++++++++++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 21 deletions(-) diff --git a/src/GitPrompt.ps1 b/src/GitPrompt.ps1 index 137dc8be9..379ef26ea 100644 --- a/src/GitPrompt.ps1 +++ b/src/GitPrompt.ps1 @@ -1,7 +1,7 @@ # Inspired by Mark Embling # http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration -$global:GitPromptSettings = [GitPromptSettings]::new() +$global:GitPromptSettings = [PoshGitPromptSettings]::new() # Override some of the normal colors if the background color is set to the default DarkMagenta. $s = $global:GitPromptSettings @@ -13,15 +13,19 @@ if ($Host.UI.RawUI.BackgroundColor -eq [ConsoleColor]::DarkMagenta) { $s.WorkingColor.ForegroundColor = 'Red' } -$isAdminProcess = Test-Administrator -$adminHeader = if ($isAdminProcess) { 'Administrator: ' } else { '' } +$IsAdmin = Test-Administrator -$WindowTitleSupported = $true -# TODO: Hmm, this is a curious way to detemine window title supported -# Could do $host.Name -eq "Package Manager Host" but that is kinda specific -# Could attempt to change it and catch any exception and then set this to $false -if (Get-Module NuGet) { - $WindowTitleSupported = $false +# Probe $Host.UI.RawUI.WindowTitle to see if it can be set without errors +$WindowTitleSupported = $false +try { + $global:PreviousWindowTitle = $Host.UI.RawUI.WindowTitle + $newTitle = "$origTitle " + $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: $_" } <# @@ -218,14 +222,28 @@ function Write-GitStatus { $sb | Write-Prompt $s.AfterText > $null - if ($WindowTitleSupported -and $s.EnableWindowTitle) { - if (!$global:PreviousWindowTitle) { - $global:PreviousWindowTitle = $Host.UI.RawUI.WindowTitle + if ($WindowTitleSupported) { + if (!$s.EnableWindowTitle) { + if ($global:PreviousWindowTitle) { + $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle + } + } + else { + try { + if ($s.WindowTitle -is [scriptblock]) { + $windowTitleText = & $s.WindowTitle $Status $IsAdmin + } + else { + $windowTitleText = $ExecutionContext.SessionState.InvokeCommand.ExpandString("$($s.WindowTitle)") + } + + # Put $windowTitleText in a string to ensure results returned by scriptblock are flattened to a string + $Host.UI.RawUI.WindowTitle = "$windowTitleText" + } + catch { + Write-Debug "Error occurred during evaluation of `$GitPromptSettings.WindowTitle: $_" + } } - - $repoName = Split-Path -Leaf (Split-Path $status.GitDir) - $prefix = if ($s.EnableWindowTitle -is [string]) { $s.EnableWindowTitle } else { '' } - $Host.UI.RawUI.WindowTitle = "${script:adminHeader}${prefix}${repoName} [$($Status.Branch)]" } return $sb.ToString() diff --git a/src/GitUtils.ps1 b/src/GitUtils.ps1 index de19bdcec..1a46d35df 100644 --- a/src/GitUtils.ps1 +++ b/src/GitUtils.ps1 @@ -340,6 +340,7 @@ function Get-GitStatus { $result = New-Object PSObject -Property @{ GitDir = $GitDir + RepoName = Split-Path (Split-Path $GitDir -Parent) -Leaf Branch = $branch AheadBy = $aheadBy BehindBy = $behindBy diff --git a/src/PoshGitTypes.ps1 b/src/PoshGitTypes.ps1 index f5fd7e410..340ff1481 100644 --- a/src/PoshGitTypes.ps1 +++ b/src/PoshGitTypes.ps1 @@ -197,7 +197,7 @@ class PoshGitTextSpan { } } -class GitPromptSettings { +class PoshGitPromptSettings { [bool]$AnsiConsole = $Host.UI.SupportsVirtualTerminal -or ($Env:ConEmuANSI -eq "ON") [PoshGitCellColor]$DefaultColor = [PoshGitCellColor]::new() @@ -244,8 +244,9 @@ class GitPromptSettings { [Nullable[bool]]$EnableFileStatusFromCache = $null [string[]]$RepositoriesInWhichToDisableFileStatus = @() - [string]$DescribeStyle = '' - [psobject]$EnableWindowTitle = 'posh~git ~ ' + [string]$DescribeStyle = '' + [bool]$EnableWindowTitle = $true + [psobject]$WindowTitle = {param($GitStatus, [bool]$IsAdmin) "$(if ($IsAdmin) {'Admin: '})posh~git ~ $($GitStatus.RepoName) [$($GitStatus.Branch)]"} [PoshGitTextSpan]$DefaultPromptPrefix = '' [PoshGitTextSpan]$DefaultPromptSuffix = '$(''>'' * ($nestedPromptLevel + 1)) ' diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 92eebfab8..56b5ddf48 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -7,7 +7,7 @@ Describe 'Default Prompt Tests - NO ANSI' { } BeforeEach { # Ensure these settings start out set to the default values - $global:GitPromptSettings = & $module.NewBoundScriptBlock({[GitPromptSettings]::new()}) + $global:GitPromptSettings = & $module.NewBoundScriptBlock({[PoshGitPromptSettings]::new()}) $GitPromptSettings.AnsiConsole = $false } @@ -99,7 +99,7 @@ Describe 'Default Prompt Tests - ANSI' { } BeforeEach { # Ensure these settings start out set to the default values - $global:GitPromptSettings = & $module.NewBoundScriptBlock({[GitPromptSettings]::new()}) + $global:GitPromptSettings = & $module.NewBoundScriptBlock({[PoshGitPromptSettings]::new()}) $GitPromptSettings.AnsiConsole = $true } @@ -194,3 +194,61 @@ A test/Foo.Tests.ps1 } } } + +Describe 'Default Prompt Window Title Tests' { + BeforeEach { + # Ensure these settings start out set to the default values + $defaultTitle = if ($IsWindows) { "Windows PowerShell" } else { "PowerShell-$($PSVersionTable.PSVersion)" } + $Host.UI.RawUI.WindowTitle = $defaultTitle + $global:PreviousWindowTitle = $defaultTitle + $global:GitPromptSettings = & $module.NewBoundScriptBlock({[PoshGitPromptSettings]::new()}) + } + + Context 'Default WindowTitle / EnableWindowTitle work ' { + It 'Sets the expected Window title text' { + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## master +A test/Foo.Tests.ps1 + D test/Bar.Tests.ps1 + M test/Baz.Tests.ps1 + +'@ + } + + Set-Location $PSScriptRoot + & $GitPromptScriptBlock *>$null + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '(Admin: )?posh~git ~ posh-git \[master\]' + } + It 'Does not set Window title when EnableWindowText is $false' { + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## master +A test/Foo.Tests.ps1 + D test/Bar.Tests.ps1 + M test/Baz.Tests.ps1 + +'@ + } + + Set-Location $PSScriptRoot + $GitPromptSettings.EnableWindowTitle = 0 + & $GitPromptScriptBlock *>$null + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } + } +} From 7c86bf7e759d201590ed3ddc6c963037df9fb3f8 Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Thu, 25 Jan 2018 19:45:38 -0700 Subject: [PATCH 2/7] Remove EnableWindowTitle, move WindowTitle code to prompt func Add more Pester tests. --- src/GitPrompt.ps1 | 48 +----------- src/PoshGitTypes.ps1 | 3 +- src/posh-git.psm1 | 49 +++++++++++++ test/DefaultPrompt.Tests.ps1 | 138 ++++++++++++++++++++++++++++------- 4 files changed, 162 insertions(+), 76 deletions(-) diff --git a/src/GitPrompt.ps1 b/src/GitPrompt.ps1 index 379ef26ea..b891d0b37 100644 --- a/src/GitPrompt.ps1 +++ b/src/GitPrompt.ps1 @@ -13,21 +13,6 @@ if ($Host.UI.RawUI.BackgroundColor -eq [ConsoleColor]::DarkMagenta) { $s.WorkingColor.ForegroundColor = 'Red' } -$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 = "$origTitle " - $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: $_" -} - <# .SYNOPSIS Writes the object to the display or renders it as a string using ANSI/VT sequences. @@ -146,7 +131,7 @@ function Write-Prompt { return $StringBuilder } - return "" + "" } <# @@ -187,10 +172,6 @@ function Write-GitStatus { $s = $global:GitPromptSettings if (!$Status -or !$s) { - if ($global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } - return "" } @@ -202,7 +183,6 @@ function Write-GitStatus { if ($s.EnableFileStatus -and $Status.HasIndex) { $sb | Write-Prompt $s.BeforeIndexText > $null - $sb | Write-GitIndexStatus $Status > $null if ($Status.HasWorking) { @@ -222,31 +202,7 @@ function Write-GitStatus { $sb | Write-Prompt $s.AfterText > $null - if ($WindowTitleSupported) { - if (!$s.EnableWindowTitle) { - if ($global:PreviousWindowTitle) { - $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle - } - } - else { - try { - if ($s.WindowTitle -is [scriptblock]) { - $windowTitleText = & $s.WindowTitle $Status $IsAdmin - } - else { - $windowTitleText = $ExecutionContext.SessionState.InvokeCommand.ExpandString("$($s.WindowTitle)") - } - - # Put $windowTitleText in a string to ensure results returned by scriptblock are flattened to a string - $Host.UI.RawUI.WindowTitle = "$windowTitleText" - } - catch { - Write-Debug "Error occurred during evaluation of `$GitPromptSettings.WindowTitle: $_" - } - } - } - - return $sb.ToString() + $sb.ToString() } <# diff --git a/src/PoshGitTypes.ps1 b/src/PoshGitTypes.ps1 index 340ff1481..10663056f 100644 --- a/src/PoshGitTypes.ps1 +++ b/src/PoshGitTypes.ps1 @@ -245,8 +245,7 @@ class PoshGitPromptSettings { [string[]]$RepositoriesInWhichToDisableFileStatus = @() [string]$DescribeStyle = '' - [bool]$EnableWindowTitle = $true - [psobject]$WindowTitle = {param($GitStatus, [bool]$IsAdmin) "$(if ($IsAdmin) {'Admin: '})posh~git ~ $($GitStatus.RepoName) [$($GitStatus.Branch)]"} + [psobject]$WindowTitle = {param($GitStatus, [bool]$IsAdmin) "$(if ($IsAdmin) {'Administrator: '})posh~git ~ $($GitStatus.RepoName) [$($GitStatus.Branch)]"} [PoshGitTextSpan]$DefaultPromptPrefix = '' [PoshGitTextSpan]$DefaultPromptSuffix = '$(''>'' * ($nestedPromptLevel + 1)) ' diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index 339b8687a..cb47921b7 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -16,6 +16,21 @@ param([switch]$NoVersionWarn, [switch]$ForcePoshGitPrompt) if (!$Env:HOME) { $Env:HOME = "$Env:HOMEDRIVE$Env:HOMEPATH" } 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']) { @@ -29,6 +44,10 @@ else { $GitPromptScriptBlock = { $settings = $global:GitPromptSettings if (!$settings) { + if ($WindowTitleSupported -and $global:PreviousWindowTitle) { + $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle + } + return "<`$GitPromptSettings not found> " } @@ -70,6 +89,36 @@ $GitPromptScriptBlock = { $promptSuffix.Text = ' ' } + # Update the host's WindowTitle is host supports it and user has not disabled $GitPromptSettings.WindowTitle + if ($WindowTitleSupported) { + $windowTitle = $settings.WindowTitle + if (($null -eq $windowTitle) -or ($null -eq $global:GitStatus)) { + 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: $_" + } + } + } + # If prompt timing enabled, display elapsed milliseconds if ($settings.DefaultPromptEnableTiming) { $sw.Stop() diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 56b5ddf48..36ce18df3 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -195,59 +195,141 @@ A test/Foo.Tests.ps1 } } -Describe 'Default Prompt Window Title Tests' { +Describe 'Default Prompt WindowTitle Tests' { + BeforeAll { + $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() + if (!(& $module {$WindowTitleSupported})) { + Write-Warning "Current PowerShell Host does not support changing its WindowTitle." + $PSDefaultParameterValues["it:skip"] = $true + } + } + AfterAll { + $global:PSDefaultParameterValues = $originalDefaultParameterValues + } BeforeEach { - # Ensure these settings start out set to the default values + # Ensure these settings start out set to the default values as the module only grabs + # $global:PreviousWindowTitle once when the module and that happens just once for this whole test file. $defaultTitle = if ($IsWindows) { "Windows PowerShell" } else { "PowerShell-$($PSVersionTable.PSVersion)" } $Host.UI.RawUI.WindowTitle = $defaultTitle $global:PreviousWindowTitle = $defaultTitle $global:GitPromptSettings = & $module.NewBoundScriptBlock({[PoshGitPromptSettings]::new()}) } - Context 'Default WindowTitle / EnableWindowTitle work ' { - It 'Sets the expected Window title text' { - Mock -ModuleName posh-git -CommandName git { - $OFS = " " - if ($args -contains 'rev-parse') { - $res = Invoke-Expression "&$gitbin $args" - return $res - } - Convert-NativeLineEnding -SplitLines @' + Context 'In a Git repo' { + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' ## master A test/Foo.Tests.ps1 - D test/Bar.Tests.ps1 - M test/Baz.Tests.ps1 +D test/Bar.Tests.ps1 +M test/Baz.Tests.ps1 '@ + } + + It 'Default GitPromptSettings.WindowTitle sets the expected Window title text' { + Set-Location $PSScriptRoot + $res = & $GitPromptScriptBlock 6>&1 + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + if (& $module {$IsAdmin}) { + $title | Should Match '^Administrator: posh~git ~ posh-git \[master\]$' } + else { + $title | Should Match '^posh~git ~ posh-git \[master\]$' + } + } + It 'Custom GitPromptSettings.WindowTitle scriptblock sets the expected Window title text' { Set-Location $PSScriptRoot - & $GitPromptScriptBlock *>$null + $GitPromptSettings.WindowTitle = { + param($s, $admin) + "$(if ($admin) {'daboss:'} else {'loser:'}) poshgit == $($s.RepoName) / $($s.Branch)" + } + $res = & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle - $title | Should Match '(Admin: )?posh~git ~ posh-git \[master\]' + if (& $module {$IsAdmin}) { + $title | Should Match '^daboss: poshgit == posh-git / master$' + } + else { + $title | Should Match '^loser: poshgit == posh-git / master$' + } } - It 'Does not set Window title when EnableWindowText is $false' { - Mock -ModuleName posh-git -CommandName git { - $OFS = " " - if ($args -contains 'rev-parse') { - $res = Invoke-Expression "&$gitbin $args" - return $res - } - Convert-NativeLineEnding -SplitLines @' + + It 'Custom GitPromptSettings.WindowTitle single quoted string sets the expected Window title text' { + Set-Location $PSScriptRoot + $GitPromptSettings.WindowTitle = '$(if ($IsAdmin) {"daboss:"} else {"loser:"}) poshgit == $($GitStatus.RepoName) / $($GitStatus.Branch)' + $res = & $GitPromptScriptBlock 6>&1 + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + if (& $module {$IsAdmin}) { + $title | Should Match '^daboss: poshgit == posh-git / master$' + } + else { + $title | Should Match '^loser: poshgit == posh-git / master$' + } + } + + It 'Does not set Window title when GitPromptSettings.WindowText is $null' { + Set-Location $PSScriptRoot + $GitPromptSettings.WindowTitle = $null + $res = & $GitPromptScriptBlock 6>&1 + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } + } + + Context 'Not in a Git repo' { + It 'Does not set Window title when not in a Git repo' { + Set-Location $Home + $res = & $GitPromptScriptBlock 6>&1 + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } + } + + Context 'Moving in and out of a Git repo' { + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' ## master A test/Foo.Tests.ps1 - D test/Bar.Tests.ps1 - M test/Baz.Tests.ps1 +D test/Bar.Tests.ps1 +M test/Baz.Tests.ps1 '@ - } + } + + It 'Displays the correct Window title as we move in and out of a Git repo' { + Set-Location $Home + $res = & $GitPromptScriptBlock 6>&1 + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' Set-Location $PSScriptRoot - $GitPromptSettings.EnableWindowTitle = 0 - & $GitPromptScriptBlock *>$null + $res = & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle + if (& $module {$IsAdmin}) { + $title | Should Match '^Administrator: posh~git ~ posh-git \[master\]$' + } + else { + $title | Should Match '^posh~git ~ posh-git \[master\]$' + } + + Set-Location $Home + $res = & $GitPromptScriptBlock 6>&1 + $title = $Host.UI.RawUI.WindowTitle $title | Should Match '^(Windows )?PowerShell' } } From e8d54881bb04d1ea6a3fa5877712420118ae3815 Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Sat, 27 Jan 2018 19:33:11 -0700 Subject: [PATCH 3/7] Enhance default window title & always shot it if enabled --- src/PoshGitTypes.ps1 | 2 +- src/posh-git.psm1 | 7 +++++- test/DefaultPrompt.Tests.ps1 | 45 +++++++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/PoshGitTypes.ps1 b/src/PoshGitTypes.ps1 index 10663056f..9f356cc44 100644 --- a/src/PoshGitTypes.ps1 +++ b/src/PoshGitTypes.ps1 @@ -245,7 +245,7 @@ class PoshGitPromptSettings { [string[]]$RepositoriesInWhichToDisableFileStatus = @() [string]$DescribeStyle = '' - [psobject]$WindowTitle = {param($GitStatus, [bool]$IsAdmin) "$(if ($IsAdmin) {'Administrator: '})posh~git ~ $($GitStatus.RepoName) [$($GitStatus.Branch)]"} + [psobject]$WindowTitle = {param($GitStatus, [bool]$IsAdmin) "$(if ($IsAdmin) {'Administrator: '})$(if ($GitStatus) {"posh~git ~ $($GitStatus.RepoName) [$($GitStatus.Branch)] ~ "})PowerShell $($PSVersionTable.PSVersion) ($PID)"} [PoshGitTextSpan]$DefaultPromptPrefix = '' [PoshGitTextSpan]$DefaultPromptSuffix = '$(''>'' * ($nestedPromptLevel + 1)) ' diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index cb47921b7..4b203a744 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -92,7 +92,7 @@ $GitPromptScriptBlock = { # Update the host's WindowTitle is host supports it and user has not disabled $GitPromptSettings.WindowTitle if ($WindowTitleSupported) { $windowTitle = $settings.WindowTitle - if (($null -eq $windowTitle) -or ($null -eq $global:GitStatus)) { + if ($null -eq $windowTitle) { if ($global:PreviousWindowTitle) { $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle } @@ -155,6 +155,11 @@ 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 + } + # 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 } if ($promptDef -eq $GitPromptScriptBlock) { diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 36ce18df3..0c42af48f 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -202,6 +202,10 @@ Describe 'Default Prompt WindowTitle Tests' { Write-Warning "Current PowerShell Host does not support changing its WindowTitle." $PSDefaultParameterValues["it:skip"] = $true } + $repoAdminRegex = '^Administrator: posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' + $repoRegex = '^posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' + $nonRepoAdminRegex = '^Administrator: PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' + $nonRepoRegex = '^PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' } AfterAll { $global:PSDefaultParameterValues = $originalDefaultParameterValues @@ -237,10 +241,10 @@ M test/Baz.Tests.ps1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { - $title | Should Match '^Administrator: posh~git ~ posh-git \[master\]$' + $title | Should Match $repoAdminRegex } else { - $title | Should Match '^posh~git ~ posh-git \[master\]$' + $title | Should Match $repoRegex } } @@ -286,11 +290,16 @@ M test/Baz.Tests.ps1 } Context 'Not in a Git repo' { - It 'Does not set Window title when not in a Git repo' { + It 'Does not display posh-git status info in Window title when not in a Git repo' { Set-Location $Home $res = & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle - $title | Should Match '^(Windows )?PowerShell' + if (& $module {$IsAdmin}) { + $title | Should Match $nonRepoAdminRegex + } + else { + $title | Should Match $nonRepoRegex + } } } @@ -314,23 +323,43 @@ M test/Baz.Tests.ps1 Set-Location $Home $res = & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle - $title | Should Match '^(Windows )?PowerShell' + if (& $module {$IsAdmin}) { + $title | Should Match $nonRepoAdminRegex + } + else { + $title | Should Match $nonRepoRegex + } Set-Location $PSScriptRoot $res = & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { - $title | Should Match '^Administrator: posh~git ~ posh-git \[master\]$' + $title | Should Match $repoAdminRegex } else { - $title | Should Match '^posh~git ~ posh-git \[master\]$' + $title | Should Match $repoRegex } Set-Location $Home $res = & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle - $title | Should Match '^(Windows )?PowerShell' + if (& $module {$IsAdmin}) { + $title | Should Match $nonRepoAdminRegex + } + else { + $title | Should Match $nonRepoRegex + } + } + + # This test must be the last test in this file + Context 'Removing the posh-git module' { + It 'Correctly reverts the Window Title back to original state' { + Set-Item function:\prompt -Value ([Runspace]::DefaultRunspace.InitialSessionState.Commands['prompt']).Definition + Remove-Module posh-git -Force *>$null + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } } } } From 69f530ec84acb2fffb47558549965933ed90e70e Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Sun, 28 Jan 2018 15:51:46 -0700 Subject: [PATCH 4/7] Fix regex in Pester test --- test/DefaultPrompt.Tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 0c42af48f..2bbf19931 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -202,10 +202,10 @@ Describe 'Default Prompt WindowTitle Tests' { Write-Warning "Current PowerShell Host does not support changing its WindowTitle." $PSDefaultParameterValues["it:skip"] = $true } - $repoAdminRegex = '^Administrator: posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' - $repoRegex = '^posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' - $nonRepoAdminRegex = '^Administrator: PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' - $nonRepoRegex = '^PowerShell \d+\.\d+\.\d+\.\d+ \(\d+\)$' + $repoAdminRegex = '^Administrator: posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + $repoRegex = '^posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + $nonRepoAdminRegex = '^Administrator: PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + $nonRepoRegex = '^PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' } AfterAll { $global:PSDefaultParameterValues = $originalDefaultParameterValues From 30bd678c7df84b97fa9892a2ef1cf49d3c87438d Mon Sep 17 00:00:00 2001 From: Keith Hill Date: Sun, 28 Jan 2018 22:27:23 -0700 Subject: [PATCH 5/7] Eliminate some PSSA warnings in tests --- PSScriptAnalyzerSettings.psd1 | 2 +- test/DefaultPrompt.Tests.ps1 | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 index e3f881411..2ba8dd417 100644 --- a/PSScriptAnalyzerSettings.psd1 +++ b/PSScriptAnalyzerSettings.psd1 @@ -17,7 +17,7 @@ # Use ExcludeRules when you want to run most of the default set of rules except # for a few rules you wish to "exclude". Note: if a rule is in both IncludeRules # and ExcludeRules, the rule will be excluded. - ExcludeRules = @('PSAvoidUsingWriteHost', 'PSAvoidGlobalVars') + ExcludeRules = @('PSAvoidUsingWriteHost', 'PSAvoidGlobalVars', 'PSAvoidUsingInvokeExpression') # You can use the following entry to supply parameters to rules that take parameters. # For instance, the PSAvoidUsingCmdletAliases rule takes a whitelist for aliases you diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 2bbf19931..4a1a0b0df 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -2,6 +2,7 @@ Describe 'Default Prompt Tests - NO ANSI' { BeforeAll { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $prompt = Get-Item Function:\prompt $OFS = '' } @@ -94,6 +95,7 @@ A test/Foo.Tests.ps1 Describe 'Default Prompt Tests - ANSI' { BeforeAll { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $prompt = Get-Item Function:\prompt $OFS = '' } @@ -197,14 +199,20 @@ A test/Foo.Tests.ps1 Describe 'Default Prompt WindowTitle Tests' { BeforeAll { + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $originalDefaultParameterValues = $PSDefaultParameterValues.Clone() if (!(& $module {$WindowTitleSupported})) { Write-Warning "Current PowerShell Host does not support changing its WindowTitle." $PSDefaultParameterValues["it:skip"] = $true } + + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $repoAdminRegex = '^Administrator: posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $repoRegex = '^posh~git ~ posh-git \[master\] ~ PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $nonRepoAdminRegex = '^Administrator: PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssigments', '')] $nonRepoRegex = '^PowerShell \d+\.\d+\.\d+(\.\d+|-\S+)? \(\d+\)$' } AfterAll { @@ -237,7 +245,7 @@ M test/Baz.Tests.ps1 It 'Default GitPromptSettings.WindowTitle sets the expected Window title text' { Set-Location $PSScriptRoot - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { @@ -254,7 +262,7 @@ M test/Baz.Tests.ps1 param($s, $admin) "$(if ($admin) {'daboss:'} else {'loser:'}) poshgit == $($s.RepoName) / $($s.Branch)" } - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { @@ -268,7 +276,7 @@ M test/Baz.Tests.ps1 It 'Custom GitPromptSettings.WindowTitle single quoted string sets the expected Window title text' { Set-Location $PSScriptRoot $GitPromptSettings.WindowTitle = '$(if ($IsAdmin) {"daboss:"} else {"loser:"}) poshgit == $($GitStatus.RepoName) / $($GitStatus.Branch)' - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { @@ -282,7 +290,7 @@ M test/Baz.Tests.ps1 It 'Does not set Window title when GitPromptSettings.WindowText is $null' { Set-Location $PSScriptRoot $GitPromptSettings.WindowTitle = $null - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle $title | Should Match '^(Windows )?PowerShell' @@ -292,7 +300,7 @@ M test/Baz.Tests.ps1 Context 'Not in a Git repo' { It 'Does not display posh-git status info in Window title when not in a Git repo' { Set-Location $Home - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { $title | Should Match $nonRepoAdminRegex @@ -321,7 +329,7 @@ M test/Baz.Tests.ps1 It 'Displays the correct Window title as we move in and out of a Git repo' { Set-Location $Home - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { $title | Should Match $nonRepoAdminRegex @@ -331,7 +339,7 @@ M test/Baz.Tests.ps1 } Set-Location $PSScriptRoot - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 Assert-MockCalled git -ModuleName posh-git -Scope It $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { @@ -342,7 +350,7 @@ M test/Baz.Tests.ps1 } Set-Location $Home - $res = & $GitPromptScriptBlock 6>&1 + & $GitPromptScriptBlock 6>&1 $title = $Host.UI.RawUI.WindowTitle if (& $module {$IsAdmin}) { $title | Should Match $nonRepoAdminRegex From 520ee6517ff7c8c8ac1a32541d779421f5aeb4b7 Mon Sep 17 00:00:00 2001 From: Keith Dahlby Date: Mon, 29 Jan 2018 15:35:28 -0600 Subject: [PATCH 6/7] Disable WindowTitle for anything falsey --- src/posh-git.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index 4b203a744..cbc620a55 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -92,7 +92,7 @@ $GitPromptScriptBlock = { # Update the host's WindowTitle is host supports it and user has not disabled $GitPromptSettings.WindowTitle if ($WindowTitleSupported) { $windowTitle = $settings.WindowTitle - if ($null -eq $windowTitle) { + if (!$windowTitle) { if ($global:PreviousWindowTitle) { $Host.UI.RawUI.WindowTitle = $global:PreviousWindowTitle } From 5361bc87e218f93f9bbb2d2827f6ae4be52fecda Mon Sep 17 00:00:00 2001 From: Keith Dahlby Date: Mon, 29 Jan 2018 15:41:31 -0600 Subject: [PATCH 7/7] Add WindowTitle = falsey tests --- test/DefaultPrompt.Tests.ps1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/DefaultPrompt.Tests.ps1 b/test/DefaultPrompt.Tests.ps1 index 4a1a0b0df..8c826097b 100644 --- a/test/DefaultPrompt.Tests.ps1 +++ b/test/DefaultPrompt.Tests.ps1 @@ -295,6 +295,24 @@ M test/Baz.Tests.ps1 $title = $Host.UI.RawUI.WindowTitle $title | Should Match '^(Windows )?PowerShell' } + + It 'Does not set Window title when GitPromptSettings.WindowText is $false' { + Set-Location $PSScriptRoot + $GitPromptSettings.WindowTitle = $false + & $GitPromptScriptBlock 6>&1 + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } + + It 'Does not set Window title when GitPromptSettings.WindowText is ""' { + Set-Location $PSScriptRoot + $GitPromptSettings.WindowTitle = '' + & $GitPromptScriptBlock 6>&1 + Assert-MockCalled git -ModuleName posh-git -Scope It + $title = $Host.UI.RawUI.WindowTitle + $title | Should Match '^(Windows )?PowerShell' + } } Context 'Not in a Git repo' {