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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

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);
};