editor.ts

  1import { withOpacity } 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 hoverPopover from "./hover_popover"
 11
 12import { buildSyntax } from "../theme/syntax"
 13import { interactive, toggleable } from "../element"
 14
 15export default function editor(colorScheme: ColorScheme): any {
 16    const { is_light } = colorScheme
 17
 18    const layer = colorScheme.highest
 19
 20    const autocompleteItem = {
 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, styleSet: StyleSets) {
 31        return {
 32            textScaleFactor: 0.857,
 33            header: {
 34                border: border(layer, {
 35                    top: true,
 36                }),
 37            },
 38            message: {
 39                text: text(layer, "sans", styleSet, "default", { size: "sm" }),
 40                highlightText: text(layer, "sans", styleSet, "default", {
 41                    size: "sm",
 42                    weight: "bold",
 43                }),
 44            },
 45        }
 46    }
 47
 48    const syntax = buildSyntax(colorScheme)
 49
 50    return {
 51        textColor: syntax.primary.color,
 52        background: background(layer),
 53        activeLineBackground: withOpacity(background(layer, "on"), 0.75),
 54        highlightedLineBackground: background(layer, "on"),
 55        // Inline autocomplete suggestions, Co-pilot suggestions, etc.
 56        suggestion: syntax.predictive,
 57        codeActions: {
 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            verticalScale: 0.55,
 88        },
 89        folds: {
 90            iconMarginScale: 2.5,
 91            foldedIcon: "icons/chevron_right_8.svg",
 92            foldableIcon: "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                textColor: colorScheme.ramps.neutral(0.71).hex(),
120                corner_radiusFactor: 0.15,
121                background: {
122                    // Copied from hover_popover highlight
123                    default: {
124                        color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
125                    },
126
127                    hovered: {
128                        color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
129                    },
130
131                    clicked: {
132                        color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
133                    },
134                },
135            },
136            foldBackground: foreground(layer, "variant"),
137        },
138        diff: {
139            deleted: is_light
140                ? colorScheme.ramps.red(0.5).hex()
141                : colorScheme.ramps.red(0.4).hex(),
142            modified: is_light
143                ? colorScheme.ramps.yellow(0.5).hex()
144                : colorScheme.ramps.yellow(0.5).hex(),
145            inserted: is_light
146                ? colorScheme.ramps.green(0.4).hex()
147                : colorScheme.ramps.green(0.5).hex(),
148            removedWidthEm: 0.275,
149            widthEm: 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        documentHighlightReadBackground: withOpacity(
156            foreground(layer, "accent"),
157            0.1
158        ),
159        documentHighlightWriteBackground: colorScheme.ramps
160            .neutral(0.5)
161            .alpha(0.4)
162            .hex(), // TODO: This was blend * 2
163        errorColor: background(layer, "negative"),
164        gutterBackground: background(layer),
165        gutterPaddingFactor: 3.5,
166        lineNumber: withOpacity(foreground(layer), 0.35),
167        lineNumberActive: foreground(layer),
168        renameFade: 0.6,
169        unnecessaryCodeFade: 0.5,
170        selection: colorScheme.players[0],
171        whitespace: colorScheme.ramps.neutral(0.5).hex(),
172        guestSelections: [
173            colorScheme.players[1],
174            colorScheme.players[2],
175            colorScheme.players[3],
176            colorScheme.players[4],
177            colorScheme.players[5],
178            colorScheme.players[6],
179            colorScheme.players[7],
180        ],
181        autocomplete: {
182            background: background(colorScheme.middle),
183            corner_radius: 8,
184            padding: 4,
185            margin: {
186                left: -14,
187            },
188            border: border(colorScheme.middle),
189            shadow: colorScheme.popoverShadow,
190            matchHighlight: foreground(colorScheme.middle, "accent"),
191            item: autocompleteItem,
192            hoveredItem: {
193                ...autocompleteItem,
194                matchHighlight: foreground(
195                    colorScheme.middle,
196                    "accent",
197                    "hovered"
198                ),
199                background: background(colorScheme.middle, "hovered"),
200            },
201            selectedItem: {
202                ...autocompleteItem,
203                matchHighlight: foreground(
204                    colorScheme.middle,
205                    "accent",
206                    "active"
207                ),
208                background: background(colorScheme.middle, "active"),
209            },
210        },
211        diagnosticHeader: {
212            background: background(colorScheme.middle),
213            icon_widthFactor: 1.5,
214            textScaleFactor: 0.857,
215            border: border(colorScheme.middle, {
216                bottom: true,
217                top: true,
218            }),
219            code: {
220                ...text(colorScheme.middle, "mono", { size: "sm" }),
221                margin: {
222                    left: 10,
223                },
224            },
225            source: {
226                text: text(colorScheme.middle, "sans", {
227                    size: "sm",
228                    weight: "bold",
229                }),
230            },
231            message: {
232                highlightText: text(colorScheme.middle, "sans", {
233                    size: "sm",
234                    weight: "bold",
235                }),
236                text: text(colorScheme.middle, "sans", { size: "sm" }),
237            },
238        },
239        diagnosticPathHeader: {
240            background: background(colorScheme.middle),
241            textScaleFactor: 0.857,
242            filename: text(colorScheme.middle, "mono", { size: "sm" }),
243            path: {
244                ...text(colorScheme.middle, "mono", { size: "sm" }),
245                margin: {
246                    left: 12,
247                },
248            },
249        },
250        errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
251        warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
252        informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
253        hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
254        invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
255        invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
256        invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
257        invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
258        hoverPopover: hoverPopover(colorScheme),
259        linkDefinition: {
260            color: syntax.linkUri.color,
261            underline: syntax.linkUri.underline,
262        },
263        jumpIcon: interactive({
264            base: {
265                color: foreground(layer, "on"),
266                icon_width: 20,
267                button_width: 20,
268                corner_radius: 6,
269                padding: {
270                    top: 6,
271                    bottom: 6,
272                    left: 6,
273                    right: 6,
274                },
275            },
276            state: {
277                hovered: {
278                    background: background(layer, "on", "hovered"),
279                },
280            },
281        }),
282
283        scrollbar: {
284            width: 12,
285            minHeightFactor: 1.0,
286            track: {
287                border: border(layer, "variant", { left: true }),
288            },
289            thumb: {
290                background: withOpacity(background(layer, "inverted"), 0.3),
291                border: {
292                    width: 1,
293                    color: border_color(layer, "variant"),
294                    top: false,
295                    right: true,
296                    left: true,
297                    bottom: false,
298                },
299            },
300            git: {
301                deleted: is_light
302                    ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
303                    : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
304                modified: is_light
305                    ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
306                    : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
307                inserted: is_light
308                    ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
309                    : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
310            },
311        },
312        compositionMark: {
313            underline: {
314                thickness: 1.0,
315                color: border_color(layer),
316            },
317        },
318        syntax,
319    }
320}