class FinderModule { constructor() { this.commands = {}; this.terminal = null; } requirements() { return { met: true, missing: [] }; } getHelpInfo() { return { 'find': 'Recursively search VFS files/directories by name (usage: find )', }; } registerCommands() { this.commands['find'] = (args) => this.find(args); } find(args) { if (!args[0]) return this.terminal.print('Usage: find — recursively searches VFS files/dirs matching query', 'warning'); const query = args.join(' ').toLowerCase(); const results = []; this._recurse(this.terminal.fs.root, [], query, results); if (results.length === 0) return this.terminal.print(`No matches for "${query}"`, 'warning'); this.terminal.print(`=== Found ${results.length} match(es) for "${query}" ===`, 'info'); results.forEach(r => { const icon = r.type === 'dir' ? '📁' : '📄'; this.terminal.print(` ${icon} ${r.path}`); }); } _recurse(node, pathParts, query, results) { if (!node || !node.content) return; for (const [name, child] of Object.entries(node.content)) { const fullPath = '/' + [...pathParts, name].join('/'); if (name.toLowerCase().includes(query)) { results.push({ name, path: fullPath, type: child.type || (child.content ? 'dir' : 'file') }); } if (child.content && typeof child.content === 'object') { this._recurse(child, [...pathParts, name], query, results); } } } } if (typeof window.webx11 !== 'undefined' && window.webx11) { webx11.moduleManager.registerModule(new FinderModule(), 'https://webx11.duckdns.org/spaces/newos4/modules/ext/finder.js'); }