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