silverbullet/plugs/template/var.ts

66 lines
1.7 KiB
TypeScript
Raw Normal View History

import { CompleteEvent } from "$sb/app_event.ts";
import { datastore, events } from "$sb/syscalls.ts";
import {
AttributeCompleteEvent,
AttributeCompletion,
} from "../index/attributes.ts";
import { attributeCompletionsToCMCompletion } from "./snippet.ts";
export async function templateVariableComplete(completeEvent: CompleteEvent) {
// Check if we're in a query, block or template context
const fencedParent = completeEvent.parentNodes.find((node) =>
node.startsWith("FencedCode:query") ||
node.startsWith("FencedCode:template")
);
if (!fencedParent) {
return null;
}
const match = /(@|[^\{]\{\{)(\w*)$/.exec(completeEvent.linePrefix);
if (!match) {
return null;
}
let allCompletions: any[] = [];
if (match[1] !== "@") {
// Not a variable
// Function completions
const builtinFunctions = await datastore.listFunctions();
allCompletions = builtinFunctions.map((name) => ({
label: name,
detail: "function",
}));
// Attribute completions
const completions = (await events.dispatchEvent(
`attribute:complete:_`,
{
source: "",
prefix: match[2],
} as AttributeCompleteEvent,
)).flat() as AttributeCompletion[];
allCompletions = allCompletions.concat(
attributeCompletionsToCMCompletion(completions),
);
}
const allVariables = [...fencedParent.match(/@(\w+)/g) || []];
allVariables.push("@page");
allCompletions = allCompletions.concat(
allVariables.filter((v) => v !== match[0]).map((key) => ({
label: key,
apply: key.substring(1),
detail: "variable",
})),
);
return {
from: completeEvent.pos - match[2].length,
options: allCompletions,
};
}