From 6734a7794f15020c107606280a1a4522360b235a Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:31:11 +0530 Subject: [PATCH 01/15] update mod files including toml for parsing custom themes toml --- go.mod | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6fe9760..481ed4c 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/CosmicPredator/chibi go 1.25.0 require ( + github.com/BurntSushi/toml v1.4.0 github.com/charmbracelet/fang v0.4.4 github.com/charmbracelet/lipgloss v1.1.0 github.com/muesli/reflow v0.3.0 @@ -14,17 +15,14 @@ require ( charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/colorprofile v0.4.2 // indirect - github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1 // indirect github.com/charmbracelet/ultraviolet v0.0.0-20260221133011-393bbf1e9ada // indirect github.com/charmbracelet/x/ansi v0.11.6 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/exp/charmtone v0.0.0-20260216111343-536eb63c1f4c // indirect - github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/charmbracelet/x/termios v0.1.1 // indirect github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect - github.com/clipperhouse/stringish v0.1.1 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/google/uuid v1.6.0 // indirect From 4a2f46a84f6b20bdca18e27c95438c2d65aae957 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:31:24 +0530 Subject: [PATCH 02/15] update cmd theme to let the user know they can add their own themes --- cmd/cmd_theme.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/cmd_theme.go b/cmd/cmd_theme.go index a748d05..d4b262e 100644 --- a/cmd/cmd_theme.go +++ b/cmd/cmd_theme.go @@ -14,6 +14,11 @@ func handleTheme(_ *cobra.Command, args []string) { fmt.Printf("Current theme: %s\n", theme.CurrentName()) fmt.Printf("Available themes: %s\n", strings.Join(theme.Available(), ", ")) fmt.Println("Set a theme with: chibi theme ") + if themesPath, err := theme.ThemesPath(); err == nil { + fmt.Printf("Add your own theme: create a .toml file in %s\n", themesPath) + } else { + fmt.Println("Add your own theme: create a .toml file in DATA_DIR/themes") + } return } From e8b3ae332d2c80915bba3b5372557ccb74b1c5f7 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:31:38 +0530 Subject: [PATCH 03/15] update readme for custom config tomls --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c3738d8..15c697c 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,12 @@ chibi login ``` ### Themes -Chibi supports built-in themes for CLI colors. +Chibi loads themes from `DATA_DIR/themes` using TOML files. + +`DATA_DIR` is resolved the same way as local config storage: +- `CHIBI_DATA_PATH` (preferred) +- `CHIBI_PATH` (legacy fallback) +- OS config directory fallback - Show active theme and available themes: ```bash @@ -103,6 +108,9 @@ Chibi supports built-in themes for CLI colors. CHIBI_THEME=sunset chibi profile ``` +Each theme file in `DATA_DIR/themes/*.toml` should include all color keys. +Example themes are available in the repository `themes/` directory. + ## Documentation You can check the docs [here](https://chibi-cli.pages.dev/). From 3b6fcf17326d6e286c78c6b15e2e352bb3838b03 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:31:59 +0530 Subject: [PATCH 04/15] update theme test for custom themes using toml configs --- internal/theme/theme_test.go | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/internal/theme/theme_test.go b/internal/theme/theme_test.go index 590dba7..e89c85a 100644 --- a/internal/theme/theme_test.go +++ b/internal/theme/theme_test.go @@ -1,6 +1,8 @@ package theme import ( + "os" + "path/filepath" "testing" "github.com/CosmicPredator/chibi/internal" @@ -13,6 +15,20 @@ func resetDefaultTheme(t *testing.T) { } } +func writeThemeFile(t *testing.T, dataPath, name, content string) { + t.Helper() + + themesPath := filepath.Join(dataPath, "themes") + if err := os.MkdirAll(themesPath, 0o755); err != nil { + t.Fatalf("unable to create themes directory: %v", err) + } + + themePath := filepath.Join(themesPath, name) + if err := os.WriteFile(themePath, []byte(content), 0o644); err != nil { + t.Fatalf("unable to write theme file: %v", err) + } +} + func TestSetCurrentCaseInsensitive(t *testing.T) { resetDefaultTheme(t) defer resetDefaultTheme(t) @@ -80,3 +96,88 @@ func TestEnvThemeOverridesPersistedTheme(t *testing.T) { t.Fatalf("CurrentName() = %q, want %q", got, want) } } + +func TestLoadReadsThemeFilesFromDataPath(t *testing.T) { + resetDefaultTheme(t) + defer resetDefaultTheme(t) + + dataPath := t.TempDir() + t.Setenv(internal.DATA_PATH_ENV, dataPath) + t.Setenv(ThemeEnvName, "") + + writeThemeFile(t, dataPath, "ocean.toml", ` +name = "ocean" +success_text = "#65D6CE" +error_text = "#FF6B6B" +highlight_text = "#6EC6FF" +spinner = "#4FC3F7" +prompt_title = "#4FC3F7" +prompt_default = "#FFD166" +key_text = "#B39DDB" +value_text = "#80CBC4" +table_header = "#4FC3F7" +table_id = "#6EC6FF" +table_format = "#65D6CE" +table_metric = "#FFD166" +table_repeating = "#5C6BC0" +message_error = "#FF6B6B" +message_success = "#65D6CE" +message_other = "#6EC6FF" +`) + + if err := Load(); err != nil { + t.Fatalf("Load returned error: %v", err) + } + + if err := SetCurrent("ocean"); err != nil { + t.Fatalf("SetCurrent returned error: %v", err) + } + + if got, want := CurrentName(), "ocean"; got != want { + t.Fatalf("CurrentName() = %q, want %q", got, want) + } + + if got, want := Current().TableHeader, "#4FC3F7"; got != want { + t.Fatalf("Current().TableHeader = %q, want %q", got, want) + } +} + +func TestLoadThemeNameFallsBackToFileName(t *testing.T) { + resetDefaultTheme(t) + defer resetDefaultTheme(t) + + dataPath := t.TempDir() + t.Setenv(internal.DATA_PATH_ENV, dataPath) + t.Setenv(ThemeEnvName, "") + + writeThemeFile(t, dataPath, "retro.toml", ` +success_text = "#A6E22E" +error_text = "#F92672" +highlight_text = "#66D9EF" +spinner = "#FD971F" +prompt_title = "#FD971F" +prompt_default = "#E6DB74" +key_text = "#AE81FF" +value_text = "#66D9EF" +table_header = "#FD971F" +table_id = "#66D9EF" +table_format = "#A6E22E" +table_metric = "#E6DB74" +table_repeating = "#AE81FF" +message_error = "#F92672" +message_success = "#A6E22E" +message_other = "#66D9EF" +`) + + if err := Load(); err != nil { + t.Fatalf("Load returned error: %v", err) + } + + if err := SetCurrent("retro"); err != nil { + t.Fatalf("SetCurrent returned error: %v", err) + } + + if got, want := CurrentName(), "retro"; got != want { + t.Fatalf("CurrentName() = %q, want %q", got, want) + } +} From 373c57f9fe3b69b338a8f0b1840571e7e366ebf0 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:07 +0530 Subject: [PATCH 05/15] update checksums --- go.sum | 57 +++++++-------------------------------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/go.sum b/go.sum index 5b05514..642ac7a 100644 --- a/go.sum +++ b/go.sum @@ -1,42 +1,27 @@ charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410 h1:D9PbaszZYpB4nj+d6HTWr1onlmlyuGVNfL9gAi8iB3k= charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251106193318-19329a3e8410/go.mod h1:1qZyvvVCenJO2M1ac2mX0yyiIZJoZmDM4DG4s0udJkU= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= -github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= -github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40= -github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= +github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY= github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8= -github.com/charmbracelet/fang v0.1.0 h1:SlZS2crf3/zQh7Mr4+W+7QR1k+L08rrPX5rm5z3d7Wg= -github.com/charmbracelet/fang v0.1.0/go.mod h1:Zl/zeUQ8EtQuGyiV0ZKZlZPDowKRTzu8s/367EpN/fc= github.com/charmbracelet/fang v0.4.4 h1:G4qKxF6or/eTPgmAolwPuRNyuci3hTUGGX1rj1YkHJY= github.com/charmbracelet/fang v0.4.4/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1 h1:SOylT6+BQzPHEjn15TIzawBPVD0QmhKXbcb3jY0ZIKU= -github.com/charmbracelet/lipgloss/v2 v2.0.0-beta1/go.mod h1:tRlx/Hu0lo/j9viunCN2H+Ze6JrmdjQlXUQvvArgaOc= github.com/charmbracelet/ultraviolet v0.0.0-20260221133011-393bbf1e9ada h1:Spu212cBfN+UDLMlogmEw5eC0YVCCwYPbVQeze6zG9g= github.com/charmbracelet/ultraviolet v0.0.0-20260221133011-393bbf1e9ada/go.mod h1:ljOy7S9BtMxjCZyFiUDm2gQPtKm8iZBEKVxiVgb6dyo= -github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0= -github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= -github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= -github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= -github.com/charmbracelet/x/exp/charmtone v0.0.0-20250616121729-19b66ab4499b h1:Kz9OEed9DfdHqN8Z7TTUyOpqsQ2GVQS0gAN4ZyBdT2w= -github.com/charmbracelet/x/exp/charmtone v0.0.0-20250616121729-19b66ab4499b/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0= github.com/charmbracelet/x/exp/charmtone v0.0.0-20260216111343-536eb63c1f4c h1:v2FWkJFVb/hjKyEiLPEqHK15OgDV5nlWOcrv74I7Dec= github.com/charmbracelet/x/exp/charmtone v0.0.0-20260216111343-536eb63c1f4c/go.mod h1:nsExn0DGyX0lh9LwLHTn2Gg+hafdzfSXnC+QmEJTZFY= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= @@ -45,8 +30,6 @@ github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2 github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= github.com/clipperhouse/displaywidth v0.10.0 h1:GhBG8WuerxjFQQYeuZAeVTuyxuX+UraiZGD4HJQ3Y8g= github.com/clipperhouse/displaywidth v0.10.0/go.mod h1:XqJajYsaiEwkxOj4bowCTMcT1SgvHo9flfF3jQasdbs= -github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= -github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= @@ -62,27 +45,19 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/muesli/mango v0.2.0 h1:iNNc0c5VLQ6fsMgAqGQofByNUBH2Q2nEbD6TaI+5yyQ= github.com/muesli/mango v0.2.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4= -github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg= -github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= github.com/muesli/mango-cobra v1.3.0 h1:vQy5GvPg3ndOSpduxutqFoINhWk3vD5K2dXo5E8pqec= github.com/muesli/mango-cobra v1.3.0/go.mod h1:Cj1ZrBu3806Qw7UjxnAUgE+7tllUBj1NCLQDwwGx19E= -github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= -github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= github.com/muesli/mango-pflag v0.2.0 h1:QViokgKDZQCzKhYe1zH8D+UlPJzBSGoP9yx0hBG0t5k= github.com/muesli/mango-pflag v0.2.0/go.mod h1:X9LT1p/pbGA1wjvEbtwnixujKErkP0jVmrxwrw3fL0Y= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= @@ -102,12 +77,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -116,48 +87,34 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0= golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= -golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc= -modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM= modernc.org/ccgo/v4 v4.30.2 h1:4yPaaq9dXYXZ2V8s1UgrC3KIj580l2N4ClrLwnbv2so= +modernc.org/ccgo/v4 v4.30.2/go.mod h1:yZMnhWEdW0qw3EtCndG1+ldRrVGS+bIwyWmAWzS0XEw= modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE= -modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= +modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= -modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= modernc.org/libc v1.68.0 h1:PJ5ikFOV5pwpW+VqCK1hKJuEWsonkIJhhIXyuF/91pQ= modernc.org/libc v1.68.0/go.mod h1:NnKCYeoYgsEqnY3PgvNgAeaJnso968ygU8Z0DxjoEc0= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= From dd2781e96e80ac39e3ea00009635216de737ab4d Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:15 +0530 Subject: [PATCH 06/15] update path resolver --- internal/kvdb/path.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/kvdb/path.go b/internal/kvdb/path.go index 470f19d..9ed0819 100644 --- a/internal/kvdb/path.go +++ b/internal/kvdb/path.go @@ -23,3 +23,7 @@ func resolveDataPath() (string, error) { } return filepath.Join(path, internal.APP_DIR_NAME), nil } + +func DataPath() (string, error) { + return resolveDataPath() +} From ee95a80e232562bef3e3266717e2498bb646a799 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:32 +0530 Subject: [PATCH 07/15] update theme.go for built in themes support and loading/parsing user made themes --- internal/theme/theme.go | 188 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 7 deletions(-) diff --git a/internal/theme/theme.go b/internal/theme/theme.go index 7e2ff74..ad85954 100644 --- a/internal/theme/theme.go +++ b/internal/theme/theme.go @@ -6,16 +6,20 @@ import ( "errors" "fmt" "os" + "path/filepath" "sort" "strings" "sync" + "github.com/BurntSushi/toml" "github.com/CosmicPredator/chibi/internal/kvdb" ) const ( - ThemeEnvName = "CHIBI_THEME" - themeKey = "theme" + ThemeEnvName = "CHIBI_THEME" + themeKey = "theme" + themesDirName = "themes" + defaultThemeName = "default" ) type Palette struct { @@ -41,7 +45,32 @@ type Palette struct { MessageOther string } -var palettes = map[string]Palette{ +type paletteFile struct { + Name string `toml:"name"` + + SuccessText string `toml:"success_text"` + ErrorText string `toml:"error_text"` + HighlightText string `toml:"highlight_text"` + + Spinner string `toml:"spinner"` + PromptTitle string `toml:"prompt_title"` + PromptDefault string `toml:"prompt_default"` + + KeyText string `toml:"key_text"` + ValueText string `toml:"value_text"` + + TableHeader string `toml:"table_header"` + TableID string `toml:"table_id"` + TableFormat string `toml:"table_format"` + TableMetric string `toml:"table_metric"` + TableRepeating string `toml:"table_repeating"` + + MessageError string `toml:"message_error"` + MessageSuccess string `toml:"message_success"` + MessageOther string `toml:"message_other"` +} + +var defaultPalettes = map[string]Palette{ "default": { SuccessText: "#00FF00", ErrorText: "#CC0000", @@ -99,18 +128,146 @@ var palettes = map[string]Palette{ } var ( - mu sync.RWMutex - current = "default" + mu sync.RWMutex + palettes = clonePalettes(defaultPalettes) + current = defaultThemeName ) func normalizeThemeName(name string) string { return strings.TrimSpace(strings.ToLower(name)) } +func clonePalettes(source map[string]Palette) map[string]Palette { + out := make(map[string]Palette, len(source)) + for name, palette := range source { + out[name] = palette + } + return out +} + +func (file paletteFile) palette() (Palette, error) { + palette := Palette{ + SuccessText: strings.TrimSpace(file.SuccessText), + ErrorText: strings.TrimSpace(file.ErrorText), + HighlightText: strings.TrimSpace(file.HighlightText), + Spinner: strings.TrimSpace(file.Spinner), + PromptTitle: strings.TrimSpace(file.PromptTitle), + PromptDefault: strings.TrimSpace(file.PromptDefault), + KeyText: strings.TrimSpace(file.KeyText), + ValueText: strings.TrimSpace(file.ValueText), + TableHeader: strings.TrimSpace(file.TableHeader), + TableID: strings.TrimSpace(file.TableID), + TableFormat: strings.TrimSpace(file.TableFormat), + TableMetric: strings.TrimSpace(file.TableMetric), + TableRepeating: strings.TrimSpace(file.TableRepeating), + MessageError: strings.TrimSpace(file.MessageError), + MessageSuccess: strings.TrimSpace(file.MessageSuccess), + MessageOther: strings.TrimSpace(file.MessageOther), + } + + required := []struct { + name string + value string + }{ + {name: "success_text", value: palette.SuccessText}, + {name: "error_text", value: palette.ErrorText}, + {name: "highlight_text", value: palette.HighlightText}, + {name: "spinner", value: palette.Spinner}, + {name: "prompt_title", value: palette.PromptTitle}, + {name: "prompt_default", value: palette.PromptDefault}, + {name: "key_text", value: palette.KeyText}, + {name: "value_text", value: palette.ValueText}, + {name: "table_header", value: palette.TableHeader}, + {name: "table_id", value: palette.TableID}, + {name: "table_format", value: palette.TableFormat}, + {name: "table_metric", value: palette.TableMetric}, + {name: "table_repeating", value: palette.TableRepeating}, + {name: "message_error", value: palette.MessageError}, + {name: "message_success", value: palette.MessageSuccess}, + {name: "message_other", value: palette.MessageOther}, + } + + for _, field := range required { + if field.value == "" { + return Palette{}, fmt.Errorf("missing %q", field.name) + } + } + + return palette, nil +} + +func loadPalettesFromFiles() (map[string]Palette, error) { + loadedPalettes := clonePalettes(defaultPalettes) + + themesPath, err := ThemesPath() + if err != nil { + return nil, err + } + + entries, err := os.ReadDir(themesPath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return loadedPalettes, nil + } + return nil, fmt.Errorf("unable to read themes directory %q: %w", themesPath, err) + } + + sort.Slice(entries, func(i, j int) bool { + return entries[i].Name() < entries[j].Name() + }) + + for _, entry := range entries { + if entry.IsDir() { + continue + } + if !strings.EqualFold(filepath.Ext(entry.Name()), ".toml") { + continue + } + + themePath := filepath.Join(themesPath, entry.Name()) + var file paletteFile + if _, err := toml.DecodeFile(themePath, &file); err != nil { + return nil, fmt.Errorf("unable to parse theme file %q: %w", themePath, err) + } + + themeName := normalizeThemeName(file.Name) + if themeName == "" { + themeName = normalizeThemeName(strings.TrimSuffix(entry.Name(), filepath.Ext(entry.Name()))) + } + if themeName == "" { + return nil, fmt.Errorf("theme file %q has an empty name", themePath) + } + + palette, err := file.palette() + if err != nil { + return nil, fmt.Errorf("invalid theme %q in %q: %w", themeName, themePath, err) + } + + loadedPalettes[themeName] = palette + } + + return loadedPalettes, nil +} + +func ThemesPath() (string, error) { + dataPath, err := kvdb.DataPath() + if err != nil { + return "", err + } + return filepath.Join(dataPath, themesDirName), nil +} + func Current() Palette { mu.RLock() defer mu.RUnlock() - return palettes[current] + + if palette, ok := palettes[current]; ok { + return palette + } + if defaultPalette, ok := palettes[defaultThemeName]; ok { + return defaultPalette + } + return defaultPalettes[defaultThemeName] } func CurrentName() string { @@ -120,6 +277,9 @@ func CurrentName() string { } func Available() []string { + mu.RLock() + defer mu.RUnlock() + out := make([]string, 0, len(palettes)) for name := range palettes { out = append(out, name) @@ -133,7 +293,11 @@ func SetCurrent(name string) error { if normalized == "" { return errors.New("theme name cannot be empty") } - if _, ok := palettes[normalized]; !ok { + + mu.RLock() + _, ok := palettes[normalized] + mu.RUnlock() + if !ok { return fmt.Errorf( "unknown theme %q (available: %s)", name, @@ -162,6 +326,16 @@ func Save(name string) error { } func Load() error { + loadedPalettes, err := loadPalettesFromFiles() + if err != nil { + return err + } + + mu.Lock() + palettes = loadedPalettes + current = defaultThemeName + mu.Unlock() + if envTheme := strings.TrimSpace(os.Getenv(ThemeEnvName)); envTheme != "" { return SetCurrent(envTheme) } From b671e5ed03d21989a4971a596077d08f8b3e0a0d Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:38 +0530 Subject: [PATCH 08/15] create the sunset theme --- themes/sunset.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 themes/sunset.toml diff --git a/themes/sunset.toml b/themes/sunset.toml new file mode 100644 index 0000000..9e75d66 --- /dev/null +++ b/themes/sunset.toml @@ -0,0 +1,17 @@ +name = "sunset" +success_text = "#43A047" +error_text = "#E53935" +highlight_text = "#00ACC1" +spinner = "#FB8C00" +prompt_title = "#FB8C00" +prompt_default = "#F4511E" +key_text = "#8E24AA" +value_text = "#039BE5" +table_header = "#FB8C00" +table_id = "#1E88E5" +table_format = "#43A047" +table_metric = "#FDD835" +table_repeating = "#3949AB" +message_error = "#E53935" +message_success = "#43A047" +message_other = "#00ACC1" From 88b49d3911713befd3ffba0fbc62e9b027917d0f Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:45 +0530 Subject: [PATCH 09/15] create nord theme --- themes/nord.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 themes/nord.toml diff --git a/themes/nord.toml b/themes/nord.toml new file mode 100644 index 0000000..2c01e80 --- /dev/null +++ b/themes/nord.toml @@ -0,0 +1,17 @@ +name = "nord" +success_text = "#A3BE8C" +error_text = "#BF616A" +highlight_text = "#88C0D0" +spinner = "#81A1C1" +prompt_title = "#81A1C1" +prompt_default = "#D08770" +key_text = "#B48EAD" +value_text = "#8FBCBB" +table_header = "#81A1C1" +table_id = "#88C0D0" +table_format = "#A3BE8C" +table_metric = "#EBCB8B" +table_repeating = "#5E81AC" +message_error = "#BF616A" +message_success = "#A3BE8C" +message_other = "#88C0D0" From 0d8988d3760329da01f37d98dc41f1813aad16b6 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:32:57 +0530 Subject: [PATCH 10/15] create default theme --- themes/default.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 themes/default.toml diff --git a/themes/default.toml b/themes/default.toml new file mode 100644 index 0000000..c911c7d --- /dev/null +++ b/themes/default.toml @@ -0,0 +1,17 @@ +name = "default" +success_text = "#00FF00" +error_text = "#CC0000" +highlight_text = "#00FFFF" +spinner = "5" +prompt_title = "5" +prompt_default = "1" +key_text = "#FF79C6" +value_text = "#8BE9FD" +table_header = "5" +table_id = "6" +table_format = "2" +table_metric = "3" +table_repeating = "4" +message_error = "#FF0000" +message_success = "#00FF00" +message_other = "#00FFFF" From 3777668db102af7aa05e08170dddfa7577337ed7 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:33:03 +0530 Subject: [PATCH 11/15] create graphite theme --- themes/graphite.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 themes/graphite.toml diff --git a/themes/graphite.toml b/themes/graphite.toml new file mode 100644 index 0000000..617accd --- /dev/null +++ b/themes/graphite.toml @@ -0,0 +1,17 @@ +name = "graphite" +success_text = "#B0BEC5" +error_text = "#EF5350" +highlight_text = "#90CAF9" +spinner = "#78909C" +prompt_title = "#78909C" +prompt_default = "#FFB74D" +key_text = "#CE93D8" +value_text = "#80DEEA" +table_header = "#78909C" +table_id = "#90A4AE" +table_format = "#AED581" +table_metric = "#FFE082" +table_repeating = "#9FA8DA" +message_error = "#EF5350" +message_success = "#B0BEC5" +message_other = "#90CAF9" From c55f63e0992415f0931e23de7a3bfd3d3900ff36 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 19:33:25 +0530 Subject: [PATCH 12/15] create the forest theme my fav --- themes/forest.toml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 themes/forest.toml diff --git a/themes/forest.toml b/themes/forest.toml new file mode 100644 index 0000000..4bfce82 --- /dev/null +++ b/themes/forest.toml @@ -0,0 +1,17 @@ +name = "forest" +success_text = "#4CAF50" +error_text = "#D32F2F" +highlight_text = "#80CBC4" +spinner = "#2E7D32" +prompt_title = "#2E7D32" +prompt_default = "#F9A825" +key_text = "#7E57C2" +value_text = "#4DB6AC" +table_header = "#2E7D32" +table_id = "#26A69A" +table_format = "#66BB6A" +table_metric = "#FDD835" +table_repeating = "#558B2F" +message_error = "#D32F2F" +message_success = "#4CAF50" +message_other = "#80CBC4" From 2b7fda6e645fe35fb7ac62316eae4c5a71657842 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 20:02:00 +0530 Subject: [PATCH 13/15] update const to include theme_env --- internal/constants.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/constants.go b/internal/constants.go index a5542c4..fa5e528 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -9,6 +9,7 @@ const ( AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id=4593&response_type=token" APP_DIR_NAME = "chibi" DB_PATH = "chibi_config.db" + THEME_ENV = "CHIBI_THEME" DATA_PATH_ENV = "CHIBI_DATA_PATH" LEGACY_PATH_ENV = "CHIBI_PATH" ) From 6ed61bcb09b8981fc87cd0c26a054428240b60d7 Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 20:02:06 +0530 Subject: [PATCH 14/15] update theme_tests --- internal/theme/theme_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/theme/theme_test.go b/internal/theme/theme_test.go index e89c85a..2ca4632 100644 --- a/internal/theme/theme_test.go +++ b/internal/theme/theme_test.go @@ -56,7 +56,7 @@ func TestSaveAndLoadPersistedTheme(t *testing.T) { defer resetDefaultTheme(t) t.Setenv(internal.DATA_PATH_ENV, t.TempDir()) - t.Setenv(ThemeEnvName, "") + t.Setenv(internal.THEME_ENV, "") if err := Save("sunset"); err != nil { t.Fatalf("Save returned error: %v", err) @@ -79,7 +79,7 @@ func TestEnvThemeOverridesPersistedTheme(t *testing.T) { defer resetDefaultTheme(t) t.Setenv(internal.DATA_PATH_ENV, t.TempDir()) - t.Setenv(ThemeEnvName, "nord") + t.Setenv(internal.THEME_ENV, "nord") if err := Save("sunset"); err != nil { t.Fatalf("Save returned error: %v", err) @@ -103,7 +103,7 @@ func TestLoadReadsThemeFilesFromDataPath(t *testing.T) { dataPath := t.TempDir() t.Setenv(internal.DATA_PATH_ENV, dataPath) - t.Setenv(ThemeEnvName, "") + t.Setenv(internal.THEME_ENV, "") writeThemeFile(t, dataPath, "ocean.toml", ` name = "ocean" @@ -148,7 +148,7 @@ func TestLoadThemeNameFallsBackToFileName(t *testing.T) { dataPath := t.TempDir() t.Setenv(internal.DATA_PATH_ENV, dataPath) - t.Setenv(ThemeEnvName, "") + t.Setenv(internal.THEME_ENV, "") writeThemeFile(t, dataPath, "retro.toml", ` success_text = "#A6E22E" From 6abbdae2419d8548ef99f212a6036338f3e77d2d Mon Sep 17 00:00:00 2001 From: Aarav Maloo Date: Sun, 22 Feb 2026 20:02:12 +0530 Subject: [PATCH 15/15] update theme.go --- internal/theme/theme.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/theme/theme.go b/internal/theme/theme.go index ad85954..ade6c43 100644 --- a/internal/theme/theme.go +++ b/internal/theme/theme.go @@ -12,11 +12,11 @@ import ( "sync" "github.com/BurntSushi/toml" + "github.com/CosmicPredator/chibi/internal" "github.com/CosmicPredator/chibi/internal/kvdb" ) const ( - ThemeEnvName = "CHIBI_THEME" themeKey = "theme" themesDirName = "themes" defaultThemeName = "default" @@ -336,7 +336,7 @@ func Load() error { current = defaultThemeName mu.Unlock() - if envTheme := strings.TrimSpace(os.Getenv(ThemeEnvName)); envTheme != "" { + if envTheme := strings.TrimSpace(os.Getenv(internal.THEME_ENV)); envTheme != "" { return SetCurrent(envTheme) }