-
-
Notifications
You must be signed in to change notification settings - Fork 802
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
One attempt at providing a prompt function during module import. #349
Conversation
@@ -11,26 +11,79 @@ if ($psv.Major -lt 3 -and !$NoVersionWarn) { | |||
"To suppress this warning, change your profile to include 'Import-Module posh-git -Args `$true'.") | |||
} | |||
|
|||
Push-Location $psScriptRoot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we just getting lucky that nobody using PS v2 has complained about this breaking anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a pop-location later but if something crashed out before the pop-location, it would have left the current location to the module's root dir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah, $PSScriptRoot works only inside module (PSM1) files for PS v2 but not in PS1 files IIRC. That was fixed in v3 I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that makes more sense 👍
$Global:VcsPromptStatuses += $PoshGitVcsPrompt | ||
$ExecutionContext.SessionState.Module.OnRemove = { | ||
$Global:VcsPromptStatuses = $Global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove?
Update: Nevermind, I see it was just moved into the .psm1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW I need to update that logic a bit to check if someone might have installed a different prompt function after we installed the posh-git default one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And as a "module level" operation, posh-git.psm1 seemed like a more fitting place for this handler.
Also handle the case where the user creates a different prompt function *after* posh-git sets the prompt function. In that case, we won't restore the original prompt function that we stashed.
I've done some testing on PS v2 and PS v5 both with modified prompt functions and without. It is looking pretty good and I'm feeling better about posh-git installing this when the user hasn't modified their prompt function. BTW when the user has their own prompt function that uses posh-git commands, we don't remove it. This has the consequence of causing posh-git to be immediately reloaded when their prompt is evaluated after There are several workarounds including configuring a dumb prompt to allow posh-git to be removed e.g.: function prompt { "$(pwd)> " } or for v3 or higher Set-Item Function:\prompt ([Runspace]::DefaultRunspace.InitialSessionState.Commands['prompt'].Definition) They can also close all PowerShell sessions and start powershell with the |
@@ -306,8 +306,4 @@ $PoshGitVcsPrompt = { | |||
Write-GitStatus $GitStatus | |||
} | |||
|
|||
# Install handler for removal/unload of the module | |||
$Global:VcsPromptStatuses += $PoshGitVcsPrompt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And as a "module level" operation, posh-git.psm1 seemed like a more fitting place for this handler.
I wonder if this should move alongside the removal operation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do that, should we also move the decl/assignment of $PoshGitVcsPrompt
just above this line as well?
# The latter is more desirable. | ||
$pathInfo = $ExecutionContext.SessionState.Path.CurrentLocation | ||
$curPath = if ($pathInfo.Drive) { $pathInfo.Path } else { $pathInfo.ProviderPath } | ||
if ($curPath -and $curPath.ToLower().StartsWith($Home.ToLower())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a fan of the $Home
check, nice addition!
- Favor the
StringComparison
overload over comparingToLower
ed strings - According to MSDN:
The string behavior of the file system, registry keys and values, and environment variables is best represented by
StringComparison.OrdinalIgnoreCase
.
Therefore: $curPath.StartsWith($Home, [StringComparison]::OrdinalIgnoreCase)
Commence countdown to case-insensitivity bug on Linux: 5...4...3...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can check for Linux and use Ordinal.
$currentPromptDef = if ($funcInfo = Get-Command prompt -ErrorAction SilentlyContinue) { $funcInfo.Definition } | ||
if (!$currentPromptDef -or ($currentPromptDef -eq $defaultPromptDef)) { | ||
Set-Item Function:\prompt -Value { | ||
$origLastExitCode = $LASTEXITCODE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS amateur question: any reason to use $global:LASTEXITCODE
here, as below?
$promptSuffix = "`n[DBG]: PS>> " | ||
} | ||
else { | ||
$promptSuffix = "`nPS> " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer not to change the default posh-git prompt since it's what non-customizing users (like me 😀) are now used to. But we could add PromptPrefix
and PromptSuffix
(and PromptDebug*ix
?) to $GitPromptSettings
to make this particular arrangement easier to achieve without modifying prompt
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK by me. I was just floating this is an idea. If we added a setting, what would it be called? CommandEntryOnNewline
?
|
||
# If there is no prompt function or the prompt function is the default, export the posh-git prompt function. | ||
$promptReplaced = $false | ||
$currentPromptDef = if ($funcInfo = Get-Command prompt -ErrorAction SilentlyContinue) { $funcInfo.Definition } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to prefer your construction over this one?
$currentPromptDef = Get-Command prompt -ErrorAction SilentlyContinue) | Select-Object -ExpandProperty Definition
$promptSuffix | ||
} | ||
|
||
$promptReplaced = $true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we attach a property to our prompt
instead of using a separate flag? I don't suppose there's any way to set its Source = "posh-git"
like all the other functions we export?
Interesting... So my first thought is to have Then again, technically Or we could hack it ( |
I hadn't quite grokked what the Vcs* functions were for yet. Thanks for the info.
But in my prompt function I use |
So how about we just log a warning |
Sounds good to me. I'm working on an update to this PR to address the StringComparison issue and a way to select a two line prompt. Any thoughts on the name of that setting? I'm currently using |
I think we can get away with: # Write the Git status summary information.
Write-VcsStatus
$debugMode = (Test-Path Variable:\PSDebugContext) -or [runspace]::DefaultRunspace.Debugger.InBreakpoint
$global:LASTEXITCODE = $origLastExitCode
if ($debugMode) {
Write-Host (if ($GitPromptSettings.PromptDebugSuffix) { $GitPromptSettings.PromptDebugSuffix } else { ' [DBG]>> ' })
} else {
Write-Host (if ($GitPromptSettings.PromptSuffix) { $GitPromptSettings.PromptSuffix } else { '> ' })
} Your two-line prompt config becomes: $GitPromptSettings.PromptDebugSuffix = '`n[DBG]: PS>> '
$GitPromptSettings.PromptSuffix = '`nPS> '
# plus Powerline config if applicable, which posh-git doesn't need to know And anything more complex could be handled by a custom |
What if we defaulted these two settings e.g.: $GitPromptSettings.PromptDebugSuffix = ' [DBG]: >> '
$GitPromptSettings.PromptSuffix = '> ' That would also help folks know how to use these two settings. |
Change path string comparison to use [StringComparison] appropriate for the platform. Add warning in OnRemove that let's user know that their custom prompt function may cause posh-git to be re-imported. Change to use [scriptblock]::Create() otherwise $debugMode condition lied on PS v2 (although it worked fine on v5). Anyway, this change fixes this on v2. Also removed script to mess with PSReadline''s ExtraPromptLineCount.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just trivial stuff now. I'm liking where this has ended up.
Should we also drop the prompt
definition from profile.example.ps1
?
$currentPath = if ($pathInfo.Drive) { $pathInfo.Path } else { $pathInfo.ProviderPath } | ||
|
||
# File system paths are case-sensitive on Linux and case-insensitive on Windows and macOS | ||
if (($PSVersionTable.PSVersion.Major -ge 6) -and $IsLinux) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Micro-optimization, but we could calculate $stringComparison
once, assuming we can get the scriptblock to close over the variable.
$promptReplaced = $true | ||
} | ||
|
||
# Install handler for removal/unload of the module | ||
$ExecutionContext.SessionState.Module.OnRemove = { | ||
$Global:VcsPromptStatuses = $Global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt } | ||
$global:VcsPromptStatuses = $global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt } | ||
|
||
if ($promptReplaced) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if this flag has been made obsolete by the $promptDef -eq $poshGitPromptScriptBlock
check? I suppose it's an optimization, but I wouldn't be opposed to reducing complexity at the expense of a marginally slower uninstall.
I think so. Perhaps we can rename that as well? I tend to following a pattern in my profile scripts of
The test takes between 2 & 4 mSecs and StringComparison is an enum (no heap impact). It's probably not worth bothering.
There's a small chance someone could have created a custom prompt function by copying that code. In which case, we would remove it. I could go either way. |
Well anyone using
👍
I'm all for simplifying the code we have to maintain. If someone customizes their prompt poorly, that's on them - they can see all our source here. |
Update to warning message in OnRemove.
👍
Should we still remove the prompt function? I'm guessing yes but wanted to double check. |
Also, if someone sets their
I can put in a check for |
Yes.
That's what motivated the extra complexity in my version - if you don't give a good override, you get the default experience. Still a good idea to set the settings properties to match the default. if ($debugMode) {
Write-Host (if ($GitPromptSettings.PromptDebugSuffix) { $GitPromptSettings.PromptDebugSuffix } else { ' [DBG]>> ' })
} else {
Write-Host (if ($GitPromptSettings.PromptSuffix) { $GitPromptSettings.PromptSuffix } else { '> ' })
} |
Add check for $prompSuffix null/empty.
I'm feeling pretty good about this! Is there any more testing you want to do on v2 or v5 (is v3 a concern)? |
OK tested on v3. Works fine. I think this is ready to be merged. |
Fix #217. This would only export the prompt function if the prompt function is still set to the default.
I'm not suggesting we accept this just yet, just wanted to put something up folks could play with.