This commit is contained in:
LenAnderson 2024-06-23 11:31:07 -04:00
parent 5c5c4ae91a
commit ef5d4e394b
5 changed files with 286 additions and 9 deletions

View File

@ -618,14 +618,15 @@ export class QuickReply {
}
this.clone.style.position = 'fixed';
this.clone.style.visibility = 'hidden';
document.body.append(this.clone);
const mo = new MutationObserver(muts=>{
if (muts.find(it=>Array.from(it.removedNodes).includes(this.editorMessage))) {
if (muts.find(it=>[...it.removedNodes].includes(this.editorMessage) || [...it.removedNodes].find(n=>n.contains(this.editorMessage)))) {
this.clone.remove();
this.clone = null;
}
});
mo.observe(this.editorMessage.parentElement, { childList:true });
mo.observe(document.body, { childList:true });
}
document.body.append(this.clone);
this.clone.style.width = `${inputRect.width}px`;
this.clone.style.height = `${inputRect.height}px`;
this.clone.style.left = `${inputRect.left}px`;
@ -648,6 +649,7 @@ export class QuickReply {
top: locatorRect.top,
bottom: locatorRect.bottom,
};
// this.clone.remove();
return location;
}
async executeFromEditor() {
@ -689,6 +691,157 @@ export class QuickReply {
const c = this.debugController.stack.slice(ci)[0];
const wrap = document.createElement('div'); {
wrap.classList.add('qr--scope');
if (isCurrent) {
const executor = this.debugController.cmdStack.slice(-1)[0];
{
const namedTitle = document.createElement('div'); {
namedTitle.classList.add('qr--title');
namedTitle.textContent = `Named Args - /${executor.name}`;
if (executor.command.name == 'run') {
namedTitle.textContent += `${(executor.name == ':' ? '' : ' ')}${executor.unnamedArgumentList[0]?.value}`;
}
wrap.append(namedTitle);
}
const keys = new Set([...Object.keys(this.debugController.namedArguments ?? {}), ...(executor.namedArgumentList ?? []).map(it=>it.name)]);
for (const key of keys) {
if (key[0] == '_') continue;
const item = document.createElement('div'); {
item.classList.add('qr--var');
const k = document.createElement('div'); {
k.classList.add('qr--key');
k.textContent = key;
item.append(k);
}
const vUnresolved = document.createElement('div'); {
vUnresolved.classList.add('qr--val');
vUnresolved.classList.add('qr--singleCol');
const val = executor.namedArgumentList.find(it=>it.name == key)?.value;
if (val instanceof SlashCommandClosure) {
vUnresolved.classList.add('qr--closure');
vUnresolved.title = val.rawText;
vUnresolved.textContent = val.toString();
} else if (val === undefined) {
vUnresolved.classList.add('qr--undefined');
vUnresolved.textContent = 'undefined';
} else {
let jsonVal;
try { jsonVal = JSON.parse(val); } catch { /* empty */ }
if (jsonVal && typeof jsonVal == 'object') {
vUnresolved.textContent = JSON.stringify(jsonVal, null, 2);
} else {
vUnresolved.textContent = val;
vUnresolved.classList.add('qr--simple');
}
}
item.append(vUnresolved);
}
const vResolved = document.createElement('div'); {
vResolved.classList.add('qr--val');
vResolved.classList.add('qr--singleCol');
const val = this.debugController.namedArguments[key];
if (val instanceof SlashCommandClosure) {
vResolved.classList.add('qr--closure');
vResolved.title = val.rawText;
vResolved.textContent = val.toString();
} else if (val === undefined) {
vResolved.classList.add('qr--undefined');
vResolved.textContent = 'undefined';
} else {
let jsonVal;
try { jsonVal = JSON.parse(val); } catch { /* empty */ }
if (jsonVal && typeof jsonVal == 'object') {
vResolved.textContent = JSON.stringify(jsonVal, null, 2);
} else {
vResolved.textContent = val;
vResolved.classList.add('qr--simple');
}
}
item.append(vResolved);
}
wrap.append(item);
}
}
}
{
const unnamedTitle = document.createElement('div'); {
unnamedTitle.classList.add('qr--title');
unnamedTitle.textContent = `Unnamed Args - /${executor.name}`;
if (executor.command.name == 'run') {
unnamedTitle.textContent += `${(executor.name == ':' ? '' : ' ')}${executor.unnamedArgumentList[0]?.value}`;
}
wrap.append(unnamedTitle);
}
let i = 0;
let unnamed = this.debugController.unnamedArguments ?? [];
if (!Array.isArray(unnamed)) unnamed = [unnamed];
while (unnamed.length < executor.unnamedArgumentList?.length ?? 0) unnamed.push(undefined);
unnamed = unnamed.map((it,idx)=>[executor.unnamedArgumentList?.[idx], it]);
for (const arg of unnamed) {
i++;
const item = document.createElement('div'); {
item.classList.add('qr--var');
const k = document.createElement('div'); {
k.classList.add('qr--key');
k.textContent = i.toString();
item.append(k);
}
const vUnresolved = document.createElement('div'); {
vUnresolved.classList.add('qr--val');
vUnresolved.classList.add('qr--singleCol');
const val = arg[0]?.value;
if (val instanceof SlashCommandClosure) {
vUnresolved.classList.add('qr--closure');
vUnresolved.title = val.rawText;
vUnresolved.textContent = val.toString();
} else if (val === undefined) {
vUnresolved.classList.add('qr--undefined');
vUnresolved.textContent = 'undefined';
} else {
let jsonVal;
try { jsonVal = JSON.parse(val); } catch { /* empty */ }
if (jsonVal && typeof jsonVal == 'object') {
vUnresolved.textContent = JSON.stringify(jsonVal, null, 2);
} else {
vUnresolved.textContent = val;
vUnresolved.classList.add('qr--simple');
}
}
item.append(vUnresolved);
}
const vResolved = document.createElement('div'); {
vResolved.classList.add('qr--val');
vResolved.classList.add('qr--singleCol');
if (this.debugController.unnamedArguments === undefined) {
vResolved.classList.add('qr--unresolved');
} else if ((Array.isArray(this.debugController.unnamedArguments) ? this.debugController.unnamedArguments : [this.debugController.unnamedArguments]).length < i) {
// do nothing
} else {
const val = arg[1];
if (val instanceof SlashCommandClosure) {
vResolved.classList.add('qr--closure');
vResolved.title = val.rawText;
vResolved.textContent = val.toString();
} else if (val === undefined) {
vResolved.classList.add('qr--undefined');
vResolved.textContent = 'undefined';
} else {
let jsonVal;
try { jsonVal = JSON.parse(val); } catch { /* empty */ }
if (jsonVal && typeof jsonVal == 'object') {
vResolved.textContent = JSON.stringify(jsonVal, null, 2);
} else {
vResolved.textContent = val;
vResolved.classList.add('qr--simple');
}
}
}
item.append(vResolved);
}
wrap.append(item);
}
}
}
}
const title = document.createElement('div'); {
title.classList.add('qr--title');
title.textContent = isCurrent ? 'Current Scope' : 'Parent Scope';
@ -735,6 +888,7 @@ export class QuickReply {
v.textContent = JSON.stringify(jsonVal, null, 2);
} else {
v.textContent = val;
v.classList.add('qr--simple');
}
}
item.append(v);
@ -770,6 +924,7 @@ export class QuickReply {
v.textContent = JSON.stringify(jsonVal, null, 2);
} else {
v.textContent = val;
v.classList.add('qr--simple');
}
}
item.append(v);
@ -801,6 +956,7 @@ export class QuickReply {
v.textContent = JSON.stringify(jsonVal, null, 2);
} else {
v.textContent = val;
v.classList.add('qr--simple');
}
}
pipeItem.append(v);
@ -854,6 +1010,9 @@ export class QuickReply {
const layer = this.editorPopup.dlg.getBoundingClientRect();
const hi = document.createElement('div');
hi.classList.add('qr--highlight');
if (this.debugController.namedArguments === undefined) {
hi.classList.add('qr--unresolved');
}
hi.style.left = `${loc.left - layer.left}px`;
hi.style.width = `${loc.right - loc.left}px`;
hi.style.top = `${loc.top - layer.top}px`;

View File

@ -245,6 +245,9 @@
position: fixed;
z-index: 50000;
pointer-events: none;
background-color: rgba(47, 150, 180, 0.5);
}
.popup:has(#qr--modalEditor):has(.qr--isExecuting) .qr--highlight.qr--unresolved {
background-color: rgba(255, 255, 0, 0.5);
}
.popup:has(#qr--modalEditor):has(.qr--isExecuting) .qr--highlight-secondary {
@ -559,11 +562,11 @@
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope {
display: grid;
grid-template-columns: 0fr 1fr;
grid-template-columns: 0fr 1fr 1fr;
column-gap: 0em;
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--title {
grid-column: 1 / 3;
grid-column: 1 / 4;
font-weight: bold;
font-family: var(--mainFontFamily);
background-color: var(--black50a);
@ -583,6 +586,26 @@
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe:nth-child(2n + 1) .qr--val {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var:nth-child(2n + 1) .qr--val:nth-child(2n),
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro:nth-child(2n + 1) .qr--val:nth-child(2n),
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe:nth-child(2n + 1) .qr--val:nth-child(2n) {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.125);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var:nth-child(2n + 1) .qr--val:hover,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro:nth-child(2n + 1) .qr--val:hover,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe:nth-child(2n + 1) .qr--val:hover {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var:nth-child(2n) .qr--val:nth-child(2n),
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro:nth-child(2n) .qr--val:nth-child(2n),
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe:nth-child(2n) .qr--val:nth-child(2n) {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.0625);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var:nth-child(2n) .qr--val:hover,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro:nth-child(2n) .qr--val:hover,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe:nth-child(2n) .qr--val:hover {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var.qr--isHidden .qr--key,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro.qr--isHidden .qr--key,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe.qr--isHidden .qr--key,
@ -591,6 +614,32 @@
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe.qr--isHidden .qr--val {
opacity: 0.5;
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var .qr--val,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro .qr--val,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe .qr--val {
grid-column: 2 / 4;
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var .qr--val.qr--singleCol,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro .qr--val.qr--singleCol,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe .qr--val.qr--singleCol {
grid-column: unset;
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var .qr--val.qr--simple:before,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro .qr--val.qr--simple:before,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe .qr--val.qr--simple:before,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var .qr--val.qr--simple:after,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro .qr--val.qr--simple:after,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe .qr--val.qr--simple:after {
content: '"';
color: var(--SmartThemeQuoteColor);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var .qr--val.qr--unresolved:after,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro .qr--val.qr--unresolved:after,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe .qr--val.qr--unresolved:after {
content: '-UNRESOLVED-';
font-style: italic;
color: var(--SmartThemeQuoteColor);
}
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--key {
margin-left: 0.5em;
padding-right: 1em;

View File

@ -271,7 +271,10 @@
position: fixed;
z-index: 50000;
pointer-events: none;
background-color: rgba(255, 255, 0, 0.5);
background-color: rgb(47 150 180 / 0.5);
&.qr--unresolved {
background-color: rgb(255 255 0 / 0.5);
}
}
.qr--highlight-secondary {
position: fixed;
@ -588,10 +591,10 @@
.qr--scope {
display: grid;
grid-template-columns: 0fr 1fr;
grid-template-columns: 0fr 1fr 1fr;
column-gap: 0em;
.qr--title {
grid-column: 1 / 3;
grid-column: 1 / 4;
font-weight: bold;
font-family: var(--mainFontFamily);
background-color: var(--black50a);
@ -604,12 +607,49 @@
.qr--key, .qr--val {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.25);
}
.qr--val {
&:nth-child(2n) {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.125);
}
&:hover {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5);
}
}
}
&:nth-child(2n) {
.qr--val {
&:nth-child(2n) {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.0625);
}
&:hover {
background-color: rgb(from var(--SmartThemeEmColor) r g b / 0.5);
}
}
}
&.qr--isHidden {
.qr--key, .qr--val {
opacity: 0.5;
}
}
.qr--val {
grid-column: 2 / 4;
&.qr--singleCol {
grid-column: unset;
}
&.qr--simple {
&:before, &:after {
content: '"';
color: var(--SmartThemeQuoteColor);
}
}
&.qr--unresolved {
&:after {
content: '-UNRESOLVED-';
font-style: italic;
color: var(--SmartThemeQuoteColor);
}
}
}
}
.qr--key {
margin-left: 0.5em;

View File

@ -187,11 +187,29 @@ export class SlashCommandClosure {
if (this.debugController) {
// "execute" breakpoint
step = await stepper.next();
step = await stepper.next();
// get next executor
step = await stepper.next();
this.debugController.isStepping = yield { closure:this, executor:step.value };
const hasImmediateClosureInNamedArgs = step.value.namedArgumentList.find(it=>it.value instanceof SlashCommandClosure && it.executeNow);
const hasImmediateClosureInUnnamedArgs = step.value.unnamedArgumentList.find(it=>it.value instanceof SlashCommandClosure && it.executeNow);
if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) {
this.debugController.isStepping = yield { closure:this, executor:step.value };
} else {
this.debugController.isStepping = true;
this.debugController.stepStack[this.debugController.stepStack.length - 1] = true;
}
}
} else if (!step.done && this.debugController?.testStepping(this)) {
this.debugController.isSteppingInto = false;
const hasImmediateClosureInNamedArgs = step.value.namedArgumentList.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow);
const hasImmediateClosureInUnnamedArgs = step.value.unnamedArgumentList.find(it=>it.value instanceof SlashCommandClosure && it.value.executeNow);
if (hasImmediateClosureInNamedArgs || hasImmediateClosureInUnnamedArgs) {
this.debugController.isStepping = yield { closure:this, executor:step.value };
}
}
// resolve args
step = await stepper.next();
if (!step.done && this.debugController?.testStepping(this)) {
this.debugController.isSteppingInto = false;
this.debugController.isStepping = yield { closure:this, executor:step.value };
}
@ -225,6 +243,7 @@ export class SlashCommandClosure {
} else if (executor instanceof SlashCommandBreakPoint) {
// no execution for breakpoints, just raise counter
done++;
yield executor;
} else {
/**@type {import('./SlashCommand.js').NamedArguments} */
let args = {
@ -310,6 +329,11 @@ export class SlashCommandClosure {
if (abortResult) {
return abortResult;
}
if (this.debugController) {
this.debugController.namedArguments = args;
this.debugController.unnamedArguments = value ?? '';
}
yield executor;
executor.onProgress = (subDone, subTotal)=>this.onProgress?.(done + subDone, this.commandCount);
const isStepping = this.debugController?.testStepping(this);
if (this.debugController) {
@ -317,6 +341,8 @@ export class SlashCommandClosure {
}
this.scope.pipe = await executor.command.callback(args, value ?? '');
if (this.debugController) {
this.debugController.namedArguments = undefined;
this.debugController.unnamedArguments = undefined;
this.debugController.isStepping = isStepping;
}
this.#lintPipe(executor.command);

View File

@ -9,6 +9,9 @@ export class SlashCommandDebugController {
/**@type {boolean} */ isSteppingInto = false;
/**@type {boolean} */ isSteppingOut = false;
/**@type {object} */ namedArguments;
/**@type {string|SlashCommandClosure|(string|SlashCommandClosure)[]} */ unnamedArguments;
/**@type {Promise<boolean>} */ continuePromise;
/**@type {(boolean)=>void} */ continueResolver;