Lua: tweaks and fixes
parent
6f3d021da7
commit
236b2a7fdd
|
@ -315,6 +315,11 @@ export class LuaTable implements ILuaSettable, ILuaGettable {
|
|||
return this.arrayPart.length;
|
||||
}
|
||||
|
||||
hasKeys(): boolean {
|
||||
return !!(Object.keys(this.stringKeys).length > 0 ||
|
||||
this.arrayPart.length > 0 || (this.otherKeys && this.otherKeys.size > 0));
|
||||
}
|
||||
|
||||
keys(): any[] {
|
||||
const keys: any[] = Object.keys(this.stringKeys);
|
||||
for (let i = 0; i < this.arrayPart.length; i++) {
|
||||
|
@ -695,7 +700,7 @@ export function luaTruthy(value: any): boolean {
|
|||
return false;
|
||||
}
|
||||
if (value instanceof LuaTable) {
|
||||
return value.length > 0;
|
||||
return value.hasKeys();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -773,6 +778,17 @@ export function jsToLuaValue(value: any): any {
|
|||
return value;
|
||||
} else if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
|
||||
return value;
|
||||
} else if (Array.isArray(value) && "index" in value && "input" in value) {
|
||||
// This is a RegExpMatchArray
|
||||
const regexMatch = value as RegExpMatchArray;
|
||||
const regexMatchTable = new LuaTable();
|
||||
for (let i = 0; i < regexMatch.length; i++) {
|
||||
regexMatchTable.set(i + 1, regexMatch[i]);
|
||||
}
|
||||
regexMatchTable.set("index", regexMatch.index);
|
||||
regexMatchTable.set("input", regexMatch.input);
|
||||
regexMatchTable.set("groups", regexMatch.groups);
|
||||
return regexMatchTable;
|
||||
} else if (Array.isArray(value)) {
|
||||
const table = new LuaTable();
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
jsToLuaValue,
|
||||
LuaBuiltinFunction,
|
||||
luaCall,
|
||||
LuaMultiRes,
|
||||
|
@ -213,4 +214,13 @@ export const stringApi = new LuaTable({
|
|||
trim_end: new LuaBuiltinFunction((_sf, s: string) => {
|
||||
return s.trimEnd();
|
||||
}),
|
||||
match_regex: new LuaBuiltinFunction((_sf, s: string, pattern: string) => {
|
||||
const regex = new RegExp(pattern);
|
||||
const result = s.match(regex);
|
||||
return jsToLuaValue(result);
|
||||
// if (!result) {
|
||||
// return new LuaMultiRes([]);
|
||||
// }
|
||||
// return new LuaMultiRes(result.slice(1));
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
type ILuaFunction,
|
||||
LuaBuiltinFunction,
|
||||
type LuaEnv,
|
||||
luaEquals,
|
||||
LuaRuntimeError,
|
||||
LuaTable,
|
||||
|
@ -17,7 +18,10 @@ export const tableApi = new LuaTable({
|
|||
* @returns The concatenated string.
|
||||
*/
|
||||
concat: new LuaBuiltinFunction(
|
||||
(_sf, tbl: LuaTable, sep?: string, i?: number, j?: number) => {
|
||||
(_sf, tbl: LuaTable | any[], sep?: string, i?: number, j?: number) => {
|
||||
if (Array.isArray(tbl)) {
|
||||
return tbl.join(sep);
|
||||
}
|
||||
sep = sep ?? "";
|
||||
i = i ?? 1;
|
||||
j = j ?? tbl.length;
|
||||
|
@ -70,7 +74,8 @@ export const tableApi = new LuaTable({
|
|||
* @param tbl - The table to get the keys from.
|
||||
* @returns The keys of the table.
|
||||
*/
|
||||
keys: new LuaBuiltinFunction((_sf, tbl: LuaTable) => {
|
||||
keys: new LuaBuiltinFunction((_sf, tbl: LuaTable | LuaEnv) => {
|
||||
console.log("Keys", tbl);
|
||||
return tbl.keys();
|
||||
}),
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,7 @@ export function commandSyscalls(
|
|||
const sf = new LuaStackFrame(tl, null);
|
||||
try {
|
||||
return luaValueToJS(
|
||||
await luaCall(def.run, args.map(jsToLuaValue), sf),
|
||||
await luaCall(def.run, args.map(jsToLuaValue), {}, sf),
|
||||
);
|
||||
} catch (e: any) {
|
||||
await handleLuaError(e, commonSystem.system);
|
||||
|
@ -60,7 +60,7 @@ export function commandSyscalls(
|
|||
const sf = new LuaStackFrame(tl, null);
|
||||
try {
|
||||
return luaValueToJS(
|
||||
await luaCall(def.run, args.map(jsToLuaValue), sf),
|
||||
await luaCall(def.run, args.map(jsToLuaValue), {}, sf),
|
||||
);
|
||||
} catch (e: any) {
|
||||
await handleLuaError(e, commonSystem.system);
|
||||
|
|
|
@ -35,9 +35,10 @@ export function eventListenerSyscalls(
|
|||
);
|
||||
const sf = new LuaStackFrame(tl, null);
|
||||
try {
|
||||
return luaValueToJS(
|
||||
await luaCall(def.run, args.map(jsToLuaValue), sf),
|
||||
const val = luaValueToJS(
|
||||
await luaCall(def.run, args.map(jsToLuaValue), {}, sf),
|
||||
);
|
||||
return val;
|
||||
} catch (e: any) {
|
||||
await handleLuaError(e, commonSystem.system);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ export type SlashCommandDef = {
|
|||
name: string;
|
||||
description?: string;
|
||||
boost?: number;
|
||||
// Parent AST nodes in which this slash command is available
|
||||
contexts?: string[];
|
||||
};
|
||||
export type SlashCommandHookT = {
|
||||
slashCommand?: SlashCommandDef;
|
||||
|
|
|
@ -19,7 +19,7 @@ function config.set(key, value)
|
|||
error("Config key not defined: " .. key)
|
||||
end
|
||||
if schema != true then
|
||||
result = jsonschema.validate_object(schema, value)
|
||||
local result = jsonschema.validate_object(schema, value)
|
||||
if result != nil then
|
||||
error("Validation error (" .. key .. "): " .. result)
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ import type {
|
|||
CompletionContext,
|
||||
CompletionResult,
|
||||
} from "@codemirror/autocomplete";
|
||||
import type { Compartment } from "@codemirror/state";
|
||||
import type { Compartment, EditorState } from "@codemirror/state";
|
||||
import { EditorView } from "@codemirror/view";
|
||||
import { syntaxTree } from "@codemirror/language";
|
||||
import { compile as gitIgnoreCompiler } from "gitignore-parser";
|
||||
|
@ -892,21 +892,13 @@ export class Client implements ConfigContainer {
|
|||
const linePrefix = line.text.slice(0, selection.from - line.from);
|
||||
|
||||
// Build up list of parent nodes, some completions need this
|
||||
const parentNodes: string[] = [];
|
||||
const sTree = syntaxTree(editorState);
|
||||
const currentNode = sTree.resolveInner(selection.from);
|
||||
if (currentNode) {
|
||||
let node: SyntaxNode | null = currentNode;
|
||||
do {
|
||||
if (node.name === "FencedCode" || node.name === "FrontMatter") {
|
||||
const body = editorState.sliceDoc(node.from + 3, node.to - 3);
|
||||
parentNodes.push(`${node.name}:${body}`);
|
||||
} else {
|
||||
parentNodes.push(node.name);
|
||||
}
|
||||
node = node.parent;
|
||||
} while (node);
|
||||
}
|
||||
const currentNode = sTree.resolveInner(editorState.selection.main.from);
|
||||
|
||||
const parentNodes: string[] = this.extractParentNodes(
|
||||
editorState,
|
||||
currentNode,
|
||||
);
|
||||
|
||||
// Dispatch the event
|
||||
const results = await this.dispatchAppEvent(eventName, {
|
||||
|
@ -949,6 +941,23 @@ export class Client implements ConfigContainer {
|
|||
return currentResult;
|
||||
}
|
||||
|
||||
public extractParentNodes(editorState: EditorState, currentNode: SyntaxNode) {
|
||||
const parentNodes: string[] = [];
|
||||
if (currentNode) {
|
||||
let node: SyntaxNode | null = currentNode;
|
||||
do {
|
||||
if (node.name === "FencedCode" || node.name === "FrontMatter") {
|
||||
const body = editorState.sliceDoc(node.from + 3, node.to - 3);
|
||||
parentNodes.push(`${node.name}:${body}`);
|
||||
} else {
|
||||
parentNodes.push(node.name);
|
||||
}
|
||||
node = node.parent;
|
||||
} while (node);
|
||||
}
|
||||
return parentNodes;
|
||||
}
|
||||
|
||||
editorComplete(
|
||||
context: CompletionContext,
|
||||
): Promise<CompletionResult | null> {
|
||||
|
|
|
@ -108,7 +108,17 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
|
|||
return null;
|
||||
}
|
||||
|
||||
// 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(
|
||||
(context) => parentNodes.some((node) => node.startsWith(context)),
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
options.push({
|
||||
label: def.slashCommand.name,
|
||||
detail: def.slashCommand.description,
|
||||
|
|
Loading…
Reference in New Issue