diff options
Diffstat (limited to 'modules/ext/floating.js')
| -rw-r--r-- | modules/ext/floating.js | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/modules/ext/floating.js b/modules/ext/floating.js index b6f5a93..f59aa29 100644 --- a/modules/ext/floating.js +++ b/modules/ext/floating.js @@ -5,6 +5,11 @@ class FloatingModule { constructor() { this.commands = {}; + this.commandsMeta = { + 'floating-remove': { argType: 'enum', enumFn: '_listElementIds' }, + 'floating-toggle': { argType: 'enum', enumFn: '_listElementIds' }, + 'floating-pos': { argType: 'enum', enumFn: '_listElementIds' }, + }; this.terminal = null; this._elements = {}; this._storageKey = 'webx11_floating_elements'; @@ -14,7 +19,7 @@ class FloatingModule { getHelpInfo() { return { - 'floating-add': 'floating-add btn|menu|panel <id> <label> [command|buttons...] — Add a floating UI element', + 'floating-add': 'floating-add btn|menu|panel <id> <label> [cmd|btn:Label:cmd...] — Add a floating UI element', 'floating-remove': 'floating-remove <id> — Remove a floating element', 'floating-list': 'floating-list — Show all floating elements', 'floating-pos': 'floating-pos <id> <x|auto> <y|auto> — Reposition a floating element', @@ -30,10 +35,11 @@ class FloatingModule { this.commands['floating-pos'] = (args) => this._cmdPos(args); this.commands['floating-clear'] = () => this._cmdClear(); this.commands['floating-toggle'] = (args) => this._cmdToggle(args); - } - - seed() { - this._restore(); + // Restore persisted elements at boot — registerCommands() is the only hook called by ModuleManager + // but defer to next tick so terminal/fs are ready + setTimeout(() => { + this._restore(); + }, 0); } // ── Persistence ── @@ -202,7 +208,7 @@ class FloatingModule { _cmdAdd(args) { if (args.length < 3) { - this.terminal.print('Usage: floating-add btn|menu|panel <id> <label> [command|btn:Label|cmd...]', 'warning'); + this.terminal.print('Usage: floating-add btn|menu|panel <id> <label> [cmd|btn:Label:cmd...]', 'warning'); return; } const type = args[0]; @@ -230,14 +236,32 @@ class FloatingModule { el.type = 'menu'; el.collapsed = true; el.buttons = []; + // Remaining args are btn:Label:command pairs. Quotes or colons separate them. + // Each btn: entry runs until next btn: or end + let btnBuf = ''; for (let i = 3; i < args.length; i++) { - const m = args[i].match(/^btn:(.+?)\|(.+)$/); - if (m) { - el.buttons.push({ label: m[1], command: m[2] }); + if (btnBuf) { + btnBuf += ' ' + args[i]; + } else { + btnBuf = args[i]; + } + // Check if this completes a btn: entry + // btn:Label: remaining text — the label is between first : and second : + const firstColon = btnBuf.indexOf(':'); + if (firstColon === -1) { btnBuf = ''; continue; } // prefix doesn't start with btn: + const secondColon = btnBuf.indexOf(':', firstColon + 1); + if (secondColon === -1) continue; // need more args to find command + const prefix = btnBuf.substring(0, firstColon); + if (prefix !== 'btn') { btnBuf = ''; continue; } + const label = btnBuf.substring(firstColon + 1, secondColon); + const command = btnBuf.substring(secondColon + 1); + if (label && command) { + el.buttons.push({ label, command }); } + btnBuf = ''; } if (el.buttons.length === 0) { - this.terminal.print('No valid sub-buttons. Use btn:Label|command format', 'warning'); + this.terminal.print('No valid sub-buttons. Use btn:Label:command format', 'warning'); return; } break; @@ -328,4 +352,10 @@ class FloatingModule { this._renderAll(); this.terminal.print('All floating elements cleared', 'success'); } + + // ── Enum helpers for autocomplete ── + + _listElementIds() { + return Object.keys(this._elements); + } }
\ No newline at end of file |