Custom template slash commands

This commit is contained in:
Zef Hemel
2023-11-06 09:14:16 +01:00
parent 0e2a802bbd
commit 1afac0274e
16 changed files with 214 additions and 79 deletions
+9 -2
View File
@@ -624,7 +624,7 @@ export class Client {
}
// Code completion support
private async completeWithEvent(
async completeWithEvent(
context: CompletionContext,
eventName: AppEvent,
): Promise<CompletionResult | null> {
@@ -761,7 +761,14 @@ export class Client {
console.log("Page doesn't exist, creating new page:", pageName);
doc = {
text: "",
meta: { name: pageName, lastModified: 0, perm: "rw" } as PageMeta,
meta: {
ref: pageName,
tags: ["page"],
name: pageName,
lastModified: "",
created: "",
perm: "rw",
} as PageMeta,
};
} else {
this.flashNotification(
+46 -2
View File
@@ -4,6 +4,7 @@ import { Completion, CompletionContext, CompletionResult } from "../deps.ts";
import { safeRun } from "../../common/util.ts";
import { Client } from "../client.ts";
import { syntaxTree } from "../deps.ts";
import { SlashCompletion } from "$sb/app_event.ts";
export type SlashCommandDef = {
name: string;
@@ -53,9 +54,9 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
}
// Completer for CodeMirror
public slashCommandCompleter(
public async slashCommandCompleter(
ctx: CompletionContext,
): CompletionResult | null {
): Promise<CompletionResult | null> {
const prefix = ctx.matchBefore(slashCommandRegexp);
if (!prefix) {
return null;
@@ -68,6 +69,7 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
if (currentNode.type.name === "CommentBlock") {
return null;
}
for (const def of this.slashCommands.values()) {
options.push({
label: def.slashCommand.name,
@@ -90,6 +92,48 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
},
});
}
const slashCompletions: SlashCompletion[] | null = await this.editor
.completeWithEvent(
ctx,
"slash:complete",
) as any;
if (slashCompletions) {
for (const slashCompletion of slashCompletions) {
options.push({
label: slashCompletion.label,
detail: slashCompletion.detail,
apply: () => {
// Delete slash command part
this.editor.editorView.dispatch({
changes: {
from: prefix!.from + prefixText.indexOf("/"),
to: ctx.pos,
insert: "",
},
});
// Replace with whatever the completion is
safeRun(async () => {
const [plugName, functionName] = slashCompletion.invoke.split(
".",
);
const plug = this.editor.system.system.loadedPlugs.get(plugName);
if (!plug) {
this.editor.flashNotification(
`Plug ${plugName} not found`,
"error",
);
return;
}
await plug.invoke(functionName, [slashCompletion]);
this.editor.focus();
});
},
});
}
}
return {
// + 1 because of the '/'
from: prefix.from + prefixText.indexOf("/") + 1,
+6 -1
View File
@@ -221,8 +221,13 @@ export class Space {
}
export function fileMetaToPageMeta(fileMeta: FileMeta): PageMeta {
const name = fileMeta.name.substring(0, fileMeta.name.length - 3);
return {
...fileMeta,
name: fileMeta.name.substring(0, fileMeta.name.length - 3),
ref: name,
tags: ["page"],
name,
created: new Date(fileMeta.created).toISOString(),
lastModified: new Date(fileMeta.lastModified).toISOString(),
} as PageMeta;
}