From 1de711f3586d4142555633e90cce269b3a48ef4d Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 15 Jan 2025 22:36:54 +0100 Subject: [PATCH] added boot menu --- com/isoterminal.js | 45 ++++++++++----------- com/isoterminal/ISOTerminal.js | 65 +++++++++++++++++++++---------- com/isoterminal/feat/jsconsole.js | 44 ++++++++++++++++----- com/isoterminal/feat/term.js | 53 ++++++++++++++++++++++++- 4 files changed, 155 insertions(+), 52 deletions(-) diff --git a/com/isoterminal.js b/com/isoterminal.js index 759706f..7c6b647 100644 --- a/com/isoterminal.js +++ b/com/isoterminal.js @@ -2,28 +2,28 @@ * * css/html template * - * ┌─────────┐ ┌────────────┐ ┌─────────────┐ exit-AR - * ┌───────►│ com/dom ┼──►│ com/window ├─►│ domrenderer │◄────────── exit-VR ◄─┐ - * │ └─────────┘ └────────────┘ └─────▲───────┘ │ - * │ │ ┌───────────────┐ │ - * ┌──────────┴────────┐ ┌─────┴──────┐ │ xterm.js │ ┌─────────────────────────────┐ - * │ com/isoterminal ├────────────────────────────►│com/xterm.js│◄─┤ │ │com/html-as-texture-in-XR.js │ - * └────────┬─┬────────┘ └──┬──────┬▲─┘ │ xterm.css │ └─────────────────────────────┘ - * │ │ ┌────────┐ ┌─────────▼──┐ ││ └───────────────┘ │ ▲ - * │ └───────►│ plane ├─────►text───┼►canvas │◄────────────────── enter-VR │ │ - * │ └────────┘ └────────────┘ ││ enter-AR ◄─┘ │ - * │ renderer=canvas ││ │ - * │ ││ │ - * │ ISOTerminal.js ││ │ - * │ ┌───────────────────────────┐◄────┘│ │ - * │ │ com/isoterminal/worker.js ├──────┘ │ - * │ └──────────────┌────────────┤ │ - * │ │ v86.js │ │ - * │ │ feat/*.js │ │ - * │ │ libv86.js │ │ - * │ └────────────┘ │ - * │ │ - * └────────────────────────────────────────────────────────────────────────────────────┘ + * ┌─────────┐ ┌────────────┐ exit-AR + * ┌───────►│ com/dom ┼──►│ com/window ├───────────────── exit-VR ◄─┐ + * │ └─────────┘ └───────────┬┘ │ + * │ │ │ + * ┌──────────┴────────┐ │ ┌───────────┐ ┌─────────────────────────────┐ + * │ com/isoterminal ├────────────────────────────►│com/term.js│ │com/html-as-texture-in-XR.js │ + * └────────┬─┬────────┘ │ └──┬─────┬▲─┘ └─────────────────────────────┘ + * │ │ ┌────────┐ ┌──▼──────▼──────┐ ││ │ + * │ └───────►│ plane ├─────►text───┼►div#isoterminal│◄────────────────── enter-VR │ + * │ └────────┘ └────────────────┘ enter-AR ◄─┘ + * │ │ + * │ │ + * │ ISOTerminal.js + * │ ┌───────────────────────────┐ + * │ │ com/isoterminal/worker.js ├ + * │ └──────────────┌────────────┤ + * │ │ │ v86.js │ + * │ │ │ feat/*.js │ + * │ │ │ libv86.js │ + * │ │ └────────────┘ + * │ │ + * └─────────────────────┘ * * NOTE: For convenience reasons, events are forwarded between com/isoterminal.js, worker.js and ISOTerminal * Instead of a melting pot of different functionnames, events are flowing through everything (ISOTerminal.emit()) @@ -39,6 +39,7 @@ if( typeof AFRAME != 'undefined '){ height: { type: 'number',"default": 600 }, depth: { type: 'number',"default": 0.03 }, lineHeight: { type: 'number',"default": 18 }, + prompt: { type: 'boolean', "default": true }, // boot straight into ISO or give user choice padding: { type: 'number',"default": 18 }, maximized: { type: 'boolean',"default":false}, minimized: { type: 'boolean',"default":false}, diff --git a/com/isoterminal/ISOTerminal.js b/com/isoterminal/ISOTerminal.js index 8e54cbb..2a8d17c 100644 --- a/com/isoterminal/ISOTerminal.js +++ b/com/isoterminal/ISOTerminal.js @@ -138,6 +138,7 @@ ISOTerminal.prototype.start = function(opts){ //disable_jit: false, filesystem: {}, autostart: true, + prompt: this.opts.prompt, debug: this.opts.debug ? true : false }; @@ -160,10 +161,8 @@ ISOTerminal.prototype.setupWorker = function(opts){ return this } +ISOTerminal.prototype.getLoaderMsg = function(){ -ISOTerminal.prototype.startVM = function(opts){ - - this.emit('runISO',{...opts, bufferLatency: this.opts.bufferLatency }) const loading = [ 'loading quantum bits and bytes', 'preparing quantum flux capacitors', @@ -209,7 +208,7 @@ ISOTerminal.prototype.startVM = function(opts){ "Switching to Linux promotes sustainability by reducing demand for new gadgets and lowering e-waste" ] - const motd = ` + let motd = ` \r . . ____ _____________ ________. ._. ._. . . \r . . .\\ \\/ /\\______ \\/ _____// | \\. . \r . . . \\ / | _/\\_____ \\/ ~ \\ . @@ -219,25 +218,29 @@ ISOTerminal.prototype.startVM = function(opts){ \r ▬▬▬▬▬▬▬▬ https://xrsh.isvery.ninja ▬▬▬▬▬▬▬▬▬▬▬▬ \r local-first, polyglot, unixy WebXR IDE & runtime \r -\r credits -\r ------- -\r @nlnet@nlnet.nl -\r @lvk@mastodon.online -\r @utopiah@mastodon.pirateparty.be  -\r https://www.w3.org/TR/webxr -\r https://xrfragment.org -\r https://threejs.org -\r https://aframe.org -\r https://busybox.net -\r https://buildroot.org - ` +\r credits +\r ------- +\r @nlnet@nlnet.nl +\r @lvk@mastodon.online +\r @utopiah@mastodon.pirateparty.be  +\r https://www.w3.org/TR/webxr +\r https://xrfragment.org +\r https://threejs.org +\r https://aframe.org +\r https://busybox.net +\r https://buildroot.org +\r` const text_color = "\r" const text_reset = "\033[0m" - const loadmsg = "\n\r "+loading[ Math.floor(Math.random()*1000) % loading.length ] + "..please wait" - const empowermsg = "\n\r "+text_reset+'"'+empower[ Math.floor(Math.random()*1000) % empower.length ] + '"\n\r' - this.emit('status',loadmsg) - this.emit('serial-output-string', motd + empowermsg + text_color + loadmsg + text_reset+"\n\r") + const loadmsg = "\n\r"+loading[ Math.floor(Math.random()*1000) % loading.length ] + "..please wait \n\n\r" + const empowermsg = "\n\r"+text_reset+'"'+empower[ Math.floor(Math.random()*1000) % empower.length ] + '"\n\r' + return { motd, text_color, text_reset, loadmsg, empowermsg} +} + +ISOTerminal.prototype.startVM = function(opts){ + + this.v86opts = opts this.addEventListener('emulator-started', async (e) => { @@ -264,6 +267,28 @@ ISOTerminal.prototype.startVM = function(opts){ }) }); + let msglib = this.getLoaderMsg() + let msg = msglib.motd + + if( this.opts.prompt ){ + msg += `\r +\r 1) boot ${String(this.opts.iso || "").replace(/.*\//,'')} Linux ❤️ +\r 2) just give me a javascript-console in WebXR [=instant] +\r +\renter number> ` + }else{ + bootISO() + } + this.emit('status',msglib.loadmsg) + this.emit('serial-output-string', msg) + +} + +ISOTerminal.prototype.bootISO = function(){ + let msglib = this.getLoaderMsg() + let msg = "\n\r" + msglib.empowermsg + msglib.text_color + msglib.loadmsg + msglib.text_reset + this.emit('serial-output-string', msg) + this.emit('runISO',{...this.v86opts, bufferLatency: this.opts.bufferLatency }) } diff --git a/com/isoterminal/feat/jsconsole.js b/com/isoterminal/feat/jsconsole.js index 0e2693a..d9511a7 100644 --- a/com/isoterminal/feat/jsconsole.js +++ b/com/isoterminal/feat/jsconsole.js @@ -3,38 +3,45 @@ ISOTerminal.prototype.redirectConsole = function(handler){ const dir = console.dir; const err = console.error; const warn = console.warn; + const addLineFeeds = (str) => str.replace(/\n/g,"\n\r") + console.log = (...args)=>{ const textArg = args[0]; - handler(textArg+'\n'); + handler( addLineFeeds(textArg) ); log.apply(log, args); }; console.error = (...args)=>{ const textArg = args[0] - handler( textArg+'\n', '\x1b[31merror\x1b[0m'); + handler( addLineFeeds(textArg), '\x1b[31merror\x1b[0m'); err.apply(log, args); }; console.dir = (...args)=>{ const textArg = args[0] - handler( JSON.stringify(textArg,null,2)+'\n'); + let str = JSON.stringify(textArg,null,2)+'\n' + handler( addLineFeeds(str) ) dir.apply(log, args); }; console.warn = (...args)=>{ const textArg = args[0] - handler(textArg+'\n','\x1b[38;5;208mwarn\x1b[0m'); + handler( addLineFeeds(textArg),'\x1b[38;5;208mwarn\x1b[0m'); err.apply(log, args); }; } -ISOTerminal.addEventListener('emulator-started', function(){ +ISOTerminal.prototype.enableConsole = function(opts){ + + opts = opts || {stdout:false} this.redirectConsole( (str,prefix) => { - let finalStr = "" - prefix = prefix ? prefix+' ' : ' ' + let finalStr = opts.stdout ? "\n\r" : "" + prefix = prefix ? prefix+' ' : '' str.trim().split("\n").map( (line) => { - finalStr += '\x1b[38;5;165m/dev/browser: \x1b[0m'+prefix+line+'\n' + finalStr += `${opts.stdout ? '' : "\x1b[38;5;165m/dev/browser: \x1b[0m"}`+prefix+line+'\n' }) - this.emit('append_file', ["/dev/browser/console",finalStr]) + if( opts.stdout ){ + this.emit('serial-output-string', finalStr) + }else this.emit('append_file', ["/dev/browser/console",finalStr]) }) window.addEventListener('error', function(event) { @@ -49,4 +56,23 @@ ISOTerminal.addEventListener('emulator-started', function(){ console.error(event); }); + if( opts.stdout ){ + this.emit('serial-output-string', "\n\n\r☑ initialized javascript console\n"); + this.emit('serial-output-string', "\r☑ please use these functions to print:\n"); + this.emit('serial-output-string', "\r└☑ console.log(\"foo\")\n"); + this.emit('serial-output-string', "\r└☑ console.warn(\"foo\")\n"); + this.emit('serial-output-string', "\r└☑ console.dir({foo:12})\n"); + this.emit('serial-output-string', "\r└☑ console.error(\"foo\")\n"); + this.emit('serial-output-string', "\r\n"); + } +} + +ISOTerminal.addEventListener('emulator-started', function(){ + this.enableConsole() +}) + +ISOTerminal.addEventListener('init', function(){ + this.addEventListener('enable-console', function(opts){ + this.enableConsole(opts.detail) + }) }) diff --git a/com/isoterminal/feat/term.js b/com/isoterminal/feat/term.js index db6e421..8122667 100644 --- a/com/isoterminal/feat/term.js +++ b/com/isoterminal/feat/term.js @@ -69,8 +69,59 @@ ISOTerminal.prototype.TermInit = function(){ ]; this.term.open(el) this.term.el = el + this.term.prompt = "\r> " - this.term.setKeyHandler( (ch) => this.send(ch) ) + + // you can override this REPL in index.html via : + // + // + // + // this might change in the future into something + // more convenient + this.term.setKeyHandler( (ch) => { + if( this.ready ){ + this.send(ch) // send to v86 webworker + }else{ + if( (ch == "\n" || ch == "\r") && typeof this.console == 'undefined' ){ + switch( this.lastChar ){ + case '1': this.bootISO(); break; + case '2': { + this.emit('enable-console',{stdout:true}) + this.console = "" + setTimeout( () => this.term.write( this.term.prompt), 100 ) + break; + } + } + }else if( this.console != undefined ){ + this.term.write(ch) + const reset = () => { + this.console = "" + setTimeout( () => this.term.write( this.term.prompt),100) + } + if( (ch == "\n" || ch == "\r") ){ + try{ + if( this.console ) eval(this.console) + reset() + }catch(e){ + reset() + throw e // re throw + } + }else{ + this.console += ch + } + }else{ + this.term.write(ch) + } + this.lastChar = ch + } + }) aEntity.el.addEventListener('focus', () => el.querySelector("textarea").focus() ) aEntity.el.addEventListener('serial-output-string', (e) => { this.term.write(e.detail)