I have a custom multi-lines prompt that used to work with v0.6.1.20160330 of posh-git. The git status stays on the first line. The second line contains just the right angle bracket. Now I have installed it on a new machine, and git status is appearing in the second line.
Here's the content of my profile script:
if(!(Test-Path function:\TabExpansion)) { New-Item function:\Global:TabExpansion -value '' | Out-Null }
function Test-Administrator {
$user = [Security.Principal.WindowsIdentity]::GetCurrent();
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
function prompt {
$realLASTEXITCODE = $LASTEXITCODE
Write-Host
if (Test-Administrator) { # Use different username if elevated
Write-Host "^" -NoNewline -ForegroundColor White
}
Write-Host "$ENV:USERNAME@" -NoNewline -ForegroundColor DarkYellow
Write-Host "$ENV:COMPUTERNAME" -NoNewline -ForegroundColor Magenta
if ($s -ne $null) { # color for PSSessions
Write-Host " (`$s: " -NoNewline -ForegroundColor DarkGray
Write-Host "$($s.Name)" -NoNewline -ForegroundColor Yellow
Write-Host ") " -NoNewline -ForegroundColor DarkGray
}
Write-Host ":" -NoNewline -ForegroundColor DarkGray
Write-Host $($(Get-Location) -replace ($env:USERPROFILE).Replace('\','\\'), "~") -NoNewline -ForegroundColor Blue
Write-Host ":" -NoNewline -ForegroundColor DarkGray
Write-Host (Get-Date -Format "d-MMM HH:mm:ss") -NoNewline -ForegroundColor DarkMagenta
Write-Host ":" -NoNewline -ForegroundColor DarkGray
$global:LASTEXITCODE = $realLASTEXITCODE
Write-VcsStatus
Write-Host ""
return "> "
}
function which($command) {
get-command $command | Format-Table Path
}
Set-Alias which gcm
Import-Module 'C:\source\posh-git\src\posh-git.psd1'
I have somewhat limited understanding of Powershell and can't remember how I cobbled up that prompt. What I was trying to achieve there is an updated timestamp in the prompt every time a command is executed.
Any ideas why Write-VcsStatus now inserts a newline before it?
A lot has changed WRT to the way the Git status is written in order to support ANSI capable hosts. I have a way to fix you prompt function above but I think you'd be better off just using the new customization support in v1. Put this settings right after you import posh-git:
$GitPromptSettings.DefaultPromptPrefix.Text = "$(if (Test-Administrator) {'^'})${env:USERNAME}@${env:COMPUTERNAME} "
$GitPromptSettings.DefaultPromptPrefix.ForegroundColor = [System.ConsoleColor]::DarkYellow
$GitPromptSettings.PathStatusSeparator.Text = " $(Get-Date -Format "d-MMM HH:mm:ss") "
$GitPromptSettings.PathStatusSeparator.ForegroundColor = [System.ConsoleColor]::DarkMagenta
$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $true
$GitPromptSettings.DefaultPromptPath.ForegroundColor = [System.ConsoleColor]::Blue
If you want to use your old prompt function, change it to this:
function prompt {
$realLASTEXITCODE = $LASTEXITCODE
Write-Host
if (Test-Administrator) { # Use different username if elevated
Write-Host "^" -NoNewline -ForegroundColor White
}
Write-Host "$ENV:USERNAME@" -NoNewline -ForegroundColor DarkYellow
Write-Host "$ENV:COMPUTERNAME" -NoNewline -ForegroundColor Magenta
if ($s -ne $null) { # color for PSSessions
Write-Host " (`$s: " -NoNewline -ForegroundColor DarkGray
Write-Host "$($s.Name)" -NoNewline -ForegroundColor Yellow
Write-Host ") " -NoNewline -ForegroundColor DarkGray
}
Write-Host ":" -NoNewline -ForegroundColor DarkGray
Write-Host $($(Get-Location) -replace ($env:USERPROFILE).Replace('\','\\'), "~") -NoNewline -ForegroundColor Blue
Write-Host ":" -NoNewline -ForegroundColor DarkGray
Write-Host (Get-Date -Format "d-MMM HH:mm:ss") -NoNewline -ForegroundColor DarkMagenta
Write-Host ":" -NoNewline -ForegroundColor DarkGray
$global:LASTEXITCODE = $realLASTEXITCODE
"$(Write-VcsStatus)> "
}
Essentially the Write-VcsStatus returns a string in v1.x when ANSI mode is enabled ($GitPromptSettings.AnsiConsole is $true). That contains the string to display. This string has VT char sequences in it to color the text. However when your prompt function emits two strings e.g.:
Write-VcsStatus # output string here
Write-Host ""
return "> " # output string here
That object array outuput is not accepted by PowerShell. You can see this by executing:
PS> Get-Member -InputObject (prompt)
TypeName: System.Object[]
So outputting just "$(Write-VcsStatus)> " results in the prompt function output being a single string.
In the process of coming up with a $GitPromptSettings customization to get you your exact prompt (sans the PSSession bit - couldn't tell exactly where $s was coming from), I found a few bugs in v1 that I'd like to fix. The following won't work right now but it should after I get a few changes merged in. After those changes are merged, the following will work:
$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $true
$GitPromptSettings.DefaultPromptPath.Text = $null
$GitPromptSettings.DefaultPromptPrefix.CustomAnsi =
"`n`$(Get-PromptConnectionInfo -Format '[{1}@{0}]: ')" +
"`$(if (global:Test-Administrator) {`"$([char]27)[37m^`"})" +
"$([char]27)[33m`${env:USERNAME}@$([char]27)[95m`${env:COMPUTERNAME}$([char]27)[90m:" +
"$([char]27)[94m`$(Get-PromptPath)$([char]27)[90m:" +
"$([char]27)[35m`$(Get-Date -Format `"d-MMM HH:mm:ss`")$([char]27)[90m:"
This will give a prompt like this:

BTW if you ran only on PS Core, you could use the esc char e support to simplify the one setting:
# ONLY WORKS IN POWERSHELL CORE AFTER FIXES MERGED
$GitPromptSettings.DefaultPromptPrefix.CustomAnsi =
"`n`$(Get-PromptConnectionInfo -Format '[{1}@{0}]: ')" +
"`$(if (global:Test-Administrator) {`"`e[37m^`"})" +
"`e[33m`${env:USERNAME}@`e[95m`${env:COMPUTERNAME}`e[90m:" +
"`e[94m`$(Get-PromptPath)`e[90m:" +
"`e[35m`$(Get-Date -Format `"d-MMM HH:mm:ss`")`e[90m:"
Thank you for all that. I ended up modifying my prompt function as you suggested, adding a newline character in the final output to be $(Write-VcsStatus) and >. Now it works just like before! I used this method because I would like this prompt even if I didn't have posh-git installed. I can just remove the call to Write-VcsStatus in that case.
@dahlbyk I think this actually reveals a subtle bug that could trip up folks moving from v0.x to v1 and are running in a host without VT support. This is somewhat of a corner case scenario given the v1 requires PS v5. But if someone has v5 installed on Win7, they could hit it. The issue is this. In v0.x, Write-VcsStatus returned nothing. It simply wrote to the host. So this part of the OP's prompt worked fine because it output a single string >:
Write-Host ""
return "> "
However, in v1 when AnsiConsole is $false and we use Write-Host, we still output a single, empty string from Write-VcsStatus. That changes the function above to output [object[]] now with an empty string in ndx 0 and > at ndx 1. That breaks PowerShell's prompt handling. It gets confused by the prompt function outputting something other than a single string.
In order to fix this, we'd have to modify Write-GitStatus and Write-VcsStatus to not output anything - not even an empty string - when AnsiConsole is $false. Is it worth it?
In order to fix this, we'd have to modify
Write-GitStatusandWrite-VcsStatusto not output anything - not even an empty string - whenAnsiConsoleis$false. Is it worth it?
This seems like it should be simple to fix, isn't it?
I think so. I'll submit a PR so we can see what the changes look like.
Most helpful comment
If you want to use your old prompt function, change it to this:
Essentially the
Write-VcsStatusreturns a string in v1.x when ANSI mode is enabled ($GitPromptSettings.AnsiConsole is $true). That contains the string to display. This string has VT char sequences in it to color the text. However when your prompt function emits two strings e.g.:That object array outuput is not accepted by PowerShell. You can see this by executing:
So outputting just
"$(Write-VcsStatus)> "results in the prompt function output being a single string.