mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
add callable closure vars
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import { substituteParams } from '../../script.js';
|
import { substituteParams } from '../../script.js';
|
||||||
|
import { SlashCommandClosureExecutor } from './SlashCommandClosureExecutor.js';
|
||||||
import { SlashCommandClosureResult } from './SlashCommandClosureResult.js';
|
import { SlashCommandClosureResult } from './SlashCommandClosureResult.js';
|
||||||
import { SlashCommandExecutor } from './SlashCommandExecutor.js';
|
import { SlashCommandExecutor } from './SlashCommandExecutor.js';
|
||||||
import { SlashCommandScope } from './SlashCommandScope.js';
|
import { SlashCommandScope } from './SlashCommandScope.js';
|
||||||
@ -10,7 +11,7 @@ export class SlashCommandClosure {
|
|||||||
/**@type {Map<string,string|SlashCommandClosure>}*/ arguments = {};
|
/**@type {Map<string,string|SlashCommandClosure>}*/ arguments = {};
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
/**@type {Map<string,string|SlashCommandClosure>}*/ providedArguments = {};
|
/**@type {Map<string,string|SlashCommandClosure>}*/ providedArguments = {};
|
||||||
/**@type {SlashCommandExecutor[]}*/ executorList = [];
|
/**@type {(SlashCommandExecutor|SlashCommandClosureExecutor)[]}*/ executorList = [];
|
||||||
/**@type {String}*/ keptText;
|
/**@type {String}*/ keptText;
|
||||||
|
|
||||||
constructor(parent) {
|
constructor(parent) {
|
||||||
@ -39,6 +40,10 @@ export class SlashCommandClosure {
|
|||||||
return closure;
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns Promise<SlashCommandClosureResult>
|
||||||
|
*/
|
||||||
async execute() {
|
async execute() {
|
||||||
const closure = this.getCopy();
|
const closure = this.getCopy();
|
||||||
return await closure.executeDirect();
|
return await closure.executeDirect();
|
||||||
@ -98,6 +103,15 @@ export class SlashCommandClosure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const executor of this.executorList) {
|
for (const executor of this.executorList) {
|
||||||
|
if (executor instanceof SlashCommandClosureExecutor) {
|
||||||
|
const closure = this.scope.getVariable(executor.name);
|
||||||
|
if (!closure || !(closure instanceof SlashCommandClosure)) throw new Error(`${name} is not a closure.`);
|
||||||
|
closure.scope.parent = this.scope;
|
||||||
|
closure.providedArguments = executor.providedArguments;
|
||||||
|
const result = await closure.execute();
|
||||||
|
this.scope.pipe = result.pipe;
|
||||||
|
interrupt = result.interrupt;
|
||||||
|
} else {
|
||||||
interrupt = executor.command.interruptsGeneration;
|
interrupt = executor.command.interruptsGeneration;
|
||||||
let args = {
|
let args = {
|
||||||
_scope: this.scope,
|
_scope: this.scope,
|
||||||
@ -174,6 +188,9 @@ export class SlashCommandClosure {
|
|||||||
|
|
||||||
this.scope.pipe = await executor.command.callback(args, value);
|
this.scope.pipe = await executor.command.callback(args, value);
|
||||||
}
|
}
|
||||||
return Object.assign(new SlashCommandClosureResult(), { interrupt, newText: this.keptText, pipe: this.scope.pipe });
|
}
|
||||||
|
/**@type {SlashCommandClosureResult} */
|
||||||
|
const result = Object.assign(new SlashCommandClosureResult(), { interrupt, newText: this.keptText, pipe: this.scope.pipe });
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
export class SlashCommandClosureExecutor {
|
||||||
|
/**@type {String}*/ name = '';
|
||||||
|
// @ts-ignore
|
||||||
|
/**@type {Map<string,string|SlashCommandClosure>}*/ providedArguments = {};
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { SlashCommand } from './SlashCommand.js';
|
import { SlashCommand } from './SlashCommand.js';
|
||||||
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
||||||
|
import { SlashCommandClosureExecutor } from './SlashCommandClosureExecutor.js';
|
||||||
import { SlashCommandExecutor } from './SlashCommandExecutor.js';
|
import { SlashCommandExecutor } from './SlashCommandExecutor.js';
|
||||||
import { SlashCommandParserError } from './SlashCommandParserError.js';
|
import { SlashCommandParserError } from './SlashCommandParserError.js';
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
@ -232,6 +233,9 @@ export class SlashCommandParser {
|
|||||||
this.discardWhitespace();
|
this.discardWhitespace();
|
||||||
}
|
}
|
||||||
while (!this.testClosureEnd()) {
|
while (!this.testClosureEnd()) {
|
||||||
|
if (this.testClosureCall()) {
|
||||||
|
closure.executorList.push(this.parseClosureCall());
|
||||||
|
}
|
||||||
if (this.testCommand()) {
|
if (this.testCommand()) {
|
||||||
closure.executorList.push(this.parseCommand());
|
closure.executorList.push(this.parseCommand());
|
||||||
} else {
|
} else {
|
||||||
@ -260,6 +264,37 @@ export class SlashCommandParser {
|
|||||||
return closure;
|
return closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClosureCall() {
|
||||||
|
return this.char == '/'
|
||||||
|
&& this.behind.slice(-1) != '\\'
|
||||||
|
&& !['/', '#'].includes(this.ahead[0])
|
||||||
|
&& /^\S+\(/.test(this.ahead)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
testClosureCallEnd() {
|
||||||
|
return this.char == ')' && this.behind.slice(-1) != '\\';
|
||||||
|
}
|
||||||
|
parseClosureCall() {
|
||||||
|
this.take(); // discard /
|
||||||
|
let name = '';
|
||||||
|
while (!/\s|\(/.test(this.char)) name += this.take(); // take chars until opening (
|
||||||
|
this.take(); // discard opening (
|
||||||
|
const executor = new SlashCommandClosureExecutor();
|
||||||
|
executor.name = name;
|
||||||
|
this.discardWhitespace();
|
||||||
|
while (this.testNamedArgument()) {
|
||||||
|
const arg = this.parseNamedArgument();
|
||||||
|
executor.providedArguments[arg.key] = arg.value;
|
||||||
|
this.discardWhitespace();
|
||||||
|
}
|
||||||
|
if (this.testClosureCallEnd()) {
|
||||||
|
this.take(); // discard closing )
|
||||||
|
return executor;
|
||||||
|
} else {
|
||||||
|
throw new SlashCommandParserError(`Unexpected end of closure call at position ${this.index - 2}`, this.text, this.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
testCommand() {
|
testCommand() {
|
||||||
return this.char == '/' && this.behind.slice(-1) != '\\' && !['/', '#'].includes(this.ahead[0]);
|
return this.char == '/' && this.behind.slice(-1) != '\\' && !['/', '#'].includes(this.ahead[0]);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user