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

Custom prompt hooks protected from later overwriting #952

Merged
merged 6 commits into from
Oct 19, 2016
113 changes: 87 additions & 26 deletions vendor/profile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,23 @@ try {
$env:Path += $(";" + $env:CMDER_ROOT + "\vendor\git-for-windows\bin")
}

try {
Import-Module -Name "posh-git" -ErrorAction Stop >$null
$gitStatus = $true
} catch {
Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart cmder."
$gitStatus = $false
$gitLoaded = $false
function Import-Git($Loaded){
if($Loaded) { return }
$GitModule = Get-Module -Name Posh-Git -ListAvailable
if($GitModule | select version | where version -le ([version]"0.6.1.20160330")){
Import-Module Posh-Git > $null
}
if(-not ($GitModule) ) {
Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart cmder."
}
# Make sure we only run once by alawys returning true
return $true
}

function checkGit($Path) {
if (Test-Path -Path (Join-Path $Path '.git') ) {
$gitLoaded = Import-Git $gitLoaded
Write-VcsStatus
return
}
Expand All @@ -65,24 +72,6 @@ function checkGit($Path) {
}
}

# Set up a Cmder prompt, adding the git prompt parts inside git repos
function global:prompt {
$realLASTEXITCODE = $LASTEXITCODE
$Host.UI.RawUI.ForegroundColor = "White"
Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green
if($gitStatus){
checkGit($pwd.ProviderPath)
}
$global:LASTEXITCODE = $realLASTEXITCODE
Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray"
return " "
}

# Load special features come from posh-git
if ($gitStatus) {
Start-SshAgent -Quiet
}

# Move to the wanted location
# This is either a env variable set by the user or the result of
# cmder.exe setting this variable due to a commandline argument or a "cmder here"
Expand Down Expand Up @@ -110,11 +99,83 @@ foreach ($x in ls *.ps1) {
}
popd

#
# Prompt Section
# Users should modify their user-profile.ps1 as it will be safe from updates.
#

# Pre assign the hooks so the first run of cmder gets a working prompt.
[ScriptBlock]$PrePrompt = {}
[ScriptBlock]$PostPrompt = {}
[ScriptBlock]$CmderPrompt = {
$Host.UI.RawUI.ForegroundColor = "White"
Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green
checkGit($pwd.ProviderPath)
}

$CmderUserProfilePath = Join-Path $env:CMDER_ROOT "config\user-profile.ps1"
if(Test-Path $CmderUserProfilePath) {
# Create this file and place your own command in there.
. "$CmderUserProfilePath"
} else {
Write-Host "Creating user startup file: $CmderUserProfilePath"
"# Use this file to run your own startup commands" | Out-File $CmderUserProfilePath
# This multiline string cannot be indented, for this reason I've not indented the whole block

Write-Host -BackgroundColor Darkgreen -ForegroundColor White "First Run: Creating user startup file: $CmderUserProfilePath"

$UserProfileTemplate = @'
# Use this file to run your own startup commands

## Prompt Customization
<#
.SYNTAX
<PrePrompt><CMDER DEFAULT>
λ <PostPrompt> <repl input>
.EXAMPLE
<PrePrompt>N:\Documents\src\cmder [master]
λ <PostPrompt> |
#>

[ScriptBlock]$PrePrompt = {

}

# Replace the cmder prompt entirely with this.
# [ScriptBlock]$CmderPrompt = {}

[ScriptBlock]$PostPrompt = {

}

## <Continue to add your own>


'@

New-Item -ItemType File -Path $CmderUserProfilePath -Value $UserProfileTemplate > $null

}

# Once Created these code blocks cannot be overwritten
Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant
Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant
Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant

<#
This scriptblock runs every time the prompt is returned.
Explicitly use functions from MS namespace to protect from being overridden in the user session.
Custom prompt functions are loaded in as constants to get the same behaviour
#>
[ScriptBlock]$Prompt = {
$realLASTEXITCODE = $LASTEXITCODE
$host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf
PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
CmderPrompt
Microsoft.PowerShell.Utility\Write-Host "`nλ " -NoNewLine -ForegroundColor "DarkGray"
PostPrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
$global:LASTEXITCODE = $realLASTEXITCODE
return " "
}

# Functions can be made constant only at creation time
# ReadOnly at least requires `-force` to be overwritten
Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly