crates/zed/src/languages/lua/highlights.scm 🔗
@@ -158,7 +158,7 @@
[
"{"
"}"
-] @constructor)
+] @method.constructor)
;; Functions
@@ -195,4 +195,4 @@
(number) @number
-(string) @string
+(string) @string
Nate Butler created
crates/zed/src/languages/lua/highlights.scm | 4
crates/zed/src/languages/php/highlights.scm | 4
crates/zed/src/languages/typescript/highlights.scm | 6
styles/src/style_tree/editor.ts | 30
styles/src/theme/create_theme.ts | 11
styles/src/theme/syntax.ts | 382 ++-------------
styles/src/theme/theme_config.ts | 4
styles/src/theme/tokens/theme.ts | 6
styles/src/themes/atelier/common.ts | 5
styles/src/themes/ayu/common.ts | 6
styles/src/themes/gruvbox/gruvbox-common.ts | 6
styles/src/themes/one/one-dark.ts | 4
styles/src/themes/one/one-light.ts | 2
styles/src/themes/rose-pine/common.ts | 4
styles/src/types/extract_syntax_types.ts | 102 ++++
styles/src/types/syntax.ts | 203 ++++++++
16 files changed, 419 insertions(+), 360 deletions(-)
@@ -158,7 +158,7 @@
[
"{"
"}"
-] @constructor)
+] @method.constructor)
;; Functions
@@ -195,4 +195,4 @@
(number) @number
-(string) @string
+(string) @string
@@ -47,8 +47,8 @@
((name) @constant.builtin
(#match? @constant.builtin "^__[A-Z][A-Z\d_]+__$"))
-((name) @constructor
- (#match? @constructor "^[A-Z]"))
+((name) @method.constructor
+(#match? @method.constructor "^[A-Z]"))
((name) @variable.builtin
(#eq? @variable.builtin "this"))
@@ -43,8 +43,8 @@
; Special identifiers
-((identifier) @constructor
- (#match? @constructor "^[A-Z]"))
+((identifier) @method.constructor
+ (#match? @method.constructor "^[A-Z]"))
((identifier) @type
(#match? @type "^[A-Z]"))
@@ -218,4 +218,4 @@
"type"
"readonly"
"override"
-] @keyword
+] @keyword
@@ -9,9 +9,9 @@ import {
} from "./components"
import hover_popover from "./hover_popover"
-import { build_syntax } from "../theme/syntax"
import { interactive, toggleable } from "../element"
import { useTheme } from "../theme"
+import chroma from "chroma-js"
export default function editor(): any {
const theme = useTheme()
@@ -48,16 +48,28 @@ export default function editor(): any {
}
}
- const syntax = build_syntax()
-
return {
- text_color: syntax.primary.color,
+ text_color: theme.syntax.primary.color,
background: background(layer),
active_line_background: with_opacity(background(layer, "on"), 0.75),
highlighted_line_background: background(layer, "on"),
// Inline autocomplete suggestions, Co-pilot suggestions, etc.
- hint: syntax.hint,
- suggestion: syntax.predictive,
+ hint: chroma
+ .mix(
+ theme.ramps.neutral(0.6).hex(),
+ theme.ramps.blue(0.4).hex(),
+ 0.45,
+ "lch"
+ )
+ .hex(),
+ suggestion: chroma
+ .mix(
+ theme.ramps.neutral(0.4).hex(),
+ theme.ramps.blue(0.4).hex(),
+ 0.45,
+ "lch"
+ )
+ .hex(),
code_actions: {
indicator: toggleable({
base: interactive({
@@ -255,8 +267,8 @@ export default function editor(): any {
invalid_warning_diagnostic: diagnostic(theme.middle, "base"),
hover_popover: hover_popover(),
link_definition: {
- color: syntax.link_uri.color,
- underline: syntax.link_uri.underline,
+ color: theme.syntax.link_uri.color,
+ underline: theme.syntax.link_uri.underline,
},
jump_icon: interactive({
base: {
@@ -314,6 +326,6 @@ export default function editor(): any {
color: border_color(layer),
},
},
- syntax,
+ syntax: theme.syntax,
}
}
@@ -1,12 +1,12 @@
import { Scale, Color } from "chroma-js"
-import { Syntax, ThemeSyntax, SyntaxHighlightStyle } from "./syntax"
-export { Syntax, ThemeSyntax, SyntaxHighlightStyle }
import {
ThemeConfig,
ThemeAppearance,
- ThemeConfigInputColors,
+ ThemeConfigInputColors
} from "./theme_config"
import { get_ramps } from "./ramps"
+import { syntaxStyle } from "./syntax"
+import { Syntax } from "../types/syntax"
export interface Theme {
name: string
@@ -31,7 +31,7 @@ export interface Theme {
modal_shadow: Shadow
players: Players
- syntax?: Partial<ThemeSyntax>
+ syntax: Syntax
}
export interface Meta {
@@ -119,7 +119,6 @@ export function create_theme(theme: ThemeConfig): Theme {
name,
appearance,
input_color,
- override: { syntax },
} = theme
const is_light = appearance === ThemeAppearance.Light
@@ -162,6 +161,8 @@ export function create_theme(theme: ThemeConfig): Theme {
"7": player(ramps.yellow),
}
+ const syntax = syntaxStyle(ramps, theme.override.syntax ? theme.override.syntax : {})
+
return {
name,
is_light,
@@ -1,332 +1,80 @@
import deepmerge from "deepmerge"
-import { FontWeight, font_weights, useTheme } from "../common"
-import chroma from "chroma-js"
+import { font_weights, ThemeConfigInputSyntax, RampSet } from "../common"
+import { Syntax, SyntaxHighlightStyle, allSyntaxKeys } from "../types/syntax"
-export interface SyntaxHighlightStyle {
- color?: string
- weight?: FontWeight
- underline?: boolean
- italic?: boolean
-}
-
-export interface Syntax {
- // == Text Styles ====== /
- comment: SyntaxHighlightStyle
- // elixir: doc comment
- "comment.doc": SyntaxHighlightStyle
- primary: SyntaxHighlightStyle
- predictive: SyntaxHighlightStyle
- hint: SyntaxHighlightStyle
-
- // === Formatted Text ====== /
- emphasis: SyntaxHighlightStyle
- "emphasis.strong": SyntaxHighlightStyle
- title: SyntaxHighlightStyle
- link_uri: SyntaxHighlightStyle
- link_text: SyntaxHighlightStyle
- /** md: indented_code_block, fenced_code_block, code_span */
- "text.literal": SyntaxHighlightStyle
-
- // == Punctuation ====== /
- punctuation: SyntaxHighlightStyle
- /** Example: `(`, `[`, `{`...*/
- "punctuation.bracket": SyntaxHighlightStyle
- /**., ;*/
- "punctuation.delimiter": SyntaxHighlightStyle
- // js, ts: ${, } in a template literal
- // yaml: *, &, ---, ...
- "punctuation.special": SyntaxHighlightStyle
- // md: list_marker_plus, list_marker_dot, etc
- "punctuation.list_marker": SyntaxHighlightStyle
-
- // == Strings ====== /
-
- string: SyntaxHighlightStyle
- // css: color_value
- // js: this, super
- // toml: offset_date_time, local_date_time...
- "string.special": SyntaxHighlightStyle
- // elixir: atom, quoted_atom, keyword, quoted_keyword
- // ruby: simple_symbol, delimited_symbol...
- "string.special.symbol"?: SyntaxHighlightStyle
- // elixir, python, yaml...: escape_sequence
- "string.escape"?: SyntaxHighlightStyle
- // Regular expressions
- "string.regex"?: SyntaxHighlightStyle
-
- // == Types ====== /
- // We allow Function here because all JS objects literals have this property
- constructor: SyntaxHighlightStyle | Function // eslint-disable-line @typescript-eslint/ban-types
- variant: SyntaxHighlightStyle
- type: SyntaxHighlightStyle
- // js: predefined_type
- "type.builtin"?: SyntaxHighlightStyle
-
- // == Values
- variable: SyntaxHighlightStyle
- // this, ...
- // css: -- (var(--foo))
- // lua: self
- "variable.special"?: SyntaxHighlightStyle
- // c: statement_identifier,
- label: SyntaxHighlightStyle
- // css: tag_name, nesting_selector, universal_selector...
- tag: SyntaxHighlightStyle
- // css: attribute, pseudo_element_selector (tag_name),
- attribute: SyntaxHighlightStyle
- // css: class_name, property_name, namespace_name...
- property: SyntaxHighlightStyle
- // true, false, null, nullptr
- constant: SyntaxHighlightStyle
- // css: @media, @import, @supports...
- // js: declare, implements, interface, keyof, public...
- keyword: SyntaxHighlightStyle
- // note: js enum is currently defined as a keyword
- enum: SyntaxHighlightStyle
- // -, --, ->, !=, &&, ||, <=...
- operator: SyntaxHighlightStyle
- number: SyntaxHighlightStyle
- boolean: SyntaxHighlightStyle
- // elixir: __MODULE__, __DIR__, __ENV__, etc
- // go: nil, iota
- "constant.builtin"?: SyntaxHighlightStyle
-
- // == Functions ====== /
-
- function: SyntaxHighlightStyle
- // lua: assert, error, loadfile, tostring, unpack...
- "function.builtin"?: SyntaxHighlightStyle
- // go: call_expression, method_declaration
- // js: call_expression, method_definition, pair (key, arrow function)
- // rust: function_item name: (identifier)
- "function.definition"?: SyntaxHighlightStyle
- // rust: macro_definition name: (identifier)
- "function.special.definition"?: SyntaxHighlightStyle
- "function.method"?: SyntaxHighlightStyle
- // ruby: identifier/"defined?" // Nate note: I don't fully understand this one.
- "function.method.builtin"?: SyntaxHighlightStyle
-
- // == Unsorted ====== /
- // lua: hash_bang_line
- preproc: SyntaxHighlightStyle
- // elixir, python: interpolation (ex: foo in ${foo})
- // js: template_substitution
- embedded: SyntaxHighlightStyle
-}
-
-export type ThemeSyntax = Partial<Syntax>
+// Apply defaults to any missing syntax properties that are not defined manually
+function apply_defaults(ramps: RampSet, syntax_highlights: Partial<Syntax>): Syntax {
+ const restKeys: (keyof Syntax)[] = allSyntaxKeys.filter(key => !syntax_highlights[key])
-const default_syntax_highlight_style: Omit<SyntaxHighlightStyle, "color"> = {
- weight: "normal",
- underline: false,
- italic: false,
-}
-
-function build_default_syntax(): Syntax {
- const theme = useTheme()
+ const completeSyntax: Syntax = {} as Syntax
- // Make a temporary object that is allowed to be missing
- // the "color" property for each style
- const syntax: {
- [key: string]: Omit<SyntaxHighlightStyle, "color">
- } = {}
+ const defaults: SyntaxHighlightStyle = {
+ color: ramps.neutral(1).hex(),
+ }
- // then spread the default to each style
- for (const key of Object.keys({} as Syntax)) {
- syntax[key as keyof Syntax] = {
- ...default_syntax_highlight_style,
+ for (const key of restKeys) {
+ {
+ completeSyntax[key] = {
+ ...defaults,
+ }
}
}
- // Mix the neutral and blue colors to get a
- // predictive color distinct from any other color in the theme
- const predictive = chroma
- .mix(
- theme.ramps.neutral(0.4).hex(),
- theme.ramps.blue(0.4).hex(),
- 0.45,
- "lch"
- )
- .hex()
- // Mix the neutral and green colors to get a
- // hint color distinct from any other color in the theme
- const hint = chroma
- .mix(
- theme.ramps.neutral(0.6).hex(),
- theme.ramps.blue(0.4).hex(),
- 0.45,
- "lch"
- )
- .hex()
+ const mergedBaseSyntax = Object.assign(completeSyntax, syntax_highlights)
- const color = {
- primary: theme.ramps.neutral(1).hex(),
- comment: theme.ramps.neutral(0.71).hex(),
- punctuation: theme.ramps.neutral(0.86).hex(),
- predictive: predictive,
- hint: hint,
- emphasis: theme.ramps.blue(0.5).hex(),
- string: theme.ramps.orange(0.5).hex(),
- function: theme.ramps.yellow(0.5).hex(),
- type: theme.ramps.cyan(0.5).hex(),
- constructor: theme.ramps.blue(0.5).hex(),
- variant: theme.ramps.blue(0.5).hex(),
- property: theme.ramps.blue(0.5).hex(),
- enum: theme.ramps.orange(0.5).hex(),
- operator: theme.ramps.orange(0.5).hex(),
- number: theme.ramps.green(0.5).hex(),
- boolean: theme.ramps.green(0.5).hex(),
- constant: theme.ramps.green(0.5).hex(),
- keyword: theme.ramps.blue(0.5).hex(),
- }
-
- // Then assign colors and use Syntax to enforce each style getting it's own color
- const default_syntax: Syntax = {
- ...syntax,
- comment: {
- color: color.comment,
- },
- "comment.doc": {
- color: color.comment,
- },
- primary: {
- color: color.primary,
- },
- predictive: {
- color: color.predictive,
- italic: true,
- },
- hint: {
- color: color.hint,
- weight: font_weights.bold,
- },
- emphasis: {
- color: color.emphasis,
- },
- "emphasis.strong": {
- color: color.emphasis,
- weight: font_weights.bold,
- },
- title: {
- color: color.primary,
- weight: font_weights.bold,
- },
- link_uri: {
- color: theme.ramps.green(0.5).hex(),
- underline: true,
- },
- link_text: {
- color: theme.ramps.orange(0.5).hex(),
- italic: true,
- },
- "text.literal": {
- color: color.string,
- },
- punctuation: {
- color: color.punctuation,
- },
- "punctuation.bracket": {
- color: color.punctuation,
- },
- "punctuation.delimiter": {
- color: color.punctuation,
- },
- "punctuation.special": {
- color: theme.ramps.neutral(0.86).hex(),
- },
- "punctuation.list_marker": {
- color: color.punctuation,
- },
- string: {
- color: color.string,
- },
- "string.special": {
- color: color.string,
- },
- "string.special.symbol": {
- color: color.string,
- },
- "string.escape": {
- color: color.comment,
- },
- "string.regex": {
- color: color.string,
- },
- constructor: {
- color: theme.ramps.blue(0.5).hex(),
- },
- variant: {
- color: theme.ramps.blue(0.5).hex(),
- },
- type: {
- color: color.type,
- },
- variable: {
- color: color.primary,
- },
- label: {
- color: theme.ramps.blue(0.5).hex(),
- },
- tag: {
- color: theme.ramps.blue(0.5).hex(),
- },
- attribute: {
- color: theme.ramps.blue(0.5).hex(),
- },
- property: {
- color: theme.ramps.blue(0.5).hex(),
- },
- constant: {
- color: color.constant,
- },
- keyword: {
- color: color.keyword,
- },
- enum: {
- color: color.enum,
- },
- operator: {
- color: color.operator,
- },
- number: {
- color: color.number,
- },
- boolean: {
- color: color.boolean,
- },
- function: {
- color: color.function,
- },
- preproc: {
- color: color.primary,
- },
- embedded: {
- color: color.primary,
- },
- }
-
- return default_syntax
+ return mergedBaseSyntax
}
-export function build_syntax(): Syntax {
- const theme = useTheme()
-
- const default_syntax: Syntax = build_default_syntax()
+// Merge the base syntax with the theme syntax overrides
+// This is a deep merge, so any nested properties will be merged as well
+// This allows for a theme to only override a single property of a syntax highlight style
+const merge_syntax = (baseSyntax: Syntax, theme_syntax_overrides: ThemeConfigInputSyntax): Syntax => {
+ return deepmerge<Syntax, ThemeConfigInputSyntax>(baseSyntax, theme_syntax_overrides, {
+ arrayMerge: (destinationArray, sourceArray) => [
+ ...destinationArray,
+ ...sourceArray,
+ ],
+ })
+}
- if (!theme.syntax) {
- return default_syntax
+/** Returns a complete Syntax object of the combined styles of a theme's syntax overrides and the default syntax styles */
+export const syntaxStyle = (ramps: RampSet, theme_syntax_overrides: ThemeConfigInputSyntax): Syntax => {
+ const syntax_highlights: Partial<Syntax> = {
+ "comment": { color: ramps.neutral(0.71).hex() },
+ "comment.doc": { color: ramps.neutral(0.71).hex() },
+ primary: { color: ramps.neutral(1).hex() },
+ emphasis: { color: ramps.blue(0.5).hex() },
+ "emphasis.strong": { color: ramps.blue(0.5).hex(), weight: font_weights.bold },
+ link_uri: { color: ramps.green(0.5).hex(), underline: true },
+ link_text: { color: ramps.orange(0.5).hex(), italic: true },
+ "text.literal": { color: ramps.orange(0.5).hex() },
+ punctuation: { color: ramps.neutral(0.86).hex() },
+ "punctuation.bracket": { color: ramps.neutral(0.86).hex() },
+ "punctuation.special": { color: ramps.neutral(0.86).hex() },
+ "punctuation.delimiter": { color: ramps.neutral(0.86).hex() },
+ "punctuation.list_marker": { color: ramps.neutral(0.86).hex() },
+ string: { color: ramps.orange(0.5).hex() },
+ "string.special": { color: ramps.orange(0.5).hex() },
+ "string.special.symbol": { color: ramps.orange(0.5).hex() },
+ "string.escape": { color: ramps.neutral(0.71).hex() },
+ "string.regex": { color: ramps.orange(0.5).hex() },
+ "method.constructor": { color: ramps.blue(0.5).hex() },
+ type: { color: ramps.cyan(0.5).hex() },
+ variable: { color: ramps.neutral(1).hex() },
+ label: { color: ramps.blue(0.5).hex() },
+ attribute: { color: ramps.blue(0.5).hex() },
+ property: { color: ramps.blue(0.5).hex() },
+ constant: { color: ramps.green(0.5).hex() },
+ keyword: { color: ramps.blue(0.5).hex() },
+ operator: { color: ramps.orange(0.5).hex() },
+ number: { color: ramps.green(0.5).hex() },
+ boolean: { color: ramps.green(0.5).hex() },
+ function: { color: ramps.yellow(0.5).hex() },
+ preproc: { color: ramps.neutral(1).hex() },
+ embedded: { color: ramps.neutral(1).hex() },
}
- const syntax = deepmerge<Syntax, Partial<ThemeSyntax>>(
- default_syntax,
- theme.syntax,
- {
- arrayMerge: (destinationArray, sourceArray) => [
- ...destinationArray,
- ...sourceArray,
- ],
- }
- )
-
- return syntax
+ const baseSyntax = apply_defaults(ramps, syntax_highlights)
+ const mergedSyntax = merge_syntax(baseSyntax, theme_syntax_overrides)
+ return mergedSyntax
}
@@ -1,5 +1,5 @@
import { Scale, Color } from "chroma-js"
-import { Syntax } from "./syntax"
+import { SyntaxHighlightStyle, SyntaxProperty } from "../types/syntax"
interface ThemeMeta {
/** The name of the theme */
@@ -55,7 +55,7 @@ export type ThemeConfigInputColorsKeys = keyof ThemeConfigInputColors
* }
* ```
*/
-export type ThemeConfigInputSyntax = Partial<Syntax>
+export type ThemeConfigInputSyntax = Partial<Record<SyntaxProperty, Partial<SyntaxHighlightStyle>>>
interface ThemeConfigOverrides {
syntax: ThemeConfigInputSyntax
@@ -6,15 +6,13 @@ import {
} from "@tokens-studio/types"
import {
Shadow,
- SyntaxHighlightStyle,
- ThemeSyntax,
} from "../create_theme"
import { LayerToken, layer_token } from "./layer"
import { PlayersToken, players_token } from "./players"
import { color_token } from "./token"
-import { Syntax } from "../syntax"
import editor from "../../style_tree/editor"
import { useTheme } from "../../../src/common"
+import { Syntax, SyntaxHighlightStyle } from "../../types/syntax"
interface ThemeTokens {
name: SingleOtherToken
@@ -51,7 +49,7 @@ const modal_shadow_token = (): SingleBoxShadowToken => {
return create_shadow_token(shadow, "modal_shadow")
}
-type ThemeSyntaxColorTokens = Record<keyof ThemeSyntax, SingleColorToken>
+type ThemeSyntaxColorTokens = Record<keyof Syntax, SingleColorToken>
function syntax_highlight_style_color_tokens(
syntax: Syntax
@@ -1,4 +1,4 @@
-import { ThemeLicenseType, ThemeSyntax, ThemeFamilyMeta } from "../../common"
+import { ThemeLicenseType, ThemeFamilyMeta, ThemeConfigInputSyntax } from "../../common"
export interface Variant {
colors: {
@@ -29,7 +29,7 @@ export const meta: ThemeFamilyMeta = {
"https://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave/",
}
-export const build_syntax = (variant: Variant): ThemeSyntax => {
+export const build_syntax = (variant: Variant): ThemeConfigInputSyntax => {
const { colors } = variant
return {
primary: { color: colors.base06 },
@@ -50,7 +50,6 @@ export const build_syntax = (variant: Variant): ThemeSyntax => {
property: { color: colors.base08 },
variable: { color: colors.base06 },
"variable.special": { color: colors.base0E },
- variant: { color: colors.base0A },
keyword: { color: colors.base0E },
}
}
@@ -3,8 +3,8 @@ import {
chroma,
color_ramp,
ThemeLicenseType,
- ThemeSyntax,
ThemeFamilyMeta,
+ ThemeConfigInputSyntax,
} from "../../common"
export const ayu = {
@@ -27,7 +27,7 @@ export const build_theme = (t: typeof dark, light: boolean) => {
purple: t.syntax.constant.hex(),
}
- const syntax: ThemeSyntax = {
+ const syntax: ThemeConfigInputSyntax = {
constant: { color: t.syntax.constant.hex() },
"string.regex": { color: t.syntax.regexp.hex() },
string: { color: t.syntax.string.hex() },
@@ -61,7 +61,7 @@ export const build_theme = (t: typeof dark, light: boolean) => {
}
}
-export const build_syntax = (t: typeof dark): ThemeSyntax => {
+export const build_syntax = (t: typeof dark): ThemeConfigInputSyntax => {
return {
constant: { color: t.syntax.constant.hex() },
"string.regex": { color: t.syntax.regexp.hex() },
@@ -4,8 +4,8 @@ import {
ThemeAppearance,
ThemeLicenseType,
ThemeConfig,
- ThemeSyntax,
ThemeFamilyMeta,
+ ThemeConfigInputSyntax,
} from "../../common"
const meta: ThemeFamilyMeta = {
@@ -214,7 +214,7 @@ const build_variant = (variant: Variant): ThemeConfig => {
magenta: color_ramp(chroma(variant.colors.gray)),
}
- const syntax: ThemeSyntax = {
+ const syntax: ThemeConfigInputSyntax = {
primary: { color: neutral[is_light ? 0 : 8] },
"text.literal": { color: colors.blue },
comment: { color: colors.gray },
@@ -229,7 +229,7 @@ const build_variant = (variant: Variant): ThemeConfig => {
"string.special.symbol": { color: colors.aqua },
"string.regex": { color: colors.orange },
type: { color: colors.yellow },
- enum: { color: colors.orange },
+ // enum: { color: colors.orange },
tag: { color: colors.aqua },
constant: { color: colors.yellow },
keyword: { color: colors.red },
@@ -54,7 +54,6 @@ export const theme: ThemeConfig = {
syntax: {
boolean: { color: color.orange },
comment: { color: color.grey },
- enum: { color: color.red },
"emphasis.strong": { color: color.orange },
function: { color: color.blue },
keyword: { color: color.purple },
@@ -73,8 +72,7 @@ export const theme: ThemeConfig = {
"text.literal": { color: color.green },
type: { color: color.teal },
"variable.special": { color: color.orange },
- variant: { color: color.blue },
- constructor: { color: color.blue },
+ "method.constructor": { color: color.blue },
},
},
}
@@ -55,7 +55,6 @@ export const theme: ThemeConfig = {
syntax: {
boolean: { color: color.orange },
comment: { color: color.grey },
- enum: { color: color.red },
"emphasis.strong": { color: color.orange },
function: { color: color.blue },
keyword: { color: color.purple },
@@ -73,7 +72,6 @@ export const theme: ThemeConfig = {
"text.literal": { color: color.green },
type: { color: color.teal },
"variable.special": { color: color.orange },
- variant: { color: color.blue },
},
},
}
@@ -1,4 +1,4 @@
-import { ThemeSyntax } from "../../common"
+import { ThemeConfigInputSyntax } from "../../common"
export const color = {
default: {
@@ -54,7 +54,7 @@ export const color = {
},
}
-export const syntax = (c: typeof color.default): Partial<ThemeSyntax> => {
+export const syntax = (c: typeof color.default): ThemeConfigInputSyntax => {
return {
comment: { color: c.muted },
operator: { color: c.pine },
@@ -0,0 +1,102 @@
+import fs from 'fs'
+import path from 'path'
+import readline from 'readline'
+
+function escapeTypeName(name: string): string {
+ return `'${name.replace('@', '').toLowerCase()}'`
+}
+
+const generatedNote = `// This file is generated by extract_syntax_types.ts
+// Do not edit this file directly
+// It is generated from the highlight.scm files in the zed crate
+
+// To regenerate this file manually:
+// 'npm run extract-syntax-types' from ./styles`
+
+const defaultTextProperty = ` /** Default text color */
+ | 'primary'`
+
+const main = async () => {
+ const pathFromRoot = 'crates/zed/src/languages'
+ const directoryPath = path.join(__dirname, '../../../', pathFromRoot)
+ const stylesMap: Record<string, Set<string>> = {}
+ const propertyLanguageMap: Record<string, Set<string>> = {}
+
+ const processFile = async (filePath: string, language: string) => {
+ const fileStream = fs.createReadStream(filePath)
+ const rl = readline.createInterface({
+ input: fileStream,
+ crlfDelay: Infinity,
+ })
+
+ for await (const line of rl) {
+ const cleanedLine = line.replace(/"@[a-zA-Z0-9_.]*"/g, "")
+ const match = cleanedLine.match(/@(\w+\.*)*/g)
+ if (match) {
+ match.forEach((property) => {
+ const formattedProperty = escapeTypeName(property)
+ // Only add non-empty properties
+ if (formattedProperty !== "''") {
+ if (!propertyLanguageMap[formattedProperty]) {
+ propertyLanguageMap[formattedProperty] = new Set()
+ }
+ propertyLanguageMap[formattedProperty].add(language)
+ }
+ })
+ }
+ }
+ }
+
+ const directories = fs.readdirSync(directoryPath, { withFileTypes: true })
+ .filter(dirent => dirent.isDirectory())
+ .map(dirent => dirent.name)
+
+ for (const dir of directories) {
+ const highlightsFilePath = path.join(directoryPath, dir, 'highlights.scm')
+ if (fs.existsSync(highlightsFilePath)) {
+ await processFile(highlightsFilePath, dir)
+ }
+ }
+
+ for (const [language, properties] of Object.entries(stylesMap)) {
+ console.log(`${language}: ${Array.from(properties).join(', ')}`)
+ }
+
+ const sortedProperties = Object.entries(propertyLanguageMap).sort(([propA], [propB]) => propA.localeCompare(propB))
+
+ const outStream = fs.createWriteStream(path.join(__dirname, 'syntax.ts'))
+ let allProperties = ""
+ const syntaxKeys = []
+ for (const [property, languages] of sortedProperties) {
+ let languagesArray = Array.from(languages)
+ const moreThanSeven = languagesArray.length > 7
+ // Limit to the first 7 languages, append "..." if more than 7
+ languagesArray = languagesArray.slice(0, 7)
+ if (moreThanSeven) {
+ languagesArray.push('...')
+ }
+ const languagesString = languagesArray.join(', ')
+ const comment = `/** ${languagesString} */`
+ allProperties += ` ${comment}\n | ${property} \n`
+ syntaxKeys.push(property)
+ }
+ outStream.write(`${generatedNote}
+
+export type SyntaxHighlightStyle = {
+ color: string,
+ fade_out?: number,
+ italic?: boolean,
+ underline?: boolean,
+ weight?: string,
+}
+
+export type Syntax = Record<SyntaxProperty, SyntaxHighlightStyle>
+export type SyntaxOverride = Partial<Syntax>
+
+export type SyntaxProperty = \n${defaultTextProperty}\n\n${allProperties}
+
+export const allSyntaxKeys: SyntaxProperty[] = [\n ${syntaxKeys.join(',\n ')}\n]`)
+ outStream.end()
+}
+
+main().catch(console.error)
@@ -0,0 +1,203 @@
+// This file is generated by extract_syntax_types.ts
+// Do not edit this file directly
+// It is generated from the highlight.scm files in the zed crate
+
+// To regenerate this file manually:
+// 'npm run extract-syntax-types' from ./styles
+
+export type SyntaxHighlightStyle = {
+ color: string,
+ fade_out?: number,
+ italic?: boolean,
+ underline?: boolean,
+ weight?: string,
+}
+
+export type Syntax = Record<SyntaxProperty, SyntaxHighlightStyle>
+export type SyntaxOverride = Partial<Syntax>
+
+export type SyntaxProperty =
+ /** Default text color */
+ | 'primary'
+
+ /** elixir */
+ | '__attribute__'
+ /** elixir */
+ | '__name__'
+ /** elixir */
+ | '_sigil_name'
+ /** css, heex, lua */
+ | 'attribute'
+ /** javascript, lua, tsx, typescript, yaml */
+ | 'boolean'
+ /** elixir */
+ | 'comment.doc'
+ /** elixir */
+ | 'comment.unused'
+ /** bash, c, cpp, css, elixir, elm, erb, ... */
+ | 'comment'
+ /** elixir, go, javascript, lua, php, python, racket, ... */
+ | 'constant.builtin'
+ /** bash, c, cpp, elixir, elm, glsl, heex, ... */
+ | 'constant'
+ /** glsl */
+ | 'delimiter'
+ /** bash, elixir, javascript, python, ruby, tsx, typescript */
+ | 'embedded'
+ /** markdown */
+ | 'emphasis.strong'
+ /** markdown */
+ | 'emphasis'
+ /** go, python, racket, ruby, scheme */
+ | 'escape'
+ /** lua */
+ | 'field'
+ /** lua, php, python */
+ | 'function.builtin'
+ /** elm, lua, rust */
+ | 'function.definition'
+ /** ruby */
+ | 'function.method.builtin'
+ /** go, javascript, php, python, ruby, rust, tsx, ... */
+ | 'function.method'
+ /** rust */
+ | 'function.special.definition'
+ /** c, cpp, glsl, rust */
+ | 'function.special'
+ /** bash, c, cpp, css, elixir, elm, glsl, ... */
+ | 'function'
+ /** elm */
+ | 'identifier'
+ /** glsl */
+ | 'keyword.function'
+ /** bash, c, cpp, css, elixir, elm, erb, ... */
+ | 'keyword'
+ /** c, cpp, glsl */
+ | 'label'
+ /** markdown */
+ | 'link_text'
+ /** markdown */
+ | 'link_uri'
+ /** lua, php, tsx, typescript */
+ | 'method.constructor'
+ /** lua */
+ | 'method'
+ /** heex */
+ | 'module'
+ /** svelte */
+ | 'none'
+ /** bash, c, cpp, css, elixir, glsl, go, ... */
+ | 'number'
+ /** bash, c, cpp, css, elixir, elm, glsl, ... */
+ | 'operator'
+ /** lua */
+ | 'parameter'
+ /** lua */
+ | 'preproc'
+ /** bash, c, cpp, css, glsl, go, html, ... */
+ | 'property'
+ /** c, cpp, elixir, elm, heex, html, javascript, ... */
+ | 'punctuation.bracket'
+ /** c, cpp, css, elixir, elm, heex, javascript, ... */
+ | 'punctuation.delimiter'
+ /** markdown */
+ | 'punctuation.list_marker'
+ /** elixir, javascript, python, ruby, tsx, typescript, yaml */
+ | 'punctuation.special'
+ /** elixir */
+ | 'punctuation'
+ /** glsl */
+ | 'storageclass'
+ /** elixir, elm, yaml */
+ | 'string.escape'
+ /** elixir, javascript, racket, ruby, tsx, typescript */
+ | 'string.regex'
+ /** elixir, ruby */
+ | 'string.special.symbol'
+ /** css, elixir, toml */
+ | 'string.special'
+ /** bash, c, cpp, css, elixir, elm, glsl, ... */
+ | 'string'
+ /** svelte */
+ | 'tag.delimiter'
+ /** css, heex, php, svelte */
+ | 'tag'
+ /** markdown */
+ | 'text.literal'
+ /** markdown */
+ | 'title'
+ /** javascript, php, rust, tsx, typescript */
+ | 'type.builtin'
+ /** glsl */
+ | 'type.qualifier'
+ /** c, cpp, css, elixir, elm, glsl, go, ... */
+ | 'type'
+ /** glsl, php */
+ | 'variable.builtin'
+ /** cpp, css, javascript, lua, racket, ruby, rust, ... */
+ | 'variable.special'
+ /** c, cpp, elm, glsl, go, javascript, lua, ... */
+ | 'variable'
+
+
+export const allSyntaxKeys: SyntaxProperty[] = [
+ '__attribute__',
+ '__name__',
+ '_sigil_name',
+ 'attribute',
+ 'boolean',
+ 'comment.doc',
+ 'comment.unused',
+ 'comment',
+ 'constant.builtin',
+ 'constant',
+ 'delimiter',
+ 'embedded',
+ 'emphasis.strong',
+ 'emphasis',
+ 'escape',
+ 'field',
+ 'function.builtin',
+ 'function.definition',
+ 'function.method.builtin',
+ 'function.method',
+ 'function.special.definition',
+ 'function.special',
+ 'function',
+ 'identifier',
+ 'keyword.function',
+ 'keyword',
+ 'label',
+ 'link_text',
+ 'link_uri',
+ 'method.constructor',
+ 'method',
+ 'module',
+ 'none',
+ 'number',
+ 'operator',
+ 'parameter',
+ 'preproc',
+ 'property',
+ 'punctuation.bracket',
+ 'punctuation.delimiter',
+ 'punctuation.list_marker',
+ 'punctuation.special',
+ 'punctuation',
+ 'storageclass',
+ 'string.escape',
+ 'string.regex',
+ 'string.special.symbol',
+ 'string.special',
+ 'string',
+ 'tag.delimiter',
+ 'tag',
+ 'text.literal',
+ 'title',
+ 'type.builtin',
+ 'type.qualifier',
+ 'type',
+ 'variable.builtin',
+ 'variable.special',
+ 'variable'
+]