1import { with_opacity } from "../theme/color"
2import { ColorScheme, Layer, StyleSets } from "../theme/color_scheme"
3import {
4 background,
5 border,
6 border_color,
7 foreground,
8 text,
9} from "./components"
10import hover_popover from "./hover_popover"
11
12import { build_syntax } from "../theme/syntax"
13import { interactive, toggleable } from "../element"
14
15export default function editor(theme: ColorScheme): any {
16 const { is_light } = theme
17
18 const layer = theme.highest
19
20 const autocomplete_item = {
21 corner_radius: 6,
22 padding: {
23 bottom: 2,
24 left: 6,
25 right: 6,
26 top: 2,
27 },
28 }
29
30 function diagnostic(layer: Layer, style_set: StyleSets) {
31 return {
32 text_scale_factor: 0.857,
33 header: {
34 border: border(layer, {
35 top: true,
36 }),
37 },
38 message: {
39 text: text(layer, "sans", style_set, "default", { size: "sm" }),
40 highlight_text: text(layer, "sans", style_set, "default", {
41 size: "sm",
42 weight: "bold",
43 }),
44 },
45 }
46 }
47
48 const syntax = build_syntax(theme)
49
50 return {
51 text_color: syntax.primary.color,
52 background: background(layer),
53 active_line_background: with_opacity(background(layer, "on"), 0.75),
54 highlighted_line_background: background(layer, "on"),
55 // Inline autocomplete suggestions, Co-pilot suggestions, etc.
56 suggestion: syntax.predictive,
57 code_actions: {
58 indicator: toggleable({
59 base: interactive({
60 base: {
61 color: foreground(layer, "variant"),
62 },
63 state: {
64 hovered: {
65 color: foreground(layer, "variant", "hovered"),
66 },
67 clicked: {
68 color: foreground(layer, "variant", "pressed"),
69 },
70 },
71 }),
72 state: {
73 active: {
74 default: {
75 color: foreground(layer, "accent"),
76 },
77 hovered: {
78 color: foreground(layer, "accent", "hovered"),
79 },
80 clicked: {
81 color: foreground(layer, "accent", "pressed"),
82 },
83 },
84 },
85 }),
86
87 vertical_scale: 0.55,
88 },
89 folds: {
90 icon_margin_scale: 2.5,
91 folded_icon: "icons/chevron_right_8.svg",
92 foldable_icon: "icons/chevron_down_8.svg",
93 indicator: toggleable({
94 base: interactive({
95 base: {
96 color: foreground(layer, "variant"),
97 },
98 state: {
99 hovered: {
100 color: foreground(layer, "on"),
101 },
102 clicked: {
103 color: foreground(layer, "base"),
104 },
105 },
106 }),
107 state: {
108 active: {
109 default: {
110 color: foreground(layer, "default"),
111 },
112 hovered: {
113 color: foreground(layer, "variant"),
114 },
115 },
116 },
117 }),
118 ellipses: {
119 text_color: theme.ramps.neutral(0.71).hex(),
120 corner_radius_factor: 0.15,
121 background: {
122 // Copied from hover_popover highlight
123 default: {
124 color: theme.ramps.neutral(0.5).alpha(0.0).hex(),
125 },
126
127 hovered: {
128 color: theme.ramps.neutral(0.5).alpha(0.5).hex(),
129 },
130
131 clicked: {
132 color: theme.ramps.neutral(0.5).alpha(0.7).hex(),
133 },
134 },
135 },
136 fold_background: foreground(layer, "variant"),
137 },
138 diff: {
139 deleted: is_light
140 ? theme.ramps.red(0.5).hex()
141 : theme.ramps.red(0.4).hex(),
142 modified: is_light
143 ? theme.ramps.yellow(0.5).hex()
144 : theme.ramps.yellow(0.5).hex(),
145 inserted: is_light
146 ? theme.ramps.green(0.4).hex()
147 : theme.ramps.green(0.5).hex(),
148 removed_width_em: 0.275,
149 width_em: 0.15,
150 corner_radius: 0.05,
151 },
152 /** Highlights matching occurrences of what is under the cursor
153 * as well as matched brackets
154 */
155 document_highlight_read_background: with_opacity(
156 foreground(layer, "accent"),
157 0.1
158 ),
159 document_highlight_write_background: theme.ramps
160 .neutral(0.5)
161 .alpha(0.4)
162 .hex(), // TODO: This was blend * 2
163 error_color: background(layer, "negative"),
164 gutter_background: background(layer),
165 gutter_padding_factor: 3.5,
166 line_number: with_opacity(foreground(layer), 0.35),
167 line_number_active: foreground(layer),
168 rename_fade: 0.6,
169 unnecessary_code_fade: 0.5,
170 selection: theme.players[0],
171 whitespace: theme.ramps.neutral(0.5).hex(),
172 guest_selections: [
173 theme.players[1],
174 theme.players[2],
175 theme.players[3],
176 theme.players[4],
177 theme.players[5],
178 theme.players[6],
179 theme.players[7],
180 ],
181 autocomplete: {
182 background: background(theme.middle),
183 corner_radius: 8,
184 padding: 4,
185 margin: {
186 left: -14,
187 },
188 border: border(theme.middle),
189 shadow: theme.popover_shadow,
190 match_highlight: foreground(theme.middle, "accent"),
191 item: autocomplete_item,
192 hovered_item: {
193 ...autocomplete_item,
194 match_highlight: foreground(theme.middle, "accent", "hovered"),
195 background: background(theme.middle, "hovered"),
196 },
197 selected_item: {
198 ...autocomplete_item,
199 match_highlight: foreground(theme.middle, "accent", "active"),
200 background: background(theme.middle, "active"),
201 },
202 },
203 diagnostic_header: {
204 background: background(theme.middle),
205 icon_width_factor: 1.5,
206 text_scale_factor: 0.857,
207 border: border(theme.middle, {
208 bottom: true,
209 top: true,
210 }),
211 code: {
212 ...text(theme.middle, "mono", { size: "sm" }),
213 margin: {
214 left: 10,
215 },
216 },
217 source: {
218 text: text(theme.middle, "sans", {
219 size: "sm",
220 weight: "bold",
221 }),
222 },
223 message: {
224 highlight_text: text(theme.middle, "sans", {
225 size: "sm",
226 weight: "bold",
227 }),
228 text: text(theme.middle, "sans", { size: "sm" }),
229 },
230 },
231 diagnostic_path_header: {
232 background: background(theme.middle),
233 text_scale_factor: 0.857,
234 filename: text(theme.middle, "mono", { size: "sm" }),
235 path: {
236 ...text(theme.middle, "mono", { size: "sm" }),
237 margin: {
238 left: 12,
239 },
240 },
241 },
242 error_diagnostic: diagnostic(theme.middle, "negative"),
243 warning_diagnostic: diagnostic(theme.middle, "warning"),
244 information_diagnostic: diagnostic(theme.middle, "accent"),
245 hint_diagnostic: diagnostic(theme.middle, "warning"),
246 invalid_error_diagnostic: diagnostic(theme.middle, "base"),
247 invalid_hint_diagnostic: diagnostic(theme.middle, "base"),
248 invalid_information_diagnostic: diagnostic(theme.middle, "base"),
249 invalid_warning_diagnostic: diagnostic(theme.middle, "base"),
250 hover_popover: hover_popover(theme),
251 link_definition: {
252 color: syntax.link_uri.color,
253 underline: syntax.link_uri.underline,
254 },
255 jump_icon: interactive({
256 base: {
257 color: foreground(layer, "on"),
258 icon_width: 20,
259 button_width: 20,
260 corner_radius: 6,
261 padding: {
262 top: 6,
263 bottom: 6,
264 left: 6,
265 right: 6,
266 },
267 },
268 state: {
269 hovered: {
270 background: background(layer, "on", "hovered"),
271 },
272 },
273 }),
274
275 scrollbar: {
276 width: 12,
277 min_height_factor: 1.0,
278 track: {
279 border: border(layer, "variant", { left: true }),
280 },
281 thumb: {
282 background: with_opacity(background(layer, "inverted"), 0.3),
283 border: {
284 width: 1,
285 color: border_color(layer, "variant"),
286 top: false,
287 right: true,
288 left: true,
289 bottom: false,
290 },
291 },
292 git: {
293 deleted: is_light
294 ? with_opacity(theme.ramps.red(0.5).hex(), 0.8)
295 : with_opacity(theme.ramps.red(0.4).hex(), 0.8),
296 modified: is_light
297 ? with_opacity(theme.ramps.yellow(0.5).hex(), 0.8)
298 : with_opacity(theme.ramps.yellow(0.4).hex(), 0.8),
299 inserted: is_light
300 ? with_opacity(theme.ramps.green(0.5).hex(), 0.8)
301 : with_opacity(theme.ramps.green(0.4).hex(), 0.8),
302 },
303 },
304 composition_mark: {
305 underline: {
306 thickness: 1.0,
307 color: border_color(layer),
308 },
309 },
310 syntax,
311 }
312}