silverbullet/plugs/template/var.ts

92 lines
2.3 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";
2024-02-04 23:36:59 +08:00
export async function templateAttributeComplete(completeEvent: CompleteEvent) {
// Check if we're in a query, block or template context
const fencedParent = completeEvent.parentNodes.find((node) =>
node.startsWith("FencedCode:template")
);
if (!fencedParent) {
return null;
}
2024-02-04 23:36:59 +08:00
const attributeMatch = /(^|[^{])\{\{(\w*)$/.exec(completeEvent.linePrefix);
if (!attributeMatch) {
return null;
}
let allCompletions: any[] = [];
2024-02-04 23:36:59 +08:00
// Function completions
const functions = await datastore.listFunctions();
allCompletions = functions.map((name) => ({
label: name,
apply: name,
2024-02-04 23:36:59 +08:00
detail: "function",
}));
2024-02-04 23:36:59 +08:00
// Attribute completions
const completions = (await events.dispatchEvent(
`attribute:complete:_`,
{
source: "",
prefix: attributeMatch[2],
} as AttributeCompleteEvent,
)).flat() as AttributeCompletion[];
2024-02-04 23:36:59 +08:00
allCompletions = allCompletions.concat(
attributeCompletionsToCMCompletion(completions),
);
return {
from: completeEvent.pos - attributeMatch[2].length,
options: allCompletions,
};
}
export function templateVariableComplete(completeEvent: CompleteEvent) {
// Check if we're in a query, block or template context
const fencedParent = completeEvent.parentNodes.find((node) =>
node.startsWith("FencedCode:template")
);
if (!fencedParent) {
return null;
}
// Find a @ inside of a {{
const variableMatch = /\{\{[^}]*@(\w*)$/.exec(completeEvent.linePrefix);
if (!variableMatch) {
return null;
}
let allCompletions: any[] = [];
const regexp = /\s+@(\w+)\s+(=|in)\s+/g;
const allVariables = new Set<string>();
const matches = fencedParent.matchAll(regexp);
for (const match of matches) {
allVariables.add(match[1]);
}
2024-02-04 23:36:59 +08:00
allVariables.add("page");
allCompletions = allCompletions.concat(
2024-02-04 23:36:59 +08:00
[...allVariables].map((key) => ({
label: `@${key}`,
apply: key,
detail: "variable",
})),
);
return {
2024-02-04 23:36:59 +08:00
from: completeEvent.pos - variableMatch[1].length,
options: allCompletions,
};
}