PowerLine.psm1
using namespace PoshCode using namespace System.Management.Automation using namespace System.Collections.Generic using namespace PoshCode.Pansies #Region '.\Classes\PowerLineTheme.ps1' 0 #using namespace PoshCode class PowerLineTheme { [BlockCaps]$DefaultCapsLeftAligned [BlockCaps]$DefaultCapsRightAligned [BlockCaps]$DefaultSeparator [TerminalBlock[]]$Prompt [string]$PSReadLineContinuationPrompt [string]$PSReadLineContinuationPromptColor [string[]]$PSReadLinePromptText [bool]$SetCurrentDirectory [scriptblock]$Title [int]$DefaultAddIndex = -1 } Add-MetadataConverter @{ "PowerLineTheme" = { [PowerLineTheme]$args[0] } [PowerLineTheme] = { "PowerLineTheme @{ DefaultCapsLeftAligned = '$($_.DefaultCapsLeftAligned.Left)', '$($_.DefaultCapsLeftAligned.Right)' DefaultCapsRightAligned = '$($_.DefaultCapsRightAligned.Left)', '$($_.DefaultCapsRightAligned.Right)' DefaultSeparator = '$($_.DefaultSeparator.Left)', '$($_.DefaultSeparator.Right)' Prompt = @( $($_.Prompt.ToPsScript() -join "`n ") ) PSReadLineContinuationPrompt = '$($_.PSReadLineContinuationPrompt)' PSReadLineContinuationPromptColor = '$($_.PSReadLineContinuationPromptColor)' PSReadLinePromptText = '$($_.PSReadLinePromptText -join "','")' SetCurrentDirectory = $(if ($_.SetCurrentDirectory) { '$true' } else { '$false' })$( if (![string]::IsNullOrWhiteSpace($_.Title)) { "`n Title = ScriptBlock @'`n$($_.Title)`n'@" })$( if ($_.DefaultAddIndex -ge 0) { "`n DefaultAddIndex = $($_.DefaultAddIndex)'@" }) }" } } #EndRegion '.\Classes\PowerLineTheme.ps1' 38 #Region '.\Private\_init.ps1' 0 #!/usr/bin/env powershell #using namespace System.Management.Automation #using namespace System.Collections.Generic #using namespace PoshCode.Pansies [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = "","`u{E0B0}" [PoshCode.TerminalBlock]::DefaultCapsRightAligned ="`u{E0B2}","" # Ensure the global prompt variable exists and is typed the way we expect [System.Collections.Generic.List[PoshCode.TerminalBlock]]$Global:Prompt = [PoshCode.TerminalBlock[]]@( if (Test-Path Variable:Prompt) { $Prompt | ForEach-Object { [PoshCode.TerminalBlock]$_ } } ) #EndRegion '.\Private\_init.ps1' 15 #Region '.\Private\WriteExceptions.ps1' 0 function WriteExceptions { [CmdletBinding()] param( # A dictionary mapping script blocks to the exceptions which threw them [System.Collections.Specialized.OrderedDictionary]$ScriptExceptions ) $ErrorString = "" if($PromptErrors.Count -gt 0) { $global:PromptErrors = [ordered]@{} + $ScriptExceptions Write-Warning "Exception thrown from prompt block. Check `$PromptErrors. To suppress this message, Set-PowerLine -HideError" #$PromptErrors.Insert(0, "0 Preview","Exception thrown from prompt block. Check `$PromptErrors:`n") if(@($Host.PrivateData.PSTypeNames)[0] -eq "Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy") { foreach($e in $ScriptExceptions.Values) { $ErrorString += [PoshCode.Pansies.Text]@{ ForegroundColor = $Host.PrivateData.ErrorForegroundColor BackgroundColor = $Host.PrivateData.ErrorBackgroundColor Object = $e } $ErrorString += "`n" } } else { foreach($e in $ScriptExceptions) { $ErrorString += [PoshCode.Pansies.Text]@{ ForegroundColor = "Red" BackgroundColor = "Black" Object = $e } $ErrorString += "`n" } } } $ErrorString } #EndRegion '.\Private\WriteExceptions.ps1' 36 #Region '.\Public\Add-PowerLineBlock.ps1' 0 function Add-PowerLineBlock { <# .Synopsis Insert text or a ScriptBlock into the $Prompt .Description This function exists primarily to ensure that modules are able to modify the prompt easily without repeating themselves. .Example Add-PowerLineBlock { "`nI ♥ PS" } Adds the classic "I ♥ PS" to your prompt on a new line. We actually recommend having a simple line in pure 16-color mode on the last line of your prompt, to ensures that PSReadLine won't mess up your colors. PSReadline overwrites your prompt line when you type -- and it can only handle 16 color mode. .Example Add-PowerLineBlock { New-TerminalBlock { Show-Elapsed } -ForegroundColor White -BackgroundColor DarkBlue -ErrorBackground DarkRed -ElevatedForegroundColor Yellow } -Index -2 # This example uses Add-PowerLineBlock to insert a block into the prommpt _before_ the last block # It calls Show-Elapsed to show the duration of the last command as the text of the block # It uses New-TerminalBlock to control the color so that it's highlighted in red if there is an error, but otherwise in dark blue (or yellow if it's an elevated host). #> [CmdletBinding(DefaultParameterSetName="InputObject")] param( # The text, object, or scriptblock to show as output [Parameter(Position=0, Mandatory, ValueFromPipeline, ParameterSetName = "InputObject")] [Alias("Text", "Content")] [PoshCode.TerminalBlock]$InputObject, # The position to insert the InputObject at, by default, inserts in the same place as the last one [int]$Index = -1, # When set by a module, hooks the calling module to remove this block if the module is removed [Switch]$AutoRemove, # If set, adds the input to the prompt without checking if it's already there [Switch]$Force ) process { Write-Debug "Add-PowerLineBlock $InputObject" if(!$PSBoundParameters.ContainsKey("Index")) { $Index = $Script:PowerLineConfig.DefaultAddIndex++ } # If force is true, it doesn't matter what Skip is. Otherwise, calculate Skip $Skip = $Force -or @($Global:Prompt).ForEach{ $_.Content.ToString().Trim() } -eq $InputObject.Content.ToString().Trim() if ($Force -or !$Skip) { if ($Index -eq -1 -or $Index -ge $Global:Prompt.Count) { Write-Verbose "Appending '$InputObject' to the end of the prompt" $Global:Prompt.Add($InputObject) $Index = $Global:Prompt.Count } elseif($Index -lt 0) { $Index = $Global:Prompt.Count - $Index Write-Verbose "Inserting '$InputObject' at $Index of the prompt" $Global:Prompt.Insert($Index, $InputObject) } else { Write-Verbose "Inserting '$InputObject' at $Index of the prompt" $Global:Prompt.Insert($Index, $InputObject) } $Script:PowerLineConfig.DefaultAddIndex = $Index + 1 } else { Write-Verbose "Prompt already contained the InputObject block" } if ($AutoRemove) { if (($CallStack = Get-PSCallStack).Count -ge 2) { if ($Module = $CallStack[1].InvocationInfo.MyCommand.Module) { $Module.OnRemove = { Remove-PowerLineBlock $InputObject }.GetNewClosure() } } } } } #EndRegion '.\Public\Add-PowerLineBlock.ps1' 73 #Region '.\Public\Export-PowerLinePrompt.ps1' 0 function Export-PowerLinePrompt { [CmdletBinding()] param() Get-PowerLineTheme | Export-Configuration -AsHashtable } #EndRegion '.\Public\Export-PowerLinePrompt.ps1' 8 #Region '.\Public\Get-PowerLineTheme.ps1' 0 function Get-PowerLineTheme { <# .SYNOPSIS Get the themeable PowerLine settings #> [CmdletBinding()] param() [PowerLineTheme]$Local:Configuration = $Script:PowerLineConfig # We use global:Prompt except when importing and exporting $Configuration.Prompt = [PoshCode.TerminalBlock[]]$global:Prompt if (Get-Command Get-PSReadLineOption) { $PSReadLineOptions = Get-PSReadLineOption # PromptText and ContinuationPrompt can have colors in them $Configuration.PSReadLinePromptText = $PSReadLineOptions.PromptText $Configuration.PSReadLineContinuationPrompt = $PSReadLineOptions.ContinuationPrompt # If the ContinuationPrompt has color in it, this is irrelevant, but keep it anyway $Configuration.PSReadLineContinuationPromptColor = $PSReadLineOptions.ContinuationPromptColor } $Configuration } #EndRegion '.\Public\Get-PowerLineTheme.ps1' 25 #Region '.\Public\Remove-PowerLineBlock.ps1' 0 function Remove-PowerLineBlock { <# .Synopsis Remove text or a ScriptBlock from the $Prompt .Description This function exists primarily to ensure that modules are able to clean up the prompt easily when they're removed .Example Remove-PowerLineBlock { New-TerminalBlock { Show-ElapsedTime } -ForegroundColor White -BackgroundColor DarkBlue -ErrorBackground DarkRed -ElevatedForegroundColor Yellow } Removes the specified block. Note that it must be _exactly_ the same as when you added it. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidDefaultValueForMandatoryParameter', "Index", Justification = 'This rule should ignore parameters that are only mandatory in some parameter sets')] [CmdletBinding(DefaultParameterSetName="ByObject")] param( # The text, object, or scriptblock to show as output [Parameter(Position=0, Mandatory, ValueFromPipeline, ParameterSetName = "ByObject")] [Alias("Text")] $InputObject, [Parameter(Mandatory, ParameterSetName = "ByIndex")] [int]$Index = -1 ) process { if ($PSCmdlet.ParameterSetName -eq "ByObject") { if ($InputObject -is [PoshCode.TerminalBlock]) { $Index = @($Global:Prompt).IndexOf($InputObject) } if ($Index -ge 0) { $InputString = if ($InputObject.Object) { $InputObject.Object.ToString().Trim() } else { $InputObject.ToString().Trim() } $Index = @($Global:Prompt).ForEach{$_.Object.ToString().Trim()}.IndexOf($InputString) } } if ($Index -lt 0) { $Index = $Global:Prompt.Count - $Index } if ($Index -ge 0) { $null = $Global:Prompt.RemoveAt($Index) } if ($Index -lt $Script:PowerLineConfig.DefaultAddIndex) { $Script:PowerLineConfig.DefaultAddIndex-- } } } #EndRegion '.\Public\Remove-PowerLineBlock.ps1' 54 #Region '.\Public\Set-PowerLinePrompt.ps1' 0 function Set-PowerLinePrompt { #.Synopsis # Set the default PowerLine prompt function which uses the $Prompt variable #.Description # Overwrites the current prompt function with one that uses the $Prompt variable # Note that this doesn't try to preserve any changes already made to the prompt by modules like ZLocation #.Example # Set-PowerLinePrompt -SetCurrentDirectory # # Sets the powerline prompt and activates and option supported by this prompt function to update the .Net environment with the current directory each time the prompt runs. #.Example # Set-PowerLinePrompt -SetCurrentDirectory -Title { # Show-Path -HomeString "~" -Depth 2 -GitDir # } -RestoreVirtualTerminal # # Turns on all the non-prompt features of PowerLine: # - Update the .net environment with the current directory each time the prompt runs # - Update the title with a short version of the path each time the prompt runs # - This legacy option calls a Windows api to enable VirtualTerminal processing on old versions of the Windows Console where this wasn't the default (if git is messing up your terminal, try this). #.Example # Set-PowerLinePrompt -PowerLineFont # # Sets the prompt using the default PowerLine characters. Note that you can still change the characters used to separate blocks in the PowerLine output after running this, by setting the Cap and Separator. #.Example # Set-PowerLinePrompt -NoBackground # # Sets the powerline prompt without the PowerLine effect. This disables background color on ALL current blocks, and switches the Cap and Separator to just a space. Remember that you can change the characters used to separate blocks in your prompt, by setting the Cap and Separator without affecting backgrounds. [Alias("Set-PowerLineTheme")] [CmdletBinding(DefaultParameterSetName = "Manual")] param( # One or more scriptblocks or TerminalBlocks you want to use as your new prompt [Parameter(Position = 0, ValueFromPipelineByPropertyName)] $Prompt, # Resets the prompt to use the default PowerLine characters as cap and separator [Parameter(ParameterSetName = "PowerLine", Mandatory)] [switch]$PowerLineFont, # The cap character(s) that will be used (by default) on normal, left-aligned blocks # Pass two characters: the first for the left side, the second for the right side. [Parameter(ParameterSetName = "Manual", ValueFromPipelineByPropertyName)] [Alias("LeftCaps")] [PoshCode.BlockCaps]$DefaultCapsLeftAligned, # The cap character(s) that will be used by default on right-aligned blocks # Pass two characters: the first for the left side, the second for the right side. [Parameter(ParameterSetName = "Manual", ValueFromPipelineByPropertyName)] [Alias("RightCaps")] [PoshCode.BlockCaps]$DefaultCapsRightAligned, # The Left pointing and Right pointing separator characters are used when a script-based PowerLine block outputs multiple objects # Pass two strings. The first for blocks that are Left-aligned, the second for right-aligned blocks, like: "","" [Parameter(ParameterSetName = "Manual", ValueFromPipelineByPropertyName)] [Alias("Separator")] [PoshCode.BlockCaps]$DefaultSeparator, # Sets the powerline prompt without the PowerLine effect. # Disables background on ALL TerminalBlocks # Switches the Cap and Separator to just a space. [Parameter(ParameterSetName = "Reset", Mandatory)] [switch]$NoBackground, # If set, calls Export-PowerLinePrompt [Parameter()] [Switch]$Save, # A script which outputs a string used to update the Window Title each time the prompt is run [Parameter(ValueFromPipelineByPropertyName)] [scriptblock]$Title, # Keep the .Net Current Directory in sync with PowerShell's [Parameter(ValueFromPipelineByPropertyName)] [Alias("CurrentDirectory")] [switch]$SetCurrentDirectory, # Prevent errors in the prompt from being shown (like the normal PowerShell behavior) [Parameter(ValueFromPipelineByPropertyName)] [switch]$HideErrors, # When there's a parse error, PSReadLine changes a part of the prompt... # Use this option to override PSReadLine by either specifying the characters it should replace, or by specifying both the normal and error strings. # If you specify two strings, they should both be the same length (ignoring escape sequences) [Parameter(ValueFromPipelineByPropertyName)] [string[]]$PSReadLinePromptText, # When you type a command that requires a second line (like if you type | and hit enter) # This is the prompt text. Can be an empty string. Can be anything, really. [Parameter(ValueFromPipelineByPropertyName)] [AllowEmptyString()] [string]$PSReadLineContinuationPrompt, # Let's you set the fg/bg of the PSReadLine continuation prompt as escape sequences. # The easy way is to use PANSIES notation: "$fg:Red$Bg:White" [Parameter(ValueFromPipelineByPropertyName)] [AllowEmptyString()] [string]$PSReadLineContinuationPromptColor ) begin { if ($null -eq $script:OldPrompt) { $script:OldPrompt = $function:global:prompt $MyInvocation.MyCommand.Module.OnRemove = { $function:global:prompt = $script:OldPrompt } } $Configuration = Import-Configuration -ErrorAction SilentlyContinue # Strip common parameters to avoid adding nonsense to the object foreach ($name in [System.Management.Automation.PSCmdlet]::CommonParameters + @("Save", "NoBackground", "PowerLineFont")) { $null = $PSBoundParameters.Remove($name) } [PowerLineTheme]$Local:PowerLineConfig = $Configuration | Update-Object $PSBoundParameters # Set the default cap before we cast prompt blocks if ($NoBackground) { $PowerLineConfig.DefaultCapsLeftAligned = [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = " " $PowerLineConfig.DefaultCapsRightAligned = [PoshCode.TerminalBlock]::DefaultCapsRightAligned = " " $PowerLineConfig.DefaultSeparator = [PoshCode.TerminalBlock]::DefaultSeparator = " " } # For backward compatibility: if ($PSBoundParameters.ContainsKey("PowerLineFont")) { if ($PowerLineFont) { # Make sure we're using the default PowerLine characters: [PoshCode.Pansies.Entities]::ExtendedCharacters['ColorSeparator'] = [char]0xe0b0 [PoshCode.Pansies.Entities]::ExtendedCharacters['ReverseColorSeparator'] = [char]0xe0b2 [PoshCode.Pansies.Entities]::ExtendedCharacters['Separator'] = [char]0xe0b1 [PoshCode.Pansies.Entities]::ExtendedCharacters['ReverseSeparator'] = [char]0xe0b3 [PoshCode.Pansies.Entities]::ExtendedCharacters['Branch'] = [char]0xE0A0 [PoshCode.Pansies.Entities]::ExtendedCharacters['Gear'] = [char]0x26EF # [PoshCode.Pansies.Entities]::EnableNerdFonts = $true } else { # Use characters that at least work in Consolas and Lucida Console [PoshCode.Pansies.Entities]::ExtendedCharacters['ColorSeparator'] = [char]0x258C [PoshCode.Pansies.Entities]::ExtendedCharacters['ReverseColorSeparator'] = [char]0x2590 [PoshCode.Pansies.Entities]::ExtendedCharacters['Separator'] = [char]0x25BA [PoshCode.Pansies.Entities]::ExtendedCharacters['ReverseSeparator'] = [char]0x25C4 [PoshCode.Pansies.Entities]::ExtendedCharacters['Branch'] = [char]0x00A7 [PoshCode.Pansies.Entities]::ExtendedCharacters['Gear'] = [char]0x263C } # Set the new Cap and Separator options too [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = $PowerLineConfig.DefaultCapsLeftAligned = "", [PoshCode.Pansies.Entities]::ExtendedCharacters["ColorSeparator"] [PoshCode.TerminalBlock]::DefaultCapsRightAligned = $PowerLineConfig.DefaultCapsRightAligned = [PoshCode.Pansies.Entities]::ExtendedCharacters["ReverseColorSeparator"], "" [PoshCode.TerminalBlock]::DefaultSeparator = $PowerLineConfig.Separator = -join [PoshCode.Pansies.Entities]::ExtendedCharacters["Separator", "ReverseSeparator"] } if ($PSBoundParameters.ContainsKey("DefaultCapsLeftAligned")) { [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = $PowerLineConfig.DefaultCapsLeftAligned = $DefaultCapsLeftAligned [PoshCode.Pansies.Entities]::ExtendedCharacters["ColorSeparator"] = $DefaultCapsLeftAligned.Right [PoshCode.Pansies.Entities]::ExtendedCharacters["ReverseColorSeparator"] = $DefaultCapsLeftAligned.Left } elseif (!$PowerLineConfig.DefaultCapsLeftAligned) { # If there's nothing in the config, then default to Powerline style! [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = $PowerLineConfig.DefaultCapsLeftAligned = "", [PoshCode.Pansies.Entities]::ExtendedCharacters["ColorSeparator"] } elseif ($PowerLineConfig.DefaultCapsLeftAligned) { [PoshCode.TerminalBlock]::DefaultCapsLeftAligned = $PowerLineConfig.DefaultCapsLeftAligned } if ($PSBoundParameters.ContainsKey("DefaultCapsRightAligned")) { [PoshCode.TerminalBlock]::DefaultCapsRightAligned = $PowerLineConfig.DefaultCapsRightAligned = $DefaultCapsRightAligned [PoshCode.Pansies.Entities]::ExtendedCharacters["ReverseColorSeparator"] = $DefaultCapsRightAligned.Left } elseif (!$PowerLineConfig.DefaultCapsRightAligned) { # If there's nothing in the config, then default to Powerline style! [PoshCode.TerminalBlock]::DefaultCapsRightAligned = $PowerLineConfig.DefaultCapsRightAligned = [PoshCode.Pansies.Entities]::ExtendedCharacters["ReverseColorSeparator"], "" } elseif ($PowerLineConfig.DefaultCapsRightAligned) { [PoshCode.TerminalBlock]::DefaultCapsRightAligned = $PowerLineConfig.DefaultCapsRightAligned } if ($PSBoundParameters.ContainsKey("DefaultSeparator")) { [PoshCode.TerminalBlock]::DefaultSeparator = $PowerLineConfig.DefaultSeparator = $DefaultSeparator [PoshCode.Pansies.Entities]::ExtendedCharacters["Separator"] = $DefaultSeparator.Left [PoshCode.Pansies.Entities]::ExtendedCharacters["ReverseSeparator"] = $DefaultSeparator.Right } elseif (!$PowerLineConfig.DefaultSeparator) { # If there's nothing in the config, then default to Powerline style! [PoshCode.TerminalBlock]::DefaultSeparator = $PowerLineConfig.DefaultSeparator = -join [PoshCode.Pansies.Entities]::ExtendedCharacters["DefaultSeparator", "ReverseSeparator"] } elseif ($PowerLineConfig.DefaultSeparator) { [PoshCode.TerminalBlock]::DefaultSeparator = $PowerLineConfig.DefaultSeparator } } process { # These switches aren't stored in the config $null = $PSBoundParameters.Remove("Save") Write-Verbose "Setting global:Prompt" # We want to support modifying the global:prompt variable outside this function [System.Collections.Generic.List[PoshCode.TerminalBlock]]$global:Prompt = ` [PoshCode.TerminalBlock[]]$PowerLineConfig.Prompt = @( if ($PSBoundParameters.ContainsKey("Prompt")) { Write-Verbose "Setting global:Prompt from prompt parameter" $Local:Prompt # They didn't pass anything, and there's nothing set } elseif ($global:Prompt.Count -eq 0) { # If we found something in config if ($PowerLineConfig.Prompt.Count -gt 0) { Write-Verbose "Setting global:Prompt from powerline config" # If the config is already TerminalBlock, just use that: if ($PowerLineConfig.Prompt -as [PoshCode.TerminalBlock[]]) { $PowerLineConfig.Prompt } else { # Try to upgrade by casting through scriptblock [ScriptBlock[]]@($PowerLineConfig.Prompt) } } else { Write-Verbose "Setting global:Prompt from default prompt" # The default PowerLine Prompt Show-HistoryId -DefaultBackgroundColor DarkGray -ErrorBackgroundColor Red Show-Path -DefaultBackgroundColor White } } else { Write-Verbose "Setting global:Prompt from existing global:prompt" $global:Prompt } ) if ($null -eq $PowerLineConfig.DefaultAddIndex) { $PowerLineConfig.DefaultAddIndex = -1 } $Script:PowerLineConfig = $PowerLineConfig if (Get-Module PSReadLine) { $Options = @{} if ($PowerLineConfig.PSReadLinePromptText) { $Options["PromptText"] = $PowerLineConfig.PSReadLinePromptText } if ($PowerLineConfig.PSReadLineContinuationPrompt) { $Options["ContinuationPrompt"] = $PowerLineConfig.PSReadLineContinuationPrompt } if ($PowerLineConfig.PSReadLineContinuationPromptColor) { $Options["Colors"] = @{ ContinuationPrompt = $PowerLineConfig.PSReadLineContinuationPromptColor } } if ($Options) { Write-Verbose "Updating PSReadLine prompt options: `n$($Options.PromptText -join "`n")`n`n$($Options["Colors"]["ContinuationPrompt"])$($Options["ContinuationPrompt"])" Set-PSReadLineOption @Options } } # Finally, update the prompt function $function:global:prompt = { Write-PowerlinePrompt } [PoshCode.Pansies.RgbColor]::ResetConsolePalette() # If they asked us to save, or if there's nothing saved yet if($Save -or ($PSBoundParameters.Count -and !(Test-Path (Join-Path (Get-StoragePath) Configuration.psd1)))) { Export-PowerLinePrompt } } } #EndRegion '.\Public\Set-PowerLinePrompt.ps1' 254 #Region '.\Public\Write-PowerlinePrompt.ps1' 0 function Write-PowerlinePrompt { [CmdletBinding()] [OutputType([string])] param( [switch]$NoCache ) try { # Stuff these into static properties in case I want to use them from C# [PoshCode.TerminalBlock]::LastSuccess = $global:? [PoshCode.TerminalBlock]::LastExitCode = $global:LASTEXITCODE $PromptErrors = [ordered]@{} #PowerLinePrompt Features: if ($Script:PowerLineConfig.Title) { try { $Host.UI.RawUI.WindowTitle = [System.Management.Automation.LanguagePrimitives]::ConvertTo( (& $Script:PowerLineConfig.Title), [string] ) } catch { $PromptErrors.Add("0 {$($Script:PowerLineConfig.Title)}", $_) Write-Error "Failed to set Title from scriptblock { $($Script:PowerLineConfig.Title) }" } } if ($Script:PowerLineConfig.SetCurrentDirectory) { try { # Make sure Windows & .Net know where we are # They can only handle the FileSystem, and not in .Net Core [System.IO.Directory]::SetCurrentDirectory( (Get-Location -PSProvider FileSystem).ProviderPath ) } catch { $PromptErrors.Add("0 { SetCurrentDirectory }", $_) Write-Error "Failed to set CurrentDirectory to: (Get-Location -PSProvider FileSystem).ProviderPath" } } $CacheKey = if ($NoCache) { $null } else { $MyInvocation.HistoryId } # invoke them all, to find out whether they have content $PromptErrors = [ordered]@{} for ($b = 0; $b -lt $Prompt.Count; $b++) { try { $null = $Prompt[$b].Invoke($CacheKey) } catch { $PromptErrors.Add("$b { $($Prompt[$b].Content) }", $_) } } # Output them all, using the color of adjacent blocks for PowerLine's classic cap "overlap" $builder = [System.Text.StringBuilder]::new() for ($b = 0; $b -lt $Prompt.Count; $b++) { $Neighbor = $null $Block = $Prompt[$b] $n = $b # Your neighbor is the next non-empty block with the same alignment as you while (++$n -lt $Prompt.Count -and $Block.Alignment -eq $Prompt[$n].Alignment) { if ($Prompt[$n].Cache) { $Neighbor = $Prompt[$n] break; } } # Don't render spacers, if they don't have a real (non-space) neighbors if ($Block.Content -eq "Spacer" -and (!$Neighbor.Cache -or $Neighbor.Content -eq "Spacer")) { continue } $null = $builder.Append($Block.ToString($true, $Neighbor.BackgroundColor, $CacheKey)) } $result = $builder.ToString() # This is the fastest way to count characters in PowerShell. $extraLineCount = $result.Split("`n").Count # At the end, output everything as one single string # create the number of lines we need for output up front: ("`n" * $extraLineCount) + ("$([char]27)M" * $extraLineCount) + $result } catch { Write-Warning "Exception in PowerLinePrompt`n$_" "${PWD}>" } } #EndRegion '.\Public\Write-PowerlinePrompt.ps1' 85 #Region '.\postfix.ps1' 0 if (Get-Module EzTheme -ErrorAction SilentlyContinue) { Get-ModuleTheme | Set-PowerLineTheme } else { Set-PowerLinePrompt } #EndRegion '.\postfix.ps1' 6 |