From a3155d015dc9fea71b2c64dc0a680b9823f45f6f Mon Sep 17 00:00:00 2001 From: Alexandru Placinta Date: Fri, 10 Nov 2023 16:54:40 +0100 Subject: [PATCH] Add prompt border color customization (#2234) --- internal/config/styles.go | 22 ++++++++-- internal/ui/prompt.go | 10 ++--- internal/ui/prompt_test.go | 85 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/internal/config/styles.go b/internal/config/styles.go index a5fa6b69..89dbe630 100644 --- a/internal/config/styles.go +++ b/internal/config/styles.go @@ -45,9 +45,16 @@ type ( // Prompt tracks command styles Prompt struct { - FgColor Color `yaml:"fgColor"` - BgColor Color `yaml:"bgColor"` - SuggestColor Color `yaml:"suggestColor"` + FgColor Color `yaml:"fgColor"` + BgColor Color `yaml:"bgColor"` + SuggestColor Color `yaml:"suggestColor"` + Border PromptBorder `yaml:"border"` + } + + // PromptBorder tracks the color of the prompt depending on its kind (e.g., command or filter) + PromptBorder struct { + CommandColor Color `yaml:"command"` + DefaultColor Color `yaml:"default"` } // Help tracks help styles. @@ -287,6 +294,10 @@ func newPrompt() Prompt { FgColor: "cadetblue", BgColor: "black", SuggestColor: "dodgerblue", + Border: PromptBorder{ + DefaultColor: "seagreen", + CommandColor: "aqua", + }, } } @@ -511,6 +522,11 @@ func (s *Styles) Body() Body { return s.K9s.Body } +// Prompt returns prompt styles. +func (s *Styles) Prompt() Prompt { + return s.K9s.Prompt +} + // Frame returns frame styles. func (s *Styles) Frame() Frame { return s.K9s.Frame diff --git a/internal/ui/prompt.go b/internal/ui/prompt.go index dedbdfeb..117dd100 100644 --- a/internal/ui/prompt.go +++ b/internal/ui/prompt.go @@ -202,7 +202,7 @@ func (p *Prompt) write(text, suggest string) { p.SetCursorIndex(p.spacer + len(text)) txt := text if suggest != "" { - txt += fmt.Sprintf("[%s::-]%s", p.styles.K9s.Prompt.SuggestColor, suggest) + txt += fmt.Sprintf("[%s::-]%s", p.styles.Prompt().SuggestColor, suggest) } fmt.Fprintf(p, defaultPrompt, p.icon, txt) } @@ -231,7 +231,7 @@ func (p *Prompt) BufferActive(activate bool, kind model.BufferKind) { p.ShowCursor(true) p.SetBorder(true) p.SetTextColor(p.styles.FgColor()) - p.SetBorderColor(colorFor(kind)) + p.SetBorderColor(p.colorFor(kind)) p.icon = p.iconFor(kind) p.activate() return @@ -260,12 +260,12 @@ func (p *Prompt) iconFor(k model.BufferKind) rune { // ---------------------------------------------------------------------------- // Helpers... -func colorFor(k model.BufferKind) tcell.Color { +func (p *Prompt) colorFor(k model.BufferKind) tcell.Color { // nolint:exhaustive switch k { case model.CommandBuffer: - return tcell.ColorAqua + return p.styles.Prompt().Border.CommandColor.Color() default: - return tcell.ColorSeaGreen + return p.styles.Prompt().Border.DefaultColor.Color() } } diff --git a/internal/ui/prompt_test.go b/internal/ui/prompt_test.go index b41c7ec2..41b1c964 100644 --- a/internal/ui/prompt_test.go +++ b/internal/ui/prompt_test.go @@ -1,6 +1,7 @@ package ui_test import ( + "github.com/derailed/tcell/v2" "testing" "github.com/derailed/k9s/internal/config" @@ -45,3 +46,87 @@ func TestCmdMode(t *testing.T) { assert.Equal(t, f, v.InCmdMode()) } } + +// Tests that, when active, the prompt has the appropriate color +func TestPromptColor(t *testing.T) { + styles := config.NewStyles() + app := ui.App{} + + // Make sure to have different values to be sure that the prompt color actually changes depending on its type + assert.NotEqual(t, styles.Prompt().Border.DefaultColor.Color(), styles.Prompt().Border.CommandColor.Color()) + + testCases := []struct { + kind model.BufferKind + expectedColor tcell.Color + }{ + // Command prompt case + { + kind: model.CommandBuffer, + expectedColor: styles.Prompt().Border.CommandColor.Color(), + }, + // Any other prompt type case + { + // Simulate a different type of prompt since no particular constant exists + kind: model.CommandBuffer + 1, + expectedColor: styles.Prompt().Border.DefaultColor.Color(), + }, + } + + for _, testCase := range testCases { + model := model.NewFishBuff(':', testCase.kind) + prompt := ui.NewPrompt(&app, true, styles) + + prompt.SetModel(model) + model.AddListener(prompt) + + model.SetActive(true) + assert.Equal(t, prompt.GetBorderColor(), testCase.expectedColor) + } +} + +// Tests that, when a change of style occurs, the prompt will have the appropriate color when active +func TestPromptStyleChanged(t *testing.T) { + app := ui.App{} + styles := config.NewStyles() + newStyles := config.NewStyles() + newStyles.K9s.Prompt.Border = config.PromptBorder{ + DefaultColor: "green", + CommandColor: "yellow", + } + + // Check that the prompt won't change the border into the same style + assert.NotEqual(t, styles.Prompt().Border.CommandColor.Color(), newStyles.Prompt().Border.CommandColor.Color()) + assert.NotEqual(t, styles.Prompt().Border.DefaultColor.Color(), newStyles.Prompt().Border.DefaultColor.Color()) + + testCases := []struct { + kind model.BufferKind + expectedColor tcell.Color + }{ + // Command prompt case + { + kind: model.CommandBuffer, + expectedColor: newStyles.Prompt().Border.CommandColor.Color(), + }, + // Any other prompt type case + { + // Simulate a different type of prompt since no particular constant exists + kind: model.CommandBuffer + 1, + expectedColor: newStyles.Prompt().Border.DefaultColor.Color(), + }, + } + + for _, testCase := range testCases { + model := model.NewFishBuff(':', testCase.kind) + prompt := ui.NewPrompt(&app, true, styles) + + model.SetActive(true) + + prompt.SetModel(model) + model.AddListener(prompt) + + prompt.StylesChanged(newStyles) + + model.SetActive(true) + assert.Equal(t, prompt.GetBorderColor(), testCase.expectedColor) + } +}