You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
2.8 KiB
TypeScript
119 lines
2.8 KiB
TypeScript
import { Face, Color, } from "../util/colors.ts"
|
|
import { Syntax } from "../util/syntax.ts";
|
|
import { ensureDir } from "../util/fs.ts";
|
|
|
|
export interface Theme {
|
|
name: string,
|
|
faces: Faces,
|
|
}
|
|
|
|
const ts = (s: string) => `tree-sitter-hl-face:${s}`;
|
|
const fl = (s: string) => `font-lock-${s}-face`;
|
|
const syntaxToFaceName: Record<keyof Syntax, string> = {
|
|
attribute: ts("attribute"),
|
|
argumentType: ts("type.argument"),
|
|
builtinConstant: ts("constant.builtin"),
|
|
builtinFunction: ts("function.builtin"),
|
|
builtinType: ts("type.builtin"),
|
|
builtinVariable: ts("variable.builtin"),
|
|
comment: fl("comment"),
|
|
constant: fl("constant"),
|
|
constructor_: ts("constructor"),
|
|
documentaton: fl("doc"),
|
|
embedded: ts("embedded"),
|
|
escape: ts("escape"),
|
|
function: fl("function-name"),
|
|
functionCall: ts("function.call"),
|
|
keyword: fl("keyword"),
|
|
label: ts("label"),
|
|
macro: ts("macro"),
|
|
method: ts("method"),
|
|
methodCall: ts("method.call"),
|
|
number: ts("number"),
|
|
operator: ts("operator"),
|
|
parameter: ts("parameter"),
|
|
property: ts("property"),
|
|
propertyDefinition: ts("property.definition"),
|
|
punctuation: ts("punctuation"),
|
|
punctuationBracket: ts("punctuation.bracket"),
|
|
punctuationSpecial: ts("punctuation.special"),
|
|
punctuationDelimiter: ts("punctuation.delimiter"),
|
|
specialFunction: ts("function.special"),
|
|
specialString: ts("string.special"),
|
|
specialVariable: ts("variable.special"),
|
|
string: fl("string"),
|
|
super: ts("super"),
|
|
tag: ts("tag"),
|
|
type: fl("type"),
|
|
typeParameter: ts("type.parameter"),
|
|
variable: fl("variable-name"),
|
|
};
|
|
export const createTheme = (
|
|
name: string,
|
|
fi: FacesInput,
|
|
s: Partial<Syntax>,
|
|
) => {
|
|
const faces = Object.entries(syntaxToFaceName).reduce((faces, [sn, fn]) => {
|
|
const sn_ = sn as keyof Syntax;
|
|
const c = s[sn_];
|
|
if (!c) {
|
|
faces[fn] = fi.default;
|
|
return faces;
|
|
}
|
|
|
|
faces[fn] = c;
|
|
return faces;
|
|
}, {} as Record<string, Face>);
|
|
Object.assign(faces, fi);
|
|
|
|
return {
|
|
name,
|
|
faces,
|
|
};
|
|
}
|
|
|
|
export type Faces = Record<string, Face>;
|
|
export type FacesInput = Faces & {
|
|
default: Face,
|
|
};
|
|
|
|
const themeToString = (theme: Theme) => {
|
|
let s = `
|
|
(deftheme ${theme.name} "${theme.name}")
|
|
(custom-theme-set-faces
|
|
'${theme.name}
|
|
`;
|
|
for (const [name, face] of Object.entries(theme.faces)) {
|
|
s += ` \`(${name} ((t (`;
|
|
s += faceToString(face);
|
|
s += `))))\n`;
|
|
}
|
|
s += `)\n`;
|
|
|
|
return s;
|
|
}
|
|
|
|
const faceToString = (face: Face) => {
|
|
const t = (name: string, v: string) => `:${name} ${v} `;
|
|
const y = <T>(f: (v: T) => string) => {
|
|
return (n: string, v: T | null) => {
|
|
return v ? t(n, f(v)) : '';
|
|
}
|
|
};
|
|
const c = y((v: Color) => `"${v}"`);
|
|
|
|
let o = '';
|
|
o += c("background", face.bg);
|
|
o += c("foreground", face.fg);
|
|
|
|
return o;
|
|
};
|
|
|
|
export const writeTheme = async (theme: Theme, path: string) => {
|
|
await ensureDir(path);
|
|
|
|
const s = themeToString(theme);
|
|
|
|
return Deno.writeTextFile(path, s);
|
|
};
|