Skip to content

Commit

Permalink
Add hex colors
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaunLawrie committed Nov 7, 2023
1 parent 8b1f84f commit 1923bb3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 29 deletions.
9 changes: 8 additions & 1 deletion PwshSpectreConsole/private/Attributes.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ class ValidateSpectreColor : System.Management.Automation.ValidateArgumentsAttri
{
ValidateSpectreColor() : base() { }
[void]Validate([object] $Color, [System.Management.Automation.EngineIntrinsics]$EngineIntrinsics) {
# Handle hex colors
if($Color -match '^#[A-Fa-f0-9]{6}$') {
return
}

$spectreColors = [Spectre.Console.Color] | Get-Member -Static -Type Properties | Select-Object -ExpandProperty Name
$result = $spectreColors -contains $Color
if($result -eq $false) {
Expand All @@ -13,7 +18,9 @@ class ValidateSpectreColor : System.Management.Automation.ValidateArgumentsAttri
class ArgumentCompletionsSpectreColors : System.Management.Automation.ArgumentCompleterAttribute
{
ArgumentCompletionsSpectreColors() : base({
[Spectre.Console.Color] | Get-Member -Static -Type Properties | Select-Object -ExpandProperty Name
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$options = [Spectre.Console.Color] | Get-Member -Static -Type Properties | Select-Object -ExpandProperty Name
return $options | Where-Object { $_ -like "$wordToComplete*" }
}) { }
}

Expand Down
73 changes: 45 additions & 28 deletions PwshSpectreConsole/public/PwshSpectreConsole.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ function Invoke-SpectrePromptAsync {
}
}

function Convert-ToSpectreColor {
param (
[Parameter(ValueFromPipeline, Mandatory)]
[ValidateSpectreColor()]
[string] $Color
)
# Already validated in validation attribute
if($Color.StartsWith("#")) {
$hexString = $Color -replace '^#', ''
$hexBytes = [System.Convert]::FromHexString($hexString)
return [Spectre.Console.Color]::new($hexBytes[0], $hexBytes[1], $hexBytes[2])
}

# Validated in attribute as a real color already
return [Spectre.Console.Color]::$Color
}

function Set-SpectreColors {
<#
.SYNOPSIS
Expand Down Expand Up @@ -52,8 +69,8 @@ function Set-SpectreColors {
[ArgumentCompletionsSpectreColors()]
[string] $DefaultValueColor = "Grey"
)
$script:AccentColor = [Spectre.Console.Color]::$AccentColor
$script:DefaultValueColor = [Spectre.Console.Color]::$DefaultValueColor
$script:AccentColor = $AccentColor | Convert-ToSpectreColor
$script:DefaultValueColor = $DefaultValueColor | Convert-ToSpectreColor
}

function Write-SpectreRule {
Expand Down Expand Up @@ -84,7 +101,7 @@ function Write-SpectreRule {
[string] $Alignment = "Left",
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)
$rule = [Spectre.Console.Rule]::new("[$($Color)]$Title[/]")
$rule.Justification = [Spectre.Console.Justify]::$Alignment
Expand Down Expand Up @@ -118,7 +135,7 @@ function Write-SpectreFigletText {
[string] $Alignment = "Left",
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)
$figletText = [Spectre.Console.FigletText]::new($Text)
$figletText.Justification = switch($Alignment) {
Expand All @@ -127,7 +144,7 @@ function Write-SpectreFigletText {
"Centered" { [Spectre.Console.Justify]::Center }
default { Write-Error "Invalid alignment $Alignment" }
}
$figletText.Color = [Spectre.Console.Color]::$Color
$figletText.Color = ($Color | Convert-ToSpectreColor)
[Spectre.Console.AnsiConsole]::Write($figletText)
}

Expand Down Expand Up @@ -226,12 +243,12 @@ function Read-SpectreSelection {
#>
[Reflection.AssemblyMetadata("title", "Read-SpectreSelection")]
param (
[string] $Title = "What's your favourite colour [$($script:AccentColor.ToString())]option[/]?",
[string] $Title = "What's your favourite colour [$($script:AccentColor.ToMarkup())]option[/]?",
[array] $Choices = @("red", "green", "blue"),
[string] $ChoiceLabelProperty,
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString(),
[string] $Color = $script:AccentColor.ToMarkup(),
[int] $PageSize = 5
)
$prompt = [Spectre.Console.SelectionPrompt[string]]::new()
Expand All @@ -251,8 +268,8 @@ function Read-SpectreSelection {
$prompt.Title = $Title
$prompt.PageSize = $PageSize
$prompt.WrapAround = $true
$prompt.HighlightStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$prompt.MoreChoicesText = "[$($script:DefaultValueColor)](Move up and down to reveal more choices)[/]"
$prompt.HighlightStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
$prompt.MoreChoicesText = "[$($script:DefaultValueColor.ToMarkup())](Move up and down to reveal more choices)[/]"
$selected = Invoke-SpectrePromptAsync -Prompt $prompt

if($ChoiceLabelProperty) {
Expand Down Expand Up @@ -291,12 +308,12 @@ function Read-SpectreMultiSelection {
#>
[Reflection.AssemblyMetadata("title", "Read-SpectreMultiSelection")]
param (
[string] $Title = "What are your favourite [$($script:AccentColor.ToString())]colors[/]?",
[string] $Title = "What are your favourite [$($script:AccentColor.ToMarkup())]colors[/]?",
[array] $Choices = @("red", "orange", "yellow", "green", "blue", "indigo", "violet"),
[string] $ChoiceLabelProperty,
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString(),
[string] $Color = $script:AccentColor.ToMarkup(),
[int] $PageSize = 5
)
$prompt = [Spectre.Console.MultiSelectionPrompt[string]]::new()
Expand All @@ -316,9 +333,9 @@ function Read-SpectreMultiSelection {
$prompt.Title = $Title
$prompt.PageSize = $PageSize
$prompt.WrapAround = $true
$prompt.HighlightStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$prompt.InstructionsText = "[$($script:DefaultValueColor)](Press [$($script:AccentColor.ToString())]space[/] to toggle a choice and press [$($script:AccentColor.ToString())]<enter>[/] to submit your answer)[/]"
$prompt.MoreChoicesText = "[$($script:DefaultValueColor)](Move up and down to reveal more choices)[/]"
$prompt.HighlightStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
$prompt.InstructionsText = "[$($script:DefaultValueColor.ToMarkup())](Press [$($script:AccentColor.ToMarkup())]space[/] to toggle a choice and press [$($script:AccentColor.ToMarkup())]<enter>[/] to submit your answer)[/]"
$prompt.MoreChoicesText = "[$($script:DefaultValueColor.ToMarkup())](Move up and down to reveal more choices)[/]"
$selected = Invoke-SpectrePromptAsync -Prompt $prompt

if($ChoiceLabelProperty) {
Expand Down Expand Up @@ -366,7 +383,7 @@ function Read-SpectreMultiSelectionGrouped {
#>
[Reflection.AssemblyMetadata("title", "Read-SpectreMultiSelectionGrouped")]
param (
[string] $Title = "What are your favourite [$($script:AccentColor.ToString())]colors[/]?",
[string] $Title = "What are your favourite [$($script:AccentColor.ToMarkup())]colors[/]?",
[array] $Choices = @(
@{
Name = "The rainbow"
Expand All @@ -380,7 +397,7 @@ function Read-SpectreMultiSelectionGrouped {
[string] $ChoiceLabelProperty,
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString(),
[string] $Color = $script:AccentColor.ToMarkup(),
[int] $PageSize = 10
)
$prompt = [Spectre.Console.MultiSelectionPrompt[string]]::new()
Expand All @@ -406,9 +423,9 @@ function Read-SpectreMultiSelectionGrouped {
$prompt.Title = $Title
$prompt.PageSize = $PageSize
$prompt.WrapAround = $true
$prompt.HighlightStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$prompt.InstructionsText = "[$($script:DefaultValueColor)](Press [$($script:AccentColor.ToString())]space[/] to toggle a choice and press [$($script:AccentColor.ToString())]<enter>[/] to submit your answer)[/]"
$prompt.MoreChoicesText = "[$($script:DefaultValueColor)](Move up and down to reveal more choices)[/]"
$prompt.HighlightStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
$prompt.InstructionsText = "[$($script:DefaultValueColor.ToMarkup())](Press [$($script:AccentColor.ToMarkup())]space[/] to toggle a choice and press [$($script:AccentColor.ToMarkup())]<enter>[/] to submit your answer)[/]"
$prompt.MoreChoicesText = "[$($script:DefaultValueColor.ToMarkup())](Move up and down to reveal more choices)[/]"
$selected = Invoke-SpectrePromptAsync -Prompt $prompt

if($ChoiceLabelProperty) {
Expand Down Expand Up @@ -484,14 +501,14 @@ function Invoke-SpectreCommandWithStatus {
[string] $Title,
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)
[Spectre.Console.AnsiConsole]::Status().Start($Title, {
param (
$ctx
)
$ctx.Spinner = [Spectre.Console.Spinner+Known]::$Spinner
$ctx.SpinnerStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$ctx.SpinnerStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
& $ScriptBlock $ctx
})
}
Expand Down Expand Up @@ -852,15 +869,15 @@ function Format-SpectrePanel {
[switch] $Expand,
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)
$panel = [Spectre.Console.Panel]::new($Data)
if($Title) {
$panel.Header = [Spectre.Console.PanelHeader]::new($Title)
}
$panel.Expand = $Expand
$panel.Border = [Spectre.Console.BoxBorder]::$Border
$panel.BorderStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$panel.BorderStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
[Spectre.Console.AnsiConsole]::Write($panel)
}

Expand Down Expand Up @@ -896,12 +913,12 @@ function Format-SpectreTable {
[string] $Border = "Double",
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)
begin {
$table = [Spectre.Console.Table]::new()
$table.Border = [Spectre.Console.TableBorder]::$Border
$table.BorderStyle = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$table.BorderStyle = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
$headerProcessed = $false
}
process {
Expand Down Expand Up @@ -982,7 +999,7 @@ function Format-SpectreTree {
[string] $Border = "Rounded",
[ValidateSpectreColor()]
[ArgumentCompletionsSpectreColors()]
[string] $Color = $script:AccentColor.ToString()
[string] $Color = $script:AccentColor.ToMarkup()
)

function Add-SpectreTreeNode {
Expand All @@ -1003,7 +1020,7 @@ function Format-SpectreTree {

Add-SpectreTreeNode -Node $tree -Children $Data.Children

$tree.Style = [Spectre.Console.Style]::new([Spectre.Console.Color]::$Color)
$tree.Style = [Spectre.Console.Style]::new(($Color | Convert-ToSpectreColor))
[Spectre.Console.AnsiConsole]::Write($tree)
}

Expand All @@ -1027,7 +1044,7 @@ function Read-SpectrePause {
#>
[Reflection.AssemblyMetadata("title", "Read-SpectrePause")]
param (
[string] $Message = "[$script:DefaultValueColor]Press [$script:AccentColor]<enter>[/] to continue[/]",
[string] $Message = "[$($script:DefaultValueColor.ToMarkup())]Press [$($script:AccentColor.ToMarkup())]<enter>[/] to continue[/]",
[switch] $NoNewline
)

Expand Down

1 comment on commit 1923bb3

@futuremotiondev
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Shaun,

Are you going to export Convert-ToSpectreColor in the manifest (FunctionsToExport)? If not, I'm unclear on how to use a HEX color in say, a bar chart. See code:

$data = @(
    @{ Label = "Apples"; Value = 10; Color = [Spectre.Console.Color]::Green },
    @{ Label = "Oranges"; Value = 5; Color = [Spectre.Console.Color]::Yellow },
    @{ Label = "Bananas"; Value = 3; Color = [Spectre.Console.Color]::Red }
)
Format-SpectreBarChart -Data $data -Title "Fruit Sales" -Width 50

I know that your new function Convert-ToSpectreColor could handle this, but it's not public facing so I'm not sure if there is some other way to accomplish what I'm trying to do. Is this the only way? (See below)

$data = @(
    @{ Label = "Apples"; Value = 10; Color = Convert-ToSpectreColor -Color #12D34A },
    @{ Label = "Oranges"; Value = 5; Color = Convert-ToSpectreColor -Color #F3D757 },
    @{ Label = "Bananas"; Value = 3; Color = Convert-ToSpectreColor -Color #F35757 }
)
Format-SpectreBarChart -Data $data -Title "Fruit Sales" -Width 50

Please sign in to comment.