У меня есть функция powershell, которую мне нужно изменить. Однако функция центрирует текст в терминале, мне нужно иметь возможность выводить несколько цветов для текста в одной строке. Если я сделаю -NoNewLine и сделаю больше Write-host, чтобы изменить цвет... тогда он все равно вычислит ширину терминала и все равно добавит столько отступов, сколько было бы без моего добавления -NoNewLine. По сути, я хочу, чтобы мой текст располагался по центру, и я хочу иметь возможность использовать несколько цветов. С тем, что у меня есть, я могу сделать только 1 цвет в строке.
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
}
}
Я добавил больше условий ЕСЛИ, я изменил свои вычисления заполнения, у меня возникли проблемы с тем, чтобы сделать это правильно.
Это не совсем то, что вам нужно, но его можно адаптировать: stackoverflow.com/a/46046113/45375 использует инструкции по раскрашиванию, встроенные в одну строку.





PowerShell-Module PSWriteColor уже хорошо справляется с выводом нескольких цветов в одной строке. Либо вы загружаете его напрямую с GitHub и импортируете с помощью Import-Module <PATH-TO>\PSWriteColor.psd1, либо устанавливаете напрямую из галереи PowerShell с помощью Install-Module -Name PSWriteColor.
Синтаксис вкратце: 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
}
Я скопировал расчет пробелов из этот ответ stackoverflow.
Обновлено: меня спросили, можно ли сделать эту работу без импорта модуля. Честно говоря, сейчас я чувствую себя немного грязным, потому что я зашел в исходный код хорошо написанного модуля, удалил из него всю функциональность и обработку ошибок и вставил сюда.
В любом случае, если вы замените вызов 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
}
Есть ли способ заставить это работать без модуля? Я надеялся заставить этот скрипт работать прямо из коробки.
Я скопировал код из PSWriteColor. Теперь он должен работать без модуля.
Вам нужно будет передать несколько строк и параллельный массив цветов, если вы хотите, чтобы несколько цветов отображались в одной строке, а составная строка находилась в центре.