main: work in progress [might break]

This commit is contained in:
Leon van Kammen 2024-09-15 11:18:36 +02:00
parent a3a9fae294
commit 8fcc48dcff
20 changed files with 254 additions and 26 deletions

View File

@ -0,0 +1,32 @@
#!/bin/sh
PID=$$
test -z "$1" && { echo "Usage: html '<b>hello</b>"; exit 0; }
source /etc/profile.sh
test -n "$BROWSER" || { alert warning "/dev/browser not active (are you running outside of v86?)"; }
html="$*"
# if we are run as shebang, use the file as input
test -f "$1" && {
html="$(cat $1 | tail +2)"
}
# below is not ideal
# first I tried /dev/ttyS* https://github.com/copy/v86/issues/530
# and differentiate processes by prefixing output by PID's
# to parse it later with AWK, but it was very hairy
OUTPUT=/mnt/$PID
echo "$html" > /dev/browser/html
sleep 0.1
test -f $OUTPUT && {
cat $OUTPUT
rm $OUTPUT
}
# should we use flock, an awesome way to make processes read/write the same file
# while preventing 1001 concurrency issues?
#
# flock /dev/browser/html -c "echo \"$html\" > /dev/browser/html"

View File

@ -0,0 +1,11 @@
#!/bin/sh
trap 'echo "/bin/infinite: Ctrl-C pressed..infinite does not care.."; sleep 2s' INT
source /etc/profile.sh
loop(){
while sleep 1s; do
"$@"
done
}
loop "$@"

View File

@ -27,7 +27,7 @@
# Put a getty on the serial port # Put a getty on the serial port
#console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL #console::respawn:/sbin/getty -L console 0 vt100 # GENERIC_SERIAL
console::respawn:-/bin/sh #console::respawn:-/bin/sh # vga console
# Auto-login as root on ttyS0 # Auto-login as root on ttyS0
::respawn:/sbin/getty ttyS0 38400 xterm -n -l /bin/sh ::respawn:/sbin/getty ttyS0 38400 xterm -n -l /bin/sh

View File

@ -7,10 +7,15 @@
 . . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .  . . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .
 ▬▬▬▬ https://xrsh.isvery.ninja ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬  ▬▬▬▬ https://xrsh.isvery.ninja ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
Open, local-first, unix hackable & selfcontained XR apps. Open, local-first, polyglot, unix hackable & selfcontained XR apps.
credits: NLnet | @nlnet@nlnet.nl https://nlnet.nl/project credits: NLnet | @nlnet@nlnet.nl https://nlnet.nl/project
all FOSS devs | copy.sh (v86) aframe.io (AFRAME) all FOSS devs | copy.sh (v86) aframe.io (AFRAME)
Leon van Kammen | @lvk@mastodon.online Leon van Kammen | @lvk@mastodon.online
Fabien Benetou | @utopiah@mastodon.pirateparty.be Fabien Benetou | @utopiah@mastodon.pirateparty.be
Please hook up your (bluetooth) keyboard to use xrsh.
Use Ctrl+a+0/1/2/3/.. to switch terminals.
Use Ctrl+a+c to create a new terminal.
Happy hacking! \o/

View File

@ -10,17 +10,23 @@ source /etc/profile.xrsh
# source shell functions # source shell functions
source /etc/profile.sh source /etc/profile.sh
# source user shell defaults
test -f ~/.profile && source ~/.profile
# source js functions # source js functions
test -f /etc/profile.js && chmod +x /etc/profile.js && /etc/profile.js | grep -v undefined test -f /etc/profile.js && chmod +x /etc/profile.js && /etc/profile.js | grep -v undefined
# source user js functions
test -f ~/.profile.js && chmod +x ~/.profile.js && ~/.profile.js | grep -v undefined
## forward not-found commands to javascript (via jsh) ## forward not-found commands to javascript (via jsh)
command_not_found_handle(){ command_not_found_handle(){
echo "[!] '$1' not found, did you mean $1(...) (javascript?)" echo "[!] '$1' not found, did you mean $1(...) (javascript?)"
test -n "$ONBOARDING" && echo "[i] type 'help' for handy commands" test -n "$ONBOARDING" && echo "[i] type 'help' for handy commands"
test -n "$ONBOARDING" || help test -n "$ONBOARDING" || help_tips
} }
help(){ help_tips(){
echo "" echo ""
echo 'TIPS' echo 'TIPS'
echo '----' echo '----'
@ -34,13 +40,16 @@ help(){
echo 'include file into page' "type 'require <url.js|css>'" echo 'include file into page' "type 'require <url.js|css>'"
echo 'create AFRAME a-entity' "type 'a_entity <componentname> [...]" echo 'create AFRAME a-entity' "type 'a_entity <componentname> [...]"
echo '' echo ''
echo 'type "man xrsh" to read the full manual' echo 'type "help" or "man xrsh" to read the full manual'
ONBOARDING=1 ONBOARDING=1
} }
export TERM=xterm-256color export TERM=xterm-256color
export PS1="\[\033[38;5;165m\]> \[\033[0m\]" export PS1="\[\033[38;5;165m\]> \[\033[0m\]"
# aliases
alias ls='ls -ha -w100'
# interactive login # interactive login
[[ -t 0 ]] && { [[ -t 0 ]] && {
test -n "$STY" || { test -n "$STY" || {
@ -49,7 +58,7 @@ export PS1="\[\033[38;5;165m\]> \[\033[0m\]"
# add URL-hash as extra screen session # add URL-hash as extra screen session
test -z "$HASH" || { test -z "$HASH" || {
grep 'screen -t #' /root/.screenrc || { grep 'screen -t #' /root/.screenrc || {
echo "screen -t xrsh+URL 2 /bin/sh -c '${HASH}; sh'" | sed "s/'#/'/g" >> /root/.screenrc echo "screen -t xrsh+URL 3 /bin/sh -c '${HASH}; sh'" | sed "s/'#/'/g" >> /root/.screenrc
} }
} }
screen -Aa -R -T screen-256color -c /root/.screenrc screen -Aa -R -T screen-256color -c /root/.screenrc

View File

@ -1,6 +1,18 @@
#!/bin/js #!/bin/js
window.helloworld = function(){ // do once (remember /etc/profile gets sources multiple times!)
alert("hello world") if( !window['/etc/profile.js'] ){
return "hello world"
const isoterminal = document.querySelector('[isoterminal]').components.isoterminal.isoterminal
const scene = document.querySelector('a-scene')
// map AFRAME events to ~/hook.d/{event}/* triggers
events = ['enter-ar','enter-vr','exit-vr','exit-ar']
events.map( (event) => {
scene.addEventListener( event, (e) => isoterminal.exec("hook "+event) )
})
window['/etc/profile.js'] = true
} }

View File

@ -51,13 +51,10 @@ man(){
cat /root/manual.md | less cat /root/manual.md | less
} }
} }
help(){ man xrsh; }
a_entity(){ infinite(){
code="let el = document.createElement('a-entity')" while sleep 1s; do
for i in "$@"; do "$@"
code="$code;\nel.setAttribute('$i','')\n";
done done
code="document.querySelector('a-scene').appendChild(el)"
echo "$code"
js "$code"
} }

View File

@ -3,13 +3,8 @@
test -d /dev/browser || { test -d /dev/browser || {
setup_links(){ setup_links(){
ln -fs /etc/profile ~/.profile
ln -fs /etc/profile.js ~/.profile.js
ln -fs /etc/profile.sh ~/.profile.sh
ln -fs /etc/motd ~/.motd ln -fs /etc/motd ~/.motd
ln -fs /mnt/profile.browser ~/.profile.browser ln -fs /mnt/profile.browser ~/.profile.browser
ln -fs ~/.profile.js ~/index.js
ln -fs /dev/browser/index.html ~/index.html
chmod +x ~/.profile.js chmod +x ~/.profile.js
} }
@ -18,9 +13,10 @@ test -d /dev/browser || {
echo 1 > /mnt/console.tty echo 1 > /mnt/console.tty
ln -s /mnt/console.tty /dev/browser/tty ln -s /mnt/console.tty /dev/browser/tty
ln -fs /mnt/js /dev/browser/js ln -fs /mnt/js /dev/browser/js
ln -fs /mnt/index.html /dev/browser/html
ln -fs /mnt/console /dev/browser/console ln -fs /mnt/console /dev/browser/console
touch /mnt/console touch /mnt/console
touch /dev/browser/index.html touch /mnt/index.html
} }
setup_network(){ setup_network(){
@ -34,9 +30,28 @@ test -d /dev/browser || {
test -f /mnt/overlayfs.zip && unzip /mnt/overlayfs.zip -d / test -f /mnt/overlayfs.zip && unzip /mnt/overlayfs.zip -d /
} }
setup_incoming_cmds(){
# listen for shell cmds passed to v86 from browser
# (via isoterminal.exec(...))
stty raw < /dev/ttyS1
cat /dev/ttyS1 | xargs -I{} /bin/sh -c 'source /etc/profile; logger "isoterminal.exec({})"; {}'
}
setup_reflect_index_html(){
# listen for writes to index.html and send them to DOM
inotifyd echo /root/index.html | awk '/^w / { system("cat "$2" | grep -vE \"^#!\" > /dev/browser/html") }'
}
setup_reflect_index_js(){
# listen for writes to index.js and send them to DOM
inotifyd echo /root/index.js | awk '/^w / { system("cat "$2" | grep -vE \"^#!\" > /dev/browser/js") }'
}
setup_browser_dev setup_browser_dev
setup_links setup_links
setup_network setup_network
setup_overlayfs setup_overlayfs
setup_incoming_cmds &
setup_reflect_index_html &
setup_reflect_index_js &
} }

View File

@ -0,0 +1,10 @@
help
echo $BROWSER
js 'alert("hello")'
jsh alert hello
jsh
enterVR
enterAR
exitVR
exitAR
tail -n1 -f /dev/browser/console /var/log/messages

View File

@ -0,0 +1,15 @@
alias enterVR='js "document.querySelector(\"a-scene\").enterVR()"'
alias enterAR='js "document.querySelector(\"a-scene\").enterAR()"'
alias exitVR='js "document.querySelector(\"a-scene\").enterVR()"'
alias exitAR='js "document.querySelector(\"a-scene\").enterAR()"'
# (new)user friendlyness
alias vi='echo "HINT: type :q (and press enter) to quit";read;vi';
alias mg='echo "HINT: type Ctrl+c Ctrl-x to quit";read;me';
alias nano='echo "HINT: type Ctrl+x to quit" ;read;nano';
# start index.js
test -f index.js && chmod +x index.js && ./index.js
# start index.html
test -f index.html && chmod +x index.html && ./index.html

View File

@ -0,0 +1,15 @@
#!/bin/js
if( !window['~/.profile.js'] ){ // do once (remember /etc/profile gets sources multiple times!)
const isoterminal = document.querySelector('[isoterminal]').components.isoterminal.isoterminal
const scene = document.querySelector('a-scene')
window.helloworld = function(){
alert("hello world")
return "hello world"
}
window['~/.profile.js'] = true
}

View File

@ -33,5 +33,6 @@ term xterm-256color
defbce on # use current bg color for erased chars defbce on # use current bg color for erased chars
# setup windows # setup windows
screen -t jsconsole 0 tail -f /dev/browser/console screen -t manual 0 /bin/sh -c '/bin/infinite help'
screen -t xrsh 1 screen -t logs 1 /bin/sh -c '/bin/infinite tail -n1 -f /dev/browser/console /var/log/messages'
screen -t xrsh 2

View File

@ -0,0 +1,2 @@
#!/bin/sh
logger "$0: AFRAME fired enter-ar event"

View File

@ -0,0 +1,2 @@
#!/bin/sh
logger "$0: AFRAME fired enter-vr event"

View File

@ -0,0 +1,2 @@
#!/bin/sh
logger "$0 AFRAME fired exit-ar event"

View File

@ -0,0 +1,2 @@
#!/bin/sh
logger "$0: AFRAME fired exit-vr event"

View File

@ -0,0 +1,5 @@
#!/bin/html
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>

View File

@ -0,0 +1,2 @@
#!/bin/js
console.log("/root/index.js: hello world")

View File

@ -1,6 +1,98 @@
XRSH Manual XRSH Manual
=========== ===========
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . ____ _____________ ________. ._. ._. . . . . . . . .
. . _\ \/ /\______ \/ _____// | \. . . . . . . .
. . _ \ / | _/\_____ \/ ~ \ . . . . . . .
_ _ / \ | | \/ \ Y / _ _ _ _ _ _ _
. . /___/\ \ |____|_ /_______ /\___|_ /. . . . . . . .
. . . . . .\_/. . . . \/ . . . .\/ . . _ \/ . . . . . . . .
▬▬▬▬ https://xrsh.isvery.ninja ▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬
Open, local-first, polyglot, unix hackable & selfcontained XR apps.
Using worlds first WebXR linux distro.
credits: NLnet | @nlnet@nlnet.nl https://nlnet.nl/project
all FOSS devs | copy.sh (v86) aframe.io (AFRAME)
Leon van Kammen | @lvk@mastodon.online
Fabien Benetou | @utopiah@mastodon.pirateparty.be
# Getting started
Please hook up your (bluetooth) keyboard to use xrsh.
> tip use ctrl+a+0/1/2/3/.. to switch (GNU) screen terminals (and ctrl+a+c to create new ones)
| usecase | command |
|-----------------------|--------------------------------------------------------|
| js run | js 'alert("hello")' |
| js console.log: | console document.baseURI |
| js inspect: | js "return document.baseURI" |
# Polyglot environment
Currently the following languages are supported:
* shellscript (busybox sh)
* awk (busybox awk v1.33.0)
* python (micropython)
* javascript (via your browser)
* lua (5.3.6)
> TIP: type `ls -la ~/hook.d/alert/*` for examples
# Editors
* vi (busybox vi)
* nano (busybox nano)
* mg (microemacs)
# Boot sequence
The following files are loaded during boot (via `/etc/profile`)
| file | info |
|-----------------------|---------------------------------------------------|
| /etc/profile.xrsh | sets up xrsh environment |
| /etc/profile.sh | global shellscript functions |
| /etc/profile.js | global javascript functions |
| /mnt/profile.browser | environment vars set by browser (`echo $HOSTNAME`)|
| /root/.profile | user shellscript functions/settings |
| /root/.profile.js | user javascript functions |
| /root/.screenrc | GNU screen initialisations |
| https://.../#ls | URI fragment is executed as command in own screen |
> TIP: to keep things portable with future versions of XRSH: modify files in `/root/*`
# Calling terminal from javascript
```javascript
const term = document.querySelector('[isoterminal]').components.isoterminal.isoterminal
term.exec("ls -la")
```
# Calling javascript from terminal
Various options:
1. Just add the `#!/bin/js` shebang to the top of a javascript file (+ chmod +x)
2. Run `js "alert('hello')"` in the shell
3. Run `jsh alert hello` in the shell
4. Run `jsh` to start an interactive shell
# Hybrid Terminal/Browser Events
Events are automatically triggering scripts in `/root/hook.d/{eventname}/*`
> They can be triggered by the following ways
1. from shellscript: `hook myevent` (will trigger **executable** files in /root/hook.d/myevent)
2. from javascript: `isoterminal.exec("hook myevent")` (idem)
3. via jsh: `jsh alert hello` (will trigger **executable** files in /root/hook.d/alert)
These are various ways to enable hybrid eventing between browser and terminal (languages).
# Multiple terminals [GNU screen] # Multiple terminals [GNU screen]
## From the cmdline ## From the cmdline