Skip to content
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

Merged
merged 7 commits into from
Jan 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions GitPrompt.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ $global:GitPromptSettings = New-Object PSObject -Property @{

EnableWindowTitle = 'posh~git ~ '

PromptSuffix = '> '
PromptDebugSuffix = ' [DBG]>> '

Debug = $false

BranchNameLimit = 0
Expand Down Expand Up @@ -306,8 +309,4 @@ $PoshGitVcsPrompt = {
Write-GitStatus $GitStatus
}

# Install handler for removal/unload of the module
$Global:VcsPromptStatuses += $PoshGitVcsPrompt
Copy link
Owner

@dahlbyk dahlbyk Jan 3, 2017

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

Copy link
Owner

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?

Copy link
Collaborator Author

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?

$ExecutionContext.SessionState.Module.OnRemove = {
$Global:VcsPromptStatuses = $Global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt }
}
34 changes: 18 additions & 16 deletions posh-git.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,24 @@ Description = 'A PowerShell environment for Git'
PowerShellVersion = '2.0'

# Functions to export from this module
FunctionsToExport = @('Invoke-NullCoalescing',
'Write-GitStatus',
'Write-Prompt',
'Write-VcsStatus',
'Get-GitStatus',
'Enable-GitColors',
'Get-GitDirectory',
'TabExpansion',
'Get-AliasPattern',
'Get-SshAgent',
'Start-SshAgent',
'Stop-SshAgent',
'Add-SshKey',
'Get-SshPath',
'Update-AllBranches',
'tgit')
FunctionsToExport = @(
'Invoke-NullCoalescing',
'Write-GitStatus',
'Write-Prompt',
'Write-VcsStatus',
'Get-GitStatus',
'Enable-GitColors',
'Get-GitDirectory',
'TabExpansion',
'Get-AliasPattern',
'Get-SshAgent',
'Start-SshAgent',
'Stop-SshAgent',
'Add-SshKey',
'Get-SshPath',
'Update-AllBranches',
'tgit'
)

# Cmdlets to export from this module
CmdletsToExport = @()
Expand Down
104 changes: 89 additions & 15 deletions posh-git.psm1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
param([switch]$NoVersionWarn = $false)
param([switch]$NoVersionWarn)

if (Get-Module posh-git) { return }

Expand All @@ -11,26 +11,98 @@ 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
.\CheckVersion.ps1 > $null
& $PSScriptRoot\CheckVersion.ps1 > $null
Copy link
Owner

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

Copy link
Owner

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 👍


. .\Utils.ps1
. .\GitUtils.ps1
. .\GitPrompt.ps1
. .\GitTabExpansion.ps1
. .\TortoiseGit.ps1
Pop-Location
. $PSScriptRoot\Utils.ps1
. $PSScriptRoot\GitUtils.ps1
. $PSScriptRoot\GitPrompt.ps1
. $PSScriptRoot\GitTabExpansion.ps1
. $PSScriptRoot\TortoiseGit.ps1

if (!$Env:HOME) { $Env:HOME = "$Env:HOMEDRIVE$Env:HOMEPATH" }
if (!$Env:HOME) { $Env:HOME = "$Env:USERPROFILE" }

Get-TempEnv 'SSH_AGENT_PID'
Get-TempEnv 'SSH_AUTH_SOCK'

Export-ModuleMember `
-Alias @(
'??') `
-Function @(
# Get the default prompt definition.
if ($psv.Major -eq 2) {
$defaultPromptDef = "`$(if (test-path variable:/PSDebugContext) { '[DBG]: ' } else { '' }) + 'PS ' + `$(Get-Location) + `$(if (`$nestedpromptlevel -ge 1) { '>>' }) + '> '"
}
else {
$defaultPromptDef = [Runspace]::DefaultRunspace.InitialSessionState.Commands['prompt'].Definition
}

# If there is no prompt function or the prompt function is the default, replace the current prompt function definition
$poshGitPromptScriptBlock = $null

$currentPromptDef = if ($funcInfo = Get-Command prompt -ErrorAction SilentlyContinue) { $funcInfo.Definition }
Copy link
Owner

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

if (!$currentPromptDef -or ($currentPromptDef -eq $defaultPromptDef)) {
# Have to use [scriptblock]::Create() to get debugger detection to work in PS v2
$poshGitPromptScriptBlock = [scriptblock]::Create(@'
$origLastExitCode = $global:LASTEXITCODE

# A UNC path has no drive so it's better to use the ProviderPath e.g. "\\server\share".
# However for any path with a drive defined, it's better to use the Path property.
# In this case, ProviderPath is "\LocalMachine\My"" whereas Path is "Cert:\LocalMachine\My".
# The latter is more desirable.
$pathInfo = $ExecutionContext.SessionState.Path.CurrentLocation
$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) {
Copy link
Owner

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.

$stringComparison = [System.StringComparison]::Ordinal
}
else {
$stringComparison = [System.StringComparison]::OrdinalIgnoreCase
}

# Abbreviate path by replacing beginning of path with ~ *iff* the path is in the user's home dir
if ($currentPath -and $currentPath.StartsWith($Home, $stringComparison))
{
$currentPath = "~" + $currentPath.SubString($Home.Length)
}

# Write the abbreviated current path
Write-Host $currentPath -NoNewline

# Write the Git status summary information
Write-VcsStatus

# If stopped in the debugger, the prompt needs to indicate that in some fashion
$debugMode = (Test-Path Variable:/PSDebugContext) -or [runspace]::DefaultRunspace.Debugger.InBreakpoint
$promptSuffix = if ($debugMode) { $GitPromptSettings.PromptDebugSuffix } else { $GitPromptSettings.PromptSuffix }

# If user specifies $null or empty string, set to ' ' to avoid "PS>" unexpectedly being displayed
if (!$promptSuffix) {
$promptSuffix = ' '
}

$global:LASTEXITCODE = $origLastExitCode
$promptSuffix
'@)

# Set the posh-git prompt as the default prompt
Set-Item Function:\prompt -Value $poshGitPromptScriptBlock
}

# Install handler for removal/unload of the module
$ExecutionContext.SessionState.Module.OnRemove = {
$global:VcsPromptStatuses = $global:VcsPromptStatuses | Where-Object { $_ -ne $PoshGitVcsPrompt }

# 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 $poshGitPromptScriptBlock) {
Set-Item Function:\prompt -Value ([scriptblock]::Create($defaultPromptDef))
return
}

Write-Warning 'If your prompt function uses any posh-git commands, it will cause posh-git to be re-imported every time your prompt function is invoked.'
}

$exportModuleMemberParams = @{
Alias = @('??') # TODO: Remove in 1.0.0
Function = @(
'Invoke-NullCoalescing',
'Write-GitStatus',
'Write-Prompt',
Expand All @@ -46,6 +118,8 @@ Export-ModuleMember `
'Add-SshKey',
'Get-SshPath',
'Update-AllBranches',
'tgit')

'tgit'
)
}

Export-ModuleMember @exportModuleMemberParams
19 changes: 0 additions & 19 deletions profile.example.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,6 @@ else {
throw "Failed to import posh-git."
}

# Set up a simple prompt that displays Git status summary info when inside of a Git repo.
function global:prompt {
$origLastExitCode = $LASTEXITCODE

# A UNC path has no drive so it's better to use the ProviderPath e.g. "\\server\share".
# However for any path with a drive defined, it's better to use the Path property.
# In this case, ProviderPath is "\LocalMachine\My"" whereas Path is "Cert:\LocalMachine\My".
# The latter is more desirable.
$pathInfo = $ExecutionContext.SessionState.Path.CurrentLocation
$curPath = if ($pathInfo.Drive) { $pathInfo.Path } else { $pathInfo.ProviderPath }
Write-Host $curPath -NoNewline

# Write the Git status summary information to the host.
Write-VcsStatus

$global:LASTEXITCODE = $origLastExitCode
"> "
}

# Settings for the prompt are in GitPrompt.ps1, so add any desired settings changes here.
# Example:
# $Global:GitPromptSettings.BranchBehindAndAheadDisplay = "Compact"
Expand Down