diff --git a/README.md b/README.md index d368d9614..182e6e2bc 100644 --- a/README.md +++ b/README.md @@ -354,6 +354,26 @@ This will change the prompt to: ![~\GitHub\posh-git [main ≡] > ][prompt-two-line] +If you prefer to show the remote repository name for the branch, use this setting: + +```text +$GitPromptSettings.RemoteNamePlacement = "Start" +``` + +This will change the prompt to: + +![~\GitHub\posh-git [origin/master ≡]> ][prompt-show-remote-name] + +Alternatively, you can change the placement of remote name relative to branch name and specify any value between the +two. Such as: + +```text +$GitPromptSettings.RemoteNameSymbol = " -> " +$GitPromptSettings.RemoteNamePlacement = "End" +``` + +![~\GitHub\posh-git [master -> origin ≡]> ][prompt-show-remote-name-end] + You can swap the order of the path and the Git status summary with the following setting: ```text @@ -512,6 +532,8 @@ function prompt { [psgallery-img]: https://img.shields.io/powershellgallery/dt/posh-git.svg [psgallery-site]: https://www.powershellgallery.com/packages/posh-git [psgallery-v1]: https://www.powershellgallery.com/packages/posh-git/1.0.0 +[prompt-show-remote-name]: https://github.com/dahlbyk/posh-git/wiki/images/PromptShowRemoteName.png "~\GitHub\posh-git> [origin/main ≡] " +[prompt-show-remote-name-end]: https://github.com/dahlbyk/posh-git/wiki/images/PromptShowRemoteNameEnd.png "~\GitHub\posh-git> [main -> origin ≡] " [w3c-colors]: https://www.w3schools.com/colors/colors_names.asp [posh-sshell-url]: https://github.com/dahlbyk/posh-sshell diff --git a/src/GitPrompt.ps1 b/src/GitPrompt.ps1 index 2a752b93c..845191517 100644 --- a/src/GitPrompt.ps1 +++ b/src/GitPrompt.ps1 @@ -220,7 +220,13 @@ function Write-GitStatus { } $sb | Write-Prompt $s.BeforeStatus > $null - $sb | Write-GitBranchName $Status -NoLeadingSpace > $null + if($s.RemoteNamePlacement -eq [Placement]::Start) { + $sb | Write-GitRemoteRepositoryLabel $Status | Write-GitBranchName $Status -NoLeadingSpace > $null + } elseif($s.RemoteNamePlacement -eq [Placement]::End) { + $sb | Write-GitBranchName $Status -NoLeadingSpace | Write-GitRemoteRepositoryLabel $Status > $null + } else { + $sb | Write-GitBranchName $Status -NoLeadingSpace > $null + } $sb | Write-GitBranchStatus $Status > $null $sb | Write-Prompt $s.BeforeIndex > $null @@ -350,6 +356,82 @@ function Get-GitBranchStatusColor { $branchStatusTextSpan } +<# +.SYNOPSIS + Writes the tracked repository name for branch with seperator. +.DESCRIPTION + Writes the tracked/remote repository name (value of `Upstream` property from Write-GitStatus) + for branch and the seperator which is determined by the value of + $GitPromptSettings: RemoteNameSymbol. The placement of the seperator is + determined by the value of $GitPromptSettings: RemoteNamePlacement. + If that property has a value of `"Start"`, the value of RemoteNameSymbol + will be positioned right of name. And if that property has a value of + `"End"`, the value of RemoteNameSymbol will be positioned left of name. + + When there is no tracked repository for a branch, this command doesn't + return a value. And this also applies when + $GitPromptSettings.RemoteNamePlacement has a value of `"None"`. +.EXAMPLE + PS C:\> $GitPromptSettings.RemoteNameSymbol = " / " + PS C:\> $GitPromptSettings.RemoteNamePlacement = "Start" + PS C:\> Write-GitRemoteRepositoryLabel (Get-GitStatus) + + Writes the tracked repository name for branch followed by seperator ('/') + or empty line if branch is untracked. For instance, `origin / master` +.EXAMPLE + PS C:\> $GitPromptSettings.RemoteNameSymbol = " -> " + PS C:\> $GitPromptSettings.RemoteNamePlacement = "End" + PS C:\> Write-GitRemoteRepositoryLabel (Get-GitStatus) + + Writes the seperator ("->") followed by name of the remote name for + branch, followed by or empty line when no Upstream is set. For instance, + `master -> origin` +.INPUTS + System.Management.Automation.PSCustomObject + This is PSCustomObject returned by Get-GitStatus +.OUTPUTS + System.String, System.Text.StringBuilder + This command returns a System.String object unless the -StringBuilder parameter + is supplied. In this case, it returns a System.Text.StringBuilder. +#> +function Write-GitRemoteRepositoryLabel { + param( + # The Git status object that provides the status information to be written. + # This object is retrieved via the Get-GitStatus command. + [Parameter(Position = 0)] + $Status, + + # If specified the branch name is written into the provided StringBuilder object. + [Parameter(ValueFromPipeline = $true)] + [System.Text.StringBuilder] + $StringBuilder + ) + + $s = $global:GitPromptSettings + if (!$Status -or !$s -or ($s.RemoteNamePlacement -eq [Placement]::None)) { + return $(if ($StringBuilder) { $StringBuilder } else { "" }) + } + + $str = "" + + # Expecting similar format as 'origin/master' or 'origin/development/master' + if($Status.Upstream -match '(?\w+)(?\/).*' ) { + $remoteNameTextSpan = [PoshGitTextSpan]::new($s.DefaultColor) + $remoteNameTextSpan.Text = $s.RemoteNamePlacement -eq [Placement]::Start ? + $Matches.remotename + $s.RemoteNameSymbol : + $s.RemoteNameSymbol + $Matches.remotename + + if ($StringBuilder) { + $StringBuilder | Write-Prompt $remoteNameTextSpan > $null + } + else { + $str = Write-Prompt $remoteNameTextSpan + } + } + + return $(if ($StringBuilder) { $StringBuilder } else { $str }) +} + <# .SYNOPSIS Writes the branch name given the current Git status. diff --git a/src/PoshGitTypes.ps1 b/src/PoshGitTypes.ps1 index bd33a7d6c..66281b01f 100644 --- a/src/PoshGitTypes.ps1 +++ b/src/PoshGitTypes.ps1 @@ -1,5 +1,6 @@ enum BranchBehindAndAheadDisplayOptions { Full; Compact; Minimal } enum UntrackedFilesMode { Default; No; Normal; All } +[Flags()]enum Placement { None; Start; End } class PoshGitCellColor { [psobject]$BackgroundColor @@ -266,6 +267,8 @@ class PoshGitPromptSettings { [bool]$EnableStashStatus = $false [bool]$ShowStatusWhenZero = $true + [Placement]$RemoteNamePlacement = [Placement]::None + [string]$RemoteNameSymbol = '/' [bool]$AutoRefreshIndex = $true [UntrackedFilesMode]$UntrackedFilesMode = [UntrackedFilesMode]::Default diff --git a/src/posh-git.psd1 b/src/posh-git.psd1 index b203727c7..28a9ebe08 100644 --- a/src/posh-git.psd1 +++ b/src/posh-git.psd1 @@ -36,6 +36,7 @@ FunctionsToExport = @( 'Remove-PoshGitFromProfile', 'Update-AllBranches', 'Write-GitStatus', + 'Write-GitRemoteRepositoryLabel', 'Write-GitBranchName', 'Write-GitBranchStatus', 'Write-GitIndexStatus', diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index 06e45159a..977336272 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -174,6 +174,7 @@ $exportModuleMemberParams = @{ 'Remove-PoshGitFromProfile', 'Update-AllBranches', 'Write-GitStatus', + 'Write-GitRemoteRepositoryLabel', 'Write-GitBranchName', 'Write-GitBranchStatus', 'Write-GitIndexStatus', diff --git a/test/Get-GitStatus.Tests.ps1 b/test/Get-GitStatus.Tests.ps1 index 418a55a7d..64d756d2f 100644 --- a/test/Get-GitStatus.Tests.ps1 +++ b/test/Get-GitStatus.Tests.ps1 @@ -36,8 +36,35 @@ Describe 'Get-GitStatus Tests' { $status.Index.Modified.Count | Should -Be 0 $status.Index.Unmerged.Count | Should -Be 0 } + It 'Returns the correct remote repository name' { + Mock -ModuleName posh-git git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding @' +## rkeithill/more-status-tests...origin/rkeithill/more-status-tests +'@ + } + $status = Get-GitStatus + Should -Invoke -ModuleName posh-git -CommandName git -Exactly 1 + $status.Branch | Should -Be "rkeithill/more-status-tests" + $status.Upstream | Should -Be "origin/rkeithill/more-status-tests" + $status.HasIndex | Should -Be $false + $status.HasUntracked | Should -Be $false + $status.HasWorking | Should -Be $false + $status.Working.Added.Count | Should -Be 0 + $status.Working.Deleted.Count | Should -Be 0 + $status.Working.Modified.Count | Should -Be 0 + $status.Working.Unmerged.Count | Should -Be 0 + $status.Index.Added.Count | Should -Be 0 + $status.Index.Deleted.Count | Should -Be 0 + $status.Index.Modified.Count | Should -Be 0 + $status.Index.Unmerged.Count | Should -Be 0 + } It 'Returns the correct number of added untracked working files' { Mock -ModuleName posh-git git { $OFS = " " diff --git a/test/GitPrompt.Tests.ps1 b/test/GitPrompt.Tests.ps1 index 022a19b16..d93bed210 100644 --- a/test/GitPrompt.Tests.ps1 +++ b/test/GitPrompt.Tests.ps1 @@ -54,3 +54,109 @@ M test/Baz.Tests.ps1 } } } + +Describe 'Write-GitRemoteRepositoryLabel Tests' { + Context 'RemoteNamePlacement having a value of `"Start"` with single segment branch name' { + BeforeAll { + # Ensure these settings start out set to the default values + $global:GitPromptSettings = New-GitPromptSettings + $GitPromptSettings.RemoteNamePlacement = "Start" + $GitPromptSettings.RemoteNameSymbol = "/" + + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## master...origin/master +'@ + } + } + + It 'Should write repository name followed by seperator' { + $res = Write-GitRemoteRepositoryLabel (Get-GitStatus) + Should -Invoke -ModuleName posh-git -CommandName git -Exactly 1 + $res | Should -BeExactly "origin/" + } + } + + Context 'RemoteNamePlacement having a value of `"Start"` with multi segment branch name' { + BeforeAll { + # Ensure these settings start out set to the default values + $global:GitPromptSettings = New-GitPromptSettings + $GitPromptSettings.RemoteNamePlacement = "Start" + $GitPromptSettings.RemoteNameSymbol = "/" + + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## development/master...origin/development/master +'@ + } + } + + It 'Should write repository name followed by seperator' { + $res = Write-GitRemoteRepositoryLabel (Get-GitStatus) + Should -Invoke -ModuleName posh-git -CommandName git -Exactly 1 + $res | Should -BeExactly "origin/" + } + } + + Context 'RemoteNamePlacement having a value of `"End"` with single segment branch name' { + BeforeAll { + # Ensure these settings start out set to the default values + $global:GitPromptSettings = New-GitPromptSettings + $GitPromptSettings.RemoteNamePlacement = "End" + $GitPromptSettings.RemoteNameSymbol = " -> " + + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## master...origin/master +'@ + } + } + + It 'Should write seperator followed by repository name' { + $res = Write-GitRemoteRepositoryLabel (Get-GitStatus) + Should -Invoke -ModuleName posh-git -CommandName git -Exactly 1 + $res | Should -BeExactly " -> origin" + } + } + + Context 'RemoteNamePlacement having a value of `"None"`' { + BeforeAll { + # Ensure these settings start out set to the default values + $global:GitPromptSettings = New-GitPromptSettings + $GitPromptSettings.RemoteNamePlacement = "None" + $GitPromptSettings.RemoteNameSymbol = "/" + + Mock -ModuleName posh-git -CommandName git { + $OFS = " " + if ($args -contains 'rev-parse') { + $res = Invoke-Expression "&$gitbin $args" + return $res + } + Convert-NativeLineEnding -SplitLines @' +## master...origin/master +'@ + } + } + + It 'Should not return any sort of truthy' { + $res = Write-GitRemoteRepositoryLabel (Get-GitStatus) + Should -Invoke -ModuleName posh-git -CommandName git -Exactly 1 + $res | Should -BeNullOrEmpty + } + } +}