1package fang
2
3import (
4 "image/color"
5 "strings"
6
7 "github.com/charmbracelet/lipgloss/v2"
8 "github.com/charmbracelet/x/exp/charmtone"
9 "golang.org/x/text/cases"
10 "golang.org/x/text/language"
11)
12
13// ColorScheme describes a colorscheme.
14type ColorScheme struct {
15 Base color.Color
16 Title color.Color
17 Description color.Color
18 Codeblock color.Color
19 Program color.Color
20 DimmedArgument color.Color
21 Comment color.Color
22 Flag color.Color
23 FlagDefault color.Color
24 Command color.Color
25 QuotedString color.Color
26 Argument color.Color
27 Help color.Color
28 Dash color.Color
29 ErrorHeader [2]color.Color // 0=fg 1=bg
30 ErrorDetails color.Color
31}
32
33// DefaultTheme is the default colorscheme.
34func DefaultTheme(isDark bool) ColorScheme {
35 c := lipgloss.LightDark(isDark)
36 return ColorScheme{
37 Base: c(charmtone.Charcoal, charmtone.Ash),
38 Title: charmtone.Charple,
39 Codeblock: c(charmtone.Salt, lipgloss.Color("#2F2E36")),
40 Program: c(charmtone.Malibu, charmtone.Guppy),
41 Command: c(charmtone.Pony, charmtone.Cheeky),
42 DimmedArgument: c(charmtone.Squid, charmtone.Oyster),
43 Comment: c(charmtone.Squid, lipgloss.Color("#747282")),
44 Flag: c(lipgloss.Color("#0CB37F"), charmtone.Guac),
45 Argument: c(charmtone.Charcoal, charmtone.Ash),
46 Description: c(charmtone.Charcoal, charmtone.Ash), // flag and command descriptions
47 FlagDefault: c(charmtone.Smoke, charmtone.Squid), // flag default values in descriptions
48 QuotedString: c(charmtone.Charcoal, charmtone.Ash),
49 ErrorHeader: [2]color.Color{
50 charmtone.Butter,
51 charmtone.Cherry,
52 },
53 }
54}
55
56// Styles represents all the styles used.
57type Styles struct {
58 Text lipgloss.Style
59 Title lipgloss.Style
60 Span lipgloss.Style
61 ErrorHeader lipgloss.Style
62 ErrorText lipgloss.Style
63 FlagDescription lipgloss.Style
64 FlagDefault lipgloss.Style
65 Codeblock Codeblock
66 Program Program
67}
68
69// Codeblock styles.
70type Codeblock struct {
71 Base lipgloss.Style
72 Program Program
73 Text lipgloss.Style
74 Comment lipgloss.Style
75}
76
77// Program name, args, flags, styling.
78type Program struct {
79 Name lipgloss.Style
80 Command lipgloss.Style
81 Flag lipgloss.Style
82 Argument lipgloss.Style
83 DimmedArgument lipgloss.Style
84 QuotedString lipgloss.Style
85}
86
87func makeStyles(cs ColorScheme) Styles {
88 //nolint:mnd
89 return Styles{
90 Text: lipgloss.NewStyle().Foreground(cs.Base),
91 Title: lipgloss.NewStyle().
92 Bold(true).
93 Foreground(cs.Title).
94 Transform(strings.ToUpper).
95 Padding(1, 0).
96 Margin(0, 2),
97 FlagDescription: lipgloss.NewStyle().
98 Foreground(cs.Description).
99 Transform(titleFirstWord),
100 FlagDefault: lipgloss.NewStyle().
101 Foreground(cs.FlagDefault).
102 PaddingLeft(1),
103 Codeblock: Codeblock{
104 Base: lipgloss.NewStyle().
105 Background(cs.Codeblock).
106 Foreground(cs.Base).
107 MarginLeft(2).
108 Padding(1, 2),
109 Text: lipgloss.NewStyle().
110 Background(cs.Codeblock),
111 Comment: lipgloss.NewStyle().
112 Background(cs.Codeblock).
113 Foreground(cs.Comment),
114 Program: Program{
115 Name: lipgloss.NewStyle().
116 Background(cs.Codeblock).
117 Foreground(cs.Program),
118 Flag: lipgloss.NewStyle().
119 PaddingLeft(1).
120 Background(cs.Codeblock).
121 Foreground(cs.Flag),
122 Argument: lipgloss.NewStyle().
123 PaddingLeft(1).
124 Background(cs.Codeblock).
125 Foreground(cs.Argument),
126 DimmedArgument: lipgloss.NewStyle().
127 PaddingLeft(1).
128 Background(cs.Codeblock).
129 Foreground(cs.DimmedArgument),
130 Command: lipgloss.NewStyle().
131 PaddingLeft(1).
132 Background(cs.Codeblock).
133 Foreground(cs.Command),
134 QuotedString: lipgloss.NewStyle().
135 PaddingLeft(1).
136 Background(cs.Codeblock).
137 Foreground(cs.QuotedString),
138 },
139 },
140 Program: Program{
141 Name: lipgloss.NewStyle().
142 Foreground(cs.Program),
143 Argument: lipgloss.NewStyle().
144 PaddingLeft(1).
145 Foreground(cs.Argument),
146 DimmedArgument: lipgloss.NewStyle().
147 PaddingLeft(1).
148 Foreground(cs.DimmedArgument),
149 Flag: lipgloss.NewStyle().
150 PaddingLeft(1).
151 Foreground(cs.Flag),
152 Command: lipgloss.NewStyle().
153 Foreground(cs.Command),
154 QuotedString: lipgloss.NewStyle().
155 PaddingLeft(1).
156 Foreground(cs.QuotedString),
157 },
158 Span: lipgloss.NewStyle().
159 Background(cs.Codeblock),
160 ErrorText: lipgloss.NewStyle().
161 MarginLeft(2).
162 Width(width() - 4).
163 Transform(titleFirstWord),
164 ErrorHeader: lipgloss.NewStyle().
165 Foreground(cs.ErrorHeader[0]).
166 Background(cs.ErrorHeader[1]).
167 Bold(true).
168 Padding(0, 1).
169 Margin(1).
170 MarginLeft(2).
171 SetString("ERROR"),
172 }
173}
174
175func titleFirstWord(s string) string {
176 words := strings.Fields(s)
177 if len(words) == 0 {
178 return s
179 }
180 words[0] = cases.Title(language.AmericanEnglish).String(words[0])
181 return strings.Join(words, " ")
182}