added new build
This commit is contained in:
parent
5139be3965
commit
368daefbe6
8 changed files with 206 additions and 124 deletions
10
index.html
10
index.html
File diff suppressed because one or more lines are too long
3
make
3
make
|
@ -41,7 +41,7 @@ standalone(){ # build standalone xrsh.com binary
|
|||
echo "document.head.innerHTML += \`<style type='text/css'>"
|
||||
cat src/index.css
|
||||
echo -e "</style>\`;\n"
|
||||
cat src/assets/winbox* src/com/{isoterminal,data2event,dom,html-as-texture-in-xr,pastedrop,require,window}.js src/com/lib/*.js src/com/isoterminal/{ISOTerminal.js,term.js,feat/boot.js,feat/jsconsole.js,feat/term.js}
|
||||
cat src/assets/winbox* src/com/{isoterminal,data2event,dom,html-as-texture-in-xr,pastedrop,require,window}.js src/com/lib/*.js src/com/isoterminal/{ISOTerminal.js,term.js,feat/boot.js,feat/jsconsole.js,feat/term.js,feat/remotekeyboard.js}
|
||||
echo "// mark above libs as pre-required in require.js"
|
||||
echo "AFRAME.utils.require.required = {";
|
||||
echo " window: true,"
|
||||
|
@ -68,6 +68,7 @@ standalone(){ # build standalone xrsh.com binary
|
|||
echo " fbtermjs: true"
|
||||
echo " };"
|
||||
} > xrsh.js
|
||||
ls -lh xrsh.js
|
||||
}
|
||||
|
||||
test -z "$1" && { exec; jslib; }
|
||||
|
|
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>xrsh v0.142</title>
|
||||
<title>xrsh v0.143</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<link rel="stylesheet" href="./index.css"></link>
|
||||
|
@ -20,23 +20,7 @@
|
|||
obb-collider="showColliders:false"
|
||||
raycaster="objects: [html]; interval:100;">
|
||||
|
||||
<!--
|
||||
<a-assets timeout="1000">
|
||||
<a-asset-item id="environment" src="https://coderofsalvation.github.io/xrsh-media/assets/background.glb"></a-asset-item>
|
||||
<a-mixin id="menuitem" geometry="primitive: plane; width: 0.15; height: 0.15; depth: 0.02" obb-collider="size: 0.03 0.03 0.03" ></a-mixin>
|
||||
<a-mixin id="menubutton" geometry="primitive: circle; radius: 0.025" material="side: double; color:#4C73FE"
|
||||
obb-collider="size: 0.03 0.03 0.03" position="-0.003 -0.027 -0.077" rotation="94.53 -6.35 -59.0"></a-mixin>
|
||||
</a-assets>
|
||||
|
||||
<a-entity helloworld></a-entity>
|
||||
<a-entity helloworld-window></a-entity>
|
||||
<a-entity save></a-entity>
|
||||
|
||||
<a-entity launcher="attach: #left-hand; fingerTip: #right-hand;" dom position="-0.017 -0.094 -0.085" rotation="133.19 -24.75 -203.1"></a-entity>
|
||||
<a-entity launcher-optional="comps: cast,aframestats,paste,save,xrfragments,example/helloworld-iframe,example/helloworld-htmlform,example/helloworld-window,look-controls-toggle,wasd-controls-toggle"></a-entity>
|
||||
<a-entity noxrf gltf-model="#environment" hide-on-enter-ar></a-entity>
|
||||
-->
|
||||
<a-entity isoterminal="iso: ./../xrsh.iso" position="0 1.6 -0.3"></a-entity>
|
||||
<a-entity isoterminal="iso: ./../xrsh.iso; overlayfs: /package.overlayfs.zip" position="0 1.6 -0.3"></a-entity>
|
||||
|
||||
<a-entity id="player" >
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera" wasd-controls com="uri: com/control/gaze-touch-to-click.js"></a-entity>
|
||||
|
@ -58,6 +42,10 @@
|
|||
</body>
|
||||
|
||||
<script>
|
||||
|
||||
// HOWDY DEVELOPER!
|
||||
// for a mimimal boilerplate see this codepen instead: https://codepen.io/coderofsalvation/pen/wBwRpew
|
||||
|
||||
document.querySelector('a-scene').addEventListener('isoterminal_init', function(e){
|
||||
|
||||
// (OPTIONAL) override/extend bootmenu-array with your own REPL(s)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit aa5e6849cb93bdfd8391927c776f0b2c1b8d6bf3
|
||||
Subproject commit 04275e3f2fb9a4c7bc232e81be016c8ff44e0292
|
BIN
xrsh.com
BIN
xrsh.com
Binary file not shown.
|
@ -1 +1 @@
|
|||
e05212c68b16ff502dddd30e95d61a8f89e66d2a59ba09ebe377b83d099d91ca xrsh.com
|
||||
199e5555c3bedcc37b53491a1228868b3d2046578913a259b3f140ce0347d1a2 xrsh.com
|
||||
|
|
289
xrsh.js
289
xrsh.js
|
@ -252,7 +252,7 @@ e.removeClass=function(a){this.g.classList.remove(a);return this};e.toggleClass=
|
|||
* | property | type | default | info |
|
||||
* |------------------|-----------|------------------------|------|
|
||||
* | `iso` | `string` | https`//forgejo.isvery.ninja/assets/xrsh-buildroot/main/xrsh.iso" | |
|
||||
* | `overlayfs` | `string` | *WORK-IN-PROGRESS* | |
|
||||
* | `overlayfs` | `string` | '' | zip URL/file to autoextract on top of filesystem |
|
||||
* | `width` | `number` | 800 ||
|
||||
* | `height` | `number` | 600 ||
|
||||
* | `depth` | `number` | 0.03 ||
|
||||
|
@ -532,14 +532,15 @@ if( typeof AFRAME != 'undefined '){
|
|||
await AFRAME.utils.require(this.requires)
|
||||
|
||||
let features = { // ISOTerminal plugins
|
||||
boot: "com/isoterminal/feat/boot.js",
|
||||
javascript: "com/isoterminal/feat/javascript.js",
|
||||
jsconsole: "com/isoterminal/feat/jsconsole.js",
|
||||
indexhtml: "com/isoterminal/feat/index.html.js",
|
||||
indexjs: "com/isoterminal/feat/index.js.js",
|
||||
autorestore: "com/isoterminal/feat/autorestore.js",
|
||||
pastedropFeat: "com/isoterminal/feat/pastedrop.js",
|
||||
httpfs: "com/isoterminal/feat/httpfs.js",
|
||||
boot: "com/isoterminal/feat/boot.js",
|
||||
javascript: "com/isoterminal/feat/javascript.js",
|
||||
jsconsole: "com/isoterminal/feat/jsconsole.js",
|
||||
remotekeyboard: "com/isoterminal/feat/remotekeyboard.js",
|
||||
indexhtml: "com/isoterminal/feat/index.html.js",
|
||||
indexjs: "com/isoterminal/feat/index.js.js",
|
||||
autorestore: "com/isoterminal/feat/autorestore.js",
|
||||
pastedropFeat: "com/isoterminal/feat/pastedrop.js",
|
||||
httpfs: "com/isoterminal/feat/httpfs.js",
|
||||
}
|
||||
if( this.data.emulator == 'fbterm' ){
|
||||
features['fbtermjs'] = "com/isoterminal/term.js"
|
||||
|
@ -1557,6 +1558,7 @@ ISOTerminal.prototype.start = function(opts){
|
|||
// },
|
||||
//screen_dummy: true,
|
||||
//disable_jit: false,
|
||||
overlayfs: this.opts.overlayfs,
|
||||
filesystem: {},
|
||||
autostart: true,
|
||||
prompt: this.opts.prompt,
|
||||
|
@ -1632,26 +1634,24 @@ ISOTerminal.prototype.getLoaderMsg = function(){
|
|||
]
|
||||
|
||||
let motd = `
|
||||
\r[38;5;57m . . ____ _____________ ________. ._. ._. . .
|
||||
\r[38;5;93m . . .\\ \\/ /\\______ \\/ _____// | \\. .
|
||||
\r[38;5;93m . . . \\ / | _/\\_____ \\/ ~ \\ .
|
||||
\r[38;5;129m . . . / \\ | | \\/ \\ Y / .
|
||||
\r[38;5;165m . . ./___/\\ \\ |____|_ /_______ /\\___|_ /. .
|
||||
\r[38;5;201m . . . . . .\\_/. . . . \\/ . . . .\\/ . . _ \\/ . .
|
||||
\r[38;5;165m ▬▬▬▬▬▬▬▬ [38;5;51mhttps://xrsh.isvery.ninja[38;5;165m ▬▬▬▬▬▬▬▬▬▬▬▬
|
||||
\r[38;5;165m local-first, polyglot, unixy WebXR IDE & runtime
|
||||
\r[38;5;57m. . ____ _____________ ________. ._. ._. . .
|
||||
\r[38;5;93m. . .\\ \\/ /\\______ \\/ _____// | \\. .
|
||||
\r[38;5;93m. . . \\ / | _/\\_____ \\/ ~ \\ .
|
||||
\r[38;5;129m. . . / \\ | | \\/ \\ Y / .
|
||||
\r[38;5;165m. . ./___/\\ \\ |____|_ /_______ /\\___|_ /. .
|
||||
\r[38;5;201m. . . . . .\\_/. . . . \\/ . . . .\\/ . . _ \\/ . .
|
||||
\r[38;5;165m▬▬▬▬▬▬▬▬ [38;5;51mhttps://xrsh.isvery.ninja[38;5;165m ▬▬▬▬▬▬▬▬▬▬▬▬
|
||||
\r[38;5;165mlocal-first, polyglot, unixy WebXR IDE & runtime
|
||||
\r[38;5;57m
|
||||
\r credits
|
||||
\r -------
|
||||
\r @nlnet@nlnet.nl
|
||||
\r @lvk@mastodon.online
|
||||
\r @utopiah@mastodon.pirateparty.be [38;5;51m
|
||||
\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
|
||||
\rcredits
|
||||
\r-------
|
||||
\r[38;5;51mhttps://www.w3.org/TR/webxr
|
||||
\rhttps://xrfragment.org
|
||||
\rhttps://threejs.org
|
||||
\rhttps://aframe.org
|
||||
\rhttps://busybox.net
|
||||
\rhttps://buildroot.org
|
||||
\rfediverse: @lvk@mastodon.online @utopiah@mastodon.pirateparty.be @nlnet@nlnet.nl
|
||||
\r`
|
||||
|
||||
const text_color = "\r[38;5;129m"
|
||||
|
@ -1667,16 +1667,6 @@ ISOTerminal.prototype.startVM = function(opts){
|
|||
|
||||
this.addEventListener('emulator-started', async (e) => {
|
||||
|
||||
// OVERLAY FS *FIXME*
|
||||
//if( me.opts.overlayfs ){
|
||||
// fetch(me.opts.overlayfs)
|
||||
// .then( (f) => {
|
||||
// f.arrayBuffer().then( (buf) => {
|
||||
// emulator.create_file('overlayfs.zip', new Uint8Array(buf) )
|
||||
// })
|
||||
// })
|
||||
//}
|
||||
|
||||
let line = ''
|
||||
this.ready = false
|
||||
|
||||
|
@ -1705,6 +1695,7 @@ ISOTerminal.prototype.bootISO = function(){
|
|||
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 })
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -2059,7 +2050,7 @@ Term.prototype.refresh = function(ymin, ymax)
|
|||
|
||||
function is_http_link_char(c)
|
||||
{
|
||||
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=`.";
|
||||
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=%`.";
|
||||
return str.indexOf(String.fromCharCode(c)) >= 0;
|
||||
}
|
||||
|
||||
|
@ -2118,7 +2109,7 @@ Term.prototype.refresh = function(ymin, ymax)
|
|||
outline += '</span>';
|
||||
last_attr = this.def_attr;
|
||||
}
|
||||
outline += "<a href='" + http_link_str + "' onclick='return Term.prototype.href(this)'>";
|
||||
outline += "<a href='" + http_link_str + "' onclick='return Term.prototype.href(this)' target='_blank'>";
|
||||
}
|
||||
}
|
||||
if (i == cx) {
|
||||
|
@ -2814,9 +2805,8 @@ Term.prototype.interceptBrowserExit = function (ev)
|
|||
Term.prototype.keyDownHandler = function (ev)
|
||||
{
|
||||
var str;
|
||||
|
||||
this.interceptBrowserExit(ev);
|
||||
|
||||
|
||||
str="";
|
||||
switch(ev.keyCode) {
|
||||
case 8: /* backspace */
|
||||
|
@ -3231,9 +3221,9 @@ ISOTerminal.prototype.bootMenu = function(e){
|
|||
this.boot.menu.selected = false // reset
|
||||
let msg = '\n\r'
|
||||
this.boot.menu.map( (m) => {
|
||||
msg += `\r[36m ${m.key})[0m ${m.title(this.opts)}\n`
|
||||
msg += `\r[36m${m.key})[0m ${m.title(this.opts)}\n`
|
||||
})
|
||||
if( this.boot.menu.length ) msg += `\n\r enter choice> `
|
||||
msg += `\n\r[36menter choice>[0m `
|
||||
this.send(msg)
|
||||
}
|
||||
|
||||
|
@ -3270,58 +3260,23 @@ if( typeof window.PromiseWorker != 'undefined' ){ // if xrsh v86 is able to run
|
|||
{
|
||||
key: "1",
|
||||
title: (opts) => `boot [31m${String(opts.iso || "").replace(/.*\//,'')}[0m Linux ❤️ `,
|
||||
init: function(){ this.bootISO() },
|
||||
init: function(){
|
||||
|
||||
// hack to notify href clicks
|
||||
Term.prototype.href = (a) => {
|
||||
if( a.href ){
|
||||
this.exec(`source /etc/profile.sh; hook href "${a.href}"`)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
this.bootISO()
|
||||
},
|
||||
keyHandler: function(ch){ this.send(ch) } // send to v86 webworker
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// REPL: jsconsole
|
||||
ISOTerminal.prototype.boot.menu.push(
|
||||
{
|
||||
key: "j",
|
||||
title: (opts) => "just give me an javascript-console in WebXR instantly",
|
||||
init: function(){
|
||||
this.prompt = "\r[36m>[0m "
|
||||
this.emit('enable-console',{stdout:true})
|
||||
this.emit('status',"javascript console")
|
||||
this.console = ""
|
||||
setTimeout( () => {
|
||||
this.send(this.prompt)
|
||||
}, 100 )
|
||||
},
|
||||
keyHandler: function(ch){
|
||||
let erase = false
|
||||
if( ch == '\x7F' ){
|
||||
ch = "\b \b" // why does write() not just support \x7F ?
|
||||
erase = true
|
||||
}
|
||||
this.send(ch)
|
||||
const reset = () => {
|
||||
this.console = ""
|
||||
setTimeout( () => {
|
||||
if( this.boot.menu.selected ) this.send(this.prompt)
|
||||
},100)
|
||||
}
|
||||
if( (ch == "\n" || ch == "\r") ){
|
||||
try{
|
||||
this.send("\n\r")
|
||||
if( this.console ) eval(this.console)
|
||||
reset()
|
||||
}catch(e){
|
||||
reset()
|
||||
throw e // re throw
|
||||
}
|
||||
}else{
|
||||
if( erase ){
|
||||
this.console = this.console.split('').slice(0,-1).join('')
|
||||
}else{
|
||||
this.console += ch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
ISOTerminal.prototype.redirectConsole = function(handler){
|
||||
const log = console.log;
|
||||
const dir = console.dir;
|
||||
|
@ -3403,6 +3358,54 @@ ISOTerminal.addEventListener('init', function(){
|
|||
this.addEventListener('enable-console', function(opts){
|
||||
this.enableConsole(opts.detail)
|
||||
})
|
||||
|
||||
// REPL: jsconsole
|
||||
ISOTerminal.prototype.boot.menu.push(
|
||||
{
|
||||
key: "j",
|
||||
title: (opts) => "just give me an javascript-console in WebXR instantly",
|
||||
init: function(){
|
||||
this.prompt = "\r[36m>[0m "
|
||||
this.emit('enable-console',{stdout:true})
|
||||
this.emit('status',"javascript console")
|
||||
this.console = ""
|
||||
setTimeout( () => {
|
||||
this.send(this.prompt)
|
||||
}, 100 )
|
||||
},
|
||||
keyHandler: function(ch){
|
||||
let erase = false
|
||||
if( ch == '\x7F' ){
|
||||
ch = "\b \b" // why does write() not just support \x7F ?
|
||||
erase = true
|
||||
}
|
||||
this.send(ch)
|
||||
const reset = () => {
|
||||
this.console = ""
|
||||
setTimeout( () => {
|
||||
if( this.boot.menu.selected ) this.send(this.prompt)
|
||||
},100)
|
||||
}
|
||||
if( (ch == "\n" || ch == "\r") ){
|
||||
try{
|
||||
this.send("\n\r")
|
||||
if( this.console ) eval(this.console)
|
||||
reset()
|
||||
}catch(e){
|
||||
reset()
|
||||
throw e // re throw
|
||||
}
|
||||
}else{
|
||||
if( erase ){
|
||||
this.console = this.console.split('').slice(0,-1).join('')
|
||||
}else{
|
||||
this.console += ch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
})
|
||||
ISOTerminal.addEventListener('init', function(){
|
||||
this.TermInit()
|
||||
|
@ -3446,13 +3449,8 @@ ISOTerminal.prototype.TermInit = function(){
|
|||
}
|
||||
}( Term.prototype.keyDownHandler )
|
||||
|
||||
Term.prototype.href = (a) => {
|
||||
if( a.href ){
|
||||
this.exec(`source /etc/profile.sh; hook href "${a.href}"`)
|
||||
}
|
||||
return false
|
||||
}
|
||||
this.term = new Term( opts.termOpts )
|
||||
Term.prototype.href = (a) => true
|
||||
this.term.colors = [
|
||||
/* normal */
|
||||
"#000000",
|
||||
|
@ -3499,7 +3497,7 @@ ISOTerminal.prototype.TermInit = function(){
|
|||
})
|
||||
}
|
||||
}else{
|
||||
this.term.write(ch)
|
||||
this.term.write( ch )
|
||||
}
|
||||
if( !erase ) this.lastChar = ch
|
||||
})
|
||||
|
@ -3519,6 +3517,101 @@ ISOTerminal.prototype.TermInit = function(){
|
|||
|
||||
this.addEventListener('term_init', (opts) => setupTerm(opts.detail) )
|
||||
}
|
||||
ISOTerminal.prototype.enableRemoteKeyboard = function(opts){
|
||||
|
||||
let service = {
|
||||
ready: false,
|
||||
reset: (service) => {
|
||||
service.ip = localStorage.getItem("keyboardIP") || ""
|
||||
service.ip = service.ip.trim()
|
||||
service.state = "need-ip"
|
||||
service.attempts = 0
|
||||
},
|
||||
init: function init( mainmenu ){
|
||||
this.emit('status',"")
|
||||
this.emit('enable-console',{stdout:true})
|
||||
service.reset(service)
|
||||
setTimeout( () => {
|
||||
const clearScreen = "[1;1H[2J\r"
|
||||
this.send(clearScreen);
|
||||
this.send(`\n\rfor instructions\n\rsee ${document.location.origin}/index.html#Remote%20keyboard\n\n\r`)
|
||||
this.send("enter 'm' for mainmenu\n\n\r")
|
||||
this.send("[36mkeyboard ip-adress> [0m")
|
||||
// autofill ip
|
||||
if( service.ip ){
|
||||
for( let i = 0; i < service.ip.length; i++ ) this.send(service.ip.charAt(i))
|
||||
}
|
||||
}, 100 )
|
||||
},
|
||||
server: (term) => {
|
||||
try{
|
||||
service.addr = `ws://${service.ip}:9090/`;
|
||||
service.ws = new WebSocket(service.addr)
|
||||
service.ws.addEventListener("open", () => {
|
||||
if( service.state == 'listening' ){
|
||||
this.send(`\n\rconnected to ${service.addr}! \\o/\n\r`)
|
||||
this.bootMenu()
|
||||
}
|
||||
service.state = 'receiving'
|
||||
})
|
||||
service.ws.addEventListener("close", () => {
|
||||
service.attempts += 1
|
||||
if( service.attempts > 3 && service.state == 'listening'){
|
||||
service.reset(service)
|
||||
this.send(`\n\roops..I did not detect any connection :/\n\r`)
|
||||
localStorage.setItem("keyboardIP","") // reset ip
|
||||
this.bootMenu()
|
||||
}else setTimeout( () => service.server(term), 1000 ) // retry connection
|
||||
}) // retry on EOF
|
||||
service.ws.onmessage = function(event) {
|
||||
if( !event.data ) return
|
||||
event.data.arrayBuffer().then( (buf) => {
|
||||
const arr = new Uint8Array(buf)
|
||||
let string = Array.from(arr, byte => String.fromCharCode(byte)).join('')
|
||||
term.term.handler(string)
|
||||
service.state = 'receiving'
|
||||
localStorage.setItem("keyboardIP",service.ip) // save ip for later
|
||||
})
|
||||
};
|
||||
}catch(e){
|
||||
console.error(e)
|
||||
service.reset(service)
|
||||
localStorage.setItem("keyboardIP","") // reset ip
|
||||
this.bootMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize REPL
|
||||
ISOTerminal.prototype.boot.menu.push(
|
||||
{
|
||||
key: "k",
|
||||
title: (opts) => "connect a remote keyboard",
|
||||
init: service.init,
|
||||
keyHandler: function(ch){
|
||||
this.send(ch)
|
||||
if( service.state == 'need-ip'){
|
||||
if( ch == 'm'){
|
||||
this.send("\n\r")
|
||||
this.bootMenu()
|
||||
}else if( ch == '\n' || ch == '\r'){
|
||||
this.send("\n\rwaiting for connection..")
|
||||
service.server(this)
|
||||
service.state = 'listening'
|
||||
}else{
|
||||
service.ip = ch == '\b' ? service.ip.substr(0,this.service.ip.length-1)
|
||||
: service.ip + ch
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ISOTerminal.addEventListener('init', function(){
|
||||
this.enableRemoteKeyboard()
|
||||
})
|
||||
|
||||
// mark above libs as pre-required in require.js
|
||||
AFRAME.utils.require.required = {
|
||||
window: true,
|
||||
|
|
Loading…
Add table
Reference in a new issue