Context sensitive slashCommands (with onlyContexts and exceptContexts)

main
Zef Hemel 2025-01-26 07:35:41 +01:00
parent 236b2a7fdd
commit a28c3fd5b8
20 changed files with 95 additions and 23 deletions

View File

@ -53,8 +53,10 @@ export type SlashCommandDef = {
name: string;
description?: string;
boost?: number;
// Parent AST nodes in which this slash command is available
contexts?: string[];
// Parent AST nodes in which this slash command is available, defaults to everywhere
onlyContexts?: string[];
// Parent AST nodes in which this slash command is not available
exceptContexts?: string[];
};
export type SlashCommandHookT = {
slashCommand?: SlashCommandDef;

View File

@ -29,20 +29,37 @@ export async function snippetSlashComplete(
// where hooks.snippet.slashCommand exists
filter: ["attr", ["attr", ["attr", "hooks"], "snippet"], "slashCommand"],
}, 5);
return {
options: allTemplates.map((template) => {
const snippetTemplate = template.hooks!.snippet!;
const options: SlashCompletionOption[] = [];
for (const template of allTemplates) {
const snippetTemplate = template.hooks!.snippet!;
return {
label: snippetTemplate.slashCommand,
detail: template.description,
order: snippetTemplate.order || 0,
templatePage: template.ref,
pageName: completeEvent.pageName,
invoke: "template.insertSnippetTemplate",
};
}),
};
if (
snippetTemplate.onlyContexts && !snippetTemplate.onlyContexts.some(
(context) =>
completeEvent.parentNodes.some((node) => node.startsWith(context)),
)
) {
continue;
}
if (
snippetTemplate.exceptContexts && snippetTemplate.exceptContexts.some(
(context) =>
completeEvent.parentNodes.some((node) => node.startsWith(context)),
)
) {
continue;
}
options.push({
label: snippetTemplate.slashCommand,
detail: template.description,
order: snippetTemplate.order || 0,
templatePage: template.ref,
pageName: completeEvent.pageName,
invoke: "template.insertSnippetTemplate",
});
}
return { options };
}
export async function insertSnippetTemplate(

View File

@ -31,6 +31,8 @@ export type SnippetConfig = CommandConfig & {
// Deprecated: use matchRegex instead (for backwards compatibility)
match?: string;
insertAt?: "cursor" | "line-start" | "line-end" | "page-start" | "page-end"; // defaults to cursor
onlyContexts?: string[];
exceptContexts?: string[];
};
export type WidgetConfig = {
@ -97,6 +99,12 @@ export const SnippetConfigSchema: JSONSchemaType<SnippetConfig> = {
order: { type: "number", nullable: true },
matchRegex: { type: "string", nullable: true },
match: { type: "string", nullable: true },
onlyContexts: { type: "array", items: { type: "string" }, nullable: true },
exceptContexts: {
type: "array",
items: { type: "string" },
nullable: true,
},
insertAt: {
type: "string",
enum: [

View File

@ -110,10 +110,16 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
// Check if the slash command is available in the current context
const parentNodes = this.editor.extractParentNodes(ctx.state, currentNode);
// console.log("Parent nodes", parentNodes);
for (const def of this.slashCommands.values()) {
if (
def.slashCommand.contexts && !def.slashCommand.contexts.some(
def.slashCommand.onlyContexts && !def.slashCommand.onlyContexts.some(
(context) => parentNodes.some((node) => node.startsWith(context)),
)
) {
continue;
}
if (
def.slashCommand.exceptContexts && def.slashCommand.exceptContexts.some(
(context) => parentNodes.some((node) => node.startsWith(context)),
)
) {

View File

@ -1,7 +1,10 @@
---
description: Insert a fenced code block
tags: template
hooks.snippet.slashCommand: code
hooks.snippet:
slashCommand: code
exceptContexts:
- FencedCode
---
```|^|

View File

@ -4,6 +4,8 @@ tags: template
hooks.snippet:
slashCommand: "#each"
order: 10
onlyContexts:
- FencedCode:template
---
{{escapeDirective("#each |^|")}}

View File

@ -4,5 +4,7 @@ description: Make this a level 1 heading
hooks.snippet:
slashCommand: h1
matchRegex: "^#*\\s*"
exceptContexts:
- FencedCode
---
#

View File

@ -4,5 +4,7 @@ description: Make this a level 2 heading
hooks.snippet:
slashCommand: h2
matchRegex: "^#*\\s*"
exceptContexts:
- FencedCode
---
##

View File

@ -4,5 +4,7 @@ description: Make this a level 3 heading
hooks.snippet:
slashCommand: h3
matchRegex: "^#*\\s*"
exceptContexts:
- FencedCode
---
###

View File

@ -4,5 +4,7 @@ description: Make this a level 4 heading
hooks.snippet:
slashCommand: h4
matchRegex: "^#*\\s*"
exceptContexts:
- FencedCode
---
####

View File

@ -1,6 +1,9 @@
---
tags: template
description: Insert a horizontal rule
hooks.snippet.slashCommand: hr
hooks.snippet:
slashCommand: hr
exceptContexts:
- FencedCode
---
---

View File

@ -4,6 +4,9 @@ tags: template
hooks.snippet:
slashCommand: "#if"
order: 10
onlyContexts:
- FencedCode:template
---
{{escapeDirective("#if |^|")}}

View File

@ -4,6 +4,8 @@ tags: template
hooks.snippet:
slashCommand: "#if-else"
order: 10
onlyContexts:
- FencedCode:template
---
{{escapeDirective("#if |^|")}}

View File

@ -1,7 +1,10 @@
---
tags: template
description: Add a live preview of a page
hooks.snippet.slashCommand: include-page
hooks.snippet:
slashCommand: include-page
exceptContexts:
- FencedCode
---
```include
raw: "[[|^|]]"

View File

@ -6,5 +6,7 @@ hooks.snippet:
matchRegex: "^(\\s*)[\\-\\*]?\\s*"
command: "Text: Turn into a bullet item"
key: "Ctrl-q i"
exceptContexts:
- FencedCode
---
$1*

View File

@ -4,6 +4,8 @@ tags: template
hooks.snippet:
slashCommand: "#let"
order: 10
onlyContexts:
- FencedCode:template
---
{{escapeDirective("#let @|^| = ")}}

View File

@ -1,7 +1,10 @@
---
description: Insert a live query
tags: template
hooks.snippet.slashCommand: query
hooks.snippet:
slashCommand: query
exceptContexts:
- FencedCode
---
```query
|^|

View File

@ -1,7 +1,10 @@
---
tags: template
description: Insert a table
hooks.snippet.slashCommand: table
hooks.snippet:
slashCommand: table
exceptContexts:
- FencedCode
---
| Header A | Header B |
|----------|----------|

View File

@ -6,5 +6,7 @@ hooks.snippet:
matchRegex: "^(\\s*)[\\-\\*]?\\s*(\\[[ xX]\\])?\\s*"
command: "Text: Turn into task"
key: "Ctrl-q t"
exceptContexts:
- FencedCode
---
$1* [ ]

View File

@ -1,7 +1,10 @@
---
description: Insert a template
tags: template
hooks.snippet.slashCommand: "template"
hooks.snippet:
slashCommand: "template"
exceptContexts:
- FencedCode
---
```template
|^|