Merge pull request #2223 from zed-industries/nate/extend-syntax

Extend syntax styles available in the theme
This commit is contained in:
Nate Butler 2023-02-28 11:26:47 -05:00 committed by GitHub
commit 514da604d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 423 additions and 214 deletions

View file

@ -59,12 +59,15 @@
(super) @variable.special
[
(true)
(false)
(null)
(undefined)
] @constant.builtin
[
(true)
(false)
] @boolean
(comment) @comment
[
@ -72,15 +75,11 @@
(template_string)
] @string
(regex) @string.special
(regex) @string.regex
(number) @number
; Tokens
(template_substitution
"${" @punctuation.special
"}" @punctuation.special) @embedded
[
";"
"?."
@ -189,6 +188,10 @@
"yield"
] @keyword
(template_substitution
"${" @punctuation.special
"}" @punctuation.special) @embedded
; Types
(type_identifier) @type

View file

@ -3,7 +3,7 @@
[(string)
(here_string)
(byte_string)] @string
(regex) @string.special
(regex) @string.regex
(escape_sequence) @escape
[(comment)

View file

@ -95,7 +95,7 @@
(bare_symbol)
] @string.special.symbol
(regex) @string.special.regex
(regex) @string.regex
(escape_sequence) @escape
[

View file

@ -59,12 +59,15 @@
(super) @variable.special
[
(true)
(false)
(null)
(undefined)
] @constant.builtin
[
(true)
(false)
] @boolean
(comment) @comment
[
@ -72,15 +75,11 @@
(template_string)
] @string
(regex) @string.special
(regex) @string.regex
(number) @number
; Tokens
(template_substitution
"${" @punctuation.special
"}" @punctuation.special) @embedded
[
";"
"?."
@ -190,6 +189,10 @@
"yield"
] @keyword
(template_substitution
"${" @punctuation.special
"}" @punctuation.special) @embedded
; Types
(type_identifier) @type

View file

@ -1,16 +1,9 @@
import { fontWeights } from "../common"
import { withOpacity } from "../utils/color"
import {
ColorScheme,
Layer,
StyleSets,
Syntax,
ThemeSyntax,
} from "../themes/common/colorScheme"
import { ColorScheme, Layer, StyleSets } from "../themes/common/colorScheme"
import { background, border, borderColor, foreground, text } from "./components"
import hoverPopover from "./hoverPopover"
import deepmerge from "deepmerge"
import { buildSyntax } from "../themes/common/syntax"
export default function editor(colorScheme: ColorScheme) {
let layer = colorScheme.highest
@ -43,118 +36,7 @@ export default function editor(colorScheme: ColorScheme) {
}
}
const defaultSyntax: Syntax = {
primary: {
color: colorScheme.ramps.neutral(1).hex(),
weight: fontWeights.normal,
},
"variable.special": {
// Highlights for self, this, etc
color: colorScheme.ramps.blue(0.7).hex(),
weight: fontWeights.normal,
},
comment: {
color: colorScheme.ramps.neutral(0.71).hex(),
weight: fontWeights.normal,
},
punctuation: {
color: colorScheme.ramps.neutral(0.86).hex(),
weight: fontWeights.normal,
},
constant: {
color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal,
},
keyword: {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal,
},
function: {
color: colorScheme.ramps.yellow(0.5).hex(),
weight: fontWeights.normal,
},
type: {
color: colorScheme.ramps.cyan(0.5).hex(),
weight: fontWeights.normal,
},
constructor: {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal,
},
variant: {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal,
},
property: {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal,
},
enum: {
color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal,
},
operator: {
color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal,
},
string: {
color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal,
},
number: {
color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal,
},
boolean: {
color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal,
},
predictive: {
color: colorScheme.ramps.neutral(0.57).hex(),
weight: fontWeights.normal,
},
title: {
color: colorScheme.ramps.yellow(0.5).hex(),
weight: fontWeights.bold,
},
emphasis: {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.normal,
},
"emphasis.strong": {
color: colorScheme.ramps.blue(0.5).hex(),
weight: fontWeights.bold,
},
linkUri: {
color: colorScheme.ramps.green(0.5).hex(),
weight: fontWeights.normal,
underline: true,
},
linkText: {
color: colorScheme.ramps.orange(0.5).hex(),
weight: fontWeights.normal,
italic: true,
},
}
function createSyntax(colorScheme: ColorScheme): Syntax {
if (!colorScheme.syntax) {
return defaultSyntax
}
return deepmerge<Syntax, Partial<ThemeSyntax>>(
defaultSyntax,
colorScheme.syntax,
{
arrayMerge: (destinationArray, sourceArray) => [
...destinationArray,
...sourceArray,
],
}
)
}
const syntax = createSyntax(colorScheme)
const syntax = buildSyntax(colorScheme)
return {
textColor: syntax.primary.color,

View file

@ -27,7 +27,7 @@ const ramps = {
magenta: colorRamp(chroma("#C74DED")),
}
export const dark = createColorScheme(`${name}`, false, ramps)
export const dark = createColorScheme(name, false, ramps)
export const meta: Meta = {
name,

View file

@ -1,5 +1,6 @@
import { Scale } from "chroma-js"
import { FontWeight } from "../../common"
import { Syntax, ThemeSyntax, SyntaxHighlightStyle } from "./syntax"
export { Syntax, ThemeSyntax, SyntaxHighlightStyle }
export interface ColorScheme {
name: string
@ -100,39 +101,3 @@ export interface Style {
border: string
foreground: string
}
export interface SyntaxHighlightStyle {
color: string
weight?: FontWeight
underline?: boolean
italic?: boolean
}
export interface Syntax {
primary: SyntaxHighlightStyle
"variable.special": SyntaxHighlightStyle
comment: SyntaxHighlightStyle
punctuation: SyntaxHighlightStyle
constant: SyntaxHighlightStyle
keyword: SyntaxHighlightStyle
function: SyntaxHighlightStyle
type: SyntaxHighlightStyle
constructor: SyntaxHighlightStyle
variant: SyntaxHighlightStyle
property: SyntaxHighlightStyle
enum: SyntaxHighlightStyle
operator: SyntaxHighlightStyle
string: SyntaxHighlightStyle
number: SyntaxHighlightStyle
boolean: SyntaxHighlightStyle
predictive: SyntaxHighlightStyle
title: SyntaxHighlightStyle
emphasis: SyntaxHighlightStyle
"emphasis.strong": SyntaxHighlightStyle
linkUri: SyntaxHighlightStyle
linkText: SyntaxHighlightStyle
}
// HACK: "constructor" as a key in the syntax interface returns an error when a theme tries to use it.
// For now hack around it by omiting constructor as a valid key for overrides.
export type ThemeSyntax = Partial<Omit<Syntax, "constructor">>

View file

@ -0,0 +1,343 @@
import deepmerge from "deepmerge"
import { FontWeight, fontWeights } from "../../common"
import {
ColorScheme,
} from "./colorScheme"
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
// === Formatted Text ====== /
emphasis: SyntaxHighlightStyle
"emphasis.strong": SyntaxHighlightStyle
title: SyntaxHighlightStyle
linkUri: SyntaxHighlightStyle
linkText: 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 ====== /
constructor: SyntaxHighlightStyle
variant: SyntaxHighlightStyle
type: SyntaxHighlightStyle
// js: predefined_type
"type.builtin": SyntaxHighlightStyle
// == Values
variable: SyntaxHighlightStyle
// racket: lang_name
"variable.builtin": 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
// lua: function_call
"function.call": 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
}
// HACK: "constructor" as a key in the syntax interface returns an error when a theme tries to use it.
// For now hack around it by omiting constructor as a valid key for overrides.
export type ThemeSyntax = Partial<Omit<Syntax, "constructor">>
const defaultSyntaxHighlightStyle: Omit<SyntaxHighlightStyle, "color"> = {
weight: fontWeights.normal,
underline: false,
italic: false,
}
function buildDefaultSyntax(colorScheme: ColorScheme): Syntax {
// Make a temporary object that is allowed to be missing
// the "color" property for each style
const syntax: {
[key: string]: Omit<SyntaxHighlightStyle, "color">
} = {}
// then spread the default to each style
for (const key of Object.keys({} as Syntax)) {
syntax[key as keyof Syntax] = {
...defaultSyntaxHighlightStyle,
}
}
const color = {
primary: colorScheme.ramps.neutral(1).hex(),
comment: colorScheme.ramps.neutral(0.71).hex(),
punctuation: colorScheme.ramps.neutral(0.86).hex(),
predictive: colorScheme.ramps.neutral(0.57).hex(),
emphasis: colorScheme.ramps.blue(0.5).hex(),
string: colorScheme.ramps.orange(0.5).hex(),
function: colorScheme.ramps.yellow(0.5).hex(),
type: colorScheme.ramps.cyan(0.5).hex(),
constructor: colorScheme.ramps.blue(0.5).hex(),
variant: colorScheme.ramps.blue(0.5).hex(),
property: colorScheme.ramps.blue(0.5).hex(),
enum: colorScheme.ramps.orange(0.5).hex(),
operator: colorScheme.ramps.orange(0.5).hex(),
number: colorScheme.ramps.green(0.5).hex(),
boolean: colorScheme.ramps.green(0.5).hex(),
constant: colorScheme.ramps.green(0.5).hex(),
keyword: colorScheme.ramps.blue(0.5).hex(),
}
// Then assign colors and use Syntax to enforce each style getting it's own color
const defaultSyntax: Syntax = {
...syntax,
comment: {
color: color.comment,
},
"comment.doc": {
color: color.comment,
},
primary: {
color: color.primary,
},
predictive: {
color: color.predictive,
},
emphasis: {
color: color.emphasis,
},
"emphasis.strong": {
color: color.emphasis,
weight: fontWeights.bold,
},
title: {
color: color.primary,
weight: fontWeights.bold,
},
linkUri: {
color: colorScheme.ramps.green(0.5).hex(),
underline: true,
},
linkText: {
color: colorScheme.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: colorScheme.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: colorScheme.ramps.blue(0.5).hex(),
},
variant: {
color: colorScheme.ramps.blue(0.5).hex(),
},
type: {
color: color.type,
},
"type.builtin": {
color: color.type,
},
variable: {
color: color.primary,
},
"variable.builtin": {
color: colorScheme.ramps.blue(0.5).hex(),
},
"variable.special": {
color: colorScheme.ramps.blue(0.7).hex(),
},
label: {
color: colorScheme.ramps.blue(0.5).hex(),
},
tag: {
color: colorScheme.ramps.blue(0.5).hex(),
},
attribute: {
color: colorScheme.ramps.blue(0.5).hex(),
},
property: {
color: colorScheme.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,
},
"constant.builtin": {
color: color.constant,
},
function: {
color: color.function,
},
"function.builtin": {
color: color.function,
},
"function.call": {
color: color.function,
},
"function.definition": {
color: color.function,
},
"function.special.definition": {
color: color.function,
},
"function.method": {
color: color.function,
},
"function.method.builtin": {
color: color.function,
},
preproc: {
color: color.primary,
},
embedded: {
color: color.primary,
},
}
console.log(JSON.stringify(defaultSyntax, null, 2))
return defaultSyntax
}
function mergeSyntax(defaultSyntax: Syntax, colorScheme: ColorScheme): Syntax {
if (!colorScheme.syntax) {
return defaultSyntax
}
return deepmerge<Syntax, Partial<ThemeSyntax>>(
defaultSyntax,
colorScheme.syntax,
{
arrayMerge: (destinationArray, sourceArray) => [
...destinationArray,
...sourceArray,
],
}
)
}
export function buildSyntax(colorScheme: ColorScheme): Syntax {
const defaultSyntax: Syntax = buildDefaultSyntax(colorScheme)
const syntax = mergeSyntax(defaultSyntax, colorScheme)
return syntax
}

View file

@ -1,4 +1,5 @@
import chroma from "chroma-js"
import { fontWeights } from "../common"
import { Meta, ThemeSyntax } from "./common/colorScheme"
import { colorRamp, createColorScheme } from "./common/ramps"
@ -8,6 +9,7 @@ const color = {
white: "#ACB2BE",
grey: "#5D636F",
red: "#D07277",
darkRed: "#B1574B",
orange: "#C0966B",
yellow: "#DFC184",
green: "#A1C181",
@ -40,17 +42,27 @@ const ramps = {
}
const syntax: ThemeSyntax = {
primary: { color: color.white },
comment: { color: color.grey },
function: { color: color.blue },
type: { color: color.teal },
property: { color: color.red },
number: { color: color.orange },
string: { color: color.green },
keyword: { color: color.purple },
boolean: { color: color.orange },
punctuation: { color: color.white },
comment: { color: color.grey },
enum: { color: color.red },
"emphasis.strong": { color: color.orange },
function: { color: color.blue },
keyword: { color: color.purple },
linkText: { color: color.blue, italic: false },
linkUri: { color: color.teal },
number: { color: color.orange },
operator: { color: color.teal },
primary: { color: color.white },
property: { color: color.red },
punctuation: { color: color.white },
"punctuation.list_marker": { color: color.red },
"punctuation.special": { color: color.darkRed },
string: { color: color.green },
title: { color: color.red, weight: fontWeights.normal },
"text.literal": { color: color.green },
type: { color: color.teal },
"variable.special": { color: color.orange },
variant: { color: color.blue },
}
export const dark = createColorScheme(name, false, ramps, syntax)

View file

@ -9,6 +9,7 @@ const color = {
black: "#383A41",
grey: "#A2A3A7",
red: "#D36050",
darkRed: "#B92C46",
orange: "#AD6F26",
yellow: "#DFC184",
green: "#659F58",
@ -42,26 +43,27 @@ const ramps = {
}
const syntax: ThemeSyntax = {
primary: { color: color.black },
"variable.special": { color: color.orange },
comment: { color: color.grey },
punctuation: { color: color.black },
keyword: { color: color.purple },
function: { color: color.blue },
type: { color: color.teal },
variant: { color: color.blue },
property: { color: color.red },
enum: { color: color.red },
operator: { color: color.teal },
string: { color: color.green },
number: { color: color.orange },
boolean: { color: color.orange },
title: { color: color.red, weight: fontWeights.normal },
"emphasis.strong": {
color: color.orange,
},
comment: { color: color.grey },
enum: { color: color.red },
"emphasis.strong": { color: color.orange },
function: { color: color.blue },
keyword: { color: color.purple },
linkText: { color: color.blue },
linkUri: { color: color.teal },
number: { color: color.orange },
operator: { color: color.teal },
primary: { color: color.black },
property: { color: color.red },
punctuation: { color: color.black },
"punctuation.list_marker": { color: color.red },
"punctuation.special": { color: color.darkRed },
string: { color: color.green },
title: { color: color.red, weight: fontWeights.normal },
"text.literal": { color: color.green },
type: { color: color.teal },
"variable.special": { color: color.orange },
variant: { color: color.blue },
}
export const light = createColorScheme(name, true, ramps, syntax)

View file

@ -27,7 +27,7 @@ const ramps = {
magenta: colorRamp(chroma("#79549F")),
}
export const light = createColorScheme(`${name}`, true, ramps)
export const light = createColorScheme(name, true, ramps)
export const meta: Meta = {
name,

View file

@ -27,7 +27,7 @@ const ramps = {
magenta: colorRamp(chroma("#AB6FE9")),
}
export const dark = createColorScheme(`${name}`, false, ramps)
export const dark = createColorScheme(name, false, ramps)
export const meta: Meta = {
name,

View file

@ -25,7 +25,7 @@ const ramps = {
magenta: colorRamp(chroma("#AB6FE9")),
}
export const dark = createColorScheme(`${name}`, false, ramps)
export const dark = createColorScheme(name, false, ramps)
export const meta: Meta = {
name,

View file

@ -25,7 +25,7 @@ const ramps = {
magenta: colorRamp(chroma("#a87322")),
}
export const dark = createColorScheme(`${name}`, false, ramps)
export const dark = createColorScheme(name, false, ramps)
export const meta: Meta = {
name,

View file

@ -9,7 +9,7 @@ const license = {
url: "",
}
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#1b0d05",
"#2c1e18",

View file

@ -9,7 +9,7 @@ const license = {
url: "https://github.com/dracula/dracula-theme/blob/master/LICENSE",
}
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#282A36",
"#3a3c4e",

View file

@ -10,7 +10,7 @@ const license = {
}
// `name-[light|dark]`, isLight, color ramps
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#272822",
"#383830",

View file

@ -10,7 +10,7 @@ const license = {
}
// `name-[light|dark]`, isLight, color ramps
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#2E3440",
"#3B4252",

View file

@ -10,7 +10,7 @@ const license = {
}
// `name-[light|dark]`, isLight, color ramps
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#151718",
"#262B30",

View file

@ -10,7 +10,7 @@ const license = {
}
// `name-[light|dark]`, isLight, color ramps
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#24283B",
"#16161E",

View file

@ -9,8 +9,7 @@ const license = {
url: "",
}
// `name-[light|dark]`, isLight, color ramps
export const dark = createColorScheme(`${name}`, false, {
export const dark = createColorScheme(name, false, {
neutral: chroma.scale([
"#383838",
"#404040",

View file

@ -27,7 +27,7 @@ const ramps = {
magenta: colorRamp(chroma("#F69BE7")),
}
export const dark = createColorScheme(`${name}`, false, ramps)
export const dark = createColorScheme(name, false, ramps)
export const meta: Meta = {
name,
author: "zoefiri",