单行和居中的Powershell彩色文本

时间:2019-04-03 18:57:50

标签: windows powershell

我需要更改Powershell功能。该功能使文本在终端中居中,但是,我需要能够在一行上输出多种颜色的文本。如果我执行-NoNewLine并执行更多写入主机操作以更改颜色...,那么它仍会计算终端的宽度,并且仍会添加与不添加-NoNewLine一样多的填充。本质上,我希望文本居中,并且希望能够使用多种颜色。我所拥有的我每行只能做一种颜色。

function WriteCentered([String] $text, $color = $null)
{
    $width = [int](Get-Host).UI.RawUI.BufferSize.Width
    $twidth = [int]$text.Length
    $offset = ($width / 2) - ($twidth / 2)
    $newText = $text.PadLeft($offset + $twidth)

    if($color)
    {
        Write-Host $newText -ForegroundColor $color
    }        
    else
    {
        Write-Host $newText 
    }


}   

我添加了更多的IF条件,更改了填充计算,但无法正确设置它。

1 个答案:

答案 0 :(得分:1)

PowerShell-Module PSWriteColor在一行上输出多种颜色方面已经做得很好。您可以直接从GitHub下载并使用Import-Module <PATH-TO>\PSWriteColor.psd1导入它,也可以直接使用Install-Module -Name PSWriteColor从PowerShell库安装它。

简而言之语法为Write-Color -Text "GreenText","RedText","BlueText" -Color Green,Red,Blue。因此,我们需要在[String[]]$Text参数前面加上一个包含必要空格的字符串,以便将消息在屏幕上居中,并在[ConsoleColor[]]$Color参数上加上相应的颜色。

这里有一些用于居中的辅助功能。

#Requires -Modules @{ ModuleName="PSWriteColor"; ModuleVersion="0.8.5" }
function WriteColor-Centered {
param(
    [Parameter(Mandatory=$true)][string[]]$Text,
    [Parameter(Mandatory=$true)][ConsoleColor[]]$Color
)
    $messageLength = 0
    $Text | ForEach-Object { $messageLength += $_.Length }

    [String[]] $centeredText = "{0}" -f (' ' * (([Math]::Max(0, $Host.UI.RawUI.BufferSize.Width / 2) - [Math]::Floor($messageLength / 2))))
    $centeredText += $Text

    [ConsoleColor[]]$OutColor = @([ConsoleColor]::White)
    $OutColor += $Color

    Write-Color -Text $centeredText -Color $OutColor
    # Alt.: use WriteColor-Core, see below
    # WriteColor-Core -Text $centeredText -Color $OutColor
}

我从this stackoverflow answer复制了空格计算。

编辑:有人问我是否有可能在不导入模块的情况下完成这项工作。老实说,我现在有点脏了,因为我进入了一个编写良好的模块的源代码,剥离了所有功能和错误处理,并将其粘贴到这里。

无论如何-如果您在上面的包装函数中替换了Write-Color的调用并调用了以下WriteColor-Core,则可以省去加载PSWriteColor模块。

function WriteColor-Core {
param(
    [Parameter(Mandatory=$true)][string[]]$Text,
    [Parameter(Mandatory=$true)][ConsoleColor[]]$Color
)
    # Fallback defaults if one of the values isn't set
    $LastForegroundColor = [console]::ForegroundColor
    # The real deal coloring
    for ($i = 0; $i -lt $Text.Count; $i++) {
        $CurrentFGColor = if ($Color[$i]) { $Color[$i] } else { $LastForegroundColor }
        $WriteParams = @{
            NoNewLine       = $true
            ForegroundColor = $CurrentFGColor
        }
        Write-Host $Text[$i] @WriteParams
        # Store last color set, in case next iteration doesn't have a set color
        $LastForegroundColor = $CurrentFGColor
    }

    Write-Host
}