debugger stuff
This commit is contained in:
parent
02e1ef7606
commit
538724739b
|
@ -54,6 +54,7 @@ export class QuickReply {
|
|||
/**@type {HTMLTextAreaElement}*/ settingsDomMessage;
|
||||
|
||||
/**@type {Popup}*/ editorPopup;
|
||||
/**@type {HTMLElement}*/ editorDom;
|
||||
|
||||
/**@type {HTMLElement}*/ editorExecuteBtn;
|
||||
/**@type {HTMLElement}*/ editorExecuteBtnPause;
|
||||
|
@ -215,6 +216,7 @@ export class QuickReply {
|
|||
/**@type {HTMLElement} */
|
||||
// @ts-ignore
|
||||
const dom = this.template.cloneNode(true);
|
||||
this.editorDom = dom;
|
||||
this.editorPopup = new Popup(dom, POPUP_TYPE.TEXT, undefined, { okButton: 'OK', wide: true, large: true, rows: 1 });
|
||||
const popupResult = this.editorPopup.show();
|
||||
|
||||
|
@ -614,6 +616,7 @@ export class QuickReply {
|
|||
}
|
||||
async executeFromEditor() {
|
||||
if (this.editorExecutePromise) return;
|
||||
this.editorDom.classList.add('qr--isExecuting');
|
||||
this.editorExecuteBtn.classList.add('qr--busy');
|
||||
this.editorExecuteProgress.style.setProperty('--prog', '0');
|
||||
this.editorExecuteErrors.classList.remove('qr--hasErrors');
|
||||
|
@ -628,26 +631,133 @@ export class QuickReply {
|
|||
this.editorPopup.dlg.classList.add('qr--hide');
|
||||
}
|
||||
try {
|
||||
// this.editorExecutePromise = this.execute({}, true);
|
||||
// const result = await this.editorExecutePromise;
|
||||
this.abortController = new SlashCommandAbortController();
|
||||
this.debugController = new SlashCommandDebugController();
|
||||
this.debugController.onBreakPoint = async(closure, executor)=>{
|
||||
const vars = closure.scope.variables;
|
||||
vars['#pipe'] = closure.scope.pipe;
|
||||
let v = vars;
|
||||
let s = closure.scope.parent;
|
||||
while (s) {
|
||||
v['#parent'] = s.variables;
|
||||
v = v['#parent'];
|
||||
v['#pipe'] = s.pipe;
|
||||
s = s.parent;
|
||||
}
|
||||
this.editorDebugState.textContent = JSON.stringify(closure.scope.variables, (key, val)=>{
|
||||
if (val instanceof SlashCommandClosure) return val.toString();
|
||||
if (val === undefined) return null;
|
||||
return val;
|
||||
}, 2);
|
||||
this.editorDebugState.innerHTML = '';
|
||||
let ci = -1;
|
||||
const varNames = [];
|
||||
const macroNames = [];
|
||||
/**
|
||||
* @param {SlashCommandScope} scope
|
||||
*/
|
||||
const buildVars = (scope, isCurrent = false)=>{
|
||||
if (!isCurrent) {
|
||||
ci--;
|
||||
}
|
||||
const c = this.debugController.stack.slice(ci)[0];
|
||||
const wrap = document.createElement('div'); {
|
||||
wrap.classList.add('qr--scope');
|
||||
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(c.executorList[0].start, c.executorList.slice(-1)[0].end);
|
||||
const layer = this.editorPopup.dlg.getBoundingClientRect();
|
||||
hi = document.createElement('div');
|
||||
hi.style.position = 'fixed';
|
||||
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`;
|
||||
hi.style.zIndex = '50000';
|
||||
hi.style.pointerEvents = 'none';
|
||||
hi.style.border = '3px solid red';
|
||||
this.editorPopup.dlg.append(hi);
|
||||
});
|
||||
title.addEventListener('pointerleave', ()=>hi?.remove());
|
||||
wrap.append(title);
|
||||
}
|
||||
for (const key of Object.keys(scope.variables)) {
|
||||
const isHidden = varNames.includes(key);
|
||||
if (!isHidden) varNames.push(key);
|
||||
const item = document.createElement('div'); {
|
||||
item.classList.add('qr--var');
|
||||
if (isHidden) item.classList.add('qr--isHidden');
|
||||
const k = document.createElement('div'); {
|
||||
k.classList.add('qr--key');
|
||||
k.textContent = key;
|
||||
item.append(k);
|
||||
}
|
||||
const v = document.createElement('div'); {
|
||||
v.classList.add('qr--val');
|
||||
const val = scope.variables[key];
|
||||
if (val instanceof SlashCommandClosure) {
|
||||
v.classList.add('qr--closure');
|
||||
v.title = val.rawText;
|
||||
v.textContent = val.toString();
|
||||
} else if (val === undefined) {
|
||||
v.classList.add('qr--undefined');
|
||||
v.textContent = 'undefined';
|
||||
} else {
|
||||
v.textContent = val;
|
||||
}
|
||||
item.append(v);
|
||||
}
|
||||
wrap.append(item);
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(scope.macros)) {
|
||||
const isHidden = macroNames.includes(key);
|
||||
if (!isHidden) macroNames.push(key);
|
||||
const item = document.createElement('div'); {
|
||||
item.classList.add('qr--macro');
|
||||
if (isHidden) item.classList.add('qr--isHidden');
|
||||
const k = document.createElement('div'); {
|
||||
k.classList.add('qr--key');
|
||||
k.textContent = key;
|
||||
item.append(k);
|
||||
}
|
||||
const v = document.createElement('div'); {
|
||||
v.classList.add('qr--val');
|
||||
const val = scope.macros[key];
|
||||
if (val instanceof SlashCommandClosure) {
|
||||
v.classList.add('qr--closure');
|
||||
v.title = val.rawText;
|
||||
v.textContent = val.toString();
|
||||
} else if (val === undefined) {
|
||||
v.classList.add('qr--undefined');
|
||||
v.textContent = 'undefined';
|
||||
} else {
|
||||
v.textContent = val;
|
||||
}
|
||||
item.append(v);
|
||||
}
|
||||
wrap.append(item);
|
||||
}
|
||||
}
|
||||
const pipeItem = document.createElement('div'); {
|
||||
pipeItem.classList.add('qr--pipe');
|
||||
const k = document.createElement('div'); {
|
||||
k.classList.add('qr--key');
|
||||
k.textContent = 'pipe';
|
||||
pipeItem.append(k);
|
||||
}
|
||||
const v = document.createElement('div'); {
|
||||
v.classList.add('qr--val');
|
||||
const val = scope.pipe;
|
||||
if (val instanceof SlashCommandClosure) {
|
||||
v.classList.add('qr--closure');
|
||||
v.title = val.rawText;
|
||||
v.textContent = val.toString();
|
||||
} else if (val === undefined) {
|
||||
v.classList.add('qr--undefined');
|
||||
v.textContent = 'undefined';
|
||||
} else {
|
||||
v.textContent = val;
|
||||
}
|
||||
pipeItem.append(v);
|
||||
}
|
||||
wrap.append(pipeItem);
|
||||
}
|
||||
if (scope.parent) {
|
||||
wrap.append(buildVars(scope.parent));
|
||||
}
|
||||
}
|
||||
return wrap;
|
||||
};
|
||||
this.editorDebugState.append(buildVars(closure.scope, true));
|
||||
this.editorDebugState.classList.add('qr--active');
|
||||
const loc = this.getEditorPosition(executor.start - 1, executor.end);
|
||||
const layer = this.editorPopup.dlg.getBoundingClientRect();
|
||||
|
@ -695,6 +805,7 @@ export class QuickReply {
|
|||
this.editorExecutePromise = null;
|
||||
this.editorExecuteBtn.classList.remove('qr--busy');
|
||||
this.editorPopup.dlg.classList.remove('qr--hide');
|
||||
this.editorDom.classList.remove('qr--isExecuting');
|
||||
}
|
||||
|
||||
updateEditorProgress(done, total) {
|
||||
|
|
|
@ -238,6 +238,9 @@
|
|||
.popup:has(#qr--modalEditor) {
|
||||
aspect-ratio: unset;
|
||||
}
|
||||
.popup:has(#qr--modalEditor):has(.qr--isExecuting) .popup-controls {
|
||||
display: none;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -249,6 +252,16 @@
|
|||
gap: 1em;
|
||||
overflow: hidden;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--main > h3:first-child,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--main > .qr--labels,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--qrOptions > h3:first-child,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--qrOptions > #qr--ctxEditor,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--qrOptions > .qr--ctxEditorActions,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--qrOptions > .qr--ctxEditorActions + h3,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor.qr--isExecuting #qr--qrOptions > .qr--ctxEditorActions + h3 + div {
|
||||
display: none;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
|
@ -485,8 +498,9 @@
|
|||
display: none;
|
||||
text-align: left;
|
||||
font-size: smaller;
|
||||
font-family: var(--monoFontFamily);
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
padding: 0.5em 0;
|
||||
overflow: auto;
|
||||
min-width: 100%;
|
||||
width: 0;
|
||||
|
@ -495,6 +509,52 @@
|
|||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState.qr--active {
|
||||
display: block;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope {
|
||||
display: grid;
|
||||
grid-template-columns: 0fr 1fr;
|
||||
column-gap: 1em;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--title {
|
||||
grid-column: 1 / 3;
|
||||
font-weight: bold;
|
||||
background-color: var(--black50a);
|
||||
padding: 0.25em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe {
|
||||
display: contents;
|
||||
}
|
||||
.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,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--var.qr--isHidden .qr--val,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro.qr--isHidden .qr--val,
|
||||
.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--key {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--key:after {
|
||||
content: ": ";
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe > .qr--key:before,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro > .qr--key:before {
|
||||
content: "{{";
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--pipe > .qr--key:after,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--macro > .qr--key:after {
|
||||
content: "}}: ";
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--scope {
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--scope .qr--pipe .qr--key,
|
||||
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-debugState .qr--scope .qr--scope .qr--pipe .qr--val {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@keyframes qr--progressPulse {
|
||||
0%,
|
||||
100% {
|
||||
|
|
|
@ -262,6 +262,10 @@
|
|||
.popup:has(#qr--modalEditor) {
|
||||
aspect-ratio: unset;
|
||||
|
||||
&:has(.qr--isExecuting) .popup-controls {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -273,6 +277,21 @@
|
|||
gap: 1em;
|
||||
overflow: hidden;
|
||||
|
||||
&.qr--isExecuting {
|
||||
#qr--main > h3:first-child,
|
||||
#qr--main > .qr--labels,
|
||||
#qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings,
|
||||
#qr--qrOptions > h3:first-child,
|
||||
#qr--qrOptions > #qr--ctxEditor,
|
||||
#qr--qrOptions > .qr--ctxEditorActions,
|
||||
#qr--qrOptions > .qr--ctxEditorActions + h3,
|
||||
#qr--qrOptions > .qr--ctxEditorActions + h3 + div
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> #qr--main {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
|
@ -507,13 +526,53 @@
|
|||
}
|
||||
text-align: left;
|
||||
font-size: smaller;
|
||||
font-family: var(--monoFontFamily);
|
||||
// background-color: rgb(146, 190, 252);
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
padding: 0.5em 0;
|
||||
overflow: auto;
|
||||
min-width: 100%;
|
||||
width: 0;
|
||||
white-space: pre-wrap;
|
||||
|
||||
.qr--scope {
|
||||
display: grid;
|
||||
grid-template-columns: 0fr 1fr;
|
||||
column-gap: 1em;
|
||||
.qr--title {
|
||||
grid-column: 1 / 3;
|
||||
font-weight: bold;
|
||||
background-color: var(--black50a);
|
||||
padding: 0.25em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
.qr--var, .qr--macro, .qr--pipe {
|
||||
display: contents;
|
||||
&.qr--isHidden {
|
||||
.qr--key, .qr--val {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
.qr--key {
|
||||
margin-left: 0.5em;
|
||||
&:after { content: ": "; }
|
||||
}
|
||||
.qr--pipe, .qr--macro {
|
||||
> .qr--key {
|
||||
&:before { content: "{{"; }
|
||||
&:after { content: "}}: "; }
|
||||
}
|
||||
}
|
||||
.qr--scope {
|
||||
grid-column: 1 / 3;
|
||||
.qr--pipe {
|
||||
.qr--key, .qr--val {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ export class SlashCommandClosure {
|
|||
|
||||
/**
|
||||
*
|
||||
* @returns Promise<SlashCommandClosureResult>
|
||||
* @returns {Promise<SlashCommandClosureResult>}
|
||||
*/
|
||||
async execute() {
|
||||
const closure = this.getCopy();
|
||||
|
@ -124,6 +124,7 @@ export class SlashCommandClosure {
|
|||
}
|
||||
|
||||
async * executeDirect() {
|
||||
this.debugController?.down(this);
|
||||
// closure arguments
|
||||
for (const arg of this.argumentList) {
|
||||
let v = arg.value;
|
||||
|
@ -305,10 +306,12 @@ export class SlashCommandClosure {
|
|||
|
||||
// if execution has returned a closure result, return that (should only happen on abort)
|
||||
if (step.value instanceof SlashCommandClosureResult) {
|
||||
this.debugController?.up();
|
||||
return step.value;
|
||||
}
|
||||
/**@type {SlashCommandClosureResult} */
|
||||
const result = Object.assign(new SlashCommandClosureResult(), { pipe: this.scope.pipe });
|
||||
this.debugController?.up();
|
||||
return result;
|
||||
}
|
||||
async * executeStep() {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { SlashCommandClosure } from './SlashCommandClosure.js';
|
|||
import { SlashCommandExecutor } from './SlashCommandExecutor.js';
|
||||
|
||||
export class SlashCommandDebugController {
|
||||
/**@type {SlashCommandClosure[]} */ stack = [];
|
||||
/**@type {boolean} */ isStepping = false;
|
||||
/**@type {boolean} */ isSteppingInto = false;
|
||||
|
||||
|
@ -12,6 +13,16 @@ export class SlashCommandDebugController {
|
|||
|
||||
|
||||
|
||||
|
||||
down(closure) {
|
||||
this.stack.push(closure);
|
||||
}
|
||||
up() {
|
||||
this.stack.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
resume() {
|
||||
this.continueResolver?.(false);
|
||||
this.continuePromise = null;
|
||||
|
|
Loading…
Reference in New Issue