aboutsummaryrefslogtreecommitdiff
path: root/modules/ext/floating.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ext/floating.js')
-rw-r--r--modules/ext/floating.js50
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