better stepping into other scripts, with source indicator
This commit is contained in:
parent
67dfe7354b
commit
75317f3eb4
|
@ -73,13 +73,14 @@ export class QuickReplyApi {
|
|||
* @param {String} setName name of the existing quick reply set
|
||||
* @param {String} label label of the existing quick reply (text on the button)
|
||||
* @param {Object} [args] optional arguments
|
||||
* @param {import('../../../slash-commands.js').ExecuteSlashCommandsOptions} [options] optional execution options
|
||||
*/
|
||||
async executeQuickReply(setName, label, args = {}) {
|
||||
async executeQuickReply(setName, label, args = {}, options = {}) {
|
||||
const qr = this.getQrByLabel(setName, label);
|
||||
if (!qr) {
|
||||
throw new Error(`No quick reply with label "${label}" in set "${setName}" found.`);
|
||||
}
|
||||
return await qr.execute(args);
|
||||
return await qr.execute(args, false, false, options);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ const init = async () => {
|
|||
buttons.show();
|
||||
settings.onSave = ()=>buttons.refresh();
|
||||
|
||||
window['executeQuickReplyByName'] = async(name, args = {}) => {
|
||||
window['executeQuickReplyByName'] = async(name, args = {}, options = {}) => {
|
||||
let qr = [...settings.config.setList, ...(settings.chatConfig?.setList ?? [])]
|
||||
.map(it=>it.set.qrList)
|
||||
.flat()
|
||||
|
@ -191,7 +191,7 @@ const init = async () => {
|
|||
}
|
||||
}
|
||||
if (qr && qr.onExecute) {
|
||||
return await qr.execute(args, false, true);
|
||||
return await qr.execute(args, false, true, options);
|
||||
} else {
|
||||
throw new Error(`No Quick Reply found for "${name}".`);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ export class QuickReply {
|
|||
/**@type {Popup}*/ editorPopup;
|
||||
/**@type {HTMLElement}*/ editorDom;
|
||||
|
||||
/**@type {HTMLTextAreaElement}*/ editorMessage;
|
||||
/**@type {HTMLElement}*/ editorSyntax;
|
||||
/**@type {HTMLElement}*/ editorExecuteBtn;
|
||||
/**@type {HTMLElement}*/ editorExecuteBtnPause;
|
||||
/**@type {HTMLElement}*/ editorExecuteBtnStop;
|
||||
|
@ -500,6 +502,7 @@ export class QuickReply {
|
|||
message.style.setProperty('text-shadow', 'none', 'important');
|
||||
/**@type {HTMLElement}*/
|
||||
const messageSyntaxInner = dom.querySelector('#qr--modal-messageSyntaxInner');
|
||||
this.editorSyntax = messageSyntaxInner;
|
||||
updateSyntax();
|
||||
updateWrap();
|
||||
updateTabSize();
|
||||
|
@ -720,7 +723,7 @@ export class QuickReply {
|
|||
}
|
||||
}
|
||||
|
||||
getEditorPosition(start, end) {
|
||||
getEditorPosition(start, end, message = null) {
|
||||
const inputRect = this.editorMessage.getBoundingClientRect();
|
||||
const style = window.getComputedStyle(this.editorMessage);
|
||||
if (!this.clone) {
|
||||
|
@ -745,21 +748,22 @@ export class QuickReply {
|
|||
this.clone.style.top = `${inputRect.top}px`;
|
||||
this.clone.style.whiteSpace = style.whiteSpace;
|
||||
this.clone.style.tabSize = style.tabSize;
|
||||
const text = this.editorMessage.value;
|
||||
const text = message ?? this.editorMessage.value;
|
||||
const before = text.slice(0, start);
|
||||
this.clone.textContent = before;
|
||||
const locator = document.createElement('span');
|
||||
locator.textContent = text.slice(start, end);
|
||||
this.clone.append(locator);
|
||||
this.clone.append(text.slice(end));
|
||||
this.clone.scrollTop = this.editorMessage.scrollTop;
|
||||
this.clone.scrollLeft = this.editorMessage.scrollLeft;
|
||||
this.clone.scrollTop = this.editorSyntax.scrollTop;
|
||||
this.clone.scrollLeft = this.editorSyntax.scrollLeft;
|
||||
const locatorRect = locator.getBoundingClientRect();
|
||||
const bodyRect = document.body.getBoundingClientRect();
|
||||
const location = {
|
||||
left: locatorRect.left,
|
||||
right: locatorRect.right,
|
||||
top: locatorRect.top,
|
||||
bottom: locatorRect.bottom,
|
||||
left: locatorRect.left - bodyRect.left,
|
||||
right: locatorRect.right - bodyRect.left,
|
||||
top: locatorRect.top - bodyRect.top,
|
||||
bottom: locatorRect.bottom - bodyRect.top,
|
||||
};
|
||||
// this.clone.remove();
|
||||
return location;
|
||||
|
@ -821,8 +825,10 @@ export class QuickReply {
|
|||
//TODO populate debug code from closure.fullText and get locations, highlights, etc. from that
|
||||
//TODO keep some kind of reference (human identifier) *where* the closure code comes from?
|
||||
//TODO QR name, chat input, deserialized closure, ... ?
|
||||
this.editorMessage.value = closure.fullText;
|
||||
this.editorMessage.dispatchEvent(new Event('input', { bubbles:true }));
|
||||
// this.editorMessage.value = closure.fullText;
|
||||
// this.editorMessage.dispatchEvent(new Event('input', { bubbles:true }));
|
||||
syntax.innerHTML = hljs.highlight(`${closure.fullText}${closure.fullText.slice(-1) == '\n' ? ' ' : ''}`, { language:'stscript', ignoreIllegals:true })?.value;
|
||||
const source = closure.source;
|
||||
this.editorDebugState.innerHTML = '';
|
||||
let ci = -1;
|
||||
const varNames = [];
|
||||
|
@ -996,19 +1002,21 @@ export class QuickReply {
|
|||
const title = document.createElement('div'); {
|
||||
title.classList.add('qr--title');
|
||||
title.textContent = isCurrent ? 'Current Scope' : 'Parent Scope';
|
||||
let hi;
|
||||
title.addEventListener('pointerenter', ()=>{
|
||||
const loc = this.getEditorPosition(Math.max(0, c.executorList[0].start - 1), c.executorList.slice(-1)[0].end);
|
||||
const layer = syntax.getBoundingClientRect();
|
||||
hi = document.createElement('div');
|
||||
hi.classList.add('qr--highlight-secondary');
|
||||
hi.style.left = `${loc.left - layer.left}px`;
|
||||
hi.style.width = `${loc.right - loc.left}px`;
|
||||
hi.style.top = `${loc.top - layer.top}px`;
|
||||
hi.style.height = `${loc.bottom - loc.top}px`;
|
||||
syntax.append(hi);
|
||||
});
|
||||
title.addEventListener('pointerleave', ()=>hi?.remove());
|
||||
if (c.source == source) {
|
||||
let hi;
|
||||
title.addEventListener('pointerenter', ()=>{
|
||||
const loc = this.getEditorPosition(Math.max(0, c.executorList[0].start - 1), c.executorList.slice(-1)[0].end, c.fullText);
|
||||
const layer = syntax.getBoundingClientRect();
|
||||
hi = document.createElement('div');
|
||||
hi.classList.add('qr--highlight-secondary');
|
||||
hi.style.left = `${loc.left - layer.left}px`;
|
||||
hi.style.width = `${loc.right - loc.left}px`;
|
||||
hi.style.top = `${loc.top - layer.top}px`;
|
||||
hi.style.height = `${loc.bottom - loc.top}px`;
|
||||
syntax.append(hi);
|
||||
});
|
||||
title.addEventListener('pointerleave', ()=>hi?.remove());
|
||||
}
|
||||
wrap.append(title);
|
||||
}
|
||||
for (const key of Object.keys(scope.variables)) {
|
||||
|
@ -1128,26 +1136,41 @@ export class QuickReply {
|
|||
title.textContent = 'Call Stack';
|
||||
wrap.append(title);
|
||||
}
|
||||
let ei = -1;
|
||||
for (const executor of this.debugController.cmdStack.toReversed()) {
|
||||
ei++;
|
||||
const c = this.debugController.stack.toReversed()[ei];
|
||||
const item = document.createElement('div'); {
|
||||
item.classList.add('qr--item');
|
||||
item.textContent = `/${executor.name}`;
|
||||
if (executor.command.name == 'run') {
|
||||
item.textContent += `${(executor.name == ':' ? '' : ' ')}${executor.unnamedArgumentList[0]?.value}`;
|
||||
if (executor.source == source) {
|
||||
let hi;
|
||||
item.addEventListener('pointerenter', ()=>{
|
||||
const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end, c.fullText);
|
||||
const layer = syntax.getBoundingClientRect();
|
||||
hi = document.createElement('div');
|
||||
hi.classList.add('qr--highlight-secondary');
|
||||
hi.style.left = `${loc.left - layer.left}px`;
|
||||
hi.style.width = `${loc.right - loc.left}px`;
|
||||
hi.style.top = `${loc.top - layer.top}px`;
|
||||
hi.style.height = `${loc.bottom - loc.top}px`;
|
||||
syntax.append(hi);
|
||||
});
|
||||
item.addEventListener('pointerleave', ()=>hi?.remove());
|
||||
}
|
||||
const cmd = document.createElement('div'); {
|
||||
cmd.classList.add('qr--cmd');
|
||||
cmd.textContent = `/${executor.name}`;
|
||||
if (executor.command.name == 'run') {
|
||||
cmd.textContent += `${(executor.name == ':' ? '' : ' ')}${executor.unnamedArgumentList[0]?.value}`;
|
||||
}
|
||||
item.append(cmd);
|
||||
}
|
||||
const src = document.createElement('div'); {
|
||||
src.classList.add('qr--source');
|
||||
const line = closure.fullText.slice(0, executor.start).split('\n').length;
|
||||
src.textContent = `${executor.source}:${line}`;
|
||||
item.append(src);
|
||||
}
|
||||
let hi;
|
||||
item.addEventListener('pointerenter', ()=>{
|
||||
const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end);
|
||||
const layer = syntax.getBoundingClientRect();
|
||||
hi = document.createElement('div');
|
||||
hi.classList.add('qr--highlight-secondary');
|
||||
hi.style.left = `${loc.left - layer.left}px`;
|
||||
hi.style.width = `${loc.right - loc.left}px`;
|
||||
hi.style.top = `${loc.top - layer.top}px`;
|
||||
hi.style.height = `${loc.bottom - loc.top}px`;
|
||||
syntax.append(hi);
|
||||
});
|
||||
item.addEventListener('pointerleave', ()=>hi?.remove());
|
||||
wrap.append(item);
|
||||
}
|
||||
}
|
||||
|
@ -1157,7 +1180,7 @@ export class QuickReply {
|
|||
this.editorDebugState.append(buildVars(closure.scope, true));
|
||||
this.editorDebugState.append(buildStack());
|
||||
this.editorDebugState.classList.add('qr--active');
|
||||
const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end);
|
||||
const loc = this.getEditorPosition(Math.max(0, executor.start - 1), executor.end, closure.fullText);
|
||||
const layer = syntax.getBoundingClientRect();
|
||||
const hi = document.createElement('div');
|
||||
hi.classList.add('qr--highlight');
|
||||
|
@ -1291,7 +1314,7 @@ export class QuickReply {
|
|||
}
|
||||
|
||||
|
||||
async execute(args = {}, isEditor = false, isRun = false) {
|
||||
async execute(args = {}, isEditor = false, isRun = false, options = {}) {
|
||||
if (this.message?.length > 0 && this.onExecute) {
|
||||
const scope = new SlashCommandScope();
|
||||
for (const key of Object.keys(args)) {
|
||||
|
@ -1303,11 +1326,12 @@ export class QuickReply {
|
|||
this.abortController = new SlashCommandAbortController();
|
||||
}
|
||||
return await this.onExecute(this, {
|
||||
message:this.message,
|
||||
message: this.message,
|
||||
isAutoExecute: args.isAutoExecute ?? false,
|
||||
isEditor,
|
||||
isRun,
|
||||
scope,
|
||||
executionOptions: options,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,18 +108,9 @@ export class QuickReplySet {
|
|||
async debug(qr) {
|
||||
const parser = new SlashCommandParser();
|
||||
const closure = parser.parse(qr.message, true, [], qr.abortController, qr.debugController);
|
||||
closure.source = `${this.name}.${qr.label}`;
|
||||
closure.onProgress = (done, total) => qr.updateEditorProgress(done, total);
|
||||
closure.scope.setMacro('arg::*', '');
|
||||
// closure.abortController = qr.abortController;
|
||||
// closure.debugController = qr.debugController;
|
||||
// const stepper = closure.executeGenerator();
|
||||
// let step;
|
||||
// let isStepping = false;
|
||||
// while (!step?.done) {
|
||||
// step = await stepper.next(isStepping);
|
||||
// isStepping = yield(step.value);
|
||||
// }
|
||||
// return step.value;
|
||||
return (await closure.execute())?.pipe;
|
||||
}
|
||||
/**
|
||||
|
@ -131,6 +122,7 @@ export class QuickReplySet {
|
|||
* @param {boolean} [options.isEditor] (false) whether the execution is triggered by the QR editor
|
||||
* @param {boolean} [options.isRun] (false) whether the execution is triggered by /run or /: (window.executeQuickReplyByName)
|
||||
* @param {SlashCommandScope} [options.scope] (null) scope to be used when running the command
|
||||
* @param {import('../../../slash-commands.js').ExecuteSlashCommandsOptions} [options.executionOptions] ({}) further execution options
|
||||
* @returns
|
||||
*/
|
||||
async executeWithOptions(qr, options = {}) {
|
||||
|
@ -140,7 +132,9 @@ export class QuickReplySet {
|
|||
isEditor:false,
|
||||
isRun:false,
|
||||
scope:null,
|
||||
executionOptions:{},
|
||||
}, options);
|
||||
const execOptions = options.executionOptions;
|
||||
/**@type {HTMLTextAreaElement}*/
|
||||
const ta = document.querySelector('#send_textarea');
|
||||
const finalMessage = options.message ?? qr.message;
|
||||
|
@ -158,21 +152,24 @@ export class QuickReplySet {
|
|||
if (input[0] == '/' && !this.disableSend) {
|
||||
let result;
|
||||
if (options.isAutoExecute || options.isRun) {
|
||||
result = await executeSlashCommandsWithOptions(input, {
|
||||
result = await executeSlashCommandsWithOptions(input, Object.assign(execOptions, {
|
||||
handleParserErrors: true,
|
||||
scope: options.scope,
|
||||
});
|
||||
source: `${this.name}.${qr.label}`,
|
||||
}));
|
||||
} else if (options.isEditor) {
|
||||
result = await executeSlashCommandsWithOptions(input, {
|
||||
result = await executeSlashCommandsWithOptions(input, Object.assign(execOptions, {
|
||||
handleParserErrors: false,
|
||||
scope: options.scope,
|
||||
abortController: qr.abortController,
|
||||
source: `${this.name}.${qr.label}`,
|
||||
onProgress: (done, total) => qr.updateEditorProgress(done, total),
|
||||
});
|
||||
}));
|
||||
} else {
|
||||
result = await executeSlashCommandsOnChatInput(input, {
|
||||
result = await executeSlashCommandsOnChatInput(input, Object.assign(execOptions, {
|
||||
scope: options.scope,
|
||||
});
|
||||
source: `${this.name}.${qr.label}`,
|
||||
}));
|
||||
}
|
||||
return typeof result === 'object' ? result?.pipe : '';
|
||||
}
|
||||
|
|
|
@ -667,6 +667,10 @@
|
|||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--scope .qr--pipe .qr--val {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0fr;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--title {
|
||||
grid-column: 1 / 3;
|
||||
font-weight: bold;
|
||||
|
@ -676,10 +680,17 @@
|
|||
margin-top: 1em;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item {
|
||||
display: contents;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item:nth-child(2n + 1) .qr--name,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item:nth-child(2n + 1) .qr--source {
|
||||
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item .qr--name {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item:nth-child(2n + 1) {
|
||||
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--stack .qr--item .qr--source {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@keyframes qr--progressPulse {
|
||||
0%,
|
||||
|
|
|
@ -748,6 +748,8 @@
|
|||
}
|
||||
|
||||
.qr--stack {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 0fr;
|
||||
.qr--title {
|
||||
grid-column: 1 / 3;
|
||||
font-weight: bold;
|
||||
|
@ -757,10 +759,18 @@
|
|||
margin-top: 1em;
|
||||
}
|
||||
.qr--item {
|
||||
margin-left: 0.5em;
|
||||
display: contents;
|
||||
&:nth-child(2n + 1) {
|
||||
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
|
||||
.qr--name, .qr--source {
|
||||
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
|
||||
}
|
||||
}
|
||||
.qr--name {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.qr--source {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1824,7 +1824,12 @@ async function runCallback(args, name) {
|
|||
|
||||
try {
|
||||
name = name.trim();
|
||||
return await window['executeQuickReplyByName'](name, args);
|
||||
/**@type {ExecuteSlashCommandsOptions} */
|
||||
const options = {
|
||||
abortController: args._abortController,
|
||||
debugController: args._debugController,
|
||||
};
|
||||
return await window['executeQuickReplyByName'](name, args, options);
|
||||
} catch (error) {
|
||||
throw new Error(`Error running Quick Reply "${name}": ${error.message}`);
|
||||
}
|
||||
|
@ -3372,6 +3377,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress);
|
|||
* @prop {SlashCommandAbortController} [abortController] (null) Controller used to abort or pause command execution
|
||||
* @prop {SlashCommandDebugController} [debugController] (null) Controller used to control debug execution
|
||||
* @prop {(done:number, total:number)=>void} [onProgress] (null) Callback to handle progress events
|
||||
* @prop {string} [source] (null) String indicating where the code come from (e.g., QR name)
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -3379,6 +3385,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress);
|
|||
* @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands.
|
||||
* @prop {{[id:PARSER_FLAG]:boolean}} [parserFlags] (null) Parser flags to apply
|
||||
* @prop {boolean} [clearChatInput] (false) Whether to clear the chat input textarea
|
||||
* @prop {string} [source] (null) String indicating where the code come from (e.g., QR name)
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -3394,6 +3401,7 @@ export async function executeSlashCommandsOnChatInput(text, options = {}) {
|
|||
scope: null,
|
||||
parserFlags: null,
|
||||
clearChatInput: false,
|
||||
source: null,
|
||||
}, options);
|
||||
|
||||
isExecutingCommandsFromChatInput = true;
|
||||
|
@ -3423,6 +3431,7 @@ export async function executeSlashCommandsOnChatInput(text, options = {}) {
|
|||
onProgress: (done, total) => ta.style.setProperty('--prog', `${done / total * 100}%`),
|
||||
parserFlags: options.parserFlags,
|
||||
scope: options.scope,
|
||||
source: options.source,
|
||||
});
|
||||
if (commandsFromChatInputAbortController.signal.aborted) {
|
||||
document.querySelector('#form_sheld').classList.add('script_aborted');
|
||||
|
@ -3481,6 +3490,7 @@ async function executeSlashCommandsWithOptions(text, options = {}) {
|
|||
abortController: null,
|
||||
debugController: null,
|
||||
onProgress: null,
|
||||
source: null,
|
||||
}, options);
|
||||
|
||||
let closure;
|
||||
|
@ -3489,6 +3499,7 @@ async function executeSlashCommandsWithOptions(text, options = {}) {
|
|||
closure.scope.parent = options.scope;
|
||||
closure.onProgress = options.onProgress;
|
||||
closure.debugController = options.debugController;
|
||||
closure.source = options.source;
|
||||
} catch (e) {
|
||||
if (options.handleParserErrors && e instanceof SlashCommandParserError) {
|
||||
/**@type {SlashCommandParserError}*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { substituteParams } from '../../script.js';
|
||||
import { delay, escapeRegex } from '../utils.js';
|
||||
import { delay, escapeRegex, uuidv4 } from '../utils.js';
|
||||
import { SlashCommand } from './SlashCommand.js';
|
||||
import { SlashCommandAbortController } from './SlashCommandAbortController.js';
|
||||
import { SlashCommandBreak } from './SlashCommandBreak.js';
|
||||
|
@ -27,6 +27,14 @@ export class SlashCommandClosure {
|
|||
/**@type {string}*/ rawText;
|
||||
/**@type {string}*/ fullText;
|
||||
/**@type {string}*/ parserContext;
|
||||
/**@type {string}*/ #source = uuidv4();
|
||||
get source() { return this.#source; }
|
||||
set source(value) {
|
||||
this.#source = value;
|
||||
for (const executor of this.executorList) {
|
||||
executor.source = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**@type {number}*/
|
||||
get commandCount() {
|
||||
|
@ -114,6 +122,7 @@ export class SlashCommandClosure {
|
|||
closure.rawText = this.rawText;
|
||||
closure.fullText = this.fullText;
|
||||
closure.parserContext = this.parserContext;
|
||||
closure.source = this.source;
|
||||
closure.onProgress = this.onProgress;
|
||||
return closure;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
import { uuidv4 } from '../utils.js';
|
||||
import { SlashCommand } from './SlashCommand.js';
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
||||
|
@ -16,6 +17,17 @@ export class SlashCommandExecutor {
|
|||
/**@type {Number}*/ startUnnamedArgs;
|
||||
/**@type {Number}*/ endUnnamedArgs;
|
||||
/**@type {String}*/ name = '';
|
||||
/**@type {String}*/ #source = uuidv4();
|
||||
get source() { return this.#source; }
|
||||
set source(value) {
|
||||
this.#source = value;
|
||||
for (const arg of this.namedArgumentList.filter(it=>it.value instanceof SlashCommandClosure)) {
|
||||
arg.value.source = value;
|
||||
}
|
||||
for (const arg of this.unnamedArgumentList.filter(it=>it.value instanceof SlashCommandClosure)) {
|
||||
arg.value.source = value;
|
||||
}
|
||||
}
|
||||
/**@type {SlashCommand}*/ command;
|
||||
// @ts-ignore
|
||||
/**@type {SlashCommandNamedArgumentAssignment[]}*/ namedArgumentList = [];
|
||||
|
|
Loading…
Reference in New Issue