1import chroma from "chroma-js"
2import { Meta, ThemeSyntax } from "./common/colorScheme"
3import { colorRamp, createColorScheme } from "./common/ramps"
4
5const name = "Gruvbox"
6
7const color = {
8 dark0_hard: "#1d2021",
9 dark0: "#282828",
10 dark0_soft: "#32302f",
11 dark1: "#3c3836",
12 dark2: "#504945",
13 dark3: "#665c54",
14 dark4: "#7c6f64",
15 dark4_256: "#7c6f64",
16
17 gray_245: "#928374",
18 gray_244: "#928374",
19
20 light0_hard: "#f9f5d7",
21 light0: "#fbf1c7",
22 light0_soft: "#f2e5bc",
23 light1: "#ebdbb2",
24 light2: "#d5c4a1",
25 light3: "#bdae93",
26 light4: "#a89984",
27 light4_256: "#a89984",
28
29 bright_red: "#fb4934",
30 bright_green: "#b8bb26",
31 bright_yellow: "#fabd2f",
32 bright_blue: "#83a598",
33 bright_purple: "#d3869b",
34 bright_aqua: "#8ec07c",
35 bright_orange: "#fe8019",
36
37 neutral_red: "#cc241d",
38 neutral_green: "#98971a",
39 neutral_yellow: "#d79921",
40 neutral_blue: "#458588",
41 neutral_purple: "#b16286",
42 neutral_aqua: "#689d6a",
43 neutral_orange: "#d65d0e",
44
45 faded_red: "#9d0006",
46 faded_green: "#79740e",
47 faded_yellow: "#b57614",
48 faded_blue: "#076678",
49 faded_purple: "#8f3f71",
50 faded_aqua: "#427b58",
51 faded_orange: "#af3a03",
52}
53
54interface ThemeColors {
55 red: string
56 green: string
57 yellow: string
58 blue: string
59 purple: string
60 aqua: string
61 orange: string
62 gray: string
63}
64
65const darkNeutrals = [
66 color.dark1,
67 color.dark2,
68 color.dark3,
69 color.dark4,
70 color.light4,
71 color.light3,
72 color.light2,
73 color.light1,
74 color.light0,
75]
76
77const dark: ThemeColors = {
78 red: color.bright_red,
79 green: color.bright_green,
80 yellow: color.bright_yellow,
81 blue: color.bright_blue,
82 purple: color.bright_purple,
83 aqua: color.bright_aqua,
84 orange: color.bright_orange,
85 gray: color.light4,
86}
87
88const lightNeutrals = [
89 color.light1,
90 color.light2,
91 color.light3,
92 color.light4,
93 color.dark4,
94 color.dark3,
95 color.dark2,
96 color.dark1,
97 color.dark0,
98]
99
100const light: ThemeColors = {
101 red: color.faded_red,
102 green: color.faded_green,
103 yellow: color.faded_yellow,
104 blue: color.faded_blue,
105 purple: color.faded_purple,
106 aqua: color.faded_aqua,
107 orange: color.faded_orange,
108 gray: color.dark4,
109}
110
111const darkHardNeutral = [color.dark0_hard, ...darkNeutrals]
112const darkNeutral = [color.dark0, ...darkNeutrals]
113const darkSoftNeutral = [color.dark0_soft, ...darkNeutrals]
114
115const lightHardNeutral = [color.light0_hard, ...lightNeutrals]
116const lightNeutral = [color.light0, ...lightNeutrals]
117const lightSoftNeutral = [color.light0_soft, ...lightNeutrals]
118
119interface Variant {
120 name: string
121 appearance: "light" | "dark"
122 colors: ThemeColors
123}
124
125const variant: Variant[] = [
126 {
127 name: "Dark Hard",
128 appearance: "dark",
129 colors: dark,
130 },
131 {
132 name: "Dark",
133 appearance: "dark",
134 colors: dark,
135 },
136 {
137 name: "Dark Soft",
138 appearance: "dark",
139 colors: dark,
140 },
141 {
142 name: "Light Hard",
143 appearance: "light",
144 colors: light,
145 },
146 {
147 name: "Light",
148 appearance: "light",
149
150 colors: light,
151 },
152 {
153 name: "Light Soft",
154 appearance: "light",
155 colors: light,
156 },
157]
158
159const buildVariant = (variant: Variant) => {
160 const { colors } = variant
161
162 const name = `Gruvbox ${variant.name}`
163
164 const isLight = variant.appearance === "light"
165
166 let neutral: string[] = []
167
168 switch (variant.name) {
169 case "Dark Hard": {
170 neutral = darkHardNeutral
171 break
172 }
173 case "Dark": {
174 neutral = darkNeutral
175 break
176 }
177 case "Dark Soft": {
178 neutral = darkSoftNeutral
179 break
180 }
181 case "Light Hard": {
182 neutral = lightHardNeutral
183 break
184 }
185 case "Light": {
186 neutral = lightNeutral
187 break
188 }
189 case "Light Soft": {
190 neutral = lightSoftNeutral
191 break
192 }
193 }
194
195 const ramps = {
196 neutral: chroma.scale(isLight ? neutral.reverse() : neutral),
197 red: colorRamp(chroma(variant.colors.red)),
198 orange: colorRamp(chroma(variant.colors.orange)),
199 yellow: colorRamp(chroma(variant.colors.yellow)),
200 green: colorRamp(chroma(variant.colors.green)),
201 cyan: colorRamp(chroma(variant.colors.aqua)),
202 blue: colorRamp(chroma(variant.colors.blue)),
203 violet: colorRamp(chroma(variant.colors.purple)),
204 magenta: colorRamp(chroma(variant.colors.gray)),
205 }
206
207 const syntax: ThemeSyntax = {
208 primary: { color: neutral[isLight ? 0 : 8] },
209 "text.literal": { color: colors.blue },
210 comment: { color: colors.gray },
211 punctuation: { color: neutral[isLight ? 1 : 7] },
212 "punctuation.bracket": { color: neutral[isLight ? 3 : 5] },
213 "punctuation.list_marker": { color: neutral[isLight ? 0 : 8] },
214 operator: { color: colors.aqua },
215 boolean: { color: colors.purple },
216 number: { color: colors.purple },
217 string: { color: colors.green },
218 "string.special": { color: colors.purple },
219 "string.special.symbol": { color: colors.aqua },
220 "string.regex": { color: colors.orange },
221 type: { color: colors.yellow },
222 enum: { color: colors.orange },
223 tag: { color: colors.aqua },
224 constant: { color: colors.yellow },
225 keyword: { color: colors.red },
226 function: { color: colors.green },
227 "function.builtin": { color: colors.red },
228 variable: { color: colors.blue },
229 property: { color: neutral[isLight ? 0 : 8] },
230 embedded: { color: colors.aqua },
231 linkText: { color: colors.aqua },
232 linkUri: { color: colors.purple },
233 title: { color: colors.green },
234 }
235
236 return createColorScheme(name, isLight, ramps, syntax)
237}
238
239// Variants
240export const darkHard = buildVariant(variant[0])
241export const darkDefault = buildVariant(variant[1])
242export const darkSoft = buildVariant(variant[2])
243export const lightHard = buildVariant(variant[3])
244export const lightDefault = buildVariant(variant[4])
245export const lightSoft = buildVariant(variant[5])
246
247export const meta: Meta = {
248 name,
249 license: {
250 SPDX: "MIT", // "MIT/X11"
251 license_text:
252 "Copyright <YEAR> <COPYRIGHT HOLDER>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/ or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
253 },
254 author: "morhetz <morhetz@gmail.com>",
255 url: "https://github.com/morhetz/gruvbox",
256}