mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-28 11:40:11 +03:00
Merge branch 'next/arvo' into jon/doccords
This commit is contained in:
commit
0119eef28d
24
.github/workflows/frontend-test.yml
vendored
24
.github/workflows/frontend-test.yml
vendored
@ -1,24 +0,0 @@
|
||||
name: frontend-test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'pkg/interface/**'
|
||||
- 'pkg/btc-wallet/**'
|
||||
- 'pkg/npm/**'
|
||||
|
||||
jobs:
|
||||
frontend-test:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Test changed frontend packages"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: git fetch --prune
|
||||
- name: 'Setup root deps'
|
||||
run: npm ci
|
||||
- name: 'Setup dependencies'
|
||||
run: npm run bootstrap
|
||||
- name: 'Run tests'
|
||||
run: npm run test -- --since origin/$GITHUB_BASE_REF --include-dependents
|
79
.github/workflows/vere.yml
vendored
79
.github/workflows/vere.yml
vendored
@ -162,86 +162,9 @@ jobs:
|
||||
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
run: nix-build -A docker-image
|
||||
|
||||
mingw:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: >
|
||||
C:\msys64\msys2_shell.cmd -mingw64 -defterm -no-start -here -c
|
||||
". <(cygpath '{0}')"
|
||||
working-directory: ./pkg/urbit
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
lfs: true
|
||||
|
||||
# echo suppresses pacman prompt
|
||||
- run: echo|./configure
|
||||
env:
|
||||
CACHIX_CACHE: ares
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
|
||||
- run: mingw32-make build/urbit
|
||||
- run: mingw32-make test
|
||||
- run: >
|
||||
build/urbit -l -d -B ../../bin/solid.pill -F bus &&
|
||||
curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}'
|
||||
http://localhost:12321
|
||||
|
||||
- name: confirm binary is mostly static
|
||||
run: |
|
||||
if [ -z "$(ldd build/urbit | grep -vi "windows/system32")"]; then
|
||||
echo "it's mostly static"
|
||||
exit 0
|
||||
else
|
||||
echo "dynamic links found:"
|
||||
ldd build/urbit
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
if: inputs.upload
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- uses: google-github-actions/setup-gcloud@v0.6.0
|
||||
if: inputs.upload
|
||||
env:
|
||||
# see https://github.com/google-github-actions/setup-gcloud/issues/100
|
||||
CLOUDSDK_PYTHON: ${{env.pythonLocation}}\python.exe
|
||||
with:
|
||||
service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}
|
||||
project_id: ${{ secrets.GCS_PROJECT }}
|
||||
export_default_credentials: true
|
||||
|
||||
- name: upload binary to bootstrap.urbit.org
|
||||
if: inputs.upload
|
||||
env:
|
||||
CLOUDSDK_PYTHON: ${{env.pythonLocation}}\python.exe
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "real" == "$VERSION_TYPE" ]; then
|
||||
version="$(cat ./version)"
|
||||
else
|
||||
version="${GITHUB_SHA:0:9}"
|
||||
fi
|
||||
|
||||
system="x86_64-windows"
|
||||
target="gs://${UPLOAD_BASE}/${VERE_PACE}/${version}/vere-v${version}-${system}.exe"
|
||||
|
||||
gsutil cp -n ./build/urbit.exe "$target"
|
||||
exitcode=$?
|
||||
|
||||
test $exitcode -eq 0 &&
|
||||
echo "upload to $target complete." ||
|
||||
echo "upload to $target failed.";
|
||||
exit $exitcode
|
||||
|
||||
|
||||
after:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [urbit, mingw]
|
||||
needs: [urbit]
|
||||
if: inputs.upload
|
||||
steps:
|
||||
- uses: google-github-actions/setup-gcloud@v0.2.0
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c4247c64a7d9fc0c0f1d2f017c21dd3464ddfe56529c7d6eef0e64554bd453e8
|
||||
size 7611162
|
||||
oid sha256:bd487cdb8294fdef6878f623bceb893553b36b2a616d22d30017b430361586fb
|
||||
size 3889185
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5123a1ac30b83ec026587574df1ce13a73e72d06588ff68b5c41c09e1bebb5b7
|
||||
size 949962
|
||||
oid sha256:26ff86808886beb831e4a135f478e42ce83ef4a09ad24808b3fe97248ce7a6b7
|
||||
size 1136643
|
||||
|
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e46c7fb35826bcc3352eca8dbfeea3a8bdf1686cf46b3f873fad0c09bc25c5a7
|
||||
size 5715362
|
||||
oid sha256:f4d585474b6df173dc1c172f343192ac88bd3ced1a9c7cf6877402722ac139de
|
||||
size 5748201
|
||||
|
@ -10,9 +10,9 @@
|
||||
:::: :: ::::
|
||||
:: :: ::
|
||||
=> |% :: external structures
|
||||
+$ id @tasession :: session id
|
||||
+$ id sole-id :: session id
|
||||
+$ house :: all state
|
||||
$: %8
|
||||
$: %9
|
||||
egg=@u :: command count
|
||||
hoc=(map id session) :: conversations
|
||||
acl=(set ship) :: remote access whitelist
|
||||
@ -850,12 +850,23 @@
|
||||
=/ poz=vase (dy-sore p.cig)
|
||||
=/ kev=vase
|
||||
=/ kuv=(unit vase) (slew 7 som)
|
||||
?: =(~ q.cig)
|
||||
(fall kuv !>(~))
|
||||
=/ soz=(list [var=term vax=vase])
|
||||
%~ tap by
|
||||
%- ~(run by q.cig)
|
||||
|=(val=(unit dojo-source) ?~(val !>([~ ~]) (dy-vase p.u.val)))
|
||||
:: if the generator takes a named argument "drum-session",
|
||||
:: then if a value isn't already supplied, we set it to the session
|
||||
:: that this dojo instance is being run in.
|
||||
:: (dojo is, indeed, quite coupled with drum.)
|
||||
::
|
||||
=? soz
|
||||
?& ?=(^ kuv)
|
||||
(slab %both %drum-session p.u.kuv)
|
||||
!(~(has by q.cig) %drum-session)
|
||||
==
|
||||
[[%drum-session !>(ses.id)] soz] ::TODO does the who matter?
|
||||
?: =(~ soz)
|
||||
(fall kuv !>(~))
|
||||
~| keyword-arg-failure+~(key by q.cig)
|
||||
%+ slap
|
||||
(with-faces kuv+(need kuv) rep+(with-faces soz) ~)
|
||||
@ -1048,13 +1059,14 @@
|
||||
|= =card:agent:gall
|
||||
^+ +>
|
||||
=? card ?=(%pass -.card)
|
||||
card(p [id p.card])
|
||||
^- card:agent:gall
|
||||
card(p [(scot %p who.id) ses.id p.card])
|
||||
%_(+> moz [card moz])
|
||||
::
|
||||
++ he-diff :: emit update
|
||||
|= fec=sole-effect
|
||||
^+ +>
|
||||
(he-card %give %fact ~[/sole/[id]] %sole-effect !>(fec))
|
||||
(he-card %give %fact ~[(id-to-path:sole id)] %sole-effect !>(fec))
|
||||
::
|
||||
++ he-stop :: abort work
|
||||
^+ .
|
||||
@ -1562,21 +1574,47 @@
|
||||
::
|
||||
++ on-load
|
||||
|= ole=vase
|
||||
^- (quip card:agent:gall _..on-init)
|
||||
|^ =+ old=!<(house-any ole)
|
||||
=? old ?=(%5 -.old)
|
||||
^- house-any
|
||||
^- house-6
|
||||
(house-5-to-6 old)
|
||||
=? old ?=(?(%6 %7) -.old)
|
||||
(house-6-7-to-8 +.old)
|
||||
?> ?=(%8 -.old)
|
||||
`..on-init(state old)
|
||||
=^ caz old
|
||||
?. ?=(%8 -.old) [~ old]
|
||||
(house-8-to-9 old)
|
||||
?> ?=(%9 -.old)
|
||||
[caz ..on-init(state old)]
|
||||
::
|
||||
+$ house-any $%(house house-7 house-6 house-5)
|
||||
+$ house-any $%(house house-8 house-7 house-6 house-5)
|
||||
::
|
||||
+$ id-8 @tasession
|
||||
+$ house-8
|
||||
$: %8
|
||||
egg=@u
|
||||
hoc=(map id-8 session)
|
||||
acl=(set ship)
|
||||
==
|
||||
++ house-8-to-9
|
||||
|= old=house-8
|
||||
^- (quip card:agent:gall house)
|
||||
:- %+ turn ~(tap in ~(key by hoc.old))
|
||||
|= id=@ta
|
||||
^- card:agent:gall
|
||||
[%give %kick ~[/sole/[id]] ~]
|
||||
=- [%9 egg.old - acl.old]
|
||||
%- ~(gas by *(map sole-id session))
|
||||
%+ murn ~(tap by hoc.old)
|
||||
|= [id=@ta s=session]
|
||||
(bind (upgrade-id:sole id) (late s))
|
||||
::
|
||||
+$ house-7 [%7 house-6-7]
|
||||
+$ house-6 [%6 house-6-7]
|
||||
+$ house-6-7
|
||||
$: egg=@u :: command count
|
||||
hoc=(map id session-6) :: conversations
|
||||
hoc=(map id-8 session-6) :: conversations
|
||||
acl=(set ship) :: remote access whitelist
|
||||
== ::
|
||||
+$ session-6 :: per conversation
|
||||
@ -1603,9 +1641,10 @@
|
||||
old(poy ~, -.dir [our.hid %base ud+0])
|
||||
::
|
||||
+$ house-5
|
||||
[%5 egg=@u hoc=(map id session)]
|
||||
[%5 egg=@u hoc=(map id-8 session-6)]
|
||||
++ house-5-to-6
|
||||
|= old=house-5
|
||||
^- house-6
|
||||
[%6 egg.old hoc.old *(set ship)]
|
||||
--
|
||||
::
|
||||
@ -1621,7 +1660,8 @@
|
||||
he-abet:(~(he-type he hid id.act ~ (~(got by hoc) id.act)) act)
|
||||
::
|
||||
%lens-command
|
||||
=+ !<([=id =command:lens] vase)
|
||||
=+ !<([ses=@ta =command:lens] vase)
|
||||
=/ =id [our.hid ses]
|
||||
he-abet:(~(he-lens he hid id ~ (~(got by hoc) id)) command)
|
||||
::
|
||||
%allow-remote-login
|
||||
@ -1659,8 +1699,7 @@
|
||||
?> ?| (team:title our.hid src.hid)
|
||||
(~(has in acl) src.hid)
|
||||
==
|
||||
?> ?=([%sole @ ~] path)
|
||||
=/ id i.t.path
|
||||
=/ =id (need (path-to-id:sole path))
|
||||
=? hoc (~(has by hoc) id)
|
||||
~& [%dojo-peer-replaced id]
|
||||
(~(del by hoc) id)
|
||||
@ -1672,7 +1711,7 @@
|
||||
++ on-leave
|
||||
|= =path
|
||||
?> ?=([%sole *] path)
|
||||
=. hoc (~(del by hoc) t.path)
|
||||
=. hoc (~(del by hoc) (need (path-to-id:sole path)))
|
||||
[~ ..on-init]
|
||||
::
|
||||
++ on-peek
|
||||
@ -1681,13 +1720,15 @@
|
||||
::
|
||||
++ on-agent
|
||||
|= [=wire =sign:agent:gall]
|
||||
?> ?=([@ @ *] wire)
|
||||
=/ =session (~(got by hoc) i.wire)
|
||||
=/ he-full ~(. he hid i.wire ~ session)
|
||||
^- (quip card:agent:gall _..on-init)
|
||||
?> ?=([@ @ @ *] wire)
|
||||
=/ =id [(slav %p i.wire) i.t.wire]
|
||||
=/ =session (~(got by hoc) id)
|
||||
=/ he-full ~(. he hid id ~ session)
|
||||
=^ moves state
|
||||
=< he-abet
|
||||
^+ he
|
||||
?+ i.t.wire ~|([%dojo-bad-on-agent wire -.sign] !!)
|
||||
?+ i.t.t.wire ~|([%dojo-bad-on-agent wire -.sign] !!)
|
||||
%poke (he-unto:he-full t.wire sign)
|
||||
%wool (he-wool:he-full t.wire sign)
|
||||
==
|
||||
@ -1695,14 +1736,16 @@
|
||||
::
|
||||
++ on-arvo
|
||||
|= [=wire =sign-arvo]
|
||||
?> ?=([@ *] wire)
|
||||
=/ =session (~(got by hoc) i.wire)
|
||||
=/ he-full ~(. he hid i.wire ~ session)
|
||||
^- (quip card:agent:gall _..on-init)
|
||||
?> ?=([@ @ *] wire)
|
||||
=/ =id [(slav %p i.wire) i.t.wire]
|
||||
=/ =session (~(got by hoc) id)
|
||||
=/ he-full ~(. he hid id ~ session)
|
||||
=^ moves state
|
||||
=< he-abet
|
||||
?+ +<.sign-arvo ~|([%dojo-bad-take +<.sign-arvo] !!)
|
||||
%writ (he-writ:he-full t.wire +>.sign-arvo)
|
||||
%http-response (he-http-response:he-full t.wire +>.sign-arvo)
|
||||
%writ (he-writ:he-full t.t.wire +>.sign-arvo)
|
||||
%http-response (he-http-response:he-full t.t.wire +>.sign-arvo)
|
||||
==
|
||||
[moves ..on-init]
|
||||
:: if dojo fails unexpectedly, kill whatever each session is working on
|
||||
|
@ -1,8 +1,13 @@
|
||||
:: herm: stand-in for term.c with http interface
|
||||
::
|
||||
/- herm
|
||||
/+ default-agent, dbug, verb
|
||||
:: keep relevant mark conversions in cache for performance
|
||||
::
|
||||
/$ blit-to-json %blit %json
|
||||
/$ json-to-blit %json %blit
|
||||
/$ json-to-task %json %herm-task
|
||||
::
|
||||
=, jael
|
||||
|%
|
||||
+$ state-0 [%0 ~]
|
||||
@ -13,15 +18,18 @@
|
||||
%+ verb |
|
||||
%- agent:dbug
|
||||
^- agent:gall
|
||||
=> |%
|
||||
++ pass-session
|
||||
|= [ses=@tas tas=session-task:dill]
|
||||
[%pass /dill/[ses] %arvo %d %shot ses tas]
|
||||
--
|
||||
|_ =bowl:gall
|
||||
+* this .
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
::
|
||||
++ on-init
|
||||
^- (quip card:agent:gall _this)
|
||||
:: set up dill session subscription
|
||||
::
|
||||
[[%pass [%view %$ ~] %arvo %d %view ~]~ this]
|
||||
[~ this]
|
||||
::
|
||||
++ on-save !>([%0 ~])
|
||||
++ on-load
|
||||
@ -32,47 +40,68 @@
|
||||
++ on-watch
|
||||
|= =path
|
||||
^- (quip card:agent:gall _this)
|
||||
?> =(our src):bowl
|
||||
?> ?=([%session @ %view ~] path)
|
||||
:_ this
|
||||
:: scry prompt and cursor position out of dill for initial response
|
||||
~| path
|
||||
?> ?=([%session @ %view ~] path)
|
||||
=* ses i.t.path
|
||||
:: subscribe to the requested session
|
||||
::
|
||||
=/ base=^path
|
||||
/dx/(scot %p our.bowl)//(scot %da now.bowl)/sessions
|
||||
:~ [%give %fact ~ %blit !>(.^(blit:dill (weld base //line)))]
|
||||
[%give %fact ~ %blit !>(`blit:dill`hop+.^(@ud (weld base //cursor)))]
|
||||
==
|
||||
::NOTE multiple views do not result in multiple subscriptions
|
||||
:: because they go over the same wire/duct
|
||||
::
|
||||
[(pass-session ses %view ~)]~
|
||||
::
|
||||
++ on-arvo
|
||||
|= [=wire =sign-arvo]
|
||||
^- (quip card:agent:gall _this)
|
||||
~| wire
|
||||
?+ wire (on-arvo:def wire sign-arvo)
|
||||
[%tube *] [~ this] :: we no longer care about these
|
||||
::
|
||||
:: pass on dill blits for the session
|
||||
::
|
||||
[%view %$ ~]
|
||||
[%dill @ ~]
|
||||
=* ses i.t.wire
|
||||
?. ?=([%dill %blit *] sign-arvo)
|
||||
~| [%unexpected-sign [- +<]:sign-arvo]
|
||||
!!
|
||||
:_ this
|
||||
%+ turn p.sign-arvo
|
||||
|= =blit:dill
|
||||
[%give %fact [%session %$ %view ~]~ %blit !>(blit)]
|
||||
[%give %fact [%session ses %view ~]~ %blit !>(blit)]
|
||||
::
|
||||
:: clean up old-style subscriptions
|
||||
::
|
||||
[%view @ ~]
|
||||
=* ses i.t.wire
|
||||
:_ this
|
||||
[%pass wire %arvo %d %shot ses %flee ~]~
|
||||
==
|
||||
::
|
||||
++ on-poke
|
||||
|= [=mark =vase]
|
||||
^- (quip card:agent:gall _this)
|
||||
?> =(our src):bowl
|
||||
?. ?=(%belt mark)
|
||||
~| [%unexpected-mark mark]
|
||||
!!
|
||||
:_ this
|
||||
[%pass [%belt %$ ~] %arvo %d %belt !<(belt:dill vase)]~
|
||||
:_ ~
|
||||
?+ mark ~|([%unexpected-mark mark] !!)
|
||||
%belt (pass-session %$ %belt !<(belt:dill vase))
|
||||
%herm-task (pass-session !<(task:herm vase))
|
||||
==
|
||||
::
|
||||
++ on-peek
|
||||
|= =path
|
||||
^- (unit (unit cage))
|
||||
?+ path ~
|
||||
[%x %sessions ~]
|
||||
:+ ~ ~
|
||||
:- %json
|
||||
!> ^- json
|
||||
=- a+(turn ~(tap in -) (lead %s))
|
||||
.^((set @tas) %dy /(scot %p our.bowl)//(scot %da now.bowl)/sessions)
|
||||
==
|
||||
::
|
||||
++ on-leave on-leave:def
|
||||
++ on-peek on-peek:def
|
||||
::
|
||||
++ on-agent on-agent:def
|
||||
++ on-fail on-fail:def
|
||||
--
|
||||
|
@ -2,8 +2,8 @@
|
||||
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|
||||
|%
|
||||
+$ state
|
||||
$~ [%24 *state:drum *state:helm *state:kiln]
|
||||
$>(%24 any-state)
|
||||
$~ [%25 *state:drum *state:helm *state:kiln]
|
||||
$>(%25 any-state)
|
||||
::
|
||||
+$ any-state
|
||||
$% [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
|
||||
@ -25,6 +25,7 @@
|
||||
[%22 drum=state-4:drum helm=state-1:helm kiln=state-9:kiln]
|
||||
[%23 drum=state-4:drum helm=state-2:helm kiln=state-9:kiln]
|
||||
[%24 drum=state-4:drum helm=state-2:helm kiln=state-10:kiln]
|
||||
[%25 drum=state-5:drum helm=state-2:helm kiln=state-10:kiln]
|
||||
==
|
||||
+$ any-state-tuple
|
||||
$: drum=any-state:drum
|
||||
@ -92,8 +93,7 @@
|
||||
::
|
||||
?+ mark (on-poke:def mark vase)
|
||||
%atom poke-helm(mark %helm-atom)
|
||||
%dill-belt poke-drum(mark %drum-dill-belt)
|
||||
%dill-blit poke-drum(mark %drum-dill-blit)
|
||||
%dill-poke poke-drum
|
||||
%hood-sync poke-kiln(mark %kiln-sync)
|
||||
%write-sec-atom poke-helm(mark %helm-write-sec-atom)
|
||||
==
|
||||
@ -108,6 +108,7 @@
|
||||
?+ path (on-watch:def +<)
|
||||
[%drum *] =^(c drum.state (peer:drum-core t.path) [c this])
|
||||
[%kiln *] =^(c kiln.state (peer:kiln-core t.path) [c this])
|
||||
[%dill *] =^(c drum.state (peer:drum-core +<) [c this])
|
||||
==
|
||||
::
|
||||
++ on-agent
|
||||
|
@ -83,7 +83,8 @@
|
||||
::
|
||||
?+ -.source.com
|
||||
:_ this(job.state (some [eyre-id com]))
|
||||
[%pass /sole %agent [our.bowl %dojo] %watch /sole/[eyre-id]]~
|
||||
=/ =path /sole/(scot %p our.bowl)/[eyre-id]
|
||||
[%pass /sole %agent [our.bowl %dojo] %watch path]~
|
||||
::
|
||||
%export
|
||||
:_ this(job.state (some [eyre-id com]))
|
||||
|
@ -43,13 +43,13 @@
|
||||
++ on-fail on-fail:def
|
||||
::
|
||||
++ command-parser
|
||||
|= sole-id=@ta
|
||||
|= =sole-id:shoe
|
||||
^+ |~(nail *(like [? command]))
|
||||
%+ stag &
|
||||
(perk %demo %row %table ~)
|
||||
::
|
||||
++ tab-list
|
||||
|= sole-id=@ta
|
||||
|= =sole-id:shoe
|
||||
^- (list [@t tank])
|
||||
:~ ['demo' leaf+"run example command"]
|
||||
['row' leaf+"print a row"]
|
||||
@ -57,7 +57,7 @@
|
||||
==
|
||||
::
|
||||
++ on-command
|
||||
|= [sole-id=@ta =command]
|
||||
|= [=sole-id:shoe =command]
|
||||
^- (quip card _this)
|
||||
=; [to=(list _sole-id) fec=shoe-effect:shoe]
|
||||
[[%shoe to fec]~ this]
|
||||
@ -87,7 +87,7 @@
|
||||
==
|
||||
::
|
||||
++ can-connect
|
||||
|= sole-id=@ta
|
||||
|= =sole-id:shoe
|
||||
^- ?
|
||||
?| =(~zod src.bowl)
|
||||
(team:title [our src]:bowl)
|
||||
|
@ -5,8 +5,8 @@
|
||||
:- %aqua-events
|
||||
%+ turn
|
||||
^- (list unix-event)
|
||||
:~ [/d/term/1 %belt %ctl `@c`%e]
|
||||
[/d/term/1 %belt %ctl `@c`%u]
|
||||
:~ [/d/term/1 %belt %mod %ctl `@c`%e]
|
||||
[/d/term/1 %belt %mod %ctl `@c`%u]
|
||||
[/d/term/1 %belt %txt ((list @c) command)]
|
||||
[/d/term/1 %belt %ret ~]
|
||||
==
|
||||
|
@ -8,9 +8,11 @@
|
||||
::
|
||||
:- %say
|
||||
|= $: [now=@da eny=@uvJ byk=beak]
|
||||
[arg=$?([dap=term ~] [who=ship dap=term ~]) ~]
|
||||
arg=$?([dap=term ~] [who=ship dap=term ~])
|
||||
drum-session=@ta
|
||||
==
|
||||
:- %drum-link
|
||||
:- drum-session
|
||||
?~ +.arg
|
||||
[p.byk dap.arg]
|
||||
[who.arg dap.arg]
|
||||
|
@ -8,9 +8,11 @@
|
||||
::
|
||||
:- %say
|
||||
|= $: [now=@da eny=@uvJ byk=beak]
|
||||
[arg=$?([dap=term ~] [who=ship dap=term ~]) ~]
|
||||
arg=$?([dap=term ~] [who=ship dap=term ~])
|
||||
drum-session=@ta
|
||||
==
|
||||
:- %drum-unlink
|
||||
:- drum-session
|
||||
?~ +.arg
|
||||
[p.byk dap.arg]
|
||||
[who.arg dap.arg]
|
||||
|
1
pkg/arvo/lib/dill.hoon
Symbolic link
1
pkg/arvo/lib/dill.hoon
Symbolic link
@ -0,0 +1 @@
|
||||
../../base-dev/lib/dill.hoon
|
@ -1,34 +1,66 @@
|
||||
/- *sole
|
||||
/+ sole
|
||||
|%
|
||||
+$ state state-4
|
||||
+$ state state-5
|
||||
+$ any-state
|
||||
$~ *state
|
||||
$% state-4
|
||||
$% state-5
|
||||
state-4
|
||||
state-3
|
||||
state-2
|
||||
==
|
||||
+$ state-5 [%5 pith-5]
|
||||
+$ state-4 [%4 pith-4]
|
||||
+$ state-3 [%3 pith-3]
|
||||
+$ state-2 [%2 pith-2]
|
||||
::
|
||||
+$ pith-5
|
||||
$: bin=(map @ source) :: terminals
|
||||
==
|
||||
::
|
||||
+$ pith-4
|
||||
$: eel=(set gill:gall) :: connect to
|
||||
bin=(map bone source) :: terminals
|
||||
bin=(map bone source-4) :: terminals
|
||||
== ::
|
||||
::
|
||||
+$ source-4
|
||||
$: edg=_80
|
||||
off=@ud
|
||||
kil=kill
|
||||
inx=@ud
|
||||
fug=(map gill:gall (unit target-4))
|
||||
mir=(pair @ud stub)
|
||||
==
|
||||
::
|
||||
+$ target-4
|
||||
$: $= blt
|
||||
%+ pair
|
||||
(unit dill-belt-4)
|
||||
(unit dill-belt-4)
|
||||
ris=(unit search)
|
||||
hit=history
|
||||
pom=sole-prompt
|
||||
inp=sole-command
|
||||
==
|
||||
::
|
||||
+$ dill-belt-4
|
||||
$% [%ctl p=@c]
|
||||
[%met p=@c]
|
||||
dill-belt:dill
|
||||
==
|
||||
::
|
||||
++ pith-3 ::
|
||||
$: eel=(set gill:gall) :: connect to
|
||||
ray=(map dude:gall desk) ::
|
||||
fur=(map dude:gall (unit *)) :: servers
|
||||
bin=(map bone source) :: terminals
|
||||
bin=(map bone source-4) :: terminals
|
||||
== ::
|
||||
:: ::
|
||||
++ pith-2 ::
|
||||
$: eel=(set gill:gall) :: connect to
|
||||
ray=(set well:gall) ::
|
||||
fur=(map dude:gall (unit *)) :: servers
|
||||
bin=(map bone source) :: terminals
|
||||
bin=(map bone source-4) :: terminals
|
||||
== ::
|
||||
:: ::
|
||||
++ kill :: kill ring
|
||||
@ -42,6 +74,7 @@
|
||||
off=@ud :: window offset
|
||||
kil=kill :: kill buffer
|
||||
inx=@ud :: ring index
|
||||
eel=(set gill:gall) :: connect to
|
||||
fug=(map gill:gall (unit target)) :: connections
|
||||
mir=(pair @ud stub) :: mirrored terminal
|
||||
== ::
|
||||
@ -65,52 +98,74 @@
|
||||
pom=sole-prompt :: static prompt
|
||||
inp=sole-command :: input state
|
||||
== ::
|
||||
::
|
||||
--
|
||||
:: :: ::
|
||||
:::: :: ::
|
||||
:: :: ::
|
||||
|%
|
||||
++ en-gill :: gill to wire
|
||||
|= gyl=gill:gall
|
||||
|= [ses=@tas gyl=gill:gall]
|
||||
^- wire
|
||||
[%drum %phat (scot %p p.gyl) q.gyl ~]
|
||||
[%drum %phat (scot %p p.gyl) q.gyl ?:(=(%$ ses) ~ [ses ~])]
|
||||
::
|
||||
++ de-gill :: gill from wire
|
||||
|= way=wire ^- gill:gall
|
||||
~| way
|
||||
?>(?=([@ @ *] way) [(slav %p i.way) i.t.way])
|
||||
|= way=wire
|
||||
^- [@tas gill:gall]
|
||||
~| wire=way
|
||||
?> ?=([@ @ ?(~ [@ ~])] way)
|
||||
:- ?~(t.t.way %$ i.t.t.way)
|
||||
[(slav %p i.way) i.t.way]
|
||||
--
|
||||
:: TODO: remove .ost
|
||||
::
|
||||
|= [hid=bowl:gall state]
|
||||
=* sat +<+
|
||||
=/ ost 0
|
||||
=+ (~(gut by bin) ost *source)
|
||||
=/ ses=@tas %$
|
||||
=+ (~(gut by bin) ses *source)
|
||||
=* dev -
|
||||
=| moz=(list card:agent:gall)
|
||||
=| biz=(list dill-blit:dill)
|
||||
=| biz=(list blit:dill) ::TODO should be per-session
|
||||
|%
|
||||
++ this .
|
||||
++ klr klr:format
|
||||
+$ state ^state :: proxy
|
||||
+$ any-state ^any-state :: proxy
|
||||
++ on-init (poke-link our.hid %dojo)
|
||||
++ on-init (poke-link %$ our.hid %dojo)
|
||||
::
|
||||
++ prep
|
||||
|= s=@tas
|
||||
=. ses s
|
||||
=. dev (~(gut by bin) ses *source)
|
||||
this
|
||||
::
|
||||
++ open
|
||||
%+ cork de-gill
|
||||
|= [s=@tas g=gill:gall]
|
||||
[g (prep s)]
|
||||
::
|
||||
++ diff-sole-effect-phat :: app event
|
||||
|= [way=wire fec=sole-effect]
|
||||
=< se-abet =< se-view
|
||||
=+ gyl=(de-gill way)
|
||||
=< se-abet
|
||||
=^ gyl this (open way)
|
||||
?: (se-aint gyl) +>.$
|
||||
(se-diff gyl fec)
|
||||
::
|
||||
++ peer ::
|
||||
|= pax=path
|
||||
=? this ?=([%dill @ ~] pax)
|
||||
(prep i.t.pax)
|
||||
~| [%drum-unauthorized our+our.hid src+src.hid] :: ourself
|
||||
?> (team:title our.hid src.hid) :: or our own moon
|
||||
=< se-abet =< se-view
|
||||
=< se-abet
|
||||
(se-text "[{<src.hid>}, driving {<our.hid>}]")
|
||||
::
|
||||
++ poke-dill
|
||||
|= [ses=@tas bet=dill-belt:dill]
|
||||
(poke-dill-belt:(prep ses) bet)
|
||||
::
|
||||
++ poke-dill-belt :: terminal event
|
||||
|= bet=dill-belt:dill
|
||||
=< se-abet =< se-view
|
||||
=< se-abet
|
||||
(se-belt bet)
|
||||
::
|
||||
++ poke-dill-blit :: terminal output
|
||||
@ -118,29 +173,29 @@
|
||||
se-abet:(se-blit-sys bit)
|
||||
::
|
||||
++ poke-link :: connect app
|
||||
|= gyl=gill:gall
|
||||
=< se-abet =< se-view
|
||||
(se-link gyl)
|
||||
|= [ses=@tas gyl=gill:gall]
|
||||
=< se-abet
|
||||
(se-link:(prep ses) gyl)
|
||||
::
|
||||
++ poke-unlink :: disconnect app
|
||||
|= gyl=gill:gall
|
||||
=< se-abet =< se-view
|
||||
(se-drop:(se-pull gyl) & gyl)
|
||||
|= [ses=@ta gyl=gill:gall]
|
||||
=< se-abet
|
||||
(se-drop:(se-pull:(prep ses) gyl) & gyl)
|
||||
::
|
||||
++ poke-exit :: shutdown
|
||||
|= ~
|
||||
se-abet:(se-blit-sys `dill-blit:dill`[%qit ~])
|
||||
::
|
||||
++ poke-put :: write file
|
||||
|= [pax=path txt=@]
|
||||
|= [pax=path arg=$@(@ [@tas @])]
|
||||
=^ txt +> ?@(arg [arg +>] [+.arg (prep -.arg)])
|
||||
se-abet:(se-blit-sys [%sav pax txt]) ::
|
||||
::
|
||||
++ poke
|
||||
|= [=mark =vase]
|
||||
?> =(our src):hid
|
||||
?+ mark ~|([%poke-drum-bad-mark mark] !!)
|
||||
%drum-dill-belt =;(f (f !<(_+<.f vase)) poke-dill-belt)
|
||||
%drum-dill-blit =;(f (f !<(_+<.f vase)) poke-dill-blit)
|
||||
%dill-poke =;(f (f !<(_+<.f vase)) poke-dill)
|
||||
%drum-exit =;(f (f !<(_+<.f vase)) poke-exit)
|
||||
%drum-link =;(f (f !<(_+<.f vase)) poke-link)
|
||||
%drum-put =;(f (f !<(_+<.f vase)) poke-put)
|
||||
@ -149,19 +204,40 @@
|
||||
::
|
||||
++ on-load
|
||||
|= [hood-version=@ud old=any-state]
|
||||
=< se-abet =< se-view
|
||||
=< se-abet
|
||||
=? old ?=(%2 -.old) [%4 [eel bin]:old]
|
||||
=? old ?=(%3 -.old) [%4 [eel bin]:old]
|
||||
=? old ?=(%4 -.old)
|
||||
|^ 5+(~(run by bin.old) source-4-to-5)
|
||||
++ source-4-to-5
|
||||
|= source-4
|
||||
^- source
|
||||
=; fug [edg off kil inx eel.old fug mir]
|
||||
(~(run by fug) |=(t=(unit target-4) (bind t target-4-to-5)))
|
||||
::
|
||||
++ target-4-to-5
|
||||
|= t=target-4
|
||||
^- target
|
||||
:_ +.t
|
||||
:- (bind p.blt.t belt-4-to-5)
|
||||
(bind q.blt.t belt-4-to-5)
|
||||
::
|
||||
++ belt-4-to-5
|
||||
|= b=dill-belt-4
|
||||
^- dill-belt:dill
|
||||
?. ?=(?(%ctl %met) -.b) b
|
||||
[%mod -.b p.b]
|
||||
--
|
||||
::
|
||||
?> ?=(%4 -.old)
|
||||
?> ?=(%5 -.old)
|
||||
=. sat old
|
||||
=. dev (~(gut by bin) ost *source)
|
||||
=. dev (~(gut by bin) ses *source)
|
||||
this
|
||||
::
|
||||
++ reap-phat :: ack connect
|
||||
|= [way=wire saw=(unit tang)]
|
||||
=< se-abet =< se-view
|
||||
=+ gyl=(de-gill way)
|
||||
=< se-abet
|
||||
=^ gyl this (open way)
|
||||
?~ saw
|
||||
(se-join gyl)
|
||||
:: Don't print stack trace because we probably just crashed to
|
||||
@ -171,9 +247,9 @@
|
||||
::
|
||||
++ take-coup-phat :: ack poke
|
||||
|= [way=wire saw=(unit tang)]
|
||||
=< se-abet =< se-view
|
||||
=< se-abet
|
||||
?~ saw +>
|
||||
=+ gyl=(de-gill way)
|
||||
=^ gyl this (open way)
|
||||
?: (se-aint gyl) +>.$
|
||||
%- se-dump:(se-drop:(se-pull gyl) & gyl)
|
||||
:_ u.saw
|
||||
@ -196,8 +272,8 @@
|
||||
::
|
||||
++ quit-phat ::
|
||||
|= way=wire
|
||||
=< se-abet =< se-view
|
||||
=+ gyl=(de-gill way)
|
||||
=< se-abet
|
||||
=^ gyl this (open way)
|
||||
~& [%drum-quit src.hid gyl]
|
||||
(se-drop %| gyl)
|
||||
:: :: ::
|
||||
@ -205,13 +281,18 @@
|
||||
:: :: ::
|
||||
++ se-abet :: resolve
|
||||
^- (quip card:agent:gall state)
|
||||
=. . se-subze:se-adze
|
||||
:_ sat(bin (~(put by bin) ost dev))
|
||||
=. . se-view:se-subze:se-adze
|
||||
:_ sat(bin (~(put by bin) ses dev))
|
||||
^- (list card:agent:gall)
|
||||
?~ biz (flop moz)
|
||||
:_ (flop moz)
|
||||
=/ =dill-blit:dill ?~(t.biz i.biz [%mor (flop biz)])
|
||||
[%give %fact ~[/drum] %dill-blit !>(dill-blit)]
|
||||
=/ =blit:dill ?~(t.biz i.biz [%mor (flop biz)])
|
||||
::TODO remove /drum after dill cleans up
|
||||
::TODO but once we remove it, the empty trailing segment of
|
||||
:: /dill/[ses] would prevent outsiders from subscribing
|
||||
:: to the default session...
|
||||
=/ to=(list path) [/dill/[ses] ?~(ses ~[/drum] ~)]
|
||||
[%give %fact to %dill-blit !>(blit)]
|
||||
::
|
||||
++ se-adze :: update connections
|
||||
^+ .
|
||||
@ -230,14 +311,14 @@
|
||||
(se-peer gil)
|
||||
::
|
||||
++ se-subze :: downdate connections
|
||||
=< .(dev (~(got by bin) ost))
|
||||
=. bin (~(put by bin) ost dev)
|
||||
=< .(dev (~(got by bin) ses))
|
||||
=. bin (~(put by bin) ses dev)
|
||||
^+ .
|
||||
%- ~(rep by bin)
|
||||
=< .(con +>)
|
||||
|: $:,[[ost=bone dev=source] con=_.] ^+ con
|
||||
=+ xeno=se-subze-local:%_(con ost ost, dev dev)
|
||||
xeno(ost ost.con, dev dev.con, bin (~(put by bin) ost dev.xeno))
|
||||
|: $:,[[ses=@tas dev=source] con=_.] ^+ con
|
||||
=+ xeno=se-subze-local:%_(con ses ses, dev dev)
|
||||
xeno(ses ses.con, dev dev.con, bin (~(put by bin.xeno) ses dev.xeno))
|
||||
::
|
||||
++ se-subze-local
|
||||
^+ .
|
||||
@ -252,7 +333,7 @@
|
||||
++ se-aint :: ignore result
|
||||
|= gyl=gill:gall
|
||||
^- ?
|
||||
?. (~(has by bin) ost) &
|
||||
?. (~(has by bin) ses) &
|
||||
=+ gyr=(~(get by fug) gyl)
|
||||
|(?=(~ gyr) ?=(~ u.gyr))
|
||||
::
|
||||
@ -290,7 +371,7 @@
|
||||
[%cru *] (se-dump:(se-text (trip p.bet)) q.bet)
|
||||
[%hey *] +>(mir [0 ~]) :: refresh
|
||||
[%rez *] +>(edg (dec p.bet)) :: resize window
|
||||
[%yow *] ~&([%no-yow -.bet] +>)
|
||||
[%yow *] (se-link p.bet)
|
||||
==
|
||||
=+ gul=se-agon
|
||||
?: |(?=(~ gul) (se-aint u.gul))
|
||||
@ -341,6 +422,21 @@
|
||||
leaf+(weld (scag (sub edg 3) tape) "...")
|
||||
leaf+tape
|
||||
::
|
||||
++ se-blin :: print and newline
|
||||
|= $= lin
|
||||
$~ [%put ~]
|
||||
$>(?(%put %klr) dill-blit:dill)
|
||||
^+ +>
|
||||
:: newline means we need to redraw the prompt,
|
||||
:: so update the prompt mirror accordingly.
|
||||
::
|
||||
=. mir [0 ~]
|
||||
::TODO doing hops and wyps conditionally based on the mirror state seems
|
||||
:: better, but doesn't cover edge cases. results in dojo's ">=" being
|
||||
:: rendered alongside the prompt in scrollback, for example.
|
||||
:: figure out a way to make that work!
|
||||
(se-blit %mor [%hop 0] [%wyp ~] lin [%nel ~] ~)
|
||||
::
|
||||
++ se-dump :: print tanks
|
||||
|= tac=(list tank)
|
||||
^+ +>
|
||||
@ -351,7 +447,7 @@
|
||||
?. ((sane %t) (crip i.wol)) :: XX upstream validation
|
||||
~& bad-text+<`*`i.wol>
|
||||
$(wol t.wol)
|
||||
$(wol t.wol, +>.^$ (se-blit %out (tuba i.wol)))
|
||||
$(wol t.wol, +>.^$ (se-blin %put (tuba i.wol)))
|
||||
::
|
||||
++ se-join :: confirm connection
|
||||
|= gyl=gill:gall
|
||||
@ -379,20 +475,21 @@
|
||||
+>(eel (~(put in eel) gyl))
|
||||
::
|
||||
++ se-blit :: give output
|
||||
|= bil=dill-blit:dill
|
||||
|= bil=blit:dill
|
||||
+>(biz [bil biz])
|
||||
::
|
||||
++ se-blit-sys :: output to system
|
||||
|= bil=dill-blit:dill ^+ +>
|
||||
(se-emit %give %fact ~[/drum] %dill-blit !>(bil))
|
||||
::TODO remove /drum after dill cleans up
|
||||
(se-emit %give %fact ~[/drum /dill/[ses]] %dill-blit !>(bil))
|
||||
::
|
||||
++ se-show :: show buffer, raw
|
||||
|= lin=(pair @ud stub)
|
||||
^+ +>
|
||||
?: =(mir lin) +>
|
||||
=. +> ?:(=(p.mir p.lin) +> (se-blit %hop p.lin))
|
||||
=. +> ?:(=(q.mir q.lin) +> (se-blit %pom q.lin))
|
||||
+>(mir lin)
|
||||
%- se-blit(mir lin)
|
||||
?: =(q.mir q.lin) [%hop p.lin]
|
||||
mor+[[%hop 0] [%wyp ~] [%klr q.lin] [%hop p.lin] ~]
|
||||
::
|
||||
++ se-just :: adjusted buffer
|
||||
|= [pom=stub lin=(pair @ud (list @c))]
|
||||
@ -430,22 +527,22 @@
|
||||
?. ((sane %t) (crip txt)) :: XX upstream validation
|
||||
~& bad-text+<`*`txt>
|
||||
+>
|
||||
(se-blit %out (tuba txt))
|
||||
(se-blin %put (tuba txt))
|
||||
::
|
||||
++ se-poke :: send a poke
|
||||
|= [gyl=gill:gall par=cage]
|
||||
(se-emit %pass (en-gill gyl) %agent gyl %poke par)
|
||||
(se-emit %pass (en-gill ses gyl) %agent gyl %poke par)
|
||||
::
|
||||
++ se-peer :: send a peer
|
||||
|= gyl=gill:gall
|
||||
~> %slog.0^leaf/"drum: link {<[p q]:gyl>}"
|
||||
=/ =path /sole/(cat 3 'drum_' (scot %p our.hid))
|
||||
=/ =path (id-to-path:sole our.hid ses)
|
||||
%- se-emit(fug (~(put by fug) gyl ~))
|
||||
[%pass (en-gill gyl) %agent gyl %watch path]
|
||||
[%pass (en-gill ses gyl) %agent gyl %watch path]
|
||||
::
|
||||
++ se-pull :: cancel subscription
|
||||
|= gyl=gill:gall
|
||||
(se-emit %pass (en-gill gyl) %agent gyl %leave ~)
|
||||
(se-emit %pass (en-gill ses gyl) %agent gyl %leave ~)
|
||||
::
|
||||
++ se-tame :: switch connection
|
||||
|= gyl=gill:gall
|
||||
@ -470,7 +567,7 @@
|
||||
^+ +>
|
||||
(ta-poke %sole-action !>(act))
|
||||
::
|
||||
++ ta-id (cat 3 'drum_' (scot %p our.hid)) :: per-ship duct id
|
||||
++ ta-id [our.hid ses] :: per-ship-session id
|
||||
::
|
||||
++ ta-aro :: hear arrow
|
||||
|= key=?(%d %l %r %u)
|
||||
@ -499,13 +596,19 @@
|
||||
?< ?=([?(%cru %hey %rez %yow) *] bet) :: target-specific
|
||||
=. blt [q.blt `bet] :: remember belt
|
||||
?- bet
|
||||
@ (ta-txt bet ~)
|
||||
[%aro *] (ta-aro p.bet)
|
||||
[%bac *] ta-bac
|
||||
[%ctl *] (ta-ctl p.bet)
|
||||
[%del *] ta-del
|
||||
[%met *] (ta-met p.bet)
|
||||
[%hit *] (ta-hit +.bet)
|
||||
[%ret *] ta-ret
|
||||
[%txt *] (ta-txt p.bet)
|
||||
::
|
||||
[%mod *]
|
||||
?+ mod.bet $(bet key.bet)
|
||||
%ctl (ta-ctl key.bet)
|
||||
%met (ta-met key.bet)
|
||||
==
|
||||
==
|
||||
::
|
||||
++ ta-det :: send edit
|
||||
@ -529,7 +632,7 @@
|
||||
(ta-hom %del (dec pos.inp))
|
||||
::
|
||||
++ ta-ctl :: hear control
|
||||
|= key=@ud
|
||||
|= key=bolt:dill
|
||||
^+ +>
|
||||
=. ris ?.(?=(?(%g %r) key) ~ ris)
|
||||
?+ key ta-bel
|
||||
@ -539,7 +642,7 @@
|
||||
%d ?^ buf.say.inp
|
||||
ta-del
|
||||
?: =([our.hid %dojo] gyl)
|
||||
+>(..ta (se-blit qit+~)) :: quit pier
|
||||
+>(..ta (se-blit-sys %qit ~)) :: quit pier
|
||||
+>(..ta (se-klin gyl)) :: unlink app
|
||||
%e +>(pos.inp (lent buf.say.inp))
|
||||
%f (ta-aro %r)
|
||||
@ -550,7 +653,7 @@
|
||||
?: =(pos.inp len)
|
||||
ta-bel
|
||||
(ta-kil %r [pos.inp (sub len pos.inp)])
|
||||
%l +>(..ta (se-blit %clr ~))
|
||||
%l +>(..ta (se-blit(q.mir ~) %clr ~))
|
||||
%n (ta-aro %d)
|
||||
%p (ta-aro %u)
|
||||
%r ?~ ris
|
||||
@ -583,6 +686,14 @@
|
||||
ta-bel
|
||||
(ta-hom %del pos.inp)
|
||||
::
|
||||
++ ta-hit :: hear click
|
||||
|= [x=@ud y=@ud]
|
||||
^+ +>
|
||||
=/ pol=@ud
|
||||
(lent-char:klr (make:klr cad.pom))
|
||||
=? x (lth x pol) pol
|
||||
+>.$(pos.inp (min (sub x pol) (lent buf.say.inp)))
|
||||
::
|
||||
++ ta-erl :: hear local error
|
||||
|= pos=@ud
|
||||
ta-bel(pos.inp (min pos (lent buf.say.inp)))
|
||||
@ -594,14 +705,13 @@
|
||||
++ ta-fec :: apply effect
|
||||
|= fec=sole-effect
|
||||
^+ +>
|
||||
?- fec
|
||||
?+ fec +>(..ta (se-blit fec))
|
||||
[%bel *] ta-bel
|
||||
[%blk *] +>
|
||||
[%bye *] +>(..ta (se-klin gyl))
|
||||
[%clr *] +>(..ta (se-blit fec))
|
||||
[%det *] (ta-got +.fec)
|
||||
[%err *] (ta-err p.fec)
|
||||
[%klr *] +>(..ta (se-blit %klr (make:klr p.fec)))
|
||||
[%klr *] +>(..ta (se-blin %klr (make:klr p.fec)))
|
||||
[%mor *] |- ^+ +>.^$
|
||||
?~ p.fec +>.^$
|
||||
$(p.fec t.p.fec, +>.^$ ^$(fec i.p.fec))
|
||||
@ -609,10 +719,8 @@
|
||||
[%pro *] (ta-pro +.fec)
|
||||
[%tab *] +>(..ta (se-tab p.fec))
|
||||
[%tan *] +>(..ta (se-dump p.fec))
|
||||
[%sag *] +>(..ta (se-blit fec))
|
||||
[%sav *] +>(..ta (se-blit fec))
|
||||
[%txt *] +>(..ta (se-text p.fec))
|
||||
[%url *] +>(..ta (se-blit fec))
|
||||
[%url *] +>(..ta (se-text:(se-blit fec) (trip p.fec)))
|
||||
==
|
||||
::
|
||||
++ ta-dog :: change cursor
|
||||
@ -664,8 +772,8 @@
|
||||
kil
|
||||
?. ?& ?=(^ old.kil)
|
||||
?=(^ p.blt)
|
||||
?| ?=([%ctl ?(%k %u %w)] u.p.blt)
|
||||
?=([%met ?(%d %bac)] u.p.blt)
|
||||
?| ?=([%mod %ctl ?(%k %u %w)] u.p.blt)
|
||||
?=([%mod %met ?(%d [%bac ~])] u.p.blt)
|
||||
== ==
|
||||
%= kil :: prepend
|
||||
num +(num.kil)
|
||||
@ -682,17 +790,18 @@
|
||||
==
|
||||
::
|
||||
++ ta-met :: meta key
|
||||
|= key=@ud
|
||||
|= key=bolt:dill
|
||||
^+ +>
|
||||
=. ris ~
|
||||
?+ key ta-bel
|
||||
%dot ?. &(?=(^ old.hit) ?=(^ i.old.hit)) :: last "arg" from hist
|
||||
%'.' ?. &(?=(^ old.hit) ?=(^ i.old.hit)) :: last "arg" from hist
|
||||
ta-bel
|
||||
=+ old=`(list @c)`i.old.hit
|
||||
=+ sop=(ta-jump(buf.say.inp old) %l %ace (lent old))
|
||||
(ta-hom (cat:edit pos.inp (slag sop old)))
|
||||
::
|
||||
%bac ?: =(0 pos.inp) :: kill left-word
|
||||
[%bac ~]
|
||||
?: =(0 pos.inp) :: kill left-word
|
||||
ta-bel
|
||||
=+ sop=(ta-pos %l %edg pos.inp)
|
||||
(ta-kil %l [(sub pos.inp sop) sop])
|
||||
@ -748,8 +857,8 @@
|
||||
::
|
||||
%y ?. ?& ?=(^ old.kil) :: rotate & yank
|
||||
?=(^ p.blt)
|
||||
?| ?=([%ctl %y] u.p.blt)
|
||||
?=([%met %y] u.p.blt)
|
||||
?| ?=([%mod %ctl %y] u.p.blt)
|
||||
?=([%mod %met %y] u.p.blt)
|
||||
== ==
|
||||
ta-bel
|
||||
=+ las=(lent ta-yan)
|
||||
@ -927,82 +1036,4 @@
|
||||
?: |(?=(~ a) (alnm i.a)) i
|
||||
$(i +(i), a t.a)
|
||||
--
|
||||
::
|
||||
++ klr :: styx/stub engine
|
||||
=, dill
|
||||
|%
|
||||
++ make :: stub from styx
|
||||
|= a=styx ^- stub
|
||||
=| b=stye
|
||||
%+ reel
|
||||
|- ^- stub
|
||||
%- zing %+ turn a
|
||||
|= a=$@(@t (pair styl styx))
|
||||
?@ a [b (tuba (trip a))]~
|
||||
^$(a q.a, b (styd p.a b))
|
||||
::
|
||||
|= [a=(pair stye (list @c)) b=stub]
|
||||
?~ b [a ~]
|
||||
?. =(p.a p.i.b) [a b]
|
||||
[[p.a (weld q.a q.i.b)] t.b]
|
||||
::
|
||||
++ styd :: stye from styl
|
||||
|= [a=styl b=stye] ^+ b :: with inheritance
|
||||
:+ ?~ p.a p.b
|
||||
?~ u.p.a ~
|
||||
(~(put in p.b) u.p.a)
|
||||
(fall p.q.a p.q.b)
|
||||
(fall q.q.a q.q.b)
|
||||
::
|
||||
++ lent-char
|
||||
|= a=stub ^- @
|
||||
(roll (lnts-char a) add)
|
||||
::
|
||||
++ lnts-char :: stub pair tail lengths
|
||||
|= a=stub ^- (list @)
|
||||
%+ turn a
|
||||
|= a=(pair stye (list @c))
|
||||
(lent q.a)
|
||||
::
|
||||
++ brek :: index + incl-len of
|
||||
|= [a=@ b=(list @)] :: stub pair w= idx a
|
||||
=| [c=@ i=@]
|
||||
|- ^- (unit (pair @ @))
|
||||
?~ b ~
|
||||
=. c (add c i.b)
|
||||
?: (gte c a)
|
||||
`[i c]
|
||||
$(i +(i), b t.b)
|
||||
::
|
||||
++ slag :: slag stub, keep stye
|
||||
|= [a=@ b=stub]
|
||||
^- stub
|
||||
=+ c=(lnts-char b)
|
||||
=+ i=(brek a c)
|
||||
?~ i b
|
||||
=+ r=(^slag +(p.u.i) b)
|
||||
?: =(a q.u.i)
|
||||
r
|
||||
=+ n=(snag p.u.i b)
|
||||
:_ r :- p.n
|
||||
(^slag (sub (snag p.u.i c) (sub q.u.i a)) q.n)
|
||||
::
|
||||
++ scag :: scag stub, keep stye
|
||||
|= [a=@ b=stub]
|
||||
^- stub
|
||||
=+ c=(lnts-char b)
|
||||
=+ i=(brek a c)
|
||||
?~ i b
|
||||
?: =(a q.u.i)
|
||||
(^scag +(p.u.i) b)
|
||||
%+ welp
|
||||
(^scag p.u.i b)
|
||||
=+ n=(snag p.u.i b)
|
||||
:_ ~ :- p.n
|
||||
(^scag (sub (snag p.u.i c) (sub q.u.i a)) q.n)
|
||||
::
|
||||
++ swag :: swag stub, keep stye
|
||||
|= [[a=@ b=@] c=stub]
|
||||
(scag b (slag a c))
|
||||
--
|
||||
--
|
||||
|
@ -504,7 +504,7 @@
|
||||
[%x %kiln %pikes ~]
|
||||
=+ .^(=rock:tire %cx /(scot %p our)//(scot %da now)/tire)
|
||||
:^ ~ ~ %kiln-pikes
|
||||
!> ^- pikes
|
||||
!> ^- pikes
|
||||
%- ~(rut by rock)
|
||||
|= [=desk =zest wic=(set weft)]
|
||||
^- pike
|
||||
|
@ -45,8 +45,8 @@
|
||||
=+ cha=(tuba (trip q.kev))
|
||||
?> ?=([@ ~] cha) :: of a single character
|
||||
?+ mod !! :: modified by one buckykey
|
||||
[%ctrl ~ ~] [%ctl i.cha]
|
||||
[%alt ~ ~] [%met i.cha]
|
||||
[%ctrl ~ ~] [%mod %ctl i.cha]
|
||||
[%alt ~ ~] [%mod %met i.cha]
|
||||
==
|
||||
?@ q.kev
|
||||
[%txt (tuba (trip q.kev))]
|
||||
|
@ -19,8 +19,10 @@
|
||||
^- ^json
|
||||
?+ -.dib ~|(unsupported-blit+-.dib !!)
|
||||
%mor [%a (turn p.dib |=(a=dill-blit:dill json(dib a)))]
|
||||
%hop (frond %hop (numb p.dib))
|
||||
?(%pro %out) (frond -.dib (tape (tufa p.dib)))
|
||||
%hop %+ frond %hop
|
||||
?@ p.dib (numb p.dib)
|
||||
(pairs 'x'^(numb x.p.dib) 'y'^(numb y.p.dib) ~)
|
||||
%put (frond -.dib (tape (tufa p.dib)))
|
||||
?(%bel %clr) (frond %act %s -.dib)
|
||||
==
|
||||
--
|
||||
|
@ -1,8 +1,7 @@
|
||||
:: %drum-put: download into host system
|
||||
::
|
||||
:::: /hoon/do-claim/womb/mar
|
||||
::
|
||||
/? 310
|
||||
|_ [path @]
|
||||
|_ [path $@(@ [@ta @])]
|
||||
::
|
||||
++ grad %noun
|
||||
++ grow
|
||||
@ -11,6 +10,6 @@
|
||||
--
|
||||
++ grab :: convert from
|
||||
|%
|
||||
+$ noun [path @] :: clam from %noun
|
||||
+$ noun [path $@(@ [@ta @])] :: clam from %noun
|
||||
--
|
||||
--
|
||||
|
46
pkg/arvo/mar/herm/task.hoon
Normal file
46
pkg/arvo/mar/herm/task.hoon
Normal file
@ -0,0 +1,46 @@
|
||||
:: task: herm task for passthrough to dill
|
||||
::
|
||||
/- herm
|
||||
/+ dill
|
||||
::
|
||||
|_ =task:herm
|
||||
++ grad %noun
|
||||
:: +grab: convert from
|
||||
::
|
||||
++ grab
|
||||
|%
|
||||
++ noun task:herm
|
||||
::
|
||||
++ json
|
||||
|= jon=^json
|
||||
^+ task
|
||||
~| jon
|
||||
?> ?=([%o *] jon)
|
||||
=+ ses=(~(got by p.jon) 'session')
|
||||
?> ?=([%s *] ses)
|
||||
:- ?: =('' p.ses) %$
|
||||
(slav %tas p.ses)
|
||||
=. p.jon (~(del by p.jon) 'session')
|
||||
%. jon
|
||||
=, dejs:format
|
||||
|^ task
|
||||
++ task
|
||||
%- of
|
||||
:~ belt+belt:dejs:^dill
|
||||
blew+(ot 'w'^ni 'h'^ni ~)
|
||||
hail+ul
|
||||
open+(ot 'term'^(se %tas) 'apps'^(ar gill) ~)
|
||||
shut+ul
|
||||
==
|
||||
::
|
||||
++ gill
|
||||
(ot 'who'^(se %p) 'app'^(se %tas) ~)
|
||||
--
|
||||
--
|
||||
:: +grow: convert to
|
||||
::
|
||||
++ grow
|
||||
|%
|
||||
++ noun task
|
||||
--
|
||||
--
|
9
pkg/arvo/sur/herm.hoon
Normal file
9
pkg/arvo/sur/herm.hoon
Normal file
@ -0,0 +1,9 @@
|
||||
:: herm: stand-in for term.c with http interface
|
||||
::
|
||||
|%
|
||||
+$ task
|
||||
$~ [%$ %hail ~]
|
||||
$: session=@tas
|
||||
task=$>(?(%open %shut %belt %blew %hail) session-task:dill)
|
||||
==
|
||||
--
|
@ -1 +1 @@
|
||||
[%zuse 417]
|
||||
[%zuse 416]
|
||||
|
@ -1181,10 +1181,10 @@
|
||||
=| [l=(unit) r=(unit)]
|
||||
|. ^- ?
|
||||
?~ a &
|
||||
?& ?~(l & &((gor n.a u.l) !=(n.a u.l)))
|
||||
?~(r & &((gor u.r n.a) !=(u.r n.a)))
|
||||
?~(l.a & ?&((mor n.a n.l.a) !=(n.a n.l.a) $(a l.a, l `n.a)))
|
||||
?~(r.a & ?&((mor n.a n.r.a) !=(n.a n.r.a) $(a r.a, r `n.a)))
|
||||
?& ?~(l & (gor n.a u.l))
|
||||
?~(r & (gor u.r n.a))
|
||||
?~(l.a & ?&((mor n.a n.l.a) $(a l.a, l `n.a)))
|
||||
?~(r.a & ?&((mor n.a n.r.a) $(a r.a, r `n.a)))
|
||||
==
|
||||
::
|
||||
++ bif :: splits a by b
|
||||
|
@ -3,7 +3,7 @@
|
||||
!:
|
||||
=> ..part
|
||||
|%
|
||||
++ lull %328
|
||||
++ lull %327
|
||||
:: :: ::
|
||||
:::: :: :: (1) models
|
||||
:: :: ::
|
||||
@ -752,7 +752,6 @@
|
||||
[%hill p=(list @tas)] :: mount points
|
||||
[%done error=(unit error:ames)] :: ames message (n)ack
|
||||
[%mere p=(each (set path) (pair term tang))] :: merge result
|
||||
[%note p=@tD q=tank] :: debug message
|
||||
[%ogre p=@tas] :: delete mount point
|
||||
[%rule red=dict wit=dict] :: node r+w permissions
|
||||
[%tire p=(each rock:tire wave:tire)] :: app state
|
||||
@ -1160,9 +1159,7 @@
|
||||
++ dill ^?
|
||||
|%
|
||||
+$ gift :: out result <-$
|
||||
$% [%bbye ~] :: reset prompt
|
||||
[%blit p=(list blit)] :: terminal output
|
||||
[%burl p=@t] :: activate url
|
||||
$% [%blit p=(list blit)] :: terminal output
|
||||
[%logo ~] :: logout
|
||||
[%meld ~] :: unify memory
|
||||
[%pack ~] :: compact memory
|
||||
@ -1170,29 +1167,32 @@
|
||||
== ::
|
||||
+$ task :: in request ->$
|
||||
$~ [%vega ~] ::
|
||||
$% [%belt p=belt] :: terminal input
|
||||
[%blew p=blew] :: terminal config
|
||||
[%boot lit=? p=*] :: weird %dill boot
|
||||
$% [%boot lit=? p=*] :: weird %dill boot
|
||||
[%crop p=@ud] :: trim kernel state
|
||||
[%crud p=@tas q=(list tank)] :: print error
|
||||
[%flee session=~] :: unwatch session
|
||||
[%flog p=flog] :: wrapped error
|
||||
[%flow p=@tas q=(list gill:gall)] :: terminal config
|
||||
[%hail ~] :: terminal refresh
|
||||
[%heft ~] :: memory report
|
||||
[%hook ~] :: this term hung up
|
||||
[%harm ~] :: all terms hung up
|
||||
$>(%init vane-task) :: after gall ready
|
||||
[%meld ~] :: unify memory
|
||||
[%noop ~] :: no operation
|
||||
[%pack ~] :: compact memory
|
||||
[%talk p=tank] ::
|
||||
[%text p=tape] ::
|
||||
[%view session=~] :: watch session blits
|
||||
[%shot ses=@tas task=session-task] :: task for session
|
||||
[%talk p=(list tank)] :: print tanks
|
||||
[%text p=tape] :: print tape
|
||||
$>(%trim vane-task) :: trim state
|
||||
$>(%vega vane-task) :: report upgrade
|
||||
[%verb ~] :: verbose mode
|
||||
[%knob tag=term level=?(%hush %soft %loud)] :: error verbosity
|
||||
session-task :: for default session
|
||||
== ::
|
||||
:: ::
|
||||
+$ session-task :: session request
|
||||
$% [%belt p=belt] :: terminal input
|
||||
[%blew p=blew] :: terminal config
|
||||
[%flee ~] :: unwatch session
|
||||
[%hail ~] :: terminal refresh
|
||||
[%open p=dude:gall q=(list gill:gall)] :: setup session
|
||||
[%shut ~] :: close session
|
||||
[%view ~] :: watch session blits
|
||||
== ::
|
||||
::
|
||||
:::: :: (1d2)
|
||||
@ -1200,59 +1200,41 @@
|
||||
+$ blew [p=@ud q=@ud] :: columns rows
|
||||
+$ belt :: client input
|
||||
$? bolt :: simple input
|
||||
$% [%mod mod=?(%ctl %met %hyp) key=bolt] :: w/ modifier
|
||||
[%mod mod=?(%ctl %met %hyp) key=bolt] :: w/ modifier
|
||||
[%txt p=(list @c)] :: utf32 text
|
||||
::TODO consider moving %hey, %rez, %yow here ::
|
||||
::TMP forward backwards-compatibility ::
|
||||
:: ::
|
||||
[%ctl p=@c] ::
|
||||
[%met p=@c] ::
|
||||
== == ::
|
||||
== ::
|
||||
+$ bolt :: simple input
|
||||
$@ @c :: simple keystroke
|
||||
$% [%aro p=?(%d %l %r %u)] :: arrow key
|
||||
[%bac ~] :: true backspace
|
||||
[%del ~] :: true delete
|
||||
[%hit r=@ud c=@ud] :: mouse click
|
||||
[%hit x=@ud y=@ud] :: mouse click
|
||||
[%ret ~] :: return
|
||||
== ::
|
||||
+$ blit :: old blit
|
||||
+$ blit :: client output
|
||||
$% [%bel ~] :: make a noise
|
||||
[%clr ~] :: clear the screen
|
||||
[%hop p=@ud] :: set cursor position
|
||||
[%klr p=stub] :: set styled line
|
||||
[%lin p=(list @c)] :: set current line
|
||||
[%mor ~] :: newline
|
||||
[%hop p=$@(@ud [x=@ud y=@ud])] :: set cursor col/pos
|
||||
[%klr p=stub] :: put styled
|
||||
[%mor p=(list blit)] :: multiple blits
|
||||
[%nel ~] :: newline
|
||||
[%put p=(list @c)] :: put text at cursor
|
||||
[%sag p=path q=*] :: save to jamfile
|
||||
[%sav p=path q=@] :: save to file
|
||||
[%url p=@t] :: activate url
|
||||
[%wyp ~] :: wipe cursor line
|
||||
== ::
|
||||
+$ dill-belt :: new belt
|
||||
$% [%aro p=?(%d %l %r %u)] :: arrow key
|
||||
[%bac ~] :: true backspace
|
||||
+$ dill-belt :: arvo input
|
||||
$% belt :: client input
|
||||
[%cru p=@tas q=(list tank)] :: echo error
|
||||
[%ctl p=@] :: control-key
|
||||
[%del ~] :: true delete
|
||||
[%hey ~] :: refresh
|
||||
[%met p=@] :: meta-key
|
||||
[%ret ~] :: return
|
||||
[%rez p=@ud q=@ud] :: resize, cols, rows
|
||||
[%txt p=(list @c)] :: utf32 text
|
||||
[%yow p=gill:gall] :: connect to app
|
||||
== ::
|
||||
+$ dill-blit :: new blit
|
||||
$% [%bel ~] :: make a noise
|
||||
[%clr ~] :: clear the screen
|
||||
[%hop p=@ud] :: set cursor position
|
||||
[%klr p=stub] :: styled text
|
||||
[%mor p=(list dill-blit)] :: multiple blits
|
||||
[%pom p=stub] :: styled prompt
|
||||
[%pro p=(list @c)] :: show as cursor+line
|
||||
+$ dill-blit :: arvo output
|
||||
$% blit :: client output
|
||||
[%qit ~] :: close console
|
||||
[%out p=(list @c)] :: send output line
|
||||
[%sag p=path q=*] :: save to jamfile
|
||||
[%sav p=path q=@] :: save to file
|
||||
[%url p=@t] :: activate url
|
||||
== ::
|
||||
+$ flog :: sent to %dill
|
||||
$% [%crop p=@ud] :: trim kernel state
|
||||
@ -1263,6 +1245,11 @@
|
||||
[%text p=tape] ::
|
||||
[%verb ~] :: verbose mode
|
||||
== ::
|
||||
:: ::
|
||||
+$ poke :: dill to userspace
|
||||
$: ses=@tas :: target session
|
||||
dill-belt :: input
|
||||
== ::
|
||||
-- ::dill
|
||||
:: ::::
|
||||
:::: ++eyre :: (1e) http-server
|
||||
@ -1763,7 +1750,6 @@
|
||||
+$ gift :: outgoing result
|
||||
$% [%boon payload=*] :: ames response
|
||||
[%done error=(unit error:ames)] :: ames message (n)ack
|
||||
[%onto p=(each suss tang)] :: about agent
|
||||
[%unto p=unto] ::
|
||||
== ::
|
||||
+$ task :: incoming request
|
||||
@ -2531,9 +2517,6 @@
|
||||
:: %ames: hear packet
|
||||
::
|
||||
$>(%hear task:ames)
|
||||
:: %dill: hangup
|
||||
::
|
||||
$>(%hook task:dill)
|
||||
:: %clay: external edit
|
||||
::
|
||||
$>(%into task:clay)
|
||||
@ -2554,6 +2537,9 @@
|
||||
:: %eyre: starts handling an backdoor http request
|
||||
::
|
||||
$>(%request-local task:eyre)
|
||||
:: %dill: close session
|
||||
::
|
||||
$>(%shut task:dill)
|
||||
:: %behn: wakeup
|
||||
::
|
||||
$>(%wake task:behn)
|
||||
|
@ -432,7 +432,10 @@
|
||||
task ::
|
||||
== ::
|
||||
$: %d :: to %dill
|
||||
$>(%flog task:dill) ::
|
||||
$> $? %flog ::
|
||||
%text ::
|
||||
== ::
|
||||
task:dill ::
|
||||
== ::
|
||||
$: %g :: to %gall
|
||||
$> $? %deal
|
||||
@ -460,14 +463,12 @@
|
||||
== == ::
|
||||
$: %clay ::
|
||||
$> $? %mere ::
|
||||
%note ::
|
||||
%writ ::
|
||||
== ::
|
||||
gift ::
|
||||
== ::
|
||||
$: %gall
|
||||
$> $? %onto
|
||||
%unto
|
||||
$> $? %unto
|
||||
==
|
||||
gift:gall
|
||||
==
|
||||
@ -2209,7 +2210,8 @@
|
||||
|= [prefix=@tD paths=(set path)]
|
||||
%+ turn ~(tap in paths)
|
||||
|= =path
|
||||
[u.hun %give %note prefix (path-to-tank path)]
|
||||
^- move
|
||||
[u.hun %pass /note %d %text prefix ' ' ~(ram re (path-to-tank path))]
|
||||
::
|
||||
++ path-to-tank
|
||||
|= =path
|
||||
@ -5774,8 +5776,6 @@
|
||||
?^ dud
|
||||
~|(%clay-take-dud (mean tang.u.dud))
|
||||
?: ?=([%lu %load *] tea)
|
||||
?: ?=(%onto +<.hin)
|
||||
[~ ..^$]
|
||||
?> ?=(%unto +<.hin)
|
||||
?> ?=(%poke-ack -.p.hin)
|
||||
?~ p.p.hin
|
||||
@ -5950,7 +5950,6 @@
|
||||
q.p.p.+.hin
|
||||
[~ ..^$]
|
||||
::
|
||||
%note [[hen %give +.hin]~ ..^$]
|
||||
%wake
|
||||
:: TODO: handle behn errors
|
||||
::
|
||||
@ -5973,7 +5972,6 @@
|
||||
::
|
||||
%boon !!
|
||||
%lost !!
|
||||
%onto !!
|
||||
%unto !!
|
||||
%writ
|
||||
%- (slog leaf+"clay: strange writ (expected on upgrade to Fusion)" ~)
|
||||
|
@ -8,27 +8,25 @@
|
||||
-- ::
|
||||
=> |% :: console protocol
|
||||
+$ axle ::
|
||||
$: %4 ::TODO replace ducts with session ids ::
|
||||
$: %5 ::
|
||||
hey=(unit duct) :: default duct
|
||||
dug=(map duct axon) :: conversations
|
||||
eye=(jug duct duct) :: outside listeners
|
||||
dug=(map @tas axon) :: conversations
|
||||
eye=(jug @tas duct) :: outside listeners
|
||||
lit=? :: boot in lite mode
|
||||
$= veb :: vane verbosities
|
||||
$~ (~(put by *(map @tas log-level)) %hole %soft) :: quiet packet crashes
|
||||
(map @tas log-level) ::
|
||||
== ::
|
||||
+$ axon :: dill per duct
|
||||
+$ axon :: dill session
|
||||
$: ram=term :: console program
|
||||
tem=(unit (list dill-belt)) :: pending, reverse
|
||||
wid=_80 :: terminal width
|
||||
pos=@ud :: cursor position
|
||||
see=$%([%lin (list @c)] [%klr stub]) :: current line
|
||||
== ::
|
||||
+$ log-level ?(%hush %soft %loud) :: none, line, full
|
||||
-- => ::
|
||||
|% :: protocol outward
|
||||
+$ mess ::
|
||||
$% [%dill-belt p=(hypo dill-belt)] ::
|
||||
$% [%dill-poke p=(hypo poke)] ::
|
||||
== ::
|
||||
+$ move [p=duct q=(wind note gift)] :: local move
|
||||
+$ note :: out request $->
|
||||
@ -69,7 +67,6 @@
|
||||
== == ::
|
||||
$: %clay ::
|
||||
$> $? %mere ::
|
||||
%note ::
|
||||
%writ ::
|
||||
== ::
|
||||
gift:clay ::
|
||||
@ -78,10 +75,7 @@
|
||||
$>(%blit gift:dill) ::
|
||||
== ::
|
||||
$: %gall ::
|
||||
$> $? %onto ::
|
||||
%unto ::
|
||||
== ::
|
||||
gift:gall ::
|
||||
$>(%unto gift:gall) ::
|
||||
== == ::
|
||||
:::::::: :: dill tiles
|
||||
--
|
||||
@ -91,39 +85,27 @@
|
||||
|%
|
||||
++ as :: per cause
|
||||
=| moz=(list move)
|
||||
|_ [hen=duct axon]
|
||||
|_ [hen=duct ses=@tas axon]
|
||||
++ abet :: resolve
|
||||
^- [(list move) axle]
|
||||
[(flop moz) all(dug (~(put by dug.all) hen +<+))]
|
||||
[(flop moz) all(dug (~(put by dug.all) ses +<+>))]
|
||||
::
|
||||
++ call :: receive input
|
||||
|= kyz=task
|
||||
^+ +>
|
||||
?+ -.kyz ~& [%strange-kiss -.kyz] +>
|
||||
%flow +>
|
||||
%harm +>
|
||||
%hail (send %hey ~)
|
||||
%text (from %out (tuba p.kyz))
|
||||
%crud :: (send `dill-belt`[%cru p.kyz q.kyz])
|
||||
(crud p.kyz q.kyz)
|
||||
%blew (send %rez p.p.kyz q.p.kyz)
|
||||
%heft (pass /whey %$ whey/~)
|
||||
%meld (dump kyz)
|
||||
%pack (dump kyz)
|
||||
%crop (dump trim+p.kyz)
|
||||
%verb (pass /verb %$ kyz)
|
||||
%noop +>
|
||||
%belt
|
||||
%- send
|
||||
::TMP forwards compatibility with next-dill
|
||||
::
|
||||
?@ p.kyz [%txt p.kyz ~]
|
||||
?: ?=(%hit -.p.kyz) [%txt ~]
|
||||
?. ?=(%mod -.p.kyz) p.kyz
|
||||
=/ =@c
|
||||
?@ key.p.kyz key.p.kyz
|
||||
?:(?=(?(%bac %del %ret) -.key.p.kyz) `@`-.key.p.kyz ~-)
|
||||
?:(?=(%met mod.p.kyz) [%met c] [%ctl c])
|
||||
%hail (send %hey ~)
|
||||
%belt (send `dill-belt`p.kyz)
|
||||
%talk (talk p.kyz)
|
||||
%text (fore (tuba p.kyz) ~)
|
||||
%crud :: (send `dill-belt`[%cru p.kyz q.kyz])
|
||||
(crud p.kyz q.kyz)
|
||||
%blew (send(wid p.p.kyz) %rez p.p.kyz q.p.kyz)
|
||||
%heft (pass /whey %$ whey/~)
|
||||
%meld (dump kyz)
|
||||
%pack (dump kyz)
|
||||
%crop (dump trim+p.kyz)
|
||||
%verb (pass /verb %$ kyz)
|
||||
==
|
||||
::
|
||||
++ crud
|
||||
@ -133,30 +115,30 @@
|
||||
=/ lev=log-level (~(gut by veb.all) err %loud)
|
||||
:: apply log level for this error tag
|
||||
::
|
||||
=/ =wall
|
||||
?- lev
|
||||
%hush ~
|
||||
%soft ~["crud: %{(trip err)} event failed"]
|
||||
%loud :- "crud: %{(trip err)} event failed"
|
||||
%- zing
|
||||
%+ turn (flop tac)
|
||||
|=(a=tank (~(win re a) [0 wid]))
|
||||
==
|
||||
|- ^+ +>.^$
|
||||
?~ wall +>.^$
|
||||
$(wall t.wall, +>.^$ (from %out (tuba i.wall)))
|
||||
?- lev
|
||||
%hush +>.$
|
||||
%soft (fore (tuba "crud: %{(trip err)} event failed") ~)
|
||||
%loud (talk leaf+"crud: %{(trip err)} event failed" (flop tac))
|
||||
==
|
||||
::
|
||||
++ talk
|
||||
|= tac=(list tank)
|
||||
%- fore
|
||||
%- zing
|
||||
%+ turn tac
|
||||
|= a=tank
|
||||
(turn (~(win re a) [0 wid]) tuba)
|
||||
::
|
||||
++ dump :: pass down to hey
|
||||
|= git=gift
|
||||
?> ?=(^ hey.all)
|
||||
+>(moz [[u.hey.all %give git] moz])
|
||||
::
|
||||
++ done :: return gift
|
||||
++ done :: gift to viewers
|
||||
|= git=gift
|
||||
=- +>.$(moz (weld - moz))
|
||||
%+ turn
|
||||
:- hen
|
||||
~(tap in (~(get ju eye.all) hen))
|
||||
~(tap in (~(get ju eye.all) ses))
|
||||
|=(=duct [duct %give git])
|
||||
::
|
||||
++ deal :: pass to %gall
|
||||
@ -167,44 +149,37 @@
|
||||
|= [=wire =note]
|
||||
+>(moz :_(moz [hen %pass wire note]))
|
||||
::
|
||||
++ fore :: send dill output
|
||||
::NOTE there are still implicit assumptions
|
||||
:: about the underlying console app's
|
||||
:: semantics here. specifically, trailing
|
||||
:: newlines are important to not getting
|
||||
:: overwritten by the drum prompt, and a
|
||||
:: bottom-of-screen cursor position gives
|
||||
:: nicest results. a more agnostic solution
|
||||
:: will need to replace this arm, someday.
|
||||
:: perhaps +send this to .ram instead?
|
||||
::
|
||||
|= liz=(list (list @c))
|
||||
~? !=(%$ ses) [%d %foreing-in-session ses]
|
||||
^+ +>
|
||||
=. +>
|
||||
=| biz=(list blit)
|
||||
|- ^+ +>.^$
|
||||
?~ liz (done %blit [%hop 0] [%wyp ~] biz)
|
||||
$(liz t.liz, biz (welp biz [%put i.liz] [%nel ~] ~))
|
||||
:: since dill is acting on its own accord,
|
||||
:: we %hey the term app so it may clean up.
|
||||
::
|
||||
(send %hey ~)
|
||||
::
|
||||
++ from :: receive blit
|
||||
|= bit=dill-blit
|
||||
^+ +>
|
||||
?: ?=(%mor -.bit)
|
||||
|- ^+ +>.^$
|
||||
?~ p.bit +>.^$
|
||||
$(p.bit t.p.bit, +>.^$ ^$(bit i.p.bit))
|
||||
?: ?=(%out -.bit)
|
||||
%+ done %blit
|
||||
:~ [%lin p.bit]
|
||||
[%mor ~]
|
||||
see
|
||||
[%hop pos]
|
||||
==
|
||||
?: ?=(%klr -.bit)
|
||||
%+ done %blit
|
||||
:~ [%klr p.bit]
|
||||
[%mor ~]
|
||||
see
|
||||
[%hop pos]
|
||||
==
|
||||
?: ?=(%pro -.bit)
|
||||
=. see [%lin p.bit]
|
||||
(done %blit [see [%hop pos] ~])
|
||||
?: ?=(%pom -.bit)
|
||||
::NOTE treat "styled prompt" without style as plain prompt,
|
||||
:: to allow rendering by older runtimes
|
||||
::TODO remove me once v0.10.9+ has high/guaranteed adoption
|
||||
::
|
||||
?: (levy p.bit (cork head |*(s=stye =(*stye s))))
|
||||
$(bit [%pro (zing (turn p.bit tail))])
|
||||
=. see [%klr p.bit]
|
||||
(done %blit [see [%hop pos] ~])
|
||||
?: ?=(%hop -.bit)
|
||||
(done(pos p.bit) %blit [bit ~])
|
||||
?: ?=(%qit -.bit)
|
||||
(dump %logo ~)
|
||||
(done %blit [bit ~])
|
||||
::TODO so why is this a (list blit) again?
|
||||
(done %blit bit ~)
|
||||
::
|
||||
++ sponsor
|
||||
^- ship
|
||||
@ -221,7 +196,7 @@
|
||||
=. tem ~
|
||||
=. ..mere (pass /zest %c %zest %base %live)
|
||||
=. ..mere (show-desk %kids)
|
||||
=. ..mere drum-watch
|
||||
=. ..mere (open ~)
|
||||
|- ^+ ..mere
|
||||
?~ myt ..mere
|
||||
$(myt t.myt, ..mere (send i.myt))
|
||||
@ -231,15 +206,27 @@
|
||||
=. tem `(turn gyl |=(a=gill [%yow a]))
|
||||
(pass / [%c %warp our %base `[%sing %y [%ud 1] /]])
|
||||
::
|
||||
++ open
|
||||
|= gyl=(list gill)
|
||||
::TODO should allow handlers from non-base desks
|
||||
::TODO maybe ensure :ram is running?
|
||||
=. +> peer
|
||||
%+ roll gyl
|
||||
|= [g=gill _..open]
|
||||
(send [%yow g])
|
||||
::
|
||||
++ send :: send action
|
||||
|= bet=dill-belt
|
||||
^+ +>
|
||||
?^ tem
|
||||
+>(tem `[bet u.tem])
|
||||
(deal / [%poke [%dill-belt -:!>(bet) bet]])
|
||||
(deal /send/[ses] [%poke [%dill-poke !>([ses bet])]])
|
||||
::
|
||||
++ drum-watch
|
||||
(deal / [%watch /drum])
|
||||
++ peer
|
||||
(deal /peer/[ses] %watch /dill/[ses])
|
||||
::
|
||||
++ pull
|
||||
(deal /peer/[ses] %leave ~)
|
||||
::
|
||||
++ show-desk :: permit reads on desk
|
||||
|= des=desk
|
||||
@ -249,21 +236,11 @@
|
||||
|= [tea=wire sih=sign]
|
||||
^+ +>
|
||||
?- sih
|
||||
[%gall %onto *]
|
||||
:: NOTE effects during initial boot sequence are ignored,
|
||||
:: so :hood compilation errors will not print; slog if desired
|
||||
::
|
||||
:: ~& [%take-gall-onto +>.sih]
|
||||
?- -.+>.sih
|
||||
%| (crud %onto p.p.+>.sih)
|
||||
%& (done %blit [%lin (tuba "{<p.p.sih>}")]~)
|
||||
==
|
||||
::
|
||||
[%gall %unto *]
|
||||
:: ~& [%take-gall-unto +>.sih]
|
||||
?- -.+>.sih
|
||||
%raw-fact !!
|
||||
%kick drum-watch
|
||||
%kick peer
|
||||
%poke-ack ?~(p.p.+>.sih +>.$ (crud %coup u.p.p.+>.sih))
|
||||
%watch-ack
|
||||
?~ p.p.+>.sih
|
||||
@ -275,9 +252,6 @@
|
||||
+>.$
|
||||
(from ;;(dill-blit q.q.cage.p.+>.sih))
|
||||
==
|
||||
::
|
||||
[%clay %note *]
|
||||
(from %out (tuba p.sih ' ' ~(ram re q.sih)))
|
||||
::
|
||||
[?(%behn %clay) %writ *]
|
||||
init
|
||||
@ -292,12 +266,20 @@
|
||||
==
|
||||
--
|
||||
::
|
||||
++ ax :: make ++as
|
||||
|= hen=duct
|
||||
++ ax :: make ++as from name
|
||||
|= [hen=duct ses=@tas]
|
||||
^- (unit _as)
|
||||
=/ nux (~(get by dug.all) hen)
|
||||
=/ nux (~(get by dug.all) ses)
|
||||
?~ nux ~
|
||||
(some ~(. as hen u.nux))
|
||||
(some ~(. as hen ses u.nux))
|
||||
::
|
||||
++ aw :: make ++as from wire
|
||||
|= [hen=duct wir=wire]
|
||||
^- (unit _as)
|
||||
%+ ax hen
|
||||
?+ wir %$
|
||||
[?(%peer %send) @ *] i.t.wir
|
||||
==
|
||||
--
|
||||
|% :: poke+peek pattern
|
||||
++ call :: handle request
|
||||
@ -308,7 +290,10 @@
|
||||
^+ [*(list move) ..^$]
|
||||
~| wrapped-task
|
||||
=/ task=task ((harden task) wrapped-task)
|
||||
:: unwrap session tasks, default to session %$
|
||||
::
|
||||
=^ ses=@tas task
|
||||
?:(?=(%shot -.task) +.task [%$ task])
|
||||
:: error notifications "downcast" to %crud
|
||||
::
|
||||
=? task ?=(^ dud)
|
||||
@ -338,10 +323,11 @@
|
||||
::
|
||||
=* duc (need hey.all)
|
||||
=/ app %hood
|
||||
=/ see (tuba "<awaiting {(trip app)}, this may take a minute>")
|
||||
=/ zon=axon [app input=[~ ~] width=80 cursor=(lent see) lin+see]
|
||||
=/ say (tuba "<awaiting {(trip app)}, this may take a minute>")
|
||||
=/ zon=axon [app input=[~ ~] width=80]
|
||||
::
|
||||
=^ moz all abet:(~(into as duc zon) ~)
|
||||
=^ moz all abet:(~(into as duc %$ zon) ~)
|
||||
=. eye.all (~(put ju eye.all) %$ duc)
|
||||
[moz ..^$]
|
||||
:: %flog tasks are unwrapped and sent back to us on our default duct
|
||||
::
|
||||
@ -362,35 +348,60 @@
|
||||
?: ?=(%knob -.task)
|
||||
=. veb.all (~(put by veb.all) tag.task level.task)
|
||||
[~ ..^$]
|
||||
:: %open opens a new dill session
|
||||
::
|
||||
?: ?=(%open -.task)
|
||||
?: (~(has by dug.all) ses)
|
||||
::TODO should we allow, and just send the %yow blits?
|
||||
~| [%cannot-open-existing ses]
|
||||
!!
|
||||
=/ zon=axon [p.task ~ width=80]
|
||||
=^ moz all abet:(~(open as hen ses zon) q.task)
|
||||
=. eye.all (~(put ju eye.all) ses hen)
|
||||
[moz ..^$]
|
||||
:: %shut closes an existing dill session
|
||||
::
|
||||
?: ?=(%shut -.task)
|
||||
?: =(%$ ses)
|
||||
~| %cannot-shut-default-session
|
||||
!!
|
||||
=/ nus
|
||||
~| [%no-session ses]
|
||||
(need (ax hen ses))
|
||||
::NOTE we do deletion from state outside of the core,
|
||||
:: because +abet would re-insert.
|
||||
::TODO send a %bye blit? xx
|
||||
=^ moz all abet:pull:nus
|
||||
=. dug.all (~(del by dug.all) ses)
|
||||
=. eye.all (~(del by eye.all) ses)
|
||||
[moz ..^$]
|
||||
:: %view opens a subscription to the target session, on the current duct
|
||||
::
|
||||
?: ?=(%view -.task)
|
||||
:: crash on viewing non-existent session
|
||||
=/ nus
|
||||
:: crash on viewing non-existent session
|
||||
::
|
||||
~| [%no-session ses]
|
||||
(need (ax hen ses))
|
||||
:: register the viewer and send a %hey so they get the full screen
|
||||
::
|
||||
~| [%no-session session.task]
|
||||
?> =(~ session.task)
|
||||
=/ session (need hey.all)
|
||||
=/ =axon (~(got by dug.all) session)
|
||||
:: register the viewer and send them the prompt line
|
||||
::
|
||||
:- [hen %give %blit [see.axon]~]~
|
||||
..^$(eye.all (~(put ju eye.all) session hen))
|
||||
=^ moz all
|
||||
abet:(send:nus %hey ~)
|
||||
:- moz
|
||||
..^$(eye.all (~(put ju eye.all) ses hen))
|
||||
:: %flee closes a subscription to the target session, from the current duct
|
||||
::
|
||||
?: ?=(%flee -.task)
|
||||
:- ~
|
||||
~| [%no-session session.task]
|
||||
?> =(~ session.task)
|
||||
=/ session (need hey.all)
|
||||
..^$(eye.all (~(del ju eye.all) session hen))
|
||||
..^$(eye.all (~(del ju eye.all) ses hen))
|
||||
::
|
||||
=/ nus (ax hen)
|
||||
=? nus &(?=(~ nus) ?=(^ hey.all))
|
||||
::TODO allow specifying target session in task
|
||||
(ax u.hey.all)
|
||||
=/ nus
|
||||
(ax hen ses)
|
||||
?~ nus
|
||||
:: :hen is an unrecognized duct
|
||||
:: session :ses does not exist
|
||||
:: could be before %boot (or %boot failed)
|
||||
::
|
||||
~& [%dill-call-no-flow hen -.task]
|
||||
~& [%dill-call-no-session ses hen -.task]
|
||||
=/ tan ?:(?=(%crud -.task) q.task ~)
|
||||
[((slog (flop tan)) ~) ..^$]
|
||||
::
|
||||
@ -398,8 +409,63 @@
|
||||
[moz ..^$]
|
||||
::
|
||||
++ load :: import old state
|
||||
|= old=axle
|
||||
..^$(all old)
|
||||
=< |= old=any-axle
|
||||
?- -.old
|
||||
%5 ..^$(all old)
|
||||
%4 $(old (axle-4-to-5 old))
|
||||
==
|
||||
|%
|
||||
+$ any-axle $%(axle axle-4)
|
||||
::
|
||||
+$ axle-4
|
||||
$: %4
|
||||
hey=(unit duct)
|
||||
dug=(map duct axon-4)
|
||||
eye=(jug duct duct)
|
||||
lit=?
|
||||
veb=(map @tas log-level)
|
||||
==
|
||||
::
|
||||
+$ axon-4
|
||||
$: ram=term
|
||||
tem=(unit (list dill-belt-4))
|
||||
wid=_80
|
||||
pos=$@(@ud [@ud @ud])
|
||||
see=$%([%lin (list @c)] [%klr stub])
|
||||
==
|
||||
::
|
||||
+$ dill-belt-4
|
||||
$% [%ctl p=@c]
|
||||
[%met p=@c]
|
||||
dill-belt
|
||||
==
|
||||
::
|
||||
++ axle-4-to-5
|
||||
|= axle-4
|
||||
^- axle
|
||||
:- %5
|
||||
=- [hey nug nay lit veb]
|
||||
%+ roll ~(tap by dug)
|
||||
|= [[=duct =axon-4] nug=(map @tas axon) nay=(jug @tas duct)]
|
||||
=/ ses=@tas
|
||||
~| [%unexpected-duct duct]
|
||||
?>(=([//term/1]~ duct) %$)
|
||||
:- (~(put by nug) ses (axon-4-to-5 axon-4))
|
||||
%+ ~(put by nay) ses
|
||||
(~(put in (~(get ju eye) duct)) duct)
|
||||
::
|
||||
++ axon-4-to-5
|
||||
|= axon-4
|
||||
^- axon
|
||||
=; tem [ram tem wid]
|
||||
?~ tem ~
|
||||
%- some
|
||||
%+ turn u.tem
|
||||
|= b=dill-belt-4
|
||||
^- dill-belt
|
||||
?. ?=(?(%ctl %met) -.b) b
|
||||
[%mod -.b p.b]
|
||||
--
|
||||
::
|
||||
++ scry
|
||||
^- roon
|
||||
@ -428,19 +494,12 @@
|
||||
=(%$ syd)
|
||||
==
|
||||
~
|
||||
:: /dx/sessions//line blit current line (prompt) of default session
|
||||
:: /dx/sessions//cursor @ud current cursor position of default session
|
||||
::TODO support asking for specific sessions once session ids are real
|
||||
:: /dy/sessions (set @tas) all existing sessions
|
||||
:: /du/sessions/[ses] ? does session ses exist?
|
||||
::
|
||||
?. ?=(%x ren) ~
|
||||
?+ tyl ~
|
||||
[%sessions %$ *]
|
||||
?~ hey.all [~ ~]
|
||||
?~ session=(~(get by dug.all) u.hey.all) [~ ~]
|
||||
?+ t.t.tyl ~
|
||||
[%line ~] ``blit+!>(`blit`see.u.session)
|
||||
[%cursor ~] ``atom+!>(pos.u.session)
|
||||
==
|
||||
?+ [ren tyl] ~
|
||||
[%y %sessions ~] ``noun+!>(~(key by dug.all))
|
||||
[%u %sessions @ ~] ``noun+!>((~(has by dug.all) (snag 1 tyl)))
|
||||
==
|
||||
::
|
||||
++ stay all
|
||||
@ -451,12 +510,11 @@
|
||||
?^ dud
|
||||
~|(%dill-take-dud (mean tang.u.dud))
|
||||
::
|
||||
=/ nus (ax hen)
|
||||
=/ nus (aw hen tea)
|
||||
?~ nus
|
||||
:: :hen is an unrecognized duct
|
||||
:: could be before %boot (or %boot failed)
|
||||
:: :tea points to an unrecognized session
|
||||
::
|
||||
~& [%dill-take-no-flow hen -.hin +<.hin]
|
||||
~& [%dill-take-no-session tea -.hin +<.hin]
|
||||
[~ ..^$]
|
||||
=^ moz all abet:(take:u.nus tea hin)
|
||||
[moz ..^$]
|
||||
|
@ -198,11 +198,21 @@
|
||||
:: +mo-abet: finalize, reversing moves
|
||||
:: +mo-pass: prepend a standard %pass to the current list of moves
|
||||
:: +mo-give: prepend a standard %give to the current list of moves
|
||||
:: +mo-talk: build task to print config report or failure trace
|
||||
::
|
||||
++ mo-core .
|
||||
++ mo-abed |=(hun=duct mo-core(hen hun))
|
||||
++ mo-abet [(flop moves) gall-payload]
|
||||
++ mo-give |=(g=gift mo-core(moves [[hen give+g] moves]))
|
||||
++ mo-talk
|
||||
|= rup=(each suss tang)
|
||||
^- [wire note-arvo]
|
||||
:+ /sys/say %d
|
||||
^- task:dill
|
||||
?- -.rup
|
||||
%& [%text "gall: {(t q)}ed %{(t p)}":[t=trip p.rup]]
|
||||
%| [%talk leaf+"gall: failed" (flop p.rup)]
|
||||
==
|
||||
++ mo-pass |=(p=[wire note-arvo] mo-core(moves [[hen pass+p] moves]))
|
||||
++ mo-slip |=(p=note-arvo mo-core(moves [[hen slip+p] moves]))
|
||||
++ mo-past
|
||||
@ -303,12 +313,12 @@
|
||||
=/ ap-core +.wag
|
||||
?^ maybe-tang
|
||||
=. mo-core old
|
||||
(mo-give %onto %.n u.maybe-tang)
|
||||
(mo-pass (mo-talk %.n u.maybe-tang))
|
||||
::
|
||||
=. mo-core ap-abet:ap-core
|
||||
=. mo-core (mo-clear-queue dap)
|
||||
=/ =suss [dap %boot now]
|
||||
(mo-give %onto [%.y suss])
|
||||
(mo-pass (mo-talk %.y suss))
|
||||
:: +mo-send-foreign-request: handle local request to .ship
|
||||
::
|
||||
++ mo-send-foreign-request
|
||||
@ -904,8 +914,8 @@
|
||||
::
|
||||
=/ running (~(put by yokes.state) agent-name yoke)
|
||||
=/ moves
|
||||
=/ giver |=(report=(each suss tang) [hen %give %onto report])
|
||||
=/ from-suss (turn agent-config giver)
|
||||
=/ talker |=(report=(each suss tang) [hen %pass (mo-talk report)])
|
||||
=/ from-suss (turn agent-config talker)
|
||||
:(weld agent-moves from-suss moves)
|
||||
::
|
||||
%_ mo-core
|
||||
|
@ -105,11 +105,8 @@
|
||||
$>(%wake gift:behn) ::
|
||||
== ::
|
||||
$: %gall ::
|
||||
$> $? %onto ::
|
||||
%unto ::
|
||||
== ::
|
||||
gift:gall ::
|
||||
==
|
||||
$>(%unto gift:gall) ::
|
||||
== ::
|
||||
== ::
|
||||
-- ::
|
||||
:: ::::
|
||||
@ -507,7 +504,7 @@
|
||||
%ruin
|
||||
::NOTE we blast this out to _all_ known ducts, because the common
|
||||
:: use case for this is comets, about who nobody cares.
|
||||
=/ dus ~(key by yen.zim.pki)
|
||||
=/ dus (~(uni in nel.zim.pki) ~(key by yen.zim.pki))
|
||||
=/ sus ~(. su hen now pki etn)
|
||||
=/ sis ~(tap in ships.tac)
|
||||
|-
|
||||
@ -550,10 +547,6 @@
|
||||
=/ ships (~(get ju ship-sources-reverse.etn) source-id)
|
||||
%- curd =< abet
|
||||
(sources:~(feel su hen now pki etn) ships source)
|
||||
::
|
||||
[%gall %onto *]
|
||||
~& [%jael-onto tea hin]
|
||||
+>.$
|
||||
::
|
||||
[%gall %unto *]
|
||||
?- +>-.hin
|
||||
|
@ -4,7 +4,7 @@
|
||||
=> ..lull
|
||||
~% %zuse ..part ~
|
||||
|%
|
||||
++ zuse %417
|
||||
++ zuse %416
|
||||
:: :: ::
|
||||
:::: :: :: (2) engines
|
||||
:: :: ::
|
||||
@ -3843,6 +3843,102 @@
|
||||
~
|
||||
(some (~(run by lum) need))
|
||||
-- ::dejs-soft
|
||||
::
|
||||
++ klr :: styx/stub engine
|
||||
=, dill
|
||||
|%
|
||||
++ make :: stub from styx
|
||||
|= a=styx ^- stub
|
||||
=| b=stye
|
||||
%+ reel
|
||||
|- ^- stub
|
||||
%- zing %+ turn a
|
||||
|= a=$@(@t (pair styl styx))
|
||||
?@ a [b (tuba (trip a))]~
|
||||
^$(a q.a, b (styd p.a b))
|
||||
::
|
||||
|= [a=(pair stye (list @c)) b=stub]
|
||||
?~ b [a ~]
|
||||
?. =(p.a p.i.b) [a b]
|
||||
[[p.a (weld q.a q.i.b)] t.b]
|
||||
::
|
||||
++ styd :: stye from styl
|
||||
|= [a=styl b=stye] ^+ b :: with inheritance
|
||||
:+ ?~ p.a p.b
|
||||
?~ u.p.a ~
|
||||
(~(put in p.b) u.p.a)
|
||||
(fall p.q.a p.q.b)
|
||||
(fall q.q.a q.q.b)
|
||||
::
|
||||
++ lent-char
|
||||
|= a=stub ^- @
|
||||
(roll (lnts-char a) add)
|
||||
::
|
||||
++ lnts-char :: stub text lengths
|
||||
|= a=stub ^- (list @)
|
||||
%+ turn a
|
||||
|= a=(pair stye (list @c))
|
||||
(lent q.a)
|
||||
::
|
||||
++ brek :: index + incl-len of
|
||||
|= [a=@ b=(list @)] :: stub pair w/ idx a
|
||||
=| [c=@ i=@]
|
||||
|- ^- (unit (pair @ @))
|
||||
?~ b ~
|
||||
=. c (add c i.b)
|
||||
?: (gte c a)
|
||||
`[i c]
|
||||
$(i +(i), b t.b)
|
||||
::
|
||||
++ pact :: condense stub
|
||||
|= a=stub
|
||||
^- stub
|
||||
?~ a ~
|
||||
?~ t.a a
|
||||
?. =(p.i.a p.i.t.a) [i.a $(a t.a)]
|
||||
=. q.i.t.a (weld q.i.a q.i.t.a)
|
||||
$(a t.a)
|
||||
::
|
||||
++ slag :: slag stub
|
||||
|= [a=@ b=stub]
|
||||
^- stub
|
||||
?: =(0 a) b
|
||||
?~ b ~
|
||||
=+ c=(lent q.i.b)
|
||||
?: =(c a) t.b
|
||||
?: (gth c a)
|
||||
[[p.i.b (^slag a q.i.b)] t.b]
|
||||
$(a (sub a c), b t.b)
|
||||
::
|
||||
++ scag :: scag stub
|
||||
|= [a=@ b=stub]
|
||||
^- stub
|
||||
?: =(0 a) ~
|
||||
?~ b ~
|
||||
=+ c=(lent q.i.b)
|
||||
?: (gth c a)
|
||||
[p.i.b (^scag a q.i.b)]~
|
||||
:- i.b
|
||||
$(a (sub a c), b t.b)
|
||||
::
|
||||
++ swag :: swag stub
|
||||
|= [[a=@ b=@] c=stub]
|
||||
(scag b (slag a c))
|
||||
::
|
||||
++ wail :: overlay stub
|
||||
|= [a=stub b=@ c=stub d=@c]
|
||||
^- stub
|
||||
;: weld
|
||||
(scag b a)
|
||||
::
|
||||
=+ e=(lent-char a)
|
||||
?: (lte b e) ~
|
||||
[*stye (reap (sub b e) d)]~
|
||||
::
|
||||
c
|
||||
(slag (add b (lent-char c)) a)
|
||||
==
|
||||
-- :: klr
|
||||
--
|
||||
:: |cloy: clay helpers
|
||||
::
|
||||
@ -4928,7 +5024,7 @@
|
||||
=< q.q %- need %- need
|
||||
(rof ~ %j `beam`[[our %sein %da now] /(scot %p who)])
|
||||
--
|
||||
:: middle core: for userspace use, with .^
|
||||
:: middle core: stateless queries for default numeric sponsorship
|
||||
::
|
||||
=> |%
|
||||
:: :: ++clan:title
|
||||
@ -4968,7 +5064,7 @@
|
||||
%pawn (end 4 who)
|
||||
==
|
||||
--
|
||||
:: surface core: stateless queries for default numeric sponsorship
|
||||
:: surface core: for userspace use, with .^
|
||||
::
|
||||
|%
|
||||
:: :: ++cite:title
|
||||
@ -5003,13 +5099,25 @@
|
||||
%j
|
||||
/(scot %p our)/sein/(scot %da now)/(scot %p who)
|
||||
==
|
||||
:: +team was created with two meanings:
|
||||
:: A. her / her moon
|
||||
:: B. whoever should be able to control her ship
|
||||
::
|
||||
:: these two things aren't obviously equal anymore,
|
||||
:: and it's more important for +team to satisfy B than A,
|
||||
:: so now +team just means "her".
|
||||
::
|
||||
:: (ships can definitely be trusted to control themselves)
|
||||
:: :: ++team:title
|
||||
++ team :: our / our moon
|
||||
|= [our=ship who=ship]
|
||||
++ team :: her
|
||||
|= [her=ship who=ship]
|
||||
^- ?
|
||||
?| =(our who)
|
||||
&(?=(%earl (clan who)) =(our (^sein who)))
|
||||
==
|
||||
=(her who)
|
||||
:: :: ++moon:title
|
||||
++ moon :: her moon
|
||||
|= [her=ship who=ship]
|
||||
^- ?
|
||||
&(=(%earl (clan who)) =(her (^sein who)))
|
||||
-- ::title
|
||||
:: ::
|
||||
:::: ++milly :: (2k) milliseconds
|
||||
|
@ -17,15 +17,16 @@
|
||||
%+ roll blits
|
||||
|= [b=blit:dill line=tape]
|
||||
?- -.b
|
||||
%lin (tape p.b)
|
||||
%put (tape p.b)
|
||||
%klr (tape (zing (turn p.b tail)))
|
||||
%mor ~& "{<who>}: {line}" ""
|
||||
%nel ~& "{<who>}: {line}" ""
|
||||
%hop line
|
||||
%bel line
|
||||
%clr ""
|
||||
%sag ~& [%save-jamfile-to p.b] line
|
||||
%sav ~& [%save-file-to p.b] line
|
||||
%url ~& [%activate-url p.b] line
|
||||
%wyp ""
|
||||
==
|
||||
~? !=(~ last-line) last-line
|
||||
~
|
||||
|
@ -106,10 +106,6 @@
|
||||
:: Doesn't follow horizontal & vertical ordering
|
||||
::
|
||||
=/ unbalanced-e=(set @) [1 [3 ~ ~] [2 ~ ~]]
|
||||
:: Duplicate elements
|
||||
::
|
||||
=/ has-dupes=(set @) [1 [1 ~ ~] ~]
|
||||
::
|
||||
;: weld
|
||||
%+ expect-eq
|
||||
!> [%b-a %.y]
|
||||
@ -129,9 +125,6 @@
|
||||
%+ expect-eq
|
||||
!> [%u-e %.n]
|
||||
!> [%u-e ~(apt in unbalanced-e)]
|
||||
%+ expect-eq
|
||||
!> [%h-d %.n]
|
||||
!> [%h-d ~(apt in has-dupes)]
|
||||
==
|
||||
::
|
||||
:: Test splits a in b
|
||||
|
94
pkg/base-dev/lib/dill.hoon
Normal file
94
pkg/base-dev/lib/dill.hoon
Normal file
@ -0,0 +1,94 @@
|
||||
:: dill: utilities for dill's data structures
|
||||
::
|
||||
=, dill
|
||||
|%
|
||||
++ enjs
|
||||
|%
|
||||
++ blit
|
||||
|= =blit:dill
|
||||
^- json
|
||||
=, enjs:format
|
||||
%+ frond -.blit
|
||||
?- -.blit
|
||||
%bel b+&
|
||||
%clr b+&
|
||||
%hop ?@ p.blit (numb p.blit)
|
||||
(pairs 'x'^(numb x.p.blit) 'y'^(numb y.p.blit) ~)
|
||||
%put a+(turn p.blit |=(c=@c s+(tuft c)))
|
||||
%nel b+&
|
||||
%url s+p.blit
|
||||
%wyp b+&
|
||||
%mor a+(turn p.blit ^blit)
|
||||
::
|
||||
%sag
|
||||
%- pairs
|
||||
:~ 'path'^(path p.blit)
|
||||
'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit)))
|
||||
==
|
||||
::
|
||||
%sav
|
||||
%- pairs
|
||||
:~ 'path'^(path p.blit)
|
||||
'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit))
|
||||
==
|
||||
::
|
||||
%klr
|
||||
:- %a
|
||||
%+ turn p.blit
|
||||
|= [=stye text=(list @c)]
|
||||
%- pairs
|
||||
:~ 'text'^a+(turn text |=(c=@c s+(tuft c)))
|
||||
::
|
||||
:- 'stye'
|
||||
%- pairs
|
||||
|^ :~ 'back'^(color p.q.stye)
|
||||
'fore'^(color q.q.stye)
|
||||
'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d)))
|
||||
==
|
||||
++ color
|
||||
|= =tint
|
||||
?@ tint ?~(tint ~ s+tint)
|
||||
=, tint
|
||||
(pairs r+(numb r) g+(numb g) b+(numb b) ~)
|
||||
--
|
||||
==
|
||||
==
|
||||
--
|
||||
::
|
||||
++ dejs
|
||||
|%
|
||||
++ belt
|
||||
|= jon=json
|
||||
^- belt:dill
|
||||
?: ?=([%s *] jon)
|
||||
(taft p.jon)
|
||||
=, dejs:format
|
||||
%. jon
|
||||
%- of
|
||||
|^ :* mod+(ot 'mod'^mod 'key'^bot ~)
|
||||
txt+(ar (cu taft so))
|
||||
bol
|
||||
==
|
||||
::
|
||||
++ bol
|
||||
:~ aro+(su (perk %d %l %r %u ~))
|
||||
bac+ul
|
||||
del+ul
|
||||
hit+(ot 'x'^ni 'y'^ni ~)
|
||||
ret+ul
|
||||
==
|
||||
::
|
||||
++ bot
|
||||
|= j=json
|
||||
^- bolt:dill
|
||||
?+ j !!
|
||||
[%s *] (taft p.j)
|
||||
[%o *] ((of bol) j)
|
||||
==
|
||||
::
|
||||
++ mod
|
||||
|= j=json
|
||||
((su (perk %ctl %met %hyp ~)) j)
|
||||
--
|
||||
--
|
||||
--
|
@ -28,8 +28,8 @@
|
||||
%+ send-events-to who
|
||||
^- (list unix-event)
|
||||
:~
|
||||
[/d/term/1 %belt %ctl `@c`%e]
|
||||
[/d/term/1 %belt %ctl `@c`%u]
|
||||
[/d/term/1 %belt %mod %ctl `@c`%e]
|
||||
[/d/term/1 %belt %mod %ctl `@c`%u]
|
||||
[/d/term/1 %belt %txt ((list @c) what)]
|
||||
[/d/term/1 %belt %ret ~]
|
||||
==
|
||||
@ -40,7 +40,7 @@
|
||||
|= [who=ship what=term]
|
||||
^- (list ph-event)
|
||||
%+ send-events-to who
|
||||
:~ [/d/term/1 %belt %ctl (,@c what)]
|
||||
:~ [/d/term/1 %belt %mod %ctl (,@c what)]
|
||||
==
|
||||
::
|
||||
:: Inject a file into a ship
|
||||
@ -67,7 +67,7 @@
|
||||
::
|
||||
%+ lien p.q.uf
|
||||
|= =blit:dill
|
||||
?. ?=(%lin -.blit)
|
||||
?. ?=(%put -.blit)
|
||||
|
|
||||
!=(~ (find what p.blit))
|
||||
==
|
||||
|
@ -13,15 +13,15 @@
|
||||
/- *sole
|
||||
/+ sole, auto=language-server-complete
|
||||
|%
|
||||
+$ state-0
|
||||
$: %0
|
||||
soles=(map @ta sole-share)
|
||||
+$ state-1
|
||||
$: %1
|
||||
soles=(map sole-id sole-share)
|
||||
==
|
||||
:: $card: standard gall cards plus shoe effects
|
||||
::
|
||||
+$ card
|
||||
$% card:agent:gall
|
||||
[%shoe sole-ids=(list @ta) effect=shoe-effect] :: ~ sends to all soles
|
||||
[%shoe sole-ids=(list sole-id) effect=shoe-effect] :: ~ sends to all
|
||||
==
|
||||
:: $shoe-effect: easier sole-effects
|
||||
::
|
||||
@ -47,30 +47,30 @@
|
||||
:: if the head of the result is true, instantly run the command
|
||||
::
|
||||
++ command-parser
|
||||
|~ sole-id=@ta
|
||||
|~ =sole-id
|
||||
|~(nail *(like [? command-type]))
|
||||
:: +tab-list: autocomplete options for the session (to match +command-parser)
|
||||
::
|
||||
++ tab-list
|
||||
|~ sole-id=@ta
|
||||
|~ =sole-id
|
||||
:: (list [@t tank])
|
||||
*(list (option:auto tank))
|
||||
:: +on-command: called when a valid command is run
|
||||
::
|
||||
++ on-command
|
||||
|~ [sole-id=@ta command=command-type]
|
||||
|~ [=sole-id command=command-type]
|
||||
*(quip card _^|(..on-init))
|
||||
::
|
||||
++ can-connect
|
||||
|~ sole-id=@ta
|
||||
|~ =sole-id
|
||||
*?
|
||||
::
|
||||
++ on-connect
|
||||
|~ sole-id=@ta
|
||||
|~ =sole-id
|
||||
*(quip card _^|(..on-init))
|
||||
::
|
||||
++ on-disconnect
|
||||
|~ sole-id=@ta
|
||||
|~ =sole-id
|
||||
*(quip card _^|(..on-init))
|
||||
::
|
||||
::NOTE standard gall agent arms below, though they may produce %shoe cards
|
||||
@ -119,27 +119,27 @@
|
||||
|* [shoe=* command-type=mold]
|
||||
|_ =bowl:gall
|
||||
++ command-parser
|
||||
|= sole-id=@ta
|
||||
|= =sole-id
|
||||
(easy *[? command-type])
|
||||
::
|
||||
++ tab-list
|
||||
|= sole-id=@ta
|
||||
|= =sole-id
|
||||
~
|
||||
::
|
||||
++ on-command
|
||||
|= [sole-id=@ta command=command-type]
|
||||
|= [=sole-id command=command-type]
|
||||
[~ shoe]
|
||||
::
|
||||
++ can-connect
|
||||
|= sole-id=@ta
|
||||
|= =sole-id
|
||||
(team:title [our src]:bowl)
|
||||
::
|
||||
++ on-connect
|
||||
|= sole-id=@ta
|
||||
|= =sole-id
|
||||
[~ shoe]
|
||||
::
|
||||
++ on-disconnect
|
||||
|= sole-id=@ta
|
||||
|= =sole-id
|
||||
[~ shoe]
|
||||
--
|
||||
:: +agent: creates wrapper core that handles sole events and calls shoe arms
|
||||
@ -147,7 +147,7 @@
|
||||
++ agent
|
||||
|* command-type=mold
|
||||
|= =(shoe command-type)
|
||||
=| state-0
|
||||
=| state-1
|
||||
=* state -
|
||||
^- agent:gall
|
||||
=>
|
||||
@ -164,8 +164,7 @@
|
||||
%+ turn
|
||||
?^ sole-ids.card sole-ids.card
|
||||
~(tap in ~(key by soles))
|
||||
|= sole-id=@ta
|
||||
/sole/[sole-id]
|
||||
id-to-path:sole
|
||||
::
|
||||
%table
|
||||
=; fez=(list sole-effect)
|
||||
@ -202,9 +201,36 @@
|
||||
?. ?=([%shoe-app ^] q.old-state)
|
||||
=^ cards shoe (on-load:og old-state)
|
||||
[(deal cards) this]
|
||||
=^ old-inner state +:!<([%shoe-app vase state-0] old-state)
|
||||
=^ cards shoe (on-load:og old-inner)
|
||||
[(deal cards) this]
|
||||
|^ =| old-outer=state-any
|
||||
=^ old-inner old-outer
|
||||
+:!<([%shoe-app vase state-any] old-state)
|
||||
:: ~! q.old-state
|
||||
:: ?+ +>.q.old-state !!
|
||||
:: [%0 *] +:!<([%shoe-app vase state-0] old-state)
|
||||
:: [%1 *] +:!<([%shoe-app vase state-1] old-state)
|
||||
:: ==
|
||||
=^ caz shoe (on-load:og old-inner)
|
||||
=^ cuz old-outer
|
||||
?. ?=(%0 -.old-outer) [~ old-outer]
|
||||
(state-0-to-1 old-outer)
|
||||
?> ?=(%1 -.old-outer)
|
||||
[(weld cuz (deal caz)) this(state old-outer)]
|
||||
::
|
||||
+$ state-any $%(state-1 state-0)
|
||||
+$ state-0 [%0 soles=(map @ta sole-share)]
|
||||
++ state-0-to-1
|
||||
|= old=state-0
|
||||
^- (quip card:agent:gall state-1)
|
||||
:- %+ turn ~(tap in ~(key by soles.old))
|
||||
|= id=@ta
|
||||
^- card:agent:gall
|
||||
[%give %kick ~[/sole/[id]] ~]
|
||||
:- %1
|
||||
%- ~(gas by *(map sole-id sole-share))
|
||||
%+ murn ~(tap by soles.old)
|
||||
|= [id=@ta s=sole-share]
|
||||
(bind (upgrade-id:sole id) (late s))
|
||||
--
|
||||
::
|
||||
++ on-poke
|
||||
|= [=mark =vase]
|
||||
@ -326,19 +352,18 @@
|
||||
++ on-watch
|
||||
|= =path
|
||||
^- (quip card:agent:gall agent:gall)
|
||||
?. ?=([%sole @ ~] path)
|
||||
?~ sole-id=(path-to-id:sole path)
|
||||
=^ cards shoe
|
||||
(on-watch:og path)
|
||||
[(deal cards) this]
|
||||
=* sole-id i.t.path
|
||||
?> (can-connect:og sole-id)
|
||||
=. soles (~(put by soles) sole-id *sole-share)
|
||||
?> (can-connect:og u.sole-id)
|
||||
=. soles (~(put by soles) u.sole-id *sole-share)
|
||||
=^ cards shoe
|
||||
(on-connect:og sole-id)
|
||||
(on-connect:og u.sole-id)
|
||||
:_ this
|
||||
%- deal
|
||||
:_ cards
|
||||
[%shoe [sole-id]~ %sole %pro & dap.bowl "> "]
|
||||
[%shoe [u.sole-id]~ %sole %pro & dap.bowl "> "]
|
||||
::
|
||||
++ on-leave
|
||||
|= =path
|
||||
|
@ -136,4 +136,28 @@
|
||||
=+ dat=(transmute [%mor leg] [%ins pos `@c`0])
|
||||
?> ?=(%ins -.dat)
|
||||
p.dat
|
||||
::
|
||||
::
|
||||
++ path-to-id
|
||||
|= =path
|
||||
^- (unit sole-id)
|
||||
?. ?=([%sole @ ?(~ [@ ~])] path) ~
|
||||
?~ who=(slaw %p i.t.path) ~
|
||||
`[u.who ?~(t.t.path %$ i.t.t.path)]
|
||||
::
|
||||
++ id-to-path
|
||||
|= sole-id
|
||||
^- path
|
||||
::TODO this whole "no empty path ending" business feels icky.
|
||||
:: do we want default session to be ~.~ ?
|
||||
:: concern here is that outsiders cannot subscribe to the default
|
||||
:: session, because /sole/~zod/ isn't a valid path...
|
||||
[%sole (scot %p who) ?~(ses ~ /[ses])]
|
||||
::
|
||||
++ upgrade-id
|
||||
|= old=@ta
|
||||
^- (unit sole-id)
|
||||
%+ rush old
|
||||
%+ cook (late %$)
|
||||
;~(pfix (jest 'drum_~') fed:ag)
|
||||
--
|
||||
|
@ -1,5 +1,7 @@
|
||||
:: belt: runtime belt structure
|
||||
::
|
||||
/+ dill
|
||||
::
|
||||
|_ =belt:dill
|
||||
++ grad %noun
|
||||
:: +grab: convert from
|
||||
@ -7,18 +9,7 @@
|
||||
++ grab
|
||||
|%
|
||||
++ noun belt:dill
|
||||
++ json
|
||||
^- $-(^json belt:dill)
|
||||
=, dejs:format
|
||||
%- of
|
||||
:~ aro+(su (perk %d %l %r %u ~))
|
||||
bac+ul
|
||||
ctl+(cu taft so)
|
||||
del+ul
|
||||
met+(cu taft so)
|
||||
ret+ul
|
||||
txt+(ar (cu taft so))
|
||||
==
|
||||
++ json belt:dejs:dill
|
||||
--
|
||||
:: +grow: convert to
|
||||
::
|
||||
|
@ -1,5 +1,7 @@
|
||||
:: blit: runtime blit structure
|
||||
::
|
||||
/+ dill
|
||||
::
|
||||
|_ =blit:dill
|
||||
++ grad %noun
|
||||
:: +grab: convert from
|
||||
@ -13,49 +15,6 @@
|
||||
++ grow
|
||||
|%
|
||||
++ noun blit
|
||||
++ json
|
||||
^- ^json
|
||||
=, enjs:format
|
||||
%+ frond -.blit
|
||||
?- -.blit
|
||||
%bel b+&
|
||||
%clr b+&
|
||||
%hop (numb p.blit)
|
||||
%lin a+(turn p.blit |=(c=@c s+(tuft c)))
|
||||
%mor b+&
|
||||
%url s+p.blit
|
||||
::
|
||||
%sag
|
||||
%- pairs
|
||||
:~ 'path'^(path p.blit)
|
||||
'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit)))
|
||||
==
|
||||
::
|
||||
%sav
|
||||
%- pairs
|
||||
:~ 'path'^(path p.blit)
|
||||
'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit))
|
||||
==
|
||||
::
|
||||
%klr
|
||||
:- %a
|
||||
%+ turn p.blit
|
||||
|= [=stye text=(list @c)]
|
||||
%- pairs
|
||||
:~ 'text'^a+(turn text |=(c=@c s+(tuft c)))
|
||||
::
|
||||
:- 'stye'
|
||||
%- pairs
|
||||
|^ :~ 'back'^(color p.q.stye)
|
||||
'fore'^(color q.q.stye)
|
||||
'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d)))
|
||||
==
|
||||
++ color
|
||||
|= =tint
|
||||
?@ tint ?~(tint ~ s+tint)
|
||||
s+(crip ((x-co:co 6) (rep 3 ~[b g r]:tint)))
|
||||
--
|
||||
==
|
||||
==
|
||||
++ json (blit:enjs:dill blit)
|
||||
--
|
||||
--
|
||||
|
@ -20,7 +20,9 @@
|
||||
|= jon=^json ^- sole-action
|
||||
%- need %. jon
|
||||
=> [dejs-soft:format ..sole-action]
|
||||
|^ (ot id+so dat+(fo %ret (of det+change tab+ni ~)) ~)
|
||||
|^ (ot id+id dat+(fo %ret (of det+change tab+ni ~)) ~)
|
||||
++ id
|
||||
(ot who+(su ;~(pfix sig fed:ag)) ses+so ~)
|
||||
++ fo
|
||||
|* [a=term b=fist]
|
||||
|=(c=json ?.(=([%s a] c) (b c) (some [a ~])))
|
||||
|
@ -3,8 +3,9 @@
|
||||
::
|
||||
^?
|
||||
|%
|
||||
+$ sole-id [who=@p ses=@ta]
|
||||
+$ sole-action :: sole to app
|
||||
$: id=@ta :: duct id
|
||||
$: id=sole-id :: session id
|
||||
$= dat
|
||||
$% :: [%abo ~] :: reset interaction
|
||||
[%det sole-change] :: command line edit
|
||||
|
@ -1 +1,2 @@
|
||||
[%zuse 417]
|
||||
[%zuse 416]
|
||||
|
@ -1 +1 @@
|
||||
[%zuse 417]
|
||||
[%zuse 416]
|
||||
|
@ -119,15 +119,25 @@ deriveNoun ''BehnEf
|
||||
data Blit
|
||||
= Bel ()
|
||||
| Clr ()
|
||||
| Hop Word64
|
||||
| Hop HopTarget
|
||||
| Klr Stub
|
||||
| Lin [Char]
|
||||
| Mor ()
|
||||
| Put [Char]
|
||||
| Nel ()
|
||||
| Sag Path Noun
|
||||
| Sav Path Atom
|
||||
| Url Cord
|
||||
| Wyp ()
|
||||
--TMP backwards compatibility
|
||||
| Lin [Char]
|
||||
| Mor ()
|
||||
deriving (Eq, Ord)
|
||||
|
||||
--NOTE bottom-left-0-based coordinates
|
||||
data HopTarget
|
||||
= Col Word64
|
||||
| Roc Word64 Word64 -- row, col
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data Deco
|
||||
= DecoBl
|
||||
| DecoBr
|
||||
@ -205,18 +215,33 @@ instance FromNoun Tint where
|
||||
"w" -> pure TintW
|
||||
t -> fail ("invalid: " <> unpack t)
|
||||
|
||||
instance FromNoun HopTarget where
|
||||
parseNoun = \case
|
||||
A c -> pure $ Col (fromIntegral c)
|
||||
C (A r) (A c) -> pure $ Roc (fromIntegral r) (fromIntegral c)
|
||||
n -> fail ("invalid hop target: " <> show n)
|
||||
|
||||
instance ToNoun HopTarget where
|
||||
toNoun = \case
|
||||
Col c -> A (fromIntegral c)
|
||||
Roc r c -> C (A (fromIntegral r)) (A (fromIntegral c))
|
||||
|
||||
-- Manual instance to not save the noun/atom in Sag/Sav, because these can be
|
||||
-- megabytes and makes king hang.
|
||||
instance Show Blit where
|
||||
show (Bel ()) = "Bel ()"
|
||||
show (Clr ()) = "Clr ()"
|
||||
show (Hop x) = "Hop " ++ (show x)
|
||||
show (Hop t) = "Hop " ++ (show t)
|
||||
show (Klr s) = "Klr " ++ (show s)
|
||||
show (Lin c) = "Lin " ++ (show c)
|
||||
show (Mor ()) = "Mor ()"
|
||||
show (Put c) = "Put " ++ (show c)
|
||||
show (Nel ()) = "Nel ()"
|
||||
show (Sag path _) = "Sag " ++ (show path)
|
||||
show (Sav path _) = "Sav " ++ (show path)
|
||||
show (Url c) = "Url " ++ (show c)
|
||||
show (Wyp ()) = "Wyp ()"
|
||||
--
|
||||
show (Lin c) = "Lin " ++ (show c)
|
||||
show (Mor ()) = "Mor ()"
|
||||
|
||||
{-|
|
||||
%blip -- TODO
|
||||
|
@ -20,6 +20,7 @@ import Urbit.Arvo.Common (ReOrg(..), reorgThroughNoun)
|
||||
|
||||
import qualified Crypto.Sign.Ed25519 as Ed
|
||||
import qualified Data.ByteString as BS
|
||||
import qualified Data.Char as C
|
||||
import qualified Data.ByteString.Char8 as C
|
||||
import qualified Network.HTTP.Types.Method as H
|
||||
|
||||
@ -318,19 +319,52 @@ data LegacyBootEvent
|
||||
| Dawn Dawn
|
||||
deriving (Eq, Show)
|
||||
|
||||
data ArrowKey = D | L | R | U
|
||||
data Bolt
|
||||
= Key Char
|
||||
| Aro ArrowKey
|
||||
| Bac ()
|
||||
| Del ()
|
||||
| Hit Word64 Word64
|
||||
| Ret ()
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data Belt
|
||||
= Aro ArrowKey
|
||||
| Bac ()
|
||||
| Ctl Cord
|
||||
| Del ()
|
||||
| Met Cord
|
||||
| Ret ()
|
||||
= Bol Bolt
|
||||
| Mod Modifier Bolt
|
||||
| Txt Tour
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data ArrowKey = D | L | R | U
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
data Modifier = Ctl | Met | Hyp
|
||||
deriving (Eq, Ord, Show)
|
||||
|
||||
--NOTE required to get the above declarations into reify's type environment
|
||||
-- see also ghc/ghc#9813
|
||||
$(pure [])
|
||||
|
||||
instance FromNoun Bolt where
|
||||
parseNoun = \case
|
||||
A c -> pure $ Key $ C.chr $ fromIntegral c
|
||||
C (A 7955819) _ -> fail "%key not valid bolt tag"
|
||||
n -> $(deriveFromNounFunc ''Bolt) n
|
||||
|
||||
instance FromNoun Belt where
|
||||
parseNoun = \case
|
||||
C (A 7106402) _ -> fail "%bol not valid belt tag"
|
||||
n -> Bol <$> parseNoun n <|> $(deriveFromNounFunc ''Belt) n
|
||||
|
||||
instance ToNoun Bolt where
|
||||
toNoun = \case
|
||||
Key c -> A $ fromIntegral $ C.ord c
|
||||
n -> $(deriveToNounFunc ''Bolt) n
|
||||
|
||||
instance ToNoun Belt where
|
||||
toNoun = \case
|
||||
Bol b -> toNoun b
|
||||
n -> $(deriveToNounFunc ''Belt) n
|
||||
|
||||
data TermEv
|
||||
= TermEvBelt (UD, ()) Belt
|
||||
| TermEvBlew (UD, ()) Word Word
|
||||
@ -341,7 +375,7 @@ data TermEv
|
||||
|
||||
deriveNoun ''LegacyBootEvent
|
||||
deriveNoun ''ArrowKey
|
||||
deriveNoun ''Belt
|
||||
deriveNoun ''Modifier
|
||||
deriveNoun ''TermEv
|
||||
|
||||
|
||||
@ -392,27 +426,23 @@ instance FromNoun Ev where
|
||||
-- Short Event Names -----------------------------------------------------------
|
||||
|
||||
{-
|
||||
In the case of the user hitting enter, the cause is technically a
|
||||
terminal event, but we don't display any name because the cause is
|
||||
really the user.
|
||||
In the case of user input, the cause is technically a terminal event,
|
||||
but we don't display any name because the cause is really the user.
|
||||
-}
|
||||
getSpinnerNameForEvent :: Ev -> Maybe Text
|
||||
getSpinnerNameForEvent = \case
|
||||
EvBlip b -> case b of
|
||||
BlipEvAmes _ -> Just "ames"
|
||||
BlipEvArvo _ -> Just "arvo"
|
||||
BlipEvBehn _ -> Just "behn"
|
||||
BlipEvBoat _ -> Just "boat"
|
||||
BlipEvHttpClient _ -> Just "iris"
|
||||
BlipEvHttpServer _ -> Just "eyre"
|
||||
BlipEvJael _ -> Just "jael"
|
||||
BlipEvNewt _ -> Just "newt"
|
||||
BlipEvSync _ -> Just "clay"
|
||||
BlipEvTerm t | isRet t -> Nothing
|
||||
BlipEvTerm t -> Just "term"
|
||||
where
|
||||
isRet (TermEvBelt _ (Ret ())) = True
|
||||
isRet _ = False
|
||||
BlipEvAmes _ -> Just "ames"
|
||||
BlipEvArvo _ -> Just "arvo"
|
||||
BlipEvBehn _ -> Just "behn"
|
||||
BlipEvBoat _ -> Just "boat"
|
||||
BlipEvHttpClient _ -> Just "iris"
|
||||
BlipEvHttpServer _ -> Just "eyre"
|
||||
BlipEvJael _ -> Just "jael"
|
||||
BlipEvNewt _ -> Just "newt"
|
||||
BlipEvSync _ -> Just "clay"
|
||||
BlipEvTerm (TermEvBelt _ _) -> Nothing
|
||||
BlipEvTerm t -> Just "term"
|
||||
|
||||
summarizeEvent :: Ev -> Text
|
||||
summarizeEvent ev =
|
||||
|
@ -333,7 +333,7 @@ pier (serf, log) vSlog startedSig injected = do
|
||||
io $ readTVarIO siteSlog >>= ($ s)
|
||||
logOther "serf" (display $ T.strip $ tankToText tank)
|
||||
|
||||
let err = atomically . Term.trace muxed . (<> "\r\n")
|
||||
let err = atomically . Term.trace muxed
|
||||
(bootEvents, startDrivers) <- do
|
||||
env <- ask
|
||||
siz <- atomically $ Term.curDemuxSize demux
|
||||
|
@ -45,8 +45,8 @@ import qualified Urbit.Vere.Term.Render as T
|
||||
|
||||
-- | All stateful data in the printing to stdOutput.
|
||||
data LineState = LineState
|
||||
{ lsLine :: Text
|
||||
, lsCurPos :: Int
|
||||
{ lsLine :: [(Stye, [Char])]
|
||||
, lsCurPos :: CurPos
|
||||
, lsSpinTimer :: Maybe (Async ())
|
||||
, lsSpinCause :: Maybe Text
|
||||
, lsSpinFirstRender :: Bool
|
||||
@ -54,11 +54,19 @@ data LineState = LineState
|
||||
, lsPrevEndTime :: Wen
|
||||
}
|
||||
|
||||
data CurPos = CurPos
|
||||
{ row :: Int
|
||||
, col :: Int
|
||||
}
|
||||
|
||||
-- | A record used in reading data from stdInput.
|
||||
data ReadData = ReadData
|
||||
{ rdBuf :: Ptr Word8
|
||||
, rdEscape :: Bool
|
||||
, rdBracket :: Bool
|
||||
, rdMouse :: Bool
|
||||
, rdMouseBut :: Word8
|
||||
, rdMouseCol :: Word8
|
||||
, rdUTF8 :: ByteString
|
||||
, rdUTF8width :: Int
|
||||
}
|
||||
@ -165,7 +173,8 @@ leftBracket, rightBracket :: Text
|
||||
leftBracket = "«"
|
||||
rightBracket = "»"
|
||||
|
||||
_spin_cool_us, _spin_warm_us, _spin_rate_us, _spin_idle_us :: Integral i => i
|
||||
_spin_fast_us, _spin_cool_us, _spin_warm_us, _spin_rate_us, _spin_idle_us :: Integral i => i
|
||||
_spin_fast_us = 100000
|
||||
_spin_cool_us = 500000
|
||||
_spin_warm_us = 50000
|
||||
_spin_rate_us = 250000
|
||||
@ -201,6 +210,9 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
-- to the muxing client.
|
||||
putTMVar tsSizeChange ts)
|
||||
|
||||
-- start mouse reporting
|
||||
putStr "\x1b[?9h"
|
||||
|
||||
pWriterThread <- asyncBound
|
||||
(writeTerminal tsWriteQueue spinnerMVar tsizeTVar)
|
||||
|
||||
@ -217,7 +229,7 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
|
||||
tsReadQueue <- newTQueueIO
|
||||
pReaderThread <- asyncBound
|
||||
(readTerminal tsReadQueue tsWriteQueue (bell tsWriteQueue))
|
||||
(readTerminal tsReadQueue tsWriteQueue tsizeTVar (bell tsWriteQueue))
|
||||
|
||||
let client = Client { take = Just <$> asum
|
||||
[ readTQueue tsReadQueue <&> ClientTakeBelt,
|
||||
@ -238,6 +250,9 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
-- at shutdown, just leak the file descriptor.
|
||||
cancel pWriterThread
|
||||
|
||||
-- stop mouse reporting
|
||||
putStr "\x1b[?9l"
|
||||
|
||||
-- inject one final newline, as we're usually on the prompt.
|
||||
putStr "\r\n"
|
||||
|
||||
@ -266,31 +281,50 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
|
||||
-- Writes data to the terminal. Both the terminal reading, normal logging,
|
||||
-- and effect handling can all emit bytes which go to the terminal.
|
||||
--TODO blanks, traces and slogs should only be written into the default
|
||||
-- terminal session.
|
||||
writeTerminal :: TQueue [Term.Ev] -> TMVar () -> TVar TermSize -> RIO e ()
|
||||
writeTerminal q spinner termSizeVar = do
|
||||
currentTime <- io $ now
|
||||
loop (LineState "" 0 Nothing Nothing True 0 currentTime)
|
||||
loop
|
||||
termSizeVar
|
||||
(LineState [] (CurPos 0 0) Nothing Nothing True 0 currentTime)
|
||||
where
|
||||
writeBlank :: LineState -> RIO e LineState
|
||||
writeBlank ls = putStr "\r\n" $> ls
|
||||
writeBlank ls = do
|
||||
TermSize _ height <- readTVarIO termSizeVar
|
||||
--NOTE hijack creates a blank line
|
||||
T.hijack (fromIntegral height) $ pure ()
|
||||
pure ls
|
||||
|
||||
writeTrace :: LineState -> Text -> RIO e LineState
|
||||
writeTrace ls p = do
|
||||
putStr "\r"
|
||||
T.clearLine
|
||||
putStr p
|
||||
termRefreshLine ls
|
||||
TermSize _ height <- readTVarIO termSizeVar
|
||||
T.hijack (fromIntegral height) $ putStr p
|
||||
pure ls
|
||||
|
||||
writeSlog :: LineState -> (Atom, Tank) -> RIO e LineState
|
||||
writeSlog ls slog = do
|
||||
putStr "\r"
|
||||
T.clearLine
|
||||
TermSize width _ <- atomically $ readTVar termSizeVar
|
||||
-- TODO: Ignoring priority for now. Priority changes the color of,
|
||||
-- and adds a prefix of '>' to, the output.
|
||||
let lines = fmap unTape $ wash (WashCfg 0 width) $ tankTree $ snd slog
|
||||
forM lines $ \line -> putStr (line <> "\r\n")
|
||||
termRefreshLine ls
|
||||
TermSize width height <- readTVarIO termSizeVar
|
||||
T.hijack (fromIntegral height) do
|
||||
let lines = fmap (pref . unTape) $
|
||||
wash (WashCfg 0 width) $ tankTree $ snd slog
|
||||
T.putCsi 'm' styl
|
||||
forM (intersperse "\n" lines) $ \line -> putStr line
|
||||
T.putCsi 'm' [0]
|
||||
pure ls
|
||||
where
|
||||
prio = fromIntegral $ fst slog
|
||||
maxp = 3
|
||||
styl
|
||||
| prio == 3 = [31]
|
||||
| prio == 2 = [33]
|
||||
| prio == 1 = [32]
|
||||
| otherwise = [90]
|
||||
pref
|
||||
| prio > 0 && prio <= maxp =
|
||||
((replicate prio '>' ++ replicate (1 + maxp - prio) ' ') ++)
|
||||
| otherwise = id
|
||||
|
||||
{-
|
||||
Figure out how long to wait to show the spinner. When we
|
||||
@ -305,7 +339,7 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
|
||||
current <- io $ now
|
||||
delay <- pure $ case mTxt of
|
||||
Nothing -> 0
|
||||
Nothing -> _spin_fast_us
|
||||
Just _ ->
|
||||
if (gap current lsPrevEndTime ^. microSecs) < _spin_idle_us
|
||||
then _spin_warm_us
|
||||
@ -326,34 +360,41 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
maybe (pure ()) cancel lsSpinTimer
|
||||
-- We do a final flush of the spinner mvar to ensure we don't
|
||||
-- have a lingering signal which will redisplay the spinner after
|
||||
-- we call termRefreshLine below.
|
||||
-- we call termRestoreLine below.
|
||||
atomically $ tryTakeTMVar spinner
|
||||
|
||||
-- If we ever actually ran the spinner display callback, we need
|
||||
-- to force a redisplay of the command prompt.
|
||||
ls <- if not lsSpinFirstRender || True
|
||||
then termRefreshLine ls
|
||||
else pure ls
|
||||
if not lsSpinFirstRender
|
||||
then termRestoreLine ls termSizeVar
|
||||
else pure ()
|
||||
|
||||
endTime <- io $ now
|
||||
pure $ ls { lsSpinTimer = Nothing, lsPrevEndTime = endTime }
|
||||
|
||||
execEv :: LineState -> Term.Ev -> RIO e LineState
|
||||
execEv ls = \case
|
||||
Term.Blits bs -> foldM writeBlit ls bs
|
||||
Term.Blits bs -> foldM (writeBlit termSizeVar) ls bs
|
||||
Term.Trace p -> writeTrace ls (unCord p)
|
||||
Term.Slog s -> writeSlog ls s
|
||||
Term.Blank -> writeBlank ls
|
||||
Term.Spinr (Just txt) -> doSpin ls (unCord <$> txt)
|
||||
Term.Spinr Nothing -> unspin ls
|
||||
|
||||
-- TODO What does this do?
|
||||
spin :: LineState -> RIO e LineState
|
||||
spin ls@LineState{..} = do
|
||||
spin :: TVar TermSize -> LineState -> RIO e LineState
|
||||
spin ts ls@LineState{..} = do
|
||||
let spinner = (spinners !! lsSpinFrame) ++ case lsSpinCause of
|
||||
Nothing -> ""
|
||||
Just str -> leftBracket ++ str ++ rightBracket
|
||||
|
||||
--NOTE even after first render, because cursor might have moved...
|
||||
if row lsCurPos > 0
|
||||
then do
|
||||
TermSize _ h <- readTVarIO ts
|
||||
T.cursorMove (fromIntegral h - 1) 0
|
||||
else
|
||||
T.cursorRestore
|
||||
|
||||
putStr (spinner <> pack (ANSI.cursorBackwardCode (length spinner)))
|
||||
|
||||
let newFrame = (lsSpinFrame + 1) `mod` length spinners
|
||||
@ -362,28 +403,35 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
, lsSpinFrame = newFrame
|
||||
}
|
||||
|
||||
loop :: LineState -> RIO e ()
|
||||
loop ls = do
|
||||
loop :: TVar TermSize -> LineState -> RIO e ()
|
||||
loop ts ls = do
|
||||
join $ atomically $ asum
|
||||
[ readTQueue q >>= pure . (foldM execEv ls >=> loop)
|
||||
, takeTMVar spinner >> pure (spin ls >>= loop)
|
||||
[ readTQueue q >>= pure . (foldM execEv ls >=> loop ts)
|
||||
, takeTMVar spinner >> pure (spin ts ls >>= loop ts)
|
||||
]
|
||||
|
||||
-- Writes an individual blit to the screen
|
||||
writeBlit :: LineState -> Blit -> RIO e LineState
|
||||
writeBlit ls = \case
|
||||
writeBlit :: TVar TermSize -> LineState -> Blit -> RIO e LineState
|
||||
writeBlit ts ls = \case
|
||||
Bel () -> T.soundBell $> ls
|
||||
Clr () -> do T.clearScreen
|
||||
termRefreshLine ls
|
||||
Hop w -> termShowCursor ls (fromIntegral w)
|
||||
Klr s -> do ls2 <- termShowClear ls
|
||||
termShowStub ls2 s
|
||||
Lin c -> do ls2 <- termShowClear ls
|
||||
termShowLine ls2 (pack c)
|
||||
Mor () -> termShowMore ls
|
||||
T.cursorRestore
|
||||
pure ls
|
||||
Hop t -> case t of
|
||||
Col c -> termShowCursor ls ts 0 (fromIntegral c)
|
||||
Roc r c -> termShowCursor ls ts (fromIntegral r) (fromIntegral c)
|
||||
Klr s -> termShowStub ls s
|
||||
Put c -> termShowLine ls (pack c)
|
||||
Nel () -> termShowNewline ls
|
||||
Sag path noun -> pure ls
|
||||
Sav path atom -> pure ls
|
||||
Url url -> pure ls
|
||||
Wyp () -> termShowClear ls
|
||||
--
|
||||
Lin c -> do termShowCursor ls ts 0 0
|
||||
termShowClear ls
|
||||
termShowLine ls (pack c)
|
||||
Mor () -> termShowNewline ls
|
||||
|
||||
termRenderDeco :: Deco -> Char
|
||||
termRenderDeco = \case
|
||||
@ -428,55 +476,88 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
|
||||
styled = mconcat [escape, styles, "m", tape, escape, "0m"]
|
||||
|
||||
-- Displays and sets styled text as the current line
|
||||
bareStub :: [Char] -> [(Stye, [Char])]
|
||||
bareStub c = [(Stye (setToHoonSet mempty) TintNull TintNull, c)]
|
||||
|
||||
-- overwrite substring of base with put, starting at index
|
||||
overwriteStub :: [(Stye, [Char])] -> Int -> [(Stye, [Char])] -> [(Stye, [Char])]
|
||||
overwriteStub base index put =
|
||||
scagStub index base
|
||||
++ ( let l = lentStub base in
|
||||
if index <= l then []
|
||||
else bareStub $ take (index - l) [' ',' '..]
|
||||
)
|
||||
++ put
|
||||
++ slagStub (index + lentStub put) base
|
||||
where
|
||||
lentStub :: [(Stye, [Char])] -> Int
|
||||
lentStub s = sum $ map (length . snd) s
|
||||
|
||||
scagStub :: Int -> [(Stye, [Char])] -> [(Stye, [Char])]
|
||||
scagStub 0 _ = []
|
||||
scagStub _ [] = []
|
||||
scagStub i ((y,c):s) =
|
||||
(y, take i c) : scagStub (i - min i (length c)) s
|
||||
|
||||
slagStub :: Int -> [(Stye, [Char])] -> [(Stye, [Char])]
|
||||
slagStub 0 s = s
|
||||
slagStub _ [] = []
|
||||
slagStub i ((y,c):s)
|
||||
| i > l = slagStub (i - l) s
|
||||
| otherwise = (y, drop i c) : s
|
||||
where l = length c
|
||||
|
||||
-- Displays styled text at the cursor
|
||||
termShowStub :: LineState -> Stub -> RIO e LineState
|
||||
termShowStub ls (Stub s) = do
|
||||
let visualLength = sum $ fmap (length . snd) s
|
||||
let outText = pack $ mconcat $ fmap (uncurry termRenderStubSegment) s
|
||||
putStr outText
|
||||
pure ls { lsLine = outText, lsCurPos = visualLength }
|
||||
termShowStub ls@LineState{lsCurPos, lsLine} (Stub s) = do
|
||||
putStr $ pack $ mconcat $ fmap (uncurry termRenderStubSegment) s
|
||||
T.cursorRestore
|
||||
case row lsCurPos of
|
||||
0 -> pure ls { lsLine = overwriteStub lsLine (col lsCurPos) s }
|
||||
_ -> pure ls
|
||||
|
||||
-- Moves the cursor to the requested position
|
||||
termShowCursor :: LineState -> Int -> RIO e LineState
|
||||
termShowCursor ls@LineState{..} {-line pos)-} newPos = do
|
||||
if newPos < lsCurPos then do
|
||||
T.cursorLeft (lsCurPos - newPos)
|
||||
pure ls { lsCurPos = newPos }
|
||||
else if newPos > lsCurPos then do
|
||||
T.cursorRight (newPos - lsCurPos)
|
||||
pure ls { lsCurPos = newPos }
|
||||
else
|
||||
pure ls
|
||||
|
||||
-- Moves the cursor left without any mutation of the LineState. Used only
|
||||
-- in cursor spinning.
|
||||
_termSpinnerMoveLeft :: Int -> RIO e ()
|
||||
_termSpinnerMoveLeft = T.cursorLeft
|
||||
termShowCursor :: LineState -> TVar TermSize -> Int -> Int -> RIO e LineState
|
||||
termShowCursor ls ts row col = do
|
||||
TermSize _ h <- readTVarIO ts
|
||||
T.cursorMove (max 0 (fromIntegral h - row - 1)) col
|
||||
T.cursorSave
|
||||
pure ls { lsCurPos = CurPos row col }
|
||||
|
||||
-- Displays and sets the current line
|
||||
termShowLine :: LineState -> Text -> RIO e LineState
|
||||
termShowLine ls newStr = do
|
||||
termShowLine ls@LineState{lsCurPos, lsLine} newStr = do
|
||||
putStr newStr
|
||||
pure ls { lsLine = newStr, lsCurPos = (length newStr) }
|
||||
T.cursorRestore
|
||||
case row lsCurPos of
|
||||
0 -> pure ls { lsLine = overwriteStub lsLine (col lsCurPos) (bareStub $ unpack newStr) }
|
||||
_ -> pure ls
|
||||
|
||||
termShowClear :: LineState -> RIO e LineState
|
||||
termShowClear ls = do
|
||||
termShowClear ls@LineState{lsCurPos} = do
|
||||
putStr "\r"
|
||||
T.clearLine
|
||||
pure ls { lsLine = "", lsCurPos = 0 }
|
||||
T.cursorRestore
|
||||
case row lsCurPos of
|
||||
0 -> pure ls { lsLine = [] }
|
||||
_ -> pure ls
|
||||
|
||||
-- New Current Line
|
||||
termShowMore :: LineState -> RIO e LineState
|
||||
termShowMore ls = do
|
||||
termShowNewline :: LineState -> RIO e LineState
|
||||
termShowNewline ls@LineState{lsCurPos} = do
|
||||
putStr "\r\n"
|
||||
pure ls { lsLine = "", lsCurPos = 0 }
|
||||
case row lsCurPos of
|
||||
0 -> pure ls { lsLine = [], lsCurPos = lsCurPos { col = 0 } }
|
||||
r -> pure ls { lsCurPos = CurPos (r-1) 0 }
|
||||
|
||||
-- Redraw the current LineState, maintaining the current curpos
|
||||
termRefreshLine :: LineState -> RIO e LineState
|
||||
termRefreshLine ls@LineState{lsCurPos,lsLine} = do
|
||||
ls <- termShowClear ls
|
||||
ls <- termShowLine ls lsLine
|
||||
termShowCursor ls lsCurPos
|
||||
-- Redraw the bottom LineState, maintaining the current curpos
|
||||
termRestoreLine :: LineState -> TVar TermSize -> RIO e ()
|
||||
termRestoreLine ls@LineState{lsLine} ts = do
|
||||
TermSize _ h <- readTVarIO ts
|
||||
T.cursorMove (fromIntegral h - 1) 0
|
||||
T.clearLine
|
||||
putStr $ pack $ mconcat $ fmap (uncurry termRenderStubSegment) lsLine
|
||||
T.cursorRestore
|
||||
|
||||
-- ring my bell
|
||||
bell :: TQueue [Term.Ev] -> RIO e ()
|
||||
@ -491,9 +572,14 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
-- A better way to do this would be to get some sort of epoll on stdInput,
|
||||
-- since that's kinda closer to what libuv does?
|
||||
readTerminal :: forall e. HasLogFunc e
|
||||
=> TQueue Belt -> TQueue [Term.Ev] -> (RIO e ()) -> RIO e ()
|
||||
readTerminal rq wq bell =
|
||||
rioAllocaBytes 1 $ \ buf -> loop (ReadData buf False False mempty 0)
|
||||
=> TQueue Belt
|
||||
-> TQueue [Term.Ev]
|
||||
-> TVar TermSize
|
||||
-> RIO e ()
|
||||
-> RIO e ()
|
||||
readTerminal rq wq ts bell =
|
||||
rioAllocaBytes 1 $ \ buf
|
||||
-> loop (ReadData buf False False False 0 0 mempty 0)
|
||||
where
|
||||
loop :: ReadData -> RIO e ()
|
||||
loop rd@ReadData{..} = do
|
||||
@ -513,26 +599,41 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
if rdEscape then
|
||||
if rdBracket then do
|
||||
case c of
|
||||
'A' -> sendBelt $ Aro U
|
||||
'B' -> sendBelt $ Aro D
|
||||
'C' -> sendBelt $ Aro R
|
||||
'D' -> sendBelt $ Aro L
|
||||
'A' -> sendBelt $ Bol $ Aro U
|
||||
'B' -> sendBelt $ Bol $ Aro D
|
||||
'C' -> sendBelt $ Bol $ Aro R
|
||||
'D' -> sendBelt $ Bol $ Aro L
|
||||
'M' -> pure ()
|
||||
_ -> bell
|
||||
loop rd { rdEscape = False, rdBracket = False}
|
||||
rd <- case c of
|
||||
'M' -> pure rd { rdMouse = True }
|
||||
_ -> pure rd
|
||||
loop rd { rdEscape = False, rdBracket = False }
|
||||
else if isAsciiLower c then do
|
||||
sendBelt $ Met $ Cord $ pack [c]
|
||||
loop rd { rdEscape = False }
|
||||
else if c == '.' then do
|
||||
sendBelt $ Met $ Cord "dot"
|
||||
sendBelt $ Mod Met $ Key c
|
||||
loop rd { rdEscape = False }
|
||||
else if w == 8 || w == 127 then do
|
||||
sendBelt $ Met $ Cord "bac"
|
||||
sendBelt $ Mod Met $ Bac ()
|
||||
loop rd { rdEscape = False }
|
||||
else if c == '[' || c == '0' then do
|
||||
loop rd { rdBracket = True }
|
||||
else do
|
||||
bell
|
||||
loop rd { rdEscape = False }
|
||||
else if rdMouse then
|
||||
if rdMouseBut == 0 then do
|
||||
loop rd { rdMouseBut = w - 31 }
|
||||
else if rdMouseCol == 0 then do
|
||||
loop rd { rdMouseCol = w - 32 }
|
||||
else do
|
||||
if rdMouseBut == 1 then do
|
||||
let rdMouseRow = w - 32
|
||||
TermSize _ h <- readTVarIO ts
|
||||
sendBelt $ Bol $ Hit
|
||||
(fromIntegral h - fromIntegral rdMouseRow)
|
||||
(fromIntegral rdMouseCol - 1)
|
||||
else do pure ()
|
||||
loop rd { rdMouse = False, rdMouseBut = 0, rdMouseCol = 0 }
|
||||
else if rdUTF8width /= 0 then do
|
||||
-- continue reading into the utf8 accumulation buffer
|
||||
rd@ReadData{..} <- pure rd { rdUTF8 = snoc rdUTF8 w }
|
||||
@ -543,30 +644,31 @@ localClient doneSignal = fst <$> mkRAcquire start stop
|
||||
error "empty utf8 accumulation buffer"
|
||||
Just (c, bytes) | bytes /= rdUTF8width ->
|
||||
error "utf8 character size mismatch?!"
|
||||
Just (c, bytes) -> sendBelt $ Txt $ Tour $ [c]
|
||||
Just (c, bytes) -> sendBelt $ Bol $ Key c
|
||||
loop rd { rdUTF8 = mempty, rdUTF8width = 0 }
|
||||
else if w >= 32 && w < 127 then do
|
||||
sendBelt $ Txt $ Tour $ [c]
|
||||
sendBelt $ Bol $ Key c
|
||||
loop rd
|
||||
else if w == 0 then do
|
||||
bell
|
||||
loop rd
|
||||
else if w == 8 || w == 127 then do
|
||||
sendBelt $ Bac ()
|
||||
sendBelt $ Bol $ Bac ()
|
||||
loop rd
|
||||
else if w == 13 then do
|
||||
sendBelt $ Ret ()
|
||||
sendBelt $ Bol $ Ret ()
|
||||
loop rd
|
||||
else if w == 3 then do
|
||||
-- ETX (^C)
|
||||
logInfo $ "Ctrl-c interrupt"
|
||||
atomically $ do
|
||||
writeTQueue wq [Term.Trace "interrupt\r\n"]
|
||||
writeTQueue rq $ Ctl $ Cord "c"
|
||||
writeTQueue wq [Term.Trace "interrupt"]
|
||||
writeTQueue rq $ Mod Ctl $ Key 'c'
|
||||
loop rd
|
||||
else if w <= 26 then do
|
||||
case pack [BS.w2c (w + 97 - 1)] of
|
||||
c -> do sendBelt $ Ctl $ Cord c
|
||||
case BS.w2c (w + 97 - 1) of
|
||||
'd' -> atomically doneSignal
|
||||
c -> do sendBelt $ Mod Ctl $ Key c
|
||||
loop rd
|
||||
else if w == 27 then do
|
||||
loop rd { rdEscape = True }
|
||||
@ -643,7 +745,7 @@ term env (tsize, Client{..}) plan stat serfSIGINT = runTerm
|
||||
atomically take >>= \case
|
||||
Nothing -> pure ()
|
||||
Just (ClientTakeBelt b) -> do
|
||||
when (b == Ctl (Cord "c")) $ do
|
||||
when (b == Mod Ctl (Key 'c')) $ do
|
||||
io serfSIGINT
|
||||
let beltEv = EvBlip $ BlipEvTerm $ TermEvBelt (UD 1, ()) $ b
|
||||
let beltFailed _ = pure ()
|
||||
|
@ -22,7 +22,7 @@ import Urbit.TermSize
|
||||
Input Event for terminal driver:
|
||||
|
||||
%blits -- list of blits from arvo.
|
||||
%trace -- stderr line from runtime.
|
||||
%trace -- stderr line from runtime (without trailing newline).
|
||||
%slog -- nock worker logging with priority
|
||||
%blank -- print a blank line
|
||||
%spinr -- Start or stop the spinner
|
||||
|
@ -39,11 +39,11 @@ data Ev
|
||||
= EvLine Text
|
||||
| EvSlog (Atom, Tank)
|
||||
| EvSpin SpinnerState
|
||||
| EvMove Word
|
||||
| EvMove (Word, Word)
|
||||
| EvBell
|
||||
| EvDraw
|
||||
| EvEdit Text
|
||||
| EvMore
|
||||
| EvNewl
|
||||
deriving (Show)
|
||||
|
||||
data Ef
|
||||
@ -62,7 +62,7 @@ data History
|
||||
data St = St
|
||||
{ sHistory :: !(Seq History)
|
||||
, sLine :: !Text
|
||||
, sCurPos :: !Word
|
||||
, sCurPos :: !(Word, Word)
|
||||
, sSpinner :: !SpinnerState
|
||||
}
|
||||
deriving (Show)
|
||||
@ -70,10 +70,10 @@ data St = St
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
init :: St
|
||||
init = St mempty "" 0 Nothing
|
||||
init = St mempty "" (0, 0) Nothing
|
||||
|
||||
{-|
|
||||
When we process `EvMore`, we need to append a newline to the end of
|
||||
When we process `EvNewl`, we need to append a newline to the end of
|
||||
the current line. During normal play, the ENTER key inserts the
|
||||
newline for us, so we need to recreate that newline when we rebuild
|
||||
the state for a new terminal connection.
|
||||
@ -83,15 +83,17 @@ step st@St{..} = \case
|
||||
EvLine t -> st & recordText t
|
||||
EvSlog s -> st & recordSlog s
|
||||
EvSpin s -> st { sSpinner = s }
|
||||
EvMove w -> st { sCurPos = min w (word $ length sLine) }
|
||||
EvEdit t -> st { sLine = t, sCurPos = word (length t) }
|
||||
EvMore -> st { sLine = "", sCurPos = 0 } & recordText (sLine <> "\n")
|
||||
EvMove p -> st { sCurPos = p }
|
||||
EvBell -> st
|
||||
EvDraw -> st
|
||||
EvEdit t | (0, _) <- sCurPos -> st { sLine = t }
|
||||
| otherwise -> st
|
||||
EvNewl | (0, _) <- sCurPos ->
|
||||
st { sLine = "", sCurPos = (0, 0) }
|
||||
& recordText (sLine <> "\n")
|
||||
| otherwise ->
|
||||
st { sCurPos = (fst sCurPos - 1, 0) }
|
||||
where
|
||||
word :: Integral i => i -> Word
|
||||
word = fromIntegral
|
||||
|
||||
recordText :: Text -> St -> St
|
||||
recordText !t st@St{..} = st {
|
||||
sHistory = trim (sHistory |> (HistoryText t))
|
||||
@ -111,8 +113,10 @@ drawState :: St -> [Ev]
|
||||
drawState St{..} = hist <> out <> cur <> spin
|
||||
where
|
||||
hist = drawHistory <$> toList sHistory
|
||||
out = if null sLine then [] else [EvEdit sLine]
|
||||
cur = if 0 == sCurPos then [] else [EvMove $ fromIntegral $ sCurPos]
|
||||
out | null sLine = []
|
||||
| otherwise = [EvEdit sLine]
|
||||
cur | (0, _) <- sCurPos = []
|
||||
| otherwise = [EvMove sCurPos]
|
||||
spin = maybe [] (singleton . EvSpin . Just) sSpinner
|
||||
|
||||
drawHistory (HistoryText t) = EvLine t
|
||||
@ -123,12 +127,13 @@ drawState St{..} = hist <> out <> cur <> spin
|
||||
|
||||
fromBlit :: Arvo.Blit -> Maybe Ev
|
||||
fromBlit = \case
|
||||
Arvo.Hop w -> Just $ EvMove $ fromIntegral w
|
||||
Arvo.Bel () -> Just EvBell
|
||||
Arvo.Clr () -> Just EvDraw
|
||||
Arvo.Lin s -> Just $ EvEdit (pack s)
|
||||
Arvo.Mor () -> Just EvMore
|
||||
_ -> Nothing
|
||||
Arvo.Hop (Arvo.Col c) -> Just $ EvMove (0, fromIntegral c)
|
||||
Arvo.Hop (Arvo.Roc r c) -> Just $ EvMove (fromIntegral r, fromIntegral c)
|
||||
Arvo.Bel () -> Just EvBell
|
||||
Arvo.Clr () -> Just EvDraw
|
||||
Arvo.Put s -> Just $ EvEdit (pack s)
|
||||
Arvo.Nel () -> Just EvNewl
|
||||
_ -> Nothing
|
||||
|
||||
toCause :: Maybe Cord -> SpinnerCause
|
||||
toCause Nothing = User
|
||||
@ -148,12 +153,12 @@ fromTermEv = \case
|
||||
|
||||
toTermEv :: Ev -> Term.Ev
|
||||
toTermEv = \case
|
||||
EvLine "" -> Term.Blank
|
||||
EvLine t -> Term.Trace (Cord t)
|
||||
EvSlog s -> Term.Slog s
|
||||
EvSpin s -> Term.Spinr (fromCause <$> s)
|
||||
EvMove w -> Term.Blits [Arvo.Hop $ fromIntegral w]
|
||||
EvBell -> Term.Blits [Arvo.Bel ()]
|
||||
EvDraw -> Term.Blits [Arvo.Clr ()]
|
||||
EvEdit t -> Term.Blits [Arvo.Lin $ unpack t]
|
||||
EvMore -> Term.Blits [Arvo.Mor ()]
|
||||
EvLine "" -> Term.Blank
|
||||
EvLine t -> Term.Trace (Cord t)
|
||||
EvSlog s -> Term.Slog s
|
||||
EvSpin s -> Term.Spinr (fromCause <$> s)
|
||||
EvMove (r, c) -> Term.Blits [Arvo.Hop $ Arvo.Roc (fromIntegral r) (fromIntegral c)]
|
||||
EvBell -> Term.Blits [Arvo.Bel ()]
|
||||
EvDraw -> Term.Blits [Arvo.Clr ()]
|
||||
EvEdit t -> Term.Blits [Arvo.Put $ unpack t]
|
||||
EvNewl -> Term.Blits [Arvo.Nel ()]
|
||||
|
@ -4,9 +4,12 @@
|
||||
module Urbit.Vere.Term.Render
|
||||
( clearScreen
|
||||
, clearLine
|
||||
, cursorRight
|
||||
, cursorLeft
|
||||
, soundBell
|
||||
, cursorMove
|
||||
, cursorSave
|
||||
, cursorRestore
|
||||
, putCsi
|
||||
, hijack
|
||||
) where
|
||||
|
||||
import Urbit.Prelude
|
||||
@ -25,8 +28,27 @@ clearLine = liftIO $ ANSI.clearLine
|
||||
soundBell :: MonadIO m => m ()
|
||||
soundBell = liftIO $ putStr "\a"
|
||||
|
||||
cursorLeft :: MonadIO m => Int -> m ()
|
||||
cursorLeft = liftIO . ANSI.cursorBackward
|
||||
--NOTE top-left-0-based coordinates
|
||||
cursorMove :: MonadIO m => Int -> Int -> m ()
|
||||
cursorMove r c = liftIO $ ANSI.setCursorPosition r c
|
||||
|
||||
cursorRight :: MonadIO m => Int -> m ()
|
||||
cursorRight = liftIO . ANSI.cursorForward
|
||||
cursorSave :: MonadIO m => m ()
|
||||
cursorSave = liftIO ANSI.saveCursor
|
||||
|
||||
cursorRestore :: MonadIO m => m ()
|
||||
cursorRestore = liftIO ANSI.restoreCursor
|
||||
|
||||
putCsi :: MonadIO m => Char -> [Int] -> m ()
|
||||
putCsi c a = liftIO do
|
||||
putStr "\x1b["
|
||||
putStr $ pack $ mconcat $ intersperse ";" (fmap show a)
|
||||
putStr $ pack [c]
|
||||
|
||||
hijack :: MonadIO m => Int -> IO () -> m ()
|
||||
hijack h d = liftIO do
|
||||
putCsi 'r' [1, h-1] -- set scroll region to exclude bottom line
|
||||
putCsi 'S' [1] -- scroll up one line
|
||||
cursorMove (h-2) 0 -- move cursor to empty space
|
||||
d
|
||||
putCsi 'r' [] -- reset scroll region
|
||||
cursorRestore -- restory cursor position
|
||||
|
23
pkg/interface/webterm/.eslintrc.js
Normal file
23
pkg/interface/webterm/.eslintrc.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = exports = {
|
||||
"rules": {
|
||||
"spaced-comment": 0,
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:react/recommended",
|
||||
],
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
},
|
||||
"import/resolver": {
|
||||
typescript: {} // this loads <rootdir>/tsconfig.json to eslint
|
||||
},
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true
|
||||
},
|
||||
"plugins": ["import", "react-hooks"]
|
||||
}
|
1
pkg/interface/webterm/.nvmrc
Normal file
1
pkg/interface/webterm/.nvmrc
Normal file
@ -0,0 +1 @@
|
||||
16.14.0
|
94
pkg/interface/webterm/App.tsx
Normal file
94
pkg/interface/webterm/App.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
import React, {
|
||||
useCallback, useEffect
|
||||
} from 'react';
|
||||
|
||||
import useTermState from './state';
|
||||
import { useDark } from './lib/useDark';
|
||||
import api from './api';
|
||||
|
||||
import { _dark, _light } from '@tlon/indigo-react';
|
||||
|
||||
import 'xterm/css/xterm.css';
|
||||
|
||||
import {
|
||||
scrySessions
|
||||
} from '@urbit/api/term';
|
||||
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { Tabs } from './Tabs';
|
||||
import Buffer from './Buffer';
|
||||
import { DEFAULT_SESSION } from './constants';
|
||||
import { showSlog } from './lib/blit';
|
||||
import { InfoButton } from './InfoButton';
|
||||
|
||||
const initSessions = async () => {
|
||||
const response = await api.scry(scrySessions());
|
||||
|
||||
useTermState.getState().set((state) => {
|
||||
state.names = response.sort();
|
||||
});
|
||||
};
|
||||
|
||||
export default function TermApp() {
|
||||
const { names, selected } = useTermState();
|
||||
const dark = useDark();
|
||||
|
||||
const setupSlog = useCallback(() => {
|
||||
console.log('slog: setting up...');
|
||||
let available = false;
|
||||
const slog = new EventSource('/~_~/slog', { withCredentials: true });
|
||||
|
||||
slog.onopen = () => {
|
||||
console.log('slog: opened stream');
|
||||
available = true;
|
||||
};
|
||||
|
||||
slog.onmessage = (e) => {
|
||||
const session = useTermState.getState().sessions[DEFAULT_SESSION];
|
||||
if (!session) {
|
||||
console.log('slog: default session mia!', 'msg:', e.data);
|
||||
console.log(Object.keys(useTermState.getState().sessions), session);
|
||||
return;
|
||||
}
|
||||
showSlog(session.term, e.data);
|
||||
};
|
||||
|
||||
slog.onerror = (e) => {
|
||||
console.error('slog: eventsource error:', e);
|
||||
if (available) {
|
||||
window.setTimeout(() => {
|
||||
if (slog.readyState !== EventSource.CLOSED) {
|
||||
return;
|
||||
}
|
||||
console.log('slog: reconnecting...');
|
||||
setupSlog();
|
||||
}, 10000);
|
||||
}
|
||||
};
|
||||
|
||||
useTermState.getState().set((state) => {
|
||||
state.slogstream = slog;
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
initSessions();
|
||||
setupSlog();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider theme={dark ? _dark : _light}>
|
||||
<div className="header">
|
||||
<Tabs />
|
||||
<InfoButton />
|
||||
</div>
|
||||
<div className="buffer-container">
|
||||
{names.map((name) => {
|
||||
return <Buffer key={name} name={name} selected={name === selected} dark={dark} />;
|
||||
})}
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
);
|
||||
}
|
350
pkg/interface/webterm/Buffer.tsx
Normal file
350
pkg/interface/webterm/Buffer.tsx
Normal file
@ -0,0 +1,350 @@
|
||||
import { Terminal, ITerminalOptions } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { debounce } from 'lodash';
|
||||
import bel from './lib/bel';
|
||||
import api from './api';
|
||||
|
||||
import {
|
||||
Belt, pokeTask, pokeBelt
|
||||
} from '@urbit/api/term';
|
||||
import { Session } from './state';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import useTermState from './state';
|
||||
import React from 'react';
|
||||
import { Box, Col } from '@tlon/indigo-react';
|
||||
import { makeTheme } from './lib/theme';
|
||||
import { showBlit, csi, hasBell } from './lib/blit';
|
||||
import { DEFAULT_SESSION, RESIZE_DEBOUNCE_MS, RESIZE_THRESHOLD_PX } from './constants';
|
||||
import { retry } from './lib/retry';
|
||||
|
||||
const termConfig: ITerminalOptions = {
|
||||
logLevel: 'warn',
|
||||
//
|
||||
convertEol: true,
|
||||
//
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
scrollback: 10000,
|
||||
//
|
||||
fontFamily: '"Source Code Pro", "Roboto mono", "Courier New", monospace',
|
||||
fontWeight: 400,
|
||||
// NOTE theme colors configured dynamically
|
||||
//
|
||||
bellStyle: 'sound',
|
||||
bellSound: bel,
|
||||
//
|
||||
// allows text selection by holding modifier (option, or shift)
|
||||
macOptionClickForcesSelection: true,
|
||||
// prevent insertion of simulated arrow keys on-altclick
|
||||
altClickMovesCursor: false
|
||||
};
|
||||
|
||||
const readInput = (term: Terminal, e: string): Belt[] => {
|
||||
const belts: Belt[] = [];
|
||||
let strap = '';
|
||||
|
||||
while (e.length > 0) {
|
||||
let c = e.charCodeAt(0);
|
||||
|
||||
// text input
|
||||
//
|
||||
if (c >= 32 && c !== 127) {
|
||||
strap += e[0];
|
||||
e = e.slice(1); //TODO revisit wrt (list @c) & unicode characters
|
||||
continue;
|
||||
} else if ('' !== strap) {
|
||||
belts.push({ txt: strap.split('') });
|
||||
strap = '';
|
||||
}
|
||||
|
||||
// special keys/characters
|
||||
//
|
||||
if (0 === c) {
|
||||
term.write('\x07'); // bel
|
||||
} else if (8 === c || 127 === c) {
|
||||
belts.push({ bac: null });
|
||||
} else if (13 === c) {
|
||||
belts.push({ ret: null });
|
||||
} else if (c <= 26) {
|
||||
const k = String.fromCharCode(96 + c);
|
||||
//NOTE prevent remote shut-downs
|
||||
if ('d' !== k) {
|
||||
belts.push({ mod: { mod: 'ctl', key: k } });
|
||||
}
|
||||
}
|
||||
|
||||
// escape sequences
|
||||
//
|
||||
if (27 === c) { // ESC
|
||||
e = e.slice(1);
|
||||
c = e.charCodeAt(0);
|
||||
if (91 === c || 79 === c) { // [ or O
|
||||
e = e.slice(1);
|
||||
c = e.charCodeAt(0);
|
||||
/* eslint-disable max-statements-per-line */
|
||||
switch (c) {
|
||||
case 65: belts.push({ aro: 'u' }); break;
|
||||
case 66: belts.push({ aro: 'd' }); break;
|
||||
case 67: belts.push({ aro: 'r' }); break;
|
||||
case 68: belts.push({ aro: 'l' }); break;
|
||||
//
|
||||
case 77: {
|
||||
const m = e.charCodeAt(1) - 31;
|
||||
if (1 === m) {
|
||||
const c = e.charCodeAt(2) - 32;
|
||||
const r = e.charCodeAt(3) - 32;
|
||||
belts.push({ hit: { y: r - 1, x: c - 1 } });
|
||||
}
|
||||
e = e.slice(3);
|
||||
break;
|
||||
}
|
||||
//
|
||||
default: term.write('\x07'); break; // bel
|
||||
}
|
||||
} else if (c >= 97 && c <= 122) { // a <= c <= z
|
||||
belts.push({ mod: { mod: 'met', key: e[0] } });
|
||||
} else if (c === 46) { // .
|
||||
belts.push({ mod: { mod: 'met', key: '.' } });
|
||||
} else if (c === 8 || c === 127) {
|
||||
belts.push({ mod: { mod: 'met', key: { bac: null } } });
|
||||
} else {
|
||||
term.write('\x07'); break; // bel
|
||||
}
|
||||
}
|
||||
|
||||
e = e.slice(1);
|
||||
}
|
||||
if ('' !== strap) {
|
||||
if (1 === strap.length) {
|
||||
belts.push(strap);
|
||||
} else {
|
||||
belts.push({ txt: strap.split('') });
|
||||
}
|
||||
strap = '';
|
||||
}
|
||||
return belts;
|
||||
};
|
||||
|
||||
const onResize = async (name: string, session: Session) => {
|
||||
if (session) {
|
||||
session.fit.fit();
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].pending++;
|
||||
});
|
||||
api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })).then(() => {
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].pending--;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onInput = (name: string, session: Session, e: string) => {
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
const term = session.term;
|
||||
const belts = readInput(term, e);
|
||||
belts.forEach((b) => {
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].pending++;
|
||||
});
|
||||
api.poke(pokeBelt(name, b)).then(() => {
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].pending--;
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
interface BufferProps {
|
||||
name: string,
|
||||
selected: boolean,
|
||||
dark: boolean,
|
||||
}
|
||||
|
||||
export default function Buffer({ name, selected, dark }: BufferProps) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const session: Session = useTermState(s => s.sessions[name]);
|
||||
|
||||
const initSession = useCallback(async (name: string, dark: boolean) => {
|
||||
console.log('setting up', name === DEFAULT_SESSION ? 'default' : name);
|
||||
|
||||
// set up xterm terminal
|
||||
//
|
||||
const term = new Terminal(termConfig);
|
||||
term.options.theme = makeTheme(dark);
|
||||
const fit = new FitAddon();
|
||||
term.loadAddon(fit);
|
||||
fit.fit();
|
||||
term.focus();
|
||||
|
||||
// start mouse reporting
|
||||
//
|
||||
term.write(csi('?9h'));
|
||||
|
||||
const ses: Session = {
|
||||
term,
|
||||
fit,
|
||||
hasBell: false,
|
||||
pending: 0,
|
||||
subscriptionId: null
|
||||
};
|
||||
|
||||
// set up event handlers
|
||||
//
|
||||
term.attachCustomKeyEventHandler((e: KeyboardEvent) => {
|
||||
//NOTE ctrl+shift keypresses never make it into term.onData somehow,
|
||||
// so we handle them specially ourselves.
|
||||
// we may be able to remove this once xterm.js fixes #3382 & co.
|
||||
if (e.shiftKey
|
||||
&& e.ctrlKey
|
||||
&& e.type === 'keydown'
|
||||
&& e.key.length === 1
|
||||
) {
|
||||
api.poke(pokeBelt(name, { mod: { mod: 'ctl', key: e.key } }));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
term.onData(e => onInput(name, ses, e));
|
||||
term.onBinary(e => onInput(name, ses, e));
|
||||
|
||||
// open subscription
|
||||
//
|
||||
const initSubscription = async () => {
|
||||
const subscriptionId = await api.subscribe({
|
||||
app: 'herm', path: '/session/' + name + '/view',
|
||||
event: (e) => {
|
||||
showBlit(ses.term, e);
|
||||
//NOTE getting selected from state because selected prop is stale
|
||||
if (hasBell(e) && (useTermState.getState().selected !== name)) {
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].hasBell = true;
|
||||
});
|
||||
}
|
||||
//TODO should handle %bye on this higher level though, for deletion
|
||||
},
|
||||
err: (e, id) => {
|
||||
console.log(`subscription error, id ${id}:`, e);
|
||||
},
|
||||
quit: async () => { // quit
|
||||
console.error('quit, reconnecting...');
|
||||
try {
|
||||
const newSubscriptionId = await retry(initSubscription, () => {
|
||||
console.log('attempting to reconnect ...');
|
||||
}, 5);
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].subscriptionId = newSubscriptionId;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('unable to reconnect', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return subscriptionId;
|
||||
};
|
||||
|
||||
ses.subscriptionId = await initSubscription();
|
||||
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name] = ses;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const shouldResize = useCallback(() => {
|
||||
if(!session) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const containerHeight = document.querySelector('.buffer-container')?.clientHeight || Infinity;
|
||||
const terminalHeight = session.term.element?.clientHeight || 0;
|
||||
|
||||
return (containerHeight - terminalHeight) >= RESIZE_THRESHOLD_PX;
|
||||
}, [session]);
|
||||
|
||||
const onSelect = useCallback(async () => {
|
||||
if (session && selected && shouldResize()) {
|
||||
session.fit.fit();
|
||||
await api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } }));
|
||||
session.term.focus();
|
||||
}
|
||||
}, [session?.term, selected]);
|
||||
|
||||
// Effects
|
||||
// init session
|
||||
useEffect(() => {
|
||||
if(session) {
|
||||
return;
|
||||
}
|
||||
|
||||
initSession(name, dark);
|
||||
}, [name]);
|
||||
|
||||
// attach to DOM when ref is available
|
||||
useEffect(() => {
|
||||
if(session && containerRef.current && !session.term.element) {
|
||||
session.term.open(containerRef.current);
|
||||
}
|
||||
}, [session, containerRef]);
|
||||
|
||||
// initialize resize listeners
|
||||
//
|
||||
useEffect(() => {
|
||||
if(!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use ResizeObserver for improved performance?
|
||||
const debouncedResize = debounce(() => onResize(name, session), RESIZE_DEBOUNCE_MS);
|
||||
window.addEventListener('resize', debouncedResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', debouncedResize);
|
||||
};
|
||||
}, [session]);
|
||||
|
||||
// on dark mode change, change terminals' theme
|
||||
//
|
||||
useEffect(() => {
|
||||
const theme = makeTheme(dark);
|
||||
if (session) {
|
||||
session.term.options.theme = theme;
|
||||
}
|
||||
if (containerRef.current) {
|
||||
containerRef.current.style.backgroundColor = theme.background || '';
|
||||
}
|
||||
}, [session, dark]);
|
||||
|
||||
// On select, resize, focus, and poke herm with updated cols and rows
|
||||
useEffect(() => {
|
||||
onSelect();
|
||||
}, [onSelect]);
|
||||
|
||||
return (
|
||||
!session && !selected ?
|
||||
<p>Loading...</p>
|
||||
:
|
||||
<Box
|
||||
width='100%'
|
||||
height='100%'
|
||||
bg='white'
|
||||
fontFamily='mono'
|
||||
overflow='hidden'
|
||||
className="terminal-container"
|
||||
style={selected ? { zIndex: 999 } : {}}
|
||||
>
|
||||
<Col
|
||||
width='100%'
|
||||
height='100%'
|
||||
minHeight='0'
|
||||
px={['0', '2']}
|
||||
pb={['0', '2']}
|
||||
ref={containerRef}
|
||||
>
|
||||
</Col>
|
||||
</Box>
|
||||
);
|
||||
}
|
24
pkg/interface/webterm/InfoButton.tsx
Normal file
24
pkg/interface/webterm/InfoButton.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { Icon } from '@tlon/indigo-react';
|
||||
import { useDetectOS } from './lib/useDetectOS';
|
||||
|
||||
export const InfoButton = () => {
|
||||
const { isMacOS } = useDetectOS();
|
||||
|
||||
const onInfoClick = useCallback(() => {
|
||||
const key = isMacOS ? 'alt' : 'shift';
|
||||
|
||||
alert(`To select text in the terminal, hold down the ${key} key.`);
|
||||
}, [isMacOS]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<button className="info-btn" onClick={onInfoClick}>
|
||||
<Icon
|
||||
icon="Info"
|
||||
size="18px"
|
||||
/>
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
};
|
55
pkg/interface/webterm/Spinner.tsx
Normal file
55
pkg/interface/webterm/Spinner.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import useIsMounted from './lib/useIsMounted';
|
||||
import React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const DELAY_MS = 1000;
|
||||
const FRAME_MS = 250;
|
||||
const CHARS = '|/-\\';
|
||||
|
||||
const Spinner = () => {
|
||||
const [index, setIndex] = useState(0);
|
||||
const [intervalTimer, setIntervalTimer] = useState<ReturnType<typeof setInterval> | undefined>();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
useEffect(() => {
|
||||
setIntervalTimer(
|
||||
setInterval(() => {
|
||||
if (isMounted()) {
|
||||
setIndex(idx => idx === CHARS.length - 1 ? 0 : idx + 1);
|
||||
}
|
||||
}, FRAME_MS)
|
||||
);
|
||||
|
||||
return () => {
|
||||
if (intervalTimer) {
|
||||
clearInterval(intervalTimer);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <span> {CHARS[index]}</span>;
|
||||
};
|
||||
|
||||
export const DelayedSpinner = () => {
|
||||
const [showSpinner, setShowSpinner] = useState(false);
|
||||
const [delayTimer, setDelayTimer] = useState<ReturnType<typeof setTimeout> | undefined>();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
useEffect(() => {
|
||||
setDelayTimer(
|
||||
setTimeout(() => {
|
||||
if (isMounted()) {
|
||||
setShowSpinner(true);
|
||||
}
|
||||
}, DELAY_MS)
|
||||
);
|
||||
|
||||
return () => {
|
||||
if (delayTimer) {
|
||||
clearTimeout(delayTimer);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return showSpinner ? <Spinner /> : null;
|
||||
};
|
55
pkg/interface/webterm/Tab.tsx
Normal file
55
pkg/interface/webterm/Tab.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { DEFAULT_SESSION } from './constants';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import useTermState, { Session } from './state';
|
||||
import api from './api';
|
||||
import { pokeTask } from '@urbit/api/term';
|
||||
import { DelayedSpinner as Spinner } from './Spinner';
|
||||
|
||||
interface TabProps {
|
||||
session: Session;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const Tab = ( { session, name }: TabProps ) => {
|
||||
const isSelected = useTermState().selected === name;
|
||||
|
||||
const onClick = () => {
|
||||
useTermState.getState().set((state) => {
|
||||
state.selected = name;
|
||||
state.sessions[name].hasBell = false;
|
||||
});
|
||||
};
|
||||
|
||||
const onDelete = useCallback(async (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
// clean up subscription
|
||||
if(session && session.subscriptionId) {
|
||||
await api.unsubscribe(session.subscriptionId);
|
||||
}
|
||||
|
||||
// DELETE
|
||||
await api.poke(pokeTask(name, { shut: null }));
|
||||
|
||||
// remove from zustand
|
||||
useTermState.getState().set((state) => {
|
||||
if (state.selected === name) {
|
||||
state.selected = DEFAULT_SESSION;
|
||||
}
|
||||
state.names = state.names.filter(n => n !== name);
|
||||
delete state.sessions[name];
|
||||
});
|
||||
}, [session]);
|
||||
|
||||
return (
|
||||
<div className={'tab ' + (isSelected ? 'selected' : '')} onClick={onClick}>
|
||||
<a className='session-name'>
|
||||
{session?.hasBell ? '🔔 ' : ''}
|
||||
{name === DEFAULT_SESSION ? 'default' : name}
|
||||
{session && session.pending > 0 ? <Spinner /> : null}
|
||||
{' '}
|
||||
</a>
|
||||
{name === DEFAULT_SESSION ? null : <a className="delete-session" onClick={onDelete}>x</a>}
|
||||
</div>
|
||||
);
|
||||
};
|
26
pkg/interface/webterm/Tabs.tsx
Normal file
26
pkg/interface/webterm/Tabs.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import useTermState from './state';
|
||||
import { Tab } from './Tab';
|
||||
import { useAddSession } from './lib/useAddSession';
|
||||
import { Icon } from '@tlon/indigo-react';
|
||||
|
||||
export const Tabs = () => {
|
||||
const { sessions, names } = useTermState();
|
||||
const addSession = useAddSession();
|
||||
|
||||
return (
|
||||
<div className="tabs">
|
||||
{names.map((n, i) => {
|
||||
return (
|
||||
<Tab session={sessions[n]} name={n} key={i} />
|
||||
);
|
||||
})}
|
||||
<button className="tab" onClick={addSession}>
|
||||
<Icon
|
||||
icon="Plus"
|
||||
size="18px"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,475 +0,0 @@
|
||||
/* eslint-disable max-lines */
|
||||
import React, {
|
||||
useEffect,
|
||||
useRef,
|
||||
useCallback
|
||||
} from 'react';
|
||||
|
||||
import useTermState from './state';
|
||||
import { useDark } from './join';
|
||||
import api from './api';
|
||||
|
||||
import { Terminal, ITerminalOptions, ITheme } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { saveAs } from 'file-saver';
|
||||
|
||||
import { Box, Col, Reset, _dark, _light } from '@tlon/indigo-react';
|
||||
|
||||
import 'xterm/css/xterm.css';
|
||||
|
||||
import {
|
||||
Belt, Blit, Stye, Stub, Tint, Deco,
|
||||
pokeTask, pokeBelt
|
||||
} from '@urbit/api/term';
|
||||
|
||||
import bel from './lib/bel';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
type TermAppProps = {
|
||||
ship: string;
|
||||
}
|
||||
|
||||
const makeTheme = (dark: boolean): ITheme => {
|
||||
let fg, bg: string;
|
||||
if (dark) {
|
||||
fg = 'white';
|
||||
bg = 'rgb(26,26,26)';
|
||||
} else {
|
||||
fg = 'black';
|
||||
bg = 'white';
|
||||
}
|
||||
// TODO indigo colors.
|
||||
// we can't pluck these from ThemeContext because they have transparency.
|
||||
// technically xterm supports transparency, but it degrades performance.
|
||||
return {
|
||||
foreground: fg,
|
||||
background: bg,
|
||||
brightBlack: '#7f7f7f', // NOTE slogs
|
||||
cursor: fg,
|
||||
cursorAccent: bg,
|
||||
selection: fg
|
||||
};
|
||||
};
|
||||
|
||||
const termConfig: ITerminalOptions = {
|
||||
logLevel: 'warn',
|
||||
//
|
||||
convertEol: true,
|
||||
//
|
||||
rows: 24,
|
||||
cols: 80,
|
||||
scrollback: 10000,
|
||||
//
|
||||
fontFamily: '"Source Code Pro", "Roboto mono", "Courier New", monospace',
|
||||
fontWeight: 400,
|
||||
// NOTE theme colors configured dynamically
|
||||
//
|
||||
bellStyle: 'sound',
|
||||
bellSound: bel,
|
||||
//
|
||||
// allows text selection by holding modifier (option, or shift)
|
||||
macOptionClickForcesSelection: true,
|
||||
// prevent insertion of simulated arrow keys on-altclick
|
||||
altClickMovesCursor: false
|
||||
};
|
||||
|
||||
const csi = (cmd: string, ...args: number[]) => {
|
||||
return '\x1b[' + args.join(';') + cmd;
|
||||
};
|
||||
|
||||
const tint = (t: Tint) => {
|
||||
switch (t) {
|
||||
case null: return '9';
|
||||
case 'k': return '0';
|
||||
case 'r': return '1';
|
||||
case 'g': return '2';
|
||||
case 'y': return '3';
|
||||
case 'b': return '4';
|
||||
case 'm': return '5';
|
||||
case 'c': return '6';
|
||||
case 'w': return '7';
|
||||
default: return `8;2;${t.r%256};${t.g%256};${t.b%256}`;
|
||||
}
|
||||
};
|
||||
|
||||
const stye = (s: Stye) => {
|
||||
let out = '';
|
||||
|
||||
// text decorations
|
||||
//
|
||||
if (s.deco.length > 0) {
|
||||
out += s.deco.reduce((decs: number[], deco: Deco) => {
|
||||
/* eslint-disable max-statements-per-line */
|
||||
switch (deco) {
|
||||
case null: decs.push(0); return decs;
|
||||
case 'br': decs.push(1); return decs;
|
||||
case 'un': decs.push(4); return decs;
|
||||
case 'bl': decs.push(5); return decs;
|
||||
default: console.log('weird deco', deco); return decs;
|
||||
}
|
||||
}, []).join(';');
|
||||
}
|
||||
|
||||
// background color
|
||||
//
|
||||
if (s.back !== null) {
|
||||
if (out !== '') {
|
||||
out += ';';
|
||||
}
|
||||
out += '4';
|
||||
out += tint(s.back);
|
||||
}
|
||||
|
||||
// foreground color
|
||||
//
|
||||
if (s.fore !== null) {
|
||||
if (out !== '') {
|
||||
out += ';';
|
||||
}
|
||||
out += '3';
|
||||
out += tint(s.fore);
|
||||
}
|
||||
|
||||
if (out === '') {
|
||||
return out;
|
||||
}
|
||||
return '\x1b[' + out + 'm';
|
||||
};
|
||||
|
||||
const showBlit = (term: Terminal, blit: Blit) => {
|
||||
let out = '';
|
||||
|
||||
if ('bel' in blit) {
|
||||
out += '\x07';
|
||||
} else if ('clr' in blit) {
|
||||
term.clear();
|
||||
out += csi('u');
|
||||
} else if ('hop' in blit) {
|
||||
if (typeof blit.hop === 'number') {
|
||||
out += csi('H', term.rows, blit.hop + 1);
|
||||
} else {
|
||||
out += csi('H', term.rows - blit.hop.r, blit.hop.c + 1);
|
||||
}
|
||||
out += csi('s'); // save cursor position
|
||||
} else if ('put' in blit) {
|
||||
out += blit.put.join('');
|
||||
out += csi('u');
|
||||
} else if ('klr' in blit) {
|
||||
//TODO remove for new backend
|
||||
{
|
||||
out += csi('H', term.rows, 1);
|
||||
out += csi('K');
|
||||
}
|
||||
out += blit.klr.reduce((lin: string, p: Stub) => {
|
||||
lin += stye(p.stye);
|
||||
lin += p.text.join('');
|
||||
lin += csi('m', 0);
|
||||
return lin;
|
||||
}, '');
|
||||
out += csi('u');
|
||||
} else if ('nel' in blit) {
|
||||
out += '\n';
|
||||
} else if ('sag' in blit || 'sav' in blit) {
|
||||
const sav = ('sag' in blit) ? blit.sag : blit.sav;
|
||||
const name = sav.path.split('/').slice(-2).join('.');
|
||||
const buff = Buffer.from(sav.file, 'base64');
|
||||
const blob = new Blob([buff], { type: 'application/octet-stream' });
|
||||
saveAs(blob, name);
|
||||
} else if ('url' in blit) {
|
||||
window.open(blit.url);
|
||||
} else if ('wyp' in blit) {
|
||||
out += '\r' + csi('K');
|
||||
out += csi('u');
|
||||
//
|
||||
//TODO remove for new backend
|
||||
} else if ('lin' in blit) {
|
||||
out += csi('H', term.rows, 1);
|
||||
out += csi('K');
|
||||
out += blit.lin.join('');
|
||||
} else if ('mor' in blit) {
|
||||
out += '\n';
|
||||
} else {
|
||||
console.log('weird blit', blit);
|
||||
}
|
||||
|
||||
term.write(out);
|
||||
};
|
||||
|
||||
// NOTE should generally only be passed the default terminal session
|
||||
const showSlog = (term: Terminal, slog: string) => {
|
||||
// set scroll region to exclude the bottom line,
|
||||
// scroll up one line,
|
||||
// move cursor to start of the newly created whitespace,
|
||||
// set text to grey,
|
||||
// print the slog,
|
||||
// restore color, scroll region, and cursor.
|
||||
//
|
||||
term.write(csi('r', 1, term.rows - 1)
|
||||
+ csi('S', 1)
|
||||
+ csi('H', term.rows - 1, 1)
|
||||
+ csi('m', 90)
|
||||
+ slog
|
||||
+ csi('m', 0)
|
||||
+ csi('r')
|
||||
+ csi('u'));
|
||||
};
|
||||
|
||||
const readInput = (term: Terminal, e: string): Belt[] => {
|
||||
const belts: Belt[] = [];
|
||||
let strap = '';
|
||||
|
||||
while (e.length > 0) {
|
||||
let c = e.charCodeAt(0);
|
||||
|
||||
// text input
|
||||
//
|
||||
if (c >= 32 && c !== 127) {
|
||||
strap += e[0];
|
||||
e = e.slice(1);
|
||||
continue;
|
||||
} else if ('' !== strap) {
|
||||
belts.push({ txt: strap.split('') });
|
||||
strap = '';
|
||||
}
|
||||
|
||||
// special keys/characters
|
||||
//
|
||||
if (0 === c) {
|
||||
term.write('\x07'); // bel
|
||||
} else if (8 === c || 127 === c) {
|
||||
belts.push({ bac: null });
|
||||
} else if (13 === c) {
|
||||
belts.push({ ret: null });
|
||||
} else if (c <= 26) {
|
||||
let k = String.fromCharCode(96 + c);
|
||||
//NOTE prevent remote shut-downs
|
||||
if ('d' !== k) {
|
||||
belts.push({ ctl: k });
|
||||
//TODO for new backend
|
||||
// belts.push({ mod: { mod: 'ctl', key: k } });
|
||||
}
|
||||
}
|
||||
|
||||
// escape sequences
|
||||
//
|
||||
if (27 === c) { // ESC
|
||||
e = e.slice(1);
|
||||
c = e.charCodeAt(0);
|
||||
if (91 === c || 79 === c) { // [ or O
|
||||
e = e.slice(1);
|
||||
c = e.charCodeAt(0);
|
||||
/* eslint-disable max-statements-per-line */
|
||||
switch (c) {
|
||||
case 65: belts.push({ aro: 'u' }); break;
|
||||
case 66: belts.push({ aro: 'd' }); break;
|
||||
case 67: belts.push({ aro: 'r' }); break;
|
||||
case 68: belts.push({ aro: 'l' }); break;
|
||||
//
|
||||
case 77: {
|
||||
const m = e.charCodeAt(1) - 31;
|
||||
if (1 === m) {
|
||||
const c = e.charCodeAt(2) - 32;
|
||||
const r = e.charCodeAt(3) - 32;
|
||||
//TODO re-enable for new backend
|
||||
// belts.push({ hit: { r: term.rows - r, c: c - 1 } });
|
||||
}
|
||||
e = e.slice(3);
|
||||
break;
|
||||
}
|
||||
//
|
||||
default: term.write('\x07'); break; // bel
|
||||
}
|
||||
} else if (c >= 97 && c <= 122) { // a <= c <= z
|
||||
belts.push({ mod: { mod: 'met', key: e[0] } });
|
||||
} else if (c === 46) { // .
|
||||
belts.push({ mod: { mod: 'met', key: '.' } });
|
||||
} else if (c === 8 || c === 127) {
|
||||
belts.push({ mod: { mod: 'met', key: { bac: null } } });
|
||||
} else {
|
||||
term.write('\x07'); break; // bel
|
||||
}
|
||||
}
|
||||
|
||||
e = e.slice(1);
|
||||
}
|
||||
if ('' !== strap) {
|
||||
belts.push({ txt: strap.split('') });
|
||||
strap = '';
|
||||
}
|
||||
return belts;
|
||||
};
|
||||
|
||||
export default function TermApp(props: TermAppProps) {
|
||||
const container = useRef<HTMLDivElement>(null);
|
||||
// TODO allow switching of selected
|
||||
const { sessions, selected, slogstream, set } = useTermState();
|
||||
const session = sessions[selected];
|
||||
const dark = useDark();
|
||||
|
||||
const setupSlog = useCallback(() => {
|
||||
console.log('slog: setting up...');
|
||||
let available = false;
|
||||
const slog = new EventSource('/~_~/slog', { withCredentials: true });
|
||||
|
||||
slog.onopen = (e) => {
|
||||
console.log('slog: opened stream');
|
||||
available = true;
|
||||
};
|
||||
|
||||
slog.onmessage = (e) => {
|
||||
const session = useTermState.getState().sessions[''];
|
||||
if (!session) {
|
||||
console.log('default session mia!', 'slog:', slog);
|
||||
return;
|
||||
}
|
||||
showSlog(session.term, e.data);
|
||||
};
|
||||
|
||||
slog.onerror = (e) => {
|
||||
console.error('slog: eventsource error:', e);
|
||||
if (available) {
|
||||
window.setTimeout(() => {
|
||||
if (slog.readyState !== EventSource.CLOSED) {
|
||||
return;
|
||||
}
|
||||
console.log('slog: reconnecting...');
|
||||
setupSlog();
|
||||
}, 10000);
|
||||
}
|
||||
};
|
||||
|
||||
set((state) => {
|
||||
state.slogstream = slog;
|
||||
});
|
||||
}, [sessions]);
|
||||
|
||||
const onInput = useCallback((ses: string, e: string) => {
|
||||
const term = useTermState.getState().sessions[ses].term;
|
||||
const belts = readInput(term, e);
|
||||
belts.map((b) => { // NOTE passing api.poke(pokeBelt makes `this` undefined!
|
||||
//TODO pokeBelt(ses, b);
|
||||
api.poke({
|
||||
app: 'herm',
|
||||
mark: 'belt',
|
||||
json: b
|
||||
});
|
||||
});
|
||||
}, [sessions]);
|
||||
|
||||
const onResize = useCallback(() => {
|
||||
// TODO debounce, if it ever becomes a problem
|
||||
session?.fit.fit();
|
||||
}, [session]);
|
||||
|
||||
// on-init, open slogstream
|
||||
//
|
||||
useEffect(() => {
|
||||
if (!slogstream) {
|
||||
setupSlog();
|
||||
}
|
||||
window.addEventListener('resize', onResize);
|
||||
return () => {
|
||||
// TODO clean up subs?
|
||||
window.removeEventListener('resize', onResize);
|
||||
};
|
||||
}, [onResize, setupSlog]);
|
||||
|
||||
// on dark mode change, change terminals' theme
|
||||
//
|
||||
useEffect(() => {
|
||||
const theme = makeTheme(dark);
|
||||
for (const ses in sessions) {
|
||||
sessions[ses].term.setOption('theme', theme);
|
||||
}
|
||||
if (container.current) {
|
||||
container.current.style.backgroundColor = theme.background || '';
|
||||
}
|
||||
}, [dark, sessions]);
|
||||
|
||||
// on selected change, maybe setup the term, or put it into the container
|
||||
//
|
||||
useEffect(() => {
|
||||
let ses = session;
|
||||
// initialize terminal
|
||||
//
|
||||
if (!ses) {
|
||||
// set up terminal
|
||||
//
|
||||
const term = new Terminal(termConfig);
|
||||
term.setOption('theme', makeTheme(dark));
|
||||
const fit = new FitAddon();
|
||||
term.loadAddon(fit);
|
||||
|
||||
// start mouse reporting
|
||||
//
|
||||
term.write(csi('?9h'));
|
||||
|
||||
// set up event handlers
|
||||
//
|
||||
term.onData(e => onInput(selected, e));
|
||||
term.onBinary(e => onInput(selected, e));
|
||||
term.onResize((e) => {
|
||||
//TODO re-enable once new backend lands
|
||||
// api.poke(pokeTask(selected, { blew: { w: e.cols, h: e.rows } }));
|
||||
});
|
||||
|
||||
ses = { term, fit };
|
||||
|
||||
// open subscription
|
||||
//
|
||||
api.subscribe({ app: 'herm', path: '/session/'+selected+'/view',
|
||||
event: (e) => {
|
||||
const ses = useTermState.getState().sessions[selected];
|
||||
if (!ses) {
|
||||
console.log('on blit: no such session', selected, sessions, useTermState.getState().sessions);
|
||||
return;
|
||||
}
|
||||
showBlit(ses.term, e);
|
||||
},
|
||||
quit: () => { // quit
|
||||
// TODO show user a message
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (container.current && !container.current.contains(ses.term.element || null)) {
|
||||
ses.term.open(container.current);
|
||||
ses.fit.fit();
|
||||
ses.term.focus();
|
||||
}
|
||||
|
||||
set((state) => {
|
||||
state.sessions[selected] = ses;
|
||||
});
|
||||
|
||||
return () => {
|
||||
// TODO unload term from container
|
||||
// but term.dispose is too powerful? maybe just empty the container?
|
||||
};
|
||||
}, [set, session, container]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider theme={dark ? _dark : _light}>
|
||||
<Reset />
|
||||
<Box
|
||||
width='100%'
|
||||
height='100%'
|
||||
bg='white'
|
||||
fontFamily='mono'
|
||||
overflow='hidden'
|
||||
>
|
||||
<Col
|
||||
width='100%'
|
||||
height='100%'
|
||||
minHeight='0'
|
||||
px={['0','2']}
|
||||
pb={['0','2']}
|
||||
ref={container}
|
||||
>
|
||||
</Col>
|
||||
</Box>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
);
|
||||
}
|
28
pkg/interface/webterm/constants.ts
Normal file
28
pkg/interface/webterm/constants.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export const DEFAULT_SESSION = '';
|
||||
export const DEFAULT_HANDLER = 'hood';
|
||||
export const RESIZE_DEBOUNCE_MS = 100;
|
||||
export const RESIZE_THRESHOLD_PX = 15;
|
||||
|
||||
/**
|
||||
* Session ID validity:
|
||||
*
|
||||
* - must start with an alphabetical
|
||||
* - can be composed of alphanumerics with hyphens
|
||||
* - can be length 1 or longer
|
||||
*/
|
||||
export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*$)/;
|
||||
|
||||
/**
|
||||
* Open a session with a given agent using `[agent]![session_name]`
|
||||
*
|
||||
* For example:
|
||||
* ```
|
||||
* book!my-session
|
||||
* ```
|
||||
*
|
||||
* This will create a new session in webterm for the `%book` agent.
|
||||
*
|
||||
* Note that the second capture group after the ! is composed of the session ID
|
||||
* regex above.
|
||||
*/
|
||||
export const AGENT_SESSION_REGEX = /^([a-z]{1}[a-z\d-]*)!([a-z]{1}[a-z\d-]*$)/;
|
@ -23,10 +23,113 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body, #root {
|
||||
height: 100vh;
|
||||
height: 99vh; /* prevent scrollbar on outer frame */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.buffer-container {
|
||||
height: calc(100% - 40px);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.terminal-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
div.header {
|
||||
display: grid;
|
||||
grid-template-areas: "tabs info";
|
||||
grid-template-columns: auto min-content;
|
||||
grid-template-rows: auto;
|
||||
}
|
||||
|
||||
div.info {
|
||||
grid-area: info;
|
||||
}
|
||||
|
||||
div.tabs {
|
||||
grid-area: tabs;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
padding: 5px 5px 0 5px;
|
||||
border-bottom: 1px solid black;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.tabs > * {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
border: solid 1px black;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.tab, button.tab {
|
||||
margin-bottom: -1px; /** To overlay the selected tab on the tabs container bottom border */
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
div.tabs > div.selected {
|
||||
border-bottom: white solid 1px;
|
||||
}
|
||||
|
||||
div.tabs > div.selected > a.session-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.tabs > a.delete-session {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
button.info-btn {
|
||||
border: none;
|
||||
border-bottom: solid black 1px;
|
||||
background: transparent;
|
||||
padding: 10px;
|
||||
line-height: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
background-color: rgb(26,26,26);
|
||||
}
|
||||
|
||||
div.tabs {
|
||||
background-color: rgb(26, 26, 26);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border-bottom-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
div.tab {
|
||||
background-color: rgb(26, 26, 26);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
button.tab {
|
||||
background-color: rgb(42, 42, 42);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
div.tabs > div.selected {
|
||||
border-bottom: rgb(26,26,26) solid 1px;
|
||||
}
|
||||
|
||||
button.info-btn {
|
||||
border-bottom: solid rgba(255, 255, 255, 0.9) 1px;
|
||||
background: rgb(26, 26, 26);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
129
pkg/interface/webterm/lib/blit.ts
Normal file
129
pkg/interface/webterm/lib/blit.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { Terminal } from 'xterm';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { Blit, Stub, Stye } from '@urbit/api/term';
|
||||
import { stye } from '../lib/stye';
|
||||
|
||||
export const csi = (cmd: string, ...args: number[]) => {
|
||||
return '\x1b[' + args.join(';') + cmd;
|
||||
};
|
||||
|
||||
export const showBlit = (term: Terminal, blit: Blit) => {
|
||||
let out = '';
|
||||
|
||||
if ('mor' in blit) {
|
||||
return blit.mor.map(b => showBlit(term, b));
|
||||
} else if ('bel' in blit) {
|
||||
out += '\x07';
|
||||
} else if ('clr' in blit) {
|
||||
term.clear();
|
||||
out += csi('u');
|
||||
} else if ('hop' in blit) {
|
||||
if (typeof blit.hop === 'number') {
|
||||
out += csi('H', term.rows, blit.hop + 1);
|
||||
} else {
|
||||
out += csi('H', blit.hop.y + 1, blit.hop.x + 1);
|
||||
}
|
||||
out += csi('s'); // save cursor position
|
||||
} else if ('put' in blit) {
|
||||
out += blit.put.join('');
|
||||
out += csi('u');
|
||||
} else if ('klr' in blit) {
|
||||
out += blit.klr.reduce((lin: string, p: Stub) => {
|
||||
lin += stye(p.stye);
|
||||
lin += p.text.join('');
|
||||
lin += csi('m', 0);
|
||||
return lin;
|
||||
}, '');
|
||||
out += csi('u');
|
||||
} else if ('nel' in blit) {
|
||||
out += '\n';
|
||||
} else if ('sag' in blit || 'sav' in blit) {
|
||||
const sav = ('sag' in blit) ? blit.sag : blit.sav;
|
||||
const name = sav.path.split('/').slice(-2).join('.');
|
||||
const buff = Buffer.from(sav.file, 'base64');
|
||||
const blob = new Blob([buff], { type: 'application/octet-stream' });
|
||||
saveAs(blob, name);
|
||||
} else if ('url' in blit) {
|
||||
window.open(blit.url);
|
||||
} else if ('wyp' in blit) {
|
||||
out += '\r' + csi('K');
|
||||
out += csi('u');
|
||||
//
|
||||
} else {
|
||||
console.log('weird blit', blit);
|
||||
}
|
||||
|
||||
term.write(out);
|
||||
};
|
||||
|
||||
export const showSlog = (term: Terminal, slog: string) => {
|
||||
// set scroll region to exclude the bottom line,
|
||||
// scroll up one line,
|
||||
// move cursor to start of the newly created whitespace,
|
||||
// set text to grey,
|
||||
// print the slog,
|
||||
// restore color, scroll region, and cursor.
|
||||
//
|
||||
term.write(csi('r', 1, term.rows - 1)
|
||||
+ csi('S', 1)
|
||||
+ csi('H', term.rows - 1, 1)
|
||||
+ csi('m', 90)
|
||||
+ slog
|
||||
+ csi('m', 0)
|
||||
+ csi('r')
|
||||
+ csi('u'));
|
||||
};
|
||||
|
||||
export const hasBell = (blit: Blit) => {
|
||||
if ('bel' in blit) {
|
||||
return true;
|
||||
} else if ('mor' in blit) {
|
||||
return blit.mor.some(hasBell);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// debug rendering
|
||||
//NOTE doesn't behave nicely in the presence of eob %nel blits,
|
||||
// because those aren't idempotent
|
||||
|
||||
const blotStye: Stye = { deco: [], back: { r: 255, g: 0, b: 255 }, fore: 'k' };
|
||||
const blitToBlot = (blit: Blit): Blit => {
|
||||
if ('mor' in blit) {
|
||||
return { mor: blit.mor.map(blitToBlot) };
|
||||
} else if ('put' in blit) {
|
||||
return { klr: [{ text: blit.put, stye: blotStye }] };
|
||||
} else if ('klr' in blit) {
|
||||
return { klr: blit.klr.map((s: Stub) => {
|
||||
return { text: s.text, stye: blotStye };
|
||||
}) };
|
||||
} else {
|
||||
return blit;
|
||||
}
|
||||
};
|
||||
|
||||
const queue: {term: Terminal, blit: Blit}[] = [];
|
||||
const renderFromQueue = () => {
|
||||
const next = queue.shift();
|
||||
if (!next) {
|
||||
return;
|
||||
}
|
||||
showBlit(next.term, next.blit);
|
||||
if (0 === queue.length) {
|
||||
return;
|
||||
}
|
||||
setTimeout(renderFromQueue, 200);
|
||||
};
|
||||
|
||||
export const showBlitDebug = (term: Terminal, blit: Blit) => {
|
||||
const blot = blitToBlot(blit);
|
||||
if (0 === queue.length) {
|
||||
showBlit(term, blot);
|
||||
queue.push({ term, blit });
|
||||
setTimeout(renderFromQueue, 200);
|
||||
} else {
|
||||
queue.push({ term, blit: blot });
|
||||
queue.push({ term, blit });
|
||||
}
|
||||
};
|
39
pkg/interface/webterm/lib/retry.ts
Normal file
39
pkg/interface/webterm/lib/retry.ts
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Wait for the given milliseconds
|
||||
* @param {number} milliseconds The given time to wait
|
||||
* @returns {Promise} A fulfiled promise after the given time has passed
|
||||
*/
|
||||
function waitFor(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a promise and retry with exponential backoff
|
||||
* based on the maximum retry attempts it can perform
|
||||
* @param {Promise} promise promise to be executed
|
||||
* @param {function} onRetry callback executed on every retry
|
||||
* @param {number} maxRetries The maximum number of retries to be attempted
|
||||
* @returns {Promise} The result of the given promise passed in
|
||||
*/
|
||||
export function retry(promise, onRetry, maxRetries) {
|
||||
async function retryWithBackoff(retries) {
|
||||
try {
|
||||
if (retries > 0) {
|
||||
const timeToWait = 2 ** retries * 100;
|
||||
console.log(`waiting for ${timeToWait}ms...`);
|
||||
await waitFor(timeToWait);
|
||||
}
|
||||
return await promise();
|
||||
} catch (e) {
|
||||
if (retries < maxRetries) {
|
||||
onRetry();
|
||||
return retryWithBackoff(retries + 1);
|
||||
} else {
|
||||
console.warn('Max retries reached. Bubbling the error up');
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retryWithBackoff(0);
|
||||
}
|
60
pkg/interface/webterm/lib/stye.ts
Normal file
60
pkg/interface/webterm/lib/stye.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { Deco, Stye, Tint } from '@urbit/api/term';
|
||||
|
||||
const tint = (t: Tint) => {
|
||||
switch (t) {
|
||||
case null: return '9';
|
||||
case 'k': return '0';
|
||||
case 'r': return '1';
|
||||
case 'g': return '2';
|
||||
case 'y': return '3';
|
||||
case 'b': return '4';
|
||||
case 'm': return '5';
|
||||
case 'c': return '6';
|
||||
case 'w': return '7';
|
||||
default: return `8;2;${t.r%256};${t.g%256};${t.b%256}`;
|
||||
}
|
||||
};
|
||||
|
||||
export const stye = (s: Stye) => {
|
||||
let out = '';
|
||||
|
||||
// text decorations
|
||||
//
|
||||
if (s.deco.length > 0) {
|
||||
out += s.deco.reduce((decs: number[], deco: Deco) => {
|
||||
/* eslint-disable max-statements-per-line */
|
||||
switch (deco) {
|
||||
case null: decs.push(0); return decs;
|
||||
case 'br': decs.push(1); return decs;
|
||||
case 'un': decs.push(4); return decs;
|
||||
case 'bl': decs.push(5); return decs;
|
||||
default: console.log('weird deco', deco); return decs;
|
||||
}
|
||||
}, []).join(';');
|
||||
}
|
||||
|
||||
// background color
|
||||
//
|
||||
if (s.back !== null) {
|
||||
if (out !== '') {
|
||||
out += ';';
|
||||
}
|
||||
out += '4';
|
||||
out += tint(s.back);
|
||||
}
|
||||
|
||||
// foreground color
|
||||
//
|
||||
if (s.fore !== null) {
|
||||
if (out !== '') {
|
||||
out += ';';
|
||||
}
|
||||
out += '3';
|
||||
out += tint(s.fore);
|
||||
}
|
||||
|
||||
if (out === '') {
|
||||
return out;
|
||||
}
|
||||
return '\x1b[' + out + 'm';
|
||||
};
|
23
pkg/interface/webterm/lib/theme.ts
Normal file
23
pkg/interface/webterm/lib/theme.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ITheme } from 'xterm';
|
||||
|
||||
export const makeTheme = (dark: boolean): ITheme => {
|
||||
let fg, bg: string;
|
||||
if (dark) {
|
||||
fg = 'white';
|
||||
bg = 'rgb(26,26,26)';
|
||||
} else {
|
||||
fg = 'black';
|
||||
bg = 'white';
|
||||
}
|
||||
// TODO indigo colors.
|
||||
// we can't pluck these from ThemeContext because they have transparency.
|
||||
// technically xterm supports transparency, but it degrades performance.
|
||||
return {
|
||||
foreground: fg,
|
||||
background: bg,
|
||||
brightBlack: '#7f7f7f', // NOTE slogs
|
||||
cursor: fg,
|
||||
cursorAccent: bg,
|
||||
selection: fg
|
||||
};
|
||||
};
|
66
pkg/interface/webterm/lib/useAddSession.ts
Normal file
66
pkg/interface/webterm/lib/useAddSession.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import {
|
||||
DEFAULT_HANDLER,
|
||||
AGENT_SESSION_REGEX,
|
||||
SESSION_ID_REGEX
|
||||
} from '../constants';
|
||||
import useTermState from '../state';
|
||||
import api from '../api';
|
||||
import { pokeTask } from '@urbit/api/term';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const useAddSession = () => {
|
||||
const { names } = useTermState();
|
||||
|
||||
const addSession = useCallback(async () => {
|
||||
let agent = DEFAULT_HANDLER;
|
||||
let sessionName: string;
|
||||
|
||||
const userInput = prompt('Please enter an alpha-numeric session name.');
|
||||
// user canceled or did not enter a value
|
||||
if (null === userInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check for custom agent session syntax
|
||||
if (AGENT_SESSION_REGEX.test(userInput)) {
|
||||
const match = AGENT_SESSION_REGEX.exec(userInput);
|
||||
if (!match) {
|
||||
alert('Invalid format. Valid syntax: agent!session-name');
|
||||
return;
|
||||
}
|
||||
agent = match[1];
|
||||
sessionName = match[2];
|
||||
// else, use the default session creation regex
|
||||
} else if (SESSION_ID_REGEX.test(userInput)) {
|
||||
const match = SESSION_ID_REGEX.exec(userInput);
|
||||
if (!match) {
|
||||
alert('Invalid format. Valid syntax: session-name');
|
||||
return;
|
||||
}
|
||||
sessionName = match[1];
|
||||
} else {
|
||||
alert('Invalid format. Valid syntax: session-name');
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent duplicate sessions
|
||||
if(names.includes(sessionName)) {
|
||||
alert(`Session name must be unique ("${sessionName}" already in use)`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
//TODO eventually, customizable app pre-linking?
|
||||
await api.poke(pokeTask(sessionName, { open: { term: agent, apps: [{ who: '~' + (window as any).ship, app: 'dojo' }] } }));
|
||||
useTermState.getState().set((state) => {
|
||||
state.names = [sessionName, ...state.names].sort();
|
||||
state.selected = sessionName;
|
||||
state.sessions[sessionName] = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('unable to create session:', error);
|
||||
}
|
||||
}, [names]);
|
||||
|
||||
return addSession;
|
||||
};
|
@ -1,6 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTheme } from './settings';
|
||||
import useTermState from './state';
|
||||
import useTermState from '../state';
|
||||
|
||||
export function useDark() {
|
||||
const [osDark, setOsDark] = useState(false);
|
||||
@ -11,12 +10,11 @@ export function useDark() {
|
||||
setOsDark(e.matches);
|
||||
};
|
||||
setOsDark(themeWatcher.matches);
|
||||
themeWatcher.addListener(update);
|
||||
themeWatcher.addEventListener('change', update);
|
||||
|
||||
return () => {
|
||||
themeWatcher.removeListener(update);
|
||||
}
|
||||
|
||||
themeWatcher.removeEventListener('change', update);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const theme = useTermState(s => s.theme);
|
44
pkg/interface/webterm/lib/useDetectOS.ts
Normal file
44
pkg/interface/webterm/lib/useDetectOS.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/* eslint-disable no-useless-escape */
|
||||
// Regex patterns inspired by:
|
||||
// https://github.com/faisalman/ua-parser-js/blob/master/src/ua-parser.js
|
||||
const LINUX = [
|
||||
/\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
|
||||
/(mint)[\/\(\) ]?(\w*)/i,
|
||||
/(mageia|vectorlinux)[; ]/i,
|
||||
/([kxln]?ubuntu|debian|suse|opensuse|gentoo|arch(?= linux)|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire)(?: gnu\/linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
|
||||
/(hurd|linux) ?([\w\.]*)/i,
|
||||
/(gnu) ?([\w\.]*)/i,
|
||||
/\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
|
||||
/(haiku) (\w+)/i,
|
||||
/(sunos) ?([\w\.\d]*)/i,
|
||||
/((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
|
||||
/(aix) ((\d)(?=\.|\)| )[\w\.])*/i,
|
||||
/\b(beos|os\/2|amigaos|morphos|openvms|fuchsia|hp-ux)/i,
|
||||
/(unix) ?([\w\.]*)/i
|
||||
];
|
||||
|
||||
const MAC_OS = [
|
||||
/(mac os x) ?([\w\. ]*)/i,
|
||||
/(macintosh|mac_powerpc\b)(?!.+haiku)/i
|
||||
];
|
||||
|
||||
const WINDOWS = [
|
||||
/microsoft (windows) (vista|xp)/i,
|
||||
/(windows) nt 6\.2; (arm)/i,
|
||||
/(windows (?:phone(?: os)?|mobile))[\/ ]?([\d\.\w ]*)/i,
|
||||
/(windows)[\/ ]?([ntce\d\. ]+\w)(?!.+xbox)/i
|
||||
];
|
||||
|
||||
export const useDetectOS = () => {
|
||||
const userAgent = navigator.userAgent;
|
||||
|
||||
const isLinux = LINUX.some(regex => regex.test(userAgent));
|
||||
const isMacOS = MAC_OS.some(regex => regex.test(userAgent));
|
||||
const isWindows = WINDOWS.some(regex => regex.test(userAgent));
|
||||
|
||||
return {
|
||||
isLinux,
|
||||
isMacOS,
|
||||
isWindows
|
||||
};
|
||||
};
|
17
pkg/interface/webterm/lib/useIsMounted.ts
Normal file
17
pkg/interface/webterm/lib/useIsMounted.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
function useIsMounted() {
|
||||
const isMounted = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
isMounted.current = true;
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return useCallback(() => isMounted.current, []);
|
||||
}
|
||||
|
||||
export default useIsMounted;
|
716
pkg/interface/webterm/package-lock.json
generated
716
pkg/interface/webterm/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,7 @@
|
||||
"@urbit/api": "^1.1.1",
|
||||
"@urbit/http-api": "^1.2.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^16.14.0",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
@ -36,7 +37,7 @@
|
||||
"@types/styled-system": "^5.1.10",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.0",
|
||||
"@typescript-eslint/parser": "^4.24.0",
|
||||
"@urbit/eslint-config": "^1.0.0",
|
||||
"@urbit/eslint-config": "^1.0.3",
|
||||
"@welldone-software/why-did-you-render": "^6.1.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
@ -45,7 +46,9 @@
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"husky": "^6.0.0",
|
||||
@ -58,7 +61,8 @@
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint ./src/**/*.{ts,tsx}",
|
||||
"lint": "eslint ./**/*.{ts,tsx}",
|
||||
"lint-fix": "eslint --fix ./**/*.{ts,tsx}",
|
||||
"lint-file": "eslint",
|
||||
"tsc": "tsc",
|
||||
"tsc:watch": "tsc --watch",
|
||||
|
@ -3,21 +3,33 @@ import { FitAddon } from 'xterm-addon-fit';
|
||||
import create from 'zustand';
|
||||
import produce from 'immer';
|
||||
|
||||
type Session = { term: Terminal, fit: FitAddon };
|
||||
type Sessions = { [id: string]: Session; }
|
||||
export type Session = {
|
||||
term: Terminal,
|
||||
fit: FitAddon,
|
||||
hasBell: boolean,
|
||||
pending: number,
|
||||
subscriptionId: number | null,
|
||||
} | null;
|
||||
export type Sessions = { [id: string]: Session; }
|
||||
|
||||
export interface TermState {
|
||||
sessions: Sessions,
|
||||
names: string[],
|
||||
selected: string,
|
||||
slogstream: null | EventSource,
|
||||
theme: 'auto' | 'light' | 'dark'
|
||||
};
|
||||
theme: 'auto' | 'light' | 'dark',
|
||||
//TODO: figure out the type
|
||||
set: any,
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const useTermState = create<TermState>((set, get) => ({
|
||||
sessions: {} as Sessions,
|
||||
names: [''],
|
||||
selected: '', // empty string is default session
|
||||
slogstream: null,
|
||||
theme: 'auto',
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
set: (f: (draft: TermState) => void) => {
|
||||
set(produce(f));
|
||||
}
|
||||
|
26
pkg/interface/webterm/tsconfig.json
Normal file
26
pkg/interface/webterm/tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedParameters": false,
|
||||
"noImplicitReturns": false,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"noUnusedLocals": false,
|
||||
"noImplicitAny": false,
|
||||
"noEmit": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"strict": false,
|
||||
"strictNullChecks": true,
|
||||
"jsx": "react",
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": [
|
||||
"**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
@ -16,15 +16,15 @@
|
||||
+$ card card:shoe
|
||||
::
|
||||
+$ versioned-state
|
||||
$% state-3
|
||||
$% state-4
|
||||
state-3
|
||||
state-2
|
||||
state-1
|
||||
state-0
|
||||
==
|
||||
::
|
||||
+$ state-3
|
||||
$: %3
|
||||
::TODO support multiple sessions
|
||||
+$ state-4
|
||||
$: %4
|
||||
sessions=(map sole-id session) :: sole sessions
|
||||
bound=(map resource glyph) :: bound resource glyphs
|
||||
binds=(jug glyph resource) :: resource glyph lookup
|
||||
@ -33,7 +33,17 @@
|
||||
timez=(pair ? @ud) :: timezone adjustment
|
||||
==
|
||||
::
|
||||
+$ sole-id @ta
|
||||
+$ state-3
|
||||
$: %3
|
||||
sessions=(map @ta session)
|
||||
bound=(map resource glyph)
|
||||
binds=(jug glyph resource)
|
||||
settings=(set term)
|
||||
width=@ud
|
||||
timez=(pair ? @ud)
|
||||
==
|
||||
::
|
||||
+$ sole-id sole-id:shoe
|
||||
+$ session
|
||||
$: viewing=(set resource) :: connected graphs
|
||||
history=(list uid:post) :: scrollback pointers
|
||||
@ -115,7 +125,7 @@
|
||||
== ::
|
||||
::
|
||||
--
|
||||
=| state-3
|
||||
=| state-4
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
@ -258,14 +268,14 @@
|
||||
settings width timez
|
||||
==
|
||||
::
|
||||
=^ cards u.old
|
||||
=^ cards-1 u.old
|
||||
?. ?=(%2 -.u.old) [~ u.old]
|
||||
:- :~ [%pass /chat-store %agent [our-self %chat-store] %leave ~]
|
||||
[%pass /invites %agent [our.bowl %invite-store] %leave ~]
|
||||
==
|
||||
^- state-3
|
||||
:- %3
|
||||
:* %+ ~(put in *(map sole-id session))
|
||||
:* %+ ~(put in *(map @ta session))
|
||||
(cat 3 'drum_' (scot %p our.bowl))
|
||||
:* ~ ~ 0
|
||||
::
|
||||
@ -290,14 +300,29 @@
|
||||
timez.u.old
|
||||
==
|
||||
::
|
||||
?> ?=(%3 -.u.old)
|
||||
=^ cards-2 u.old
|
||||
?. ?=(%3 -.u.old) [~ u.old]
|
||||
:- %+ turn ~(tap in ~(key by sessions.u.old))
|
||||
|= id=@ta
|
||||
^- card:agent:gall
|
||||
[%give %kick ~[/sole/[id]] ~]
|
||||
=- u.old(- %4, sessions -)
|
||||
%- ~(gas by *(map sole-id session))
|
||||
%+ murn ~(tap by sessions.u.old)
|
||||
|= [id=@ta s=session]
|
||||
(bind (upgrade-id:sole:shoe id) (late s))
|
||||
::
|
||||
?> ?=(%4 -.u.old)
|
||||
:_ u.old
|
||||
%+ welp
|
||||
cards
|
||||
?: %- ~(has by wex.bowl)
|
||||
[/graph-store our-self %graph-store]
|
||||
~
|
||||
~[connect]
|
||||
;: welp
|
||||
cards-1
|
||||
cards-2
|
||||
::
|
||||
?: %- ~(has by wex.bowl)
|
||||
[/graph-store our-self %graph-store]
|
||||
~
|
||||
~[connect]
|
||||
==
|
||||
:: +connect: connect to the graph-store
|
||||
::
|
||||
++ connect
|
||||
|
@ -41,6 +41,7 @@
|
||||
state-one
|
||||
state-two
|
||||
state-three
|
||||
state-four
|
||||
==
|
||||
::
|
||||
+$ state-zero
|
||||
@ -61,9 +62,15 @@
|
||||
=groups
|
||||
wait=(set ship)
|
||||
==
|
||||
::
|
||||
+$ state-four
|
||||
$: %4
|
||||
=groups
|
||||
wait=(set ship)
|
||||
==
|
||||
--
|
||||
::
|
||||
=| state-three
|
||||
=| state-four
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
@ -84,7 +91,15 @@
|
||||
=| cards=(list card)
|
||||
|^
|
||||
?- -.old
|
||||
%3 [(flop cards) this(state old)]
|
||||
%4 [(flop cards) this(state old)]
|
||||
::
|
||||
%3
|
||||
%_ $
|
||||
old [%4 +.old]
|
||||
cards
|
||||
:_ cards
|
||||
[%pass /pyre/rebuild %agent [our dap]:bowl %poke noun+!>(%rebuild)]
|
||||
==
|
||||
::
|
||||
%2
|
||||
%_ $
|
||||
@ -140,6 +155,7 @@
|
||||
?+ q.vase !!
|
||||
%migrate poke-migrate:gc
|
||||
%export poke-export:gc
|
||||
%rebuild poke-rebuild:gc
|
||||
==
|
||||
::
|
||||
?(%group-update-0 %group-action)
|
||||
@ -235,6 +251,42 @@
|
||||
::
|
||||
|_ bol=bowl:gall
|
||||
+* io ~(. agentio bol)
|
||||
++ poke-rebuild
|
||||
^- (quip card _state)
|
||||
|^
|
||||
=. wait
|
||||
put-missing
|
||||
=^ cards state
|
||||
rewatch
|
||||
[cards state]
|
||||
::
|
||||
++ rewatch
|
||||
=/ wait ~(tap in wait)
|
||||
=| cards=(list card)
|
||||
|-
|
||||
?~ wait
|
||||
[cards state]
|
||||
=/ wir /gladio/(scot %p i.wait)
|
||||
=. cards
|
||||
:_(cards (watch-init-migrate i.wait))
|
||||
:: if we have a subscription already, leave first to restart
|
||||
=? cards
|
||||
(~(has by wex.bol) [wir i.wait %groups])
|
||||
:_(cards [%pass wir %agent [i.wait %groups] %leave ~])
|
||||
$(wait t.wait)
|
||||
::
|
||||
++ put-missing
|
||||
=/ wex ~(tap by wex.bol)
|
||||
|-
|
||||
?~ wex
|
||||
wait
|
||||
=/ [[=wire =ship =term] [acked=? =(pole knot)]]
|
||||
i.wex
|
||||
?. ?=([%gladio ship=@ ~] pole)
|
||||
$(wex t.wex)
|
||||
$(wex t.wex, wait (~(put in wait) (slav %p ship.pole)))
|
||||
--
|
||||
::
|
||||
++ poke-export
|
||||
^- (quip card _state)
|
||||
:_ state
|
||||
@ -351,8 +403,8 @@
|
||||
|= arc=*
|
||||
^- (quip card _state)
|
||||
|^
|
||||
=/ sty=state-three
|
||||
[%3 (remake-groups ;;((tree [resource tree-group]) +.arc)) ~]
|
||||
=/ sty=state-four
|
||||
[%4 (remake-groups ;;((tree [resource tree-group]) +.arc)) ~]
|
||||
:_ sty
|
||||
%+ roll ~(tap by groups.sty)
|
||||
|= [[rid=resource grp=group] out=(list card)]
|
||||
|
@ -9,12 +9,14 @@
|
||||
+$ card card:agent:gall
|
||||
+$ versioned-state
|
||||
$% state-zero
|
||||
state-one
|
||||
==
|
||||
::
|
||||
+$ state-zero [%0 =credentials =configuration]
|
||||
+$ state-zero [%0 =credentials:zero:past =configuration:zero:past]
|
||||
+$ state-one [%1 =credentials =configuration]
|
||||
--
|
||||
::
|
||||
=| state-zero
|
||||
=| state-one
|
||||
=* state -
|
||||
::
|
||||
%- agent:dbug
|
||||
@ -28,8 +30,28 @@
|
||||
++ on-init on-init:def
|
||||
++ on-save !>(state)
|
||||
++ on-load
|
||||
|= old-vase=vase
|
||||
[~ this(state !<(state-zero old-vase))]
|
||||
|= =vase
|
||||
=/ old !<(versioned-state vase)
|
||||
|^
|
||||
?- -.old
|
||||
%1 `this(state old)
|
||||
%0 `this(state (state-0-to-1 old))
|
||||
==
|
||||
++ state-0-to-1
|
||||
|= zer=state-zero
|
||||
^- state-one
|
||||
:* %1
|
||||
credentials.zer
|
||||
(configuration-0-to-1 configuration.zer)
|
||||
==
|
||||
++ configuration-0-to-1
|
||||
|= conf=configuration:zero:past
|
||||
^- ^configuration
|
||||
:* buckets.conf
|
||||
current-bucket.conf
|
||||
''
|
||||
==
|
||||
--
|
||||
::
|
||||
++ on-poke
|
||||
~/ %s3-poke
|
||||
@ -56,6 +78,9 @@
|
||||
::
|
||||
%set-secret-access-key
|
||||
state(secret-access-key.credentials secret-access-key.act)
|
||||
::
|
||||
%set-region
|
||||
state(region.configuration region.act)
|
||||
::
|
||||
%set-current-bucket
|
||||
%_ state
|
||||
|
10
pkg/landscape/gen/s3-store/set-region.hoon
Normal file
10
pkg/landscape/gen/s3-store/set-region.hoon
Normal file
@ -0,0 +1,10 @@
|
||||
:: s3-store|set-current-bucket: set current bucket for S3
|
||||
::
|
||||
/- *s3
|
||||
:- %say
|
||||
|= $: [now=@da eny=@uvJ =beak]
|
||||
[[region=@t ~] ~]
|
||||
==
|
||||
:- %s3-action
|
||||
^- action
|
||||
[%set-region region]
|
1
pkg/landscape/lib/dill.hoon
Symbolic link
1
pkg/landscape/lib/dill.hoon
Symbolic link
@ -0,0 +1 @@
|
||||
../../base-dev/lib/dill.hoon
|
@ -10,6 +10,7 @@
|
||||
:~ [%set-endpoint so:dejs]
|
||||
[%set-access-key-id so:dejs]
|
||||
[%set-secret-access-key so:dejs]
|
||||
[%set-region so:dejs]
|
||||
[%add-bucket so:dejs]
|
||||
[%remove-bucket so:dejs]
|
||||
[%set-current-bucket so:dejs]
|
||||
@ -25,6 +26,7 @@
|
||||
:~ ?- -.upd
|
||||
%set-current-bucket [%'setCurrentBucket' s+bucket.upd]
|
||||
%add-bucket [%'addBucket' s+bucket.upd]
|
||||
%set-region [%'setRegion' s+region.upd]
|
||||
%remove-bucket [%'removeBucket' s+bucket.upd]
|
||||
%set-endpoint [%'setEndpoint' s+endpoint.upd]
|
||||
%set-access-key-id [%'setAccessKeyId' s+access-key-id.upd]
|
||||
@ -44,6 +46,7 @@
|
||||
%- pairs:enjs
|
||||
:~ [%buckets a+(turn ~(tap in buckets.configuration.upd) |=(a=@t s+a))]
|
||||
[%'currentBucket' s+current-bucket.configuration.upd]
|
||||
[%'region' s+region.configuration.upd]
|
||||
==
|
||||
==
|
||||
==
|
||||
|
27
pkg/landscape/sur/s3-0.hoon
Normal file
27
pkg/landscape/sur/s3-0.hoon
Normal file
@ -0,0 +1,27 @@
|
||||
|%
|
||||
+$ credentials
|
||||
$: endpoint=@t
|
||||
access-key-id=@t
|
||||
secret-access-key=@t
|
||||
==
|
||||
::
|
||||
+$ configuration
|
||||
$: buckets=(set @t)
|
||||
current-bucket=@t
|
||||
==
|
||||
::
|
||||
+$ action
|
||||
$% [%set-endpoint endpoint=@t]
|
||||
[%set-access-key-id access-key-id=@t]
|
||||
[%set-secret-access-key secret-access-key=@t]
|
||||
[%add-bucket bucket=@t]
|
||||
[%remove-bucket bucket=@t]
|
||||
[%set-current-bucket bucket=@t]
|
||||
==
|
||||
::
|
||||
+$ update
|
||||
$% [%credentials =credentials]
|
||||
[%configuration =configuration]
|
||||
action
|
||||
==
|
||||
--
|
@ -1,4 +1,9 @@
|
||||
/- zer=s3-0
|
||||
|%
|
||||
++ past
|
||||
|%
|
||||
++ zero zer
|
||||
--
|
||||
+$ credentials
|
||||
$: endpoint=@t
|
||||
access-key-id=@t
|
||||
@ -8,6 +13,7 @@
|
||||
+$ configuration
|
||||
$: buckets=(set @t)
|
||||
current-bucket=@t
|
||||
region=@t
|
||||
==
|
||||
::
|
||||
+$ action
|
||||
@ -17,6 +23,7 @@
|
||||
[%add-bucket bucket=@t]
|
||||
[%remove-bucket bucket=@t]
|
||||
[%set-current-bucket bucket=@t]
|
||||
[%set-region region=@t]
|
||||
==
|
||||
::
|
||||
+$ update
|
||||
|
@ -1 +1 @@
|
||||
[%zuse 417]
|
||||
[%zuse 416]
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Poke } from '../lib'
|
||||
import { Scry } from '../../http-api/src'
|
||||
import { Poke } from '../../http-api/src/types';
|
||||
import { Belt, Task, SessionTask } from './types';
|
||||
|
||||
export const pokeTask = (session: string, task: Task): Poke<SessionTask> => ({
|
||||
@ -13,9 +14,7 @@ export const pokeBelt = (
|
||||
): Poke<SessionTask> => pokeTask(session, { belt });
|
||||
|
||||
//NOTE scry will return string[]
|
||||
// export const scrySessions = (): Scry => ({
|
||||
// app: 'herm',
|
||||
// path: `/sessions`
|
||||
// });
|
||||
//TODO remove stub once new backend lands
|
||||
export const scrySessions = (): string[] => [''];
|
||||
export const scrySessions = (): Scry => ({
|
||||
app: 'herm',
|
||||
path: `/sessions`
|
||||
});
|
||||
|
@ -25,17 +25,15 @@ export type Stub = {
|
||||
export type Blit =
|
||||
| { bel: null } // make a noise
|
||||
| { clr: null } // clear the screen
|
||||
| { hop: number | { r: number, c: number } } // set cursor col/pos
|
||||
| { hop: number | { x: number, y: number } } // set cursor col/pos
|
||||
| { klr: Stub[] } // put styled
|
||||
| { put: string[] } // put text at cursor
|
||||
| { mor: Blit[] } // multiple blits
|
||||
| { nel: null } // newline
|
||||
| { put: string[] } // put text at cursor
|
||||
| { sag: { path: string, file: string } } // save to jamfile
|
||||
| { sav: { path: string, file: string } } // save to file
|
||||
| { url: string } // activate url
|
||||
| { wyp: null } // wipe cursor line
|
||||
//
|
||||
| { lin: string[] } // legacy put
|
||||
| { mor: true } // legacy nel
|
||||
|
||||
// inputs
|
||||
//
|
||||
@ -45,21 +43,19 @@ export type Bolt =
|
||||
| { aro: 'd' | 'l' | 'r' | 'u' }
|
||||
| { bac: null }
|
||||
| { del: null }
|
||||
| { hit: { r: number, c: number } }
|
||||
| { hit: { x: number, y: number } }
|
||||
| { ret: null }
|
||||
|
||||
export type Belt =
|
||||
| Bolt
|
||||
| { mod: { mod: 'ctl' | 'met' | 'hyp', key: Bolt } }
|
||||
| { txt: Array<string> }
|
||||
//
|
||||
| { ctl: string }; // legacy mod
|
||||
|
||||
export type Task =
|
||||
| { belt: Belt }
|
||||
| { blew: { w: number, h: number } }
|
||||
| { flow: { term: string, apps: Array<{ who: string, app: string }> } }
|
||||
| { hail: null }
|
||||
| { hook: null }
|
||||
| { open: { term: string, apps: Array<{ who: string, app: string }> } }
|
||||
| { shut: null }
|
||||
|
||||
export type SessionTask = { session: string } & Task
|
||||
|
@ -167,6 +167,9 @@ u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c)
|
||||
|
||||
// Construct raw termios configuration.
|
||||
//
|
||||
// makes input available per-character, does not echo input,
|
||||
// disables special input pre-processing, output post-processing.
|
||||
//
|
||||
{
|
||||
pty_u->raw_u = pty_u->bak_u;
|
||||
|
||||
|
2
pkg/urbit/configure
vendored
2
pkg/urbit/configure
vendored
@ -211,7 +211,7 @@ for citem in $compat; do
|
||||
done
|
||||
|
||||
cat >config.mk <<EOF
|
||||
CFLAGS := $CFLAGS -funsigned-char -ffast-math -fcommon -std=gnu99
|
||||
CFLAGS := $CFLAGS -funsigned-char -ffast-math -fcommon -std=gnu99 -Wno-format-zero-length
|
||||
LDFLAGS := $LDFLAGS
|
||||
CC := ${CC-cc}
|
||||
compat := $compat
|
||||
|
@ -572,7 +572,7 @@ _setup_cert_store()
|
||||
{
|
||||
BIO* cbio = BIO_new_mem_buf(include_ca_bundle_crt, include_ca_bundle_crt_len);
|
||||
if ( !cbio || !(_cert_store = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL)) ) {
|
||||
u3l_log("boot: failed to decode embedded CA certificates\r\n");
|
||||
u3l_log("boot: failed to decode embedded CA certificates");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1267,7 +1267,7 @@ _cw_eval(c3_i argc, c3_c* argv[])
|
||||
}
|
||||
u3s_cue_xeno_done(sil_u);
|
||||
if ( c3n == u3v_boot_lite(pil) ) {
|
||||
u3l_log("lite: boot failed\r\n");
|
||||
u3l_log("lite: boot failed");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -1858,7 +1858,7 @@ _cw_vere(c3_i argc, c3_c* argv[])
|
||||
// initialize curl
|
||||
//
|
||||
if ( 0 != curl_global_init(CURL_GLOBAL_DEFAULT) ) {
|
||||
u3l_log("boot: curl initialization failed\r\n");
|
||||
u3l_log("boot: curl initialization failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -1888,11 +1888,11 @@ _cw_vere(c3_i argc, c3_c* argv[])
|
||||
|
||||
|
||||
if ( u3_king_vere(pac_c, ver_c, arc_c, dir_c, 0) ) {
|
||||
u3l_log("vere: download failed\r\n");
|
||||
u3l_log("vere: download failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
u3l_log("vere: download succeeded\r\n");
|
||||
u3l_log("vere: download succeeded");
|
||||
}
|
||||
|
||||
/* _cw_vile(): generatoe/print keyfile
|
||||
@ -2138,7 +2138,7 @@ main(c3_i argc,
|
||||
sigemptyset(&set);
|
||||
sigaddset(&set, SIGPROF);
|
||||
if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) {
|
||||
u3l_log("boot: thread mask SIGPROF: %s\r\n", strerror(errno));
|
||||
u3l_log("boot: thread mask SIGPROF: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -2230,7 +2230,7 @@ main(c3_i argc,
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
|
||||
if ( NULL == (u3_Host.cev_u = CreateEvent(&sa, FALSE, FALSE, NULL)) ) {
|
||||
u3l_log("boot: failed to create Ctrl-C event: %d\r\n", GetLastError());
|
||||
u3l_log("boot: failed to create Ctrl-C event: %d", GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -2251,7 +2251,7 @@ main(c3_i argc,
|
||||
// initialize curl
|
||||
//
|
||||
if ( 0 != curl_global_init(CURL_GLOBAL_DEFAULT) ) {
|
||||
u3l_log("boot: curl initialization failed\r\n");
|
||||
u3l_log("boot: curl initialization failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -615,6 +615,7 @@
|
||||
# define c3__khan c3_s4('k','h','a','n')
|
||||
# define c3__keep c3_s4('k','e','e','p')
|
||||
# define c3__kern c3_s4('k','e','r','n')
|
||||
# define c3__key c3_s3('k','e','y')
|
||||
# define c3__kgo c3_s3('k','g','o')
|
||||
# define c3__kick c3_s4('k','i','c','k')
|
||||
# define c3__king c3_s4('k','i','n','g')
|
||||
@ -786,6 +787,7 @@
|
||||
# define c3__ne c3_s2('n','e')
|
||||
# define c3__need c3_s4('n','e','e','d')
|
||||
# define c3__neft c3_s4('n','e','f','t')
|
||||
# define c3__nel c3_s3('n','e','l')
|
||||
# define c3__nest c3_s4('n','e','s','t')
|
||||
# define c3__netd c3_s4('n','e','t','d')
|
||||
# define c3__new c3_s3('n','e','w')
|
||||
@ -1298,6 +1300,7 @@
|
||||
# define c3__wtsg c3_s4('w','t','s','g')
|
||||
# define c3__wtts c3_s4('w','t','t','s')
|
||||
# define c3__wtzp c3_s4('w','t','z','p')
|
||||
# define c3__wyp c3_s3('w','y','p')
|
||||
# define c3__wyrd c3_s4('w','y','r','d')
|
||||
# define c3__xray c3_s4('x','r','a','y')
|
||||
# define c3__yell c3_s4('y','e','l','l')
|
||||
|
@ -145,22 +145,25 @@
|
||||
} siz;
|
||||
|
||||
struct {
|
||||
c3_y* lin_y; // current line (utf8)
|
||||
c3_w byt_w; // utf8 line-length
|
||||
c3_w wor_w; // utf32 line-length
|
||||
c3_w sap_w; // escape chars in line
|
||||
c3_w cus_w; // cursor position
|
||||
u3_noun lin; // bottom line (stub)
|
||||
c3_w rus_w; // cursor position (row)
|
||||
c3_w cus_w; // cursor position (column)
|
||||
} mir;
|
||||
|
||||
struct { // escape code control
|
||||
c3_o ape; // escape received
|
||||
c3_o bra; // bracket or O received
|
||||
c3_o mou; // M (for mouse event) received
|
||||
c3_y ton_y; // mouse button
|
||||
c3_y col_y; // column coordinate
|
||||
c3_y seq_y; // vt sequence
|
||||
} esc;
|
||||
|
||||
struct {
|
||||
c3_y syb_y[5]; // utf8 code buffer
|
||||
c3_w len_w; // present length
|
||||
c3_w wid_w; // total width
|
||||
struct { // input buffering
|
||||
c3_y syb_y[5]; // utf8 code buffer
|
||||
c3_w len_w; // present length
|
||||
c3_w wid_w; // total width
|
||||
u3_noun imp; // %txt input buffer
|
||||
} fut;
|
||||
|
||||
struct {
|
||||
@ -180,30 +183,22 @@
|
||||
struct _u3_usig* nex_u;
|
||||
} u3_usig;
|
||||
|
||||
/* u2_utfo: unix terminfo strings.
|
||||
/* u2_utfo: terminal escape sequences
|
||||
*/
|
||||
typedef struct {
|
||||
// disabled, currently unused
|
||||
uv_buf_t mon_u; // mouse reporting on
|
||||
uv_buf_t mof_u; // mouse reporting off
|
||||
//
|
||||
// struct {
|
||||
// uv_buf_t kcuu1_u; // key_up
|
||||
// uv_buf_t kcud1_u; // key_down
|
||||
// uv_buf_t kcub1_u; // key_back
|
||||
// uv_buf_t kcuf1_u; // key_forward
|
||||
// } inn;
|
||||
struct {
|
||||
uv_buf_t clear_u; // clear_screen
|
||||
uv_buf_t el_u; // clr_bol clear to beginning
|
||||
// uv_buf_t el1_u; // clr_eol clear to end
|
||||
uv_buf_t ed_u; // clear to end of screen
|
||||
uv_buf_t bel_u; // bel sound bell
|
||||
uv_buf_t cub1_u; // parm_left
|
||||
uv_buf_t cuf1_u; // parm_right
|
||||
uv_buf_t cuu1_u; // parm_up
|
||||
uv_buf_t cud1_u; // parm_down
|
||||
// uv_buf_t cub_u; // parm_left_cursor #num
|
||||
// uv_buf_t cuf_u; // parm_right_cursor #num
|
||||
} out;
|
||||
uv_buf_t reg_u; // restore scroll region
|
||||
//
|
||||
uv_buf_t suc_u; // save cursor position
|
||||
uv_buf_t ruc_u; // restore cursor position
|
||||
uv_buf_t cub_u; // move cursor left one column
|
||||
//
|
||||
uv_buf_t clr_u; // clear screen
|
||||
uv_buf_t cel_u; // clear to end of line
|
||||
//
|
||||
uv_buf_t bel_u; // bel sound bell
|
||||
} u3_utfo;
|
||||
|
||||
#if 0
|
||||
@ -253,7 +248,7 @@
|
||||
c3_l* row_l); // return tty window size
|
||||
c3_i fid_i; // file descriptor
|
||||
c3_w tid_l; // terminal identity number
|
||||
u3_utfo ufo_u; // terminfo strings
|
||||
u3_utfo ufo_u; // escape sequences
|
||||
u3_utat tat_u; // control state
|
||||
struct _u3_auto* car_u; // driver hack
|
||||
} u3_utty;
|
||||
@ -1113,7 +1108,7 @@
|
||||
/* u3_term_io_loja(): release console from cooked print.
|
||||
*/
|
||||
void
|
||||
u3_term_io_loja(int x);
|
||||
u3_term_io_loja(int x, FILE* f);
|
||||
|
||||
/* u3_term_log_init(): initialize terminal for logging
|
||||
*/
|
||||
|
@ -169,7 +169,7 @@ u3qc_rep(u3_atom a,
|
||||
return _bit_rep(b, c);
|
||||
}
|
||||
|
||||
u3l_log("rep: stub\r\n");
|
||||
u3l_log("rep: stub");
|
||||
return u3_none;
|
||||
}
|
||||
|
||||
|
@ -159,7 +159,7 @@ u3qc_rip(u3_atom a,
|
||||
return _bit_rip(b, c);
|
||||
}
|
||||
|
||||
u3l_log("rip: stub\r\n");
|
||||
u3l_log("rip: stub");
|
||||
return u3_none;
|
||||
}
|
||||
|
||||
|
@ -13,21 +13,15 @@ _in_apt(u3_noun a, u3_weak l, u3_weak r)
|
||||
u3_noun n_a, l_a, r_a;
|
||||
u3x_trel(a, &n_a, &l_a, &r_a);
|
||||
|
||||
if ( (u3_none != l) &&
|
||||
( (c3y == u3r_sing(n_a, l)) || (c3n == u3qc_gor(n_a, l)) )) {
|
||||
if ( (u3_none != l) && (c3n == u3qc_gor(n_a, l)) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( (u3_none != r) &&
|
||||
( (c3y == u3r_sing(r, n_a)) || (c3n == u3qc_gor(r, n_a)) )) {
|
||||
if ( (u3_none != r) && (c3n == u3qc_gor(r, n_a)) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( u3_nul != l_a ) {
|
||||
if ( c3y == u3r_sing(n_a, u3h(l_a)) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( c3n == u3qc_mor(n_a, u3h(l_a)) ) {
|
||||
return c3n;
|
||||
}
|
||||
@ -38,10 +32,6 @@ _in_apt(u3_noun a, u3_weak l, u3_weak r)
|
||||
}
|
||||
|
||||
if ( u3_nul != r_a ) {
|
||||
if ( c3y == u3r_sing(n_a, u3h(r_a)) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
||||
if ( c3n == u3qc_mor(n_a, u3h(r_a)) ) {
|
||||
return c3n;
|
||||
}
|
||||
|
@ -98,7 +98,7 @@
|
||||
}
|
||||
else {
|
||||
ret = u3_none;
|
||||
u3l_log("argon2-error: %s\r\n", err_c);
|
||||
u3l_log("argon2-error: %s", err_c);
|
||||
}
|
||||
|
||||
u3a_free(out_y);
|
||||
|
@ -14,14 +14,14 @@ u3qe_jam(u3_atom a)
|
||||
siz_w = u3a_count_noun(u3h(som));
|
||||
tot_w += siz_w;
|
||||
if ( 0 == siz_w ) {
|
||||
u3l_log("item: B/0\r\n");
|
||||
u3l_log("item: B/0");
|
||||
}
|
||||
else {
|
||||
u3a_print_memory(stderr, "item", siz_w);
|
||||
}
|
||||
}
|
||||
if ( u3_blip != som ) {
|
||||
u3l_log("forgot to terminate list!\r\n");
|
||||
u3l_log("forgot to terminate list!");
|
||||
}
|
||||
c3_w mem_w = u3h_count(u3R->cax.har_p);
|
||||
|
||||
@ -31,7 +31,7 @@ u3qe_jam(u3_atom a)
|
||||
u3a_print_memory(stderr, "total", tot_w);
|
||||
u3a_print_memory(stderr, "memoization cache", mem_w);
|
||||
u3h_root* har_u = u3to(u3h_root, u3R->cax.har_p);
|
||||
u3l_log("memoization entries: %d\r\n", har_u->use_w);
|
||||
u3l_log("memoization entries: %d", har_u->use_w);
|
||||
u3a_print_memory(stderr, "unused free", u3a_open(u3R));
|
||||
return tot_w;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
// Sanity check: crash if decoding more bits than available
|
||||
if ( c3y == u3qa_gth(x, m)) {
|
||||
// u3l_log("[%%rub-hard %d %d %d]\r\n", a, x, m);
|
||||
// u3l_log("[%%rub-hard %d %d %d]", a, x, m);
|
||||
return u3m_bail(c3__exit);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ u3je_secp_init()
|
||||
sec_u = malloc(urcrypt_secp_prealloc_size());
|
||||
|
||||
if ( 0 != urcrypt_secp_init(sec_u, ent_y) ) {
|
||||
u3l_log("u3e_secp_init failed\r\n");
|
||||
u3l_log("u3e_secp_init failed");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
(u3_nul == u3h(hr_con)) &&
|
||||
(u3_nul == u3t(hr_con)) )
|
||||
{
|
||||
u3l_log("old core\r\n");
|
||||
u3l_log("old core");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
u3r_trel(dab, &n_dab, &l_dab, &r_dab);
|
||||
if ( c3n == u3du(n_dab) ) {
|
||||
// return u3m_bail(c3__fail);
|
||||
u3l_log("bad look\r\n");
|
||||
u3l_log("bad look");
|
||||
return u3m_bail(c3__exit) ;
|
||||
}
|
||||
else {
|
||||
|
@ -431,7 +431,7 @@ _ca_willoc(c3_w len_w, c3_w ald_w, c3_w alp_w)
|
||||
sel_w += 1;
|
||||
}
|
||||
|
||||
// u3l_log("walloc %d: *pfr_p %x\n", len_w, u3R->all.fre_p[sel_w]);
|
||||
// u3l_log("walloc %d: *pfr_p %x", len_w, u3R->all.fre_p[sel_w]);
|
||||
while ( 1 ) {
|
||||
u3p(u3a_fbox) *pfr_p = &u3R->all.fre_p[sel_w];
|
||||
|
||||
@ -566,7 +566,7 @@ u3a_walloc(c3_w len_w)
|
||||
u3a_botox(ptr_v) == (u3a_box*)(void *)0x200dfe3e4 ) {
|
||||
static int xuc_i;
|
||||
|
||||
u3l_log("xuc_i %d\r\n", xuc_i);
|
||||
u3l_log("xuc_i %d", xuc_i);
|
||||
if ( 1 == xuc_i ) {
|
||||
u3a_box* box_u = u3a_botox(ptr_v);
|
||||
|
||||
@ -682,7 +682,7 @@ u3a_malloc(size_t len_i)
|
||||
if ( u3a_botox(out_w) == (u3a_box*)(void *)0x3bdd1c80) {
|
||||
static int xuc_i = 0;
|
||||
|
||||
u3l_log("xuc_i %d\r\n", xuc_i);
|
||||
u3l_log("xuc_i %d", xuc_i);
|
||||
// if ( 1 == xuc_i ) { abort(); }
|
||||
xuc_i++;
|
||||
}
|
||||
@ -885,7 +885,7 @@ u3a_free(void* tox_v)
|
||||
c3_w pad_w = tox_w[-1];
|
||||
c3_w* org_w = tox_w - (pad_w + 1);
|
||||
|
||||
// u3l_log("free %p %p\r\n", org_w, tox_w);
|
||||
// u3l_log("free %p %p", org_w, tox_w);
|
||||
u3a_wfree(org_w);
|
||||
}
|
||||
|
||||
@ -1013,7 +1013,7 @@ _ca_take_atom(u3a_atom* old_u)
|
||||
u3_noun new = u3a_to_pug(u3a_outa(new_u));
|
||||
|
||||
#ifdef VERBOSE_TAKE
|
||||
u3l_log("%s: atom %p to %p\r\n", ( c3y == u3a_is_north(u3R) )
|
||||
u3l_log("%s: atom %p to %p", ( c3y == u3a_is_north(u3R) )
|
||||
? "north"
|
||||
: "south",
|
||||
old_u,
|
||||
@ -1051,7 +1051,7 @@ _ca_take_cell(u3a_cell* old_u, u3_noun hed, u3_noun tel)
|
||||
u3_cell new = u3a_to_pom(u3a_outa(new_u));
|
||||
|
||||
#ifdef VERBOSE_TAKE
|
||||
u3l_log("%s: cell %p to %p\r\n", ( c3y == u3a_is_north(u3R) )
|
||||
u3l_log("%s: cell %p to %p", ( c3y == u3a_is_north(u3R) )
|
||||
? "north"
|
||||
: "south",
|
||||
old_u,
|
||||
@ -1110,7 +1110,7 @@ _ca_take_next_north(u3a_pile* pil_u, u3_noun veb)
|
||||
c3_assert( c3y == u3a_north_is_normal(u3R, nov) );
|
||||
|
||||
#ifdef VERBOSE_TAKE
|
||||
u3l_log("north: %p is already %p\r\n", veb_u, u3a_to_ptr(nov));
|
||||
u3l_log("north: %p is already %p", veb_u, u3a_to_ptr(nov));
|
||||
#endif
|
||||
|
||||
_me_gain_use(nov); // bypass branches in u3k()
|
||||
@ -1165,7 +1165,7 @@ _ca_take_next_south(u3a_pile* pil_u, u3_noun veb)
|
||||
c3_assert( c3y == u3a_south_is_normal(u3R, nov) );
|
||||
|
||||
#ifdef VERBOSE_TAKE
|
||||
u3l_log("south: %p is already %p\r\n", veb_u, u3a_to_ptr(nov));
|
||||
u3l_log("south: %p is already %p", veb_u, u3a_to_ptr(nov));
|
||||
#endif
|
||||
|
||||
_me_gain_use(nov); // bypass branches in u3k()
|
||||
|
@ -142,7 +142,7 @@ u3e_check(c3_c* cap_c)
|
||||
}
|
||||
sum_w += mug_w;
|
||||
}
|
||||
u3l_log("%s: sum %x (%x, %x)\r\n", cap_c, sum_w, nor_w, sou_w);
|
||||
u3l_log("%s: sum %x (%x, %x)", cap_c, sum_w, nor_w, sou_w);
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,7 +488,7 @@ _ce_patch_verify(u3_ce_patch* pat_u)
|
||||
}
|
||||
#if 0
|
||||
else {
|
||||
u3l_log("verify: patch %d/%d, %x\r\n", pag_w, i_w, mug_w);
|
||||
u3l_log("verify: patch %d/%d, %x", pag_w, i_w, mug_w);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -815,7 +815,7 @@ _ce_patch_apply(u3_ce_patch* pat_u)
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
u3l_log("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, pag_wiz_i));
|
||||
u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, pag_wiz_i));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -1169,13 +1169,13 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
|
||||
(u3_Loom + u3C.wor_i) - pag_wiz_i,
|
||||
-(ssize_t)pag_wiz_i);
|
||||
|
||||
u3l_log("boot: protected loom\r\n");
|
||||
u3l_log("boot: protected loom");
|
||||
}
|
||||
|
||||
/* If the images were empty, we are logically booting.
|
||||
*/
|
||||
if ( (0 == u3P.nor_u.pgs_w) && (0 == u3P.sou_u.pgs_w) ) {
|
||||
u3l_log("live: logical boot\r\n");
|
||||
u3l_log("live: logical boot");
|
||||
nuu_o = c3y;
|
||||
}
|
||||
else {
|
||||
|
@ -75,7 +75,7 @@ _cj_hash(c3_c* has_c)
|
||||
{
|
||||
c3_w i_w, len_w = strlen(has_c);
|
||||
if ( 64 != len_w ) {
|
||||
u3l_log("bash not 64 characters: %s\r\n", has_c);
|
||||
u3l_log("bash not 64 characters: %s", has_c);
|
||||
c3_assert(0);
|
||||
}
|
||||
c3_assert( 64 == len_w );
|
||||
@ -236,18 +236,18 @@ _cj_axis(u3_noun fol)
|
||||
(0 != p_fol) ||
|
||||
(!_(u3a_is_cat(q_fol))) )
|
||||
{
|
||||
u3l_log("axis: bad a\r\n");
|
||||
u3l_log("axis: bad a");
|
||||
return 0;
|
||||
}
|
||||
return q_fol;
|
||||
}
|
||||
else {
|
||||
if ( 9 != p_fol )
|
||||
{ u3l_log("axis: bad b\r\n"); return 0; }
|
||||
{ u3l_log("axis: bad b"); return 0; }
|
||||
if ( !_(u3a_is_cat(q_fol)) )
|
||||
{ u3l_log("axis: bad c\r\n"); return 0; }
|
||||
{ u3l_log("axis: bad c"); return 0; }
|
||||
if ( !_(u3du(r_fol)) || (0 != u3h(r_fol)) || (1 != u3t(r_fol)) )
|
||||
{ u3l_log("axis: bad d\r\n"); return 0; }
|
||||
{ u3l_log("axis: bad d"); return 0; }
|
||||
|
||||
return q_fol;
|
||||
}
|
||||
@ -278,7 +278,7 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc)
|
||||
((1 << 31) & (axe_l = (c3_w)axe_d)) ||
|
||||
(axe_l < 2) )
|
||||
{
|
||||
u3l_log("jets: activate: bad fcs %s\r\n", jet_u->fcs_c);
|
||||
u3l_log("jets: activate: bad fcs %s", jet_u->fcs_c);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -286,7 +286,7 @@ _cj_warm_hump(c3_l jax_l, u3_noun huc)
|
||||
u3_noun fol = u3kdb_get(u3k(huc), nam);
|
||||
|
||||
if ( u3_none == fol ) {
|
||||
u3l_log("jets: activate: bad fcs %s\r\n", jet_u->fcs_c);
|
||||
u3l_log("jets: activate: bad fcs %s", jet_u->fcs_c);
|
||||
}
|
||||
else {
|
||||
axe_l = _cj_axis(fol);
|
||||
@ -781,7 +781,7 @@ _cj_hot_mean(c3_l par_l, u3_noun nam)
|
||||
while ( (cop_u = &dev_u[i_l])->cos_c ) {
|
||||
if ( _(u3r_sing_c(cop_u->cos_c, nam)) ) {
|
||||
#if 0
|
||||
u3l_log("hot: bound jet %d/%s/%s/\r\n",
|
||||
u3l_log("hot: bound jet %d/%s/%s/",
|
||||
cop_u->jax_l,
|
||||
cop_u->cos_c,
|
||||
par_u ? par_u->cos_c : "~");
|
||||
@ -893,7 +893,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe)
|
||||
ham_u->liv = c3y;
|
||||
|
||||
if ( c3n == u3r_sing(ame, pro) ) {
|
||||
u3l_log("test: %s %s: mismatch: good %x, bad %x\r\n",
|
||||
u3l_log("test: %s %s: mismatch: good %x, bad %x",
|
||||
cop_u->cos_c,
|
||||
(!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c,
|
||||
u3r_mug(ame),
|
||||
@ -905,7 +905,7 @@ _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe)
|
||||
else {
|
||||
|
||||
#if 0
|
||||
u3l_log("test: %s %s\r\n",
|
||||
u3l_log("test: %s %s",
|
||||
cop_u->cos_c,
|
||||
(!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c);
|
||||
#endif
|
||||
@ -928,13 +928,13 @@ _cj_hook_in(u3_noun cor,
|
||||
u3_noun roc, tem, got, pat, nam, huc;
|
||||
|
||||
if ( c3n == u3du(cor) ) {
|
||||
u3l_log("_cj_hook_in failure: c3n == u3du(cor)\r\n");
|
||||
u3l_log("_cj_hook_in failure: c3n == u3du(cor)");
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
loc = _cj_spot(cor, NULL);
|
||||
if ( u3_none == loc ) {
|
||||
u3l_log("_cj_hook_in failure: u3_none == loc\r\n");
|
||||
u3l_log("_cj_hook_in failure: u3_none == loc");
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
|
||||
@ -999,7 +999,7 @@ _cj_hook_in(u3_noun cor,
|
||||
else {
|
||||
u3_noun sat = u3t(pat);
|
||||
if ( c3y == u3h(sat) ) {
|
||||
u3l_log("_cj_hook_in failure: c3y == u3h(sat)\r\n");
|
||||
u3l_log("_cj_hook_in failure: c3y == u3h(sat)");
|
||||
return u3m_bail(c3__fail);
|
||||
}
|
||||
else {
|
||||
@ -1687,7 +1687,7 @@ u3j_gate_prep(u3j_site* sit_u, u3_noun cor)
|
||||
pay = u3qc_cap(pax),
|
||||
pam = u3qc_mas(pax);
|
||||
if ( 3 != pay || 2 == pam || (3 != pam && 3 != u3qc_cap(pam)) ) {
|
||||
u3l_log("u3j_gate_prep(): parent axis includes sample\r\n");
|
||||
u3l_log("u3j_gate_prep(): parent axis includes sample");
|
||||
u3m_p("axis", pax);
|
||||
u3_weak act = _cj_find_warm(loc);
|
||||
c3_assert( u3_none != act );
|
||||
@ -1758,12 +1758,12 @@ _cj_minx(u3_noun cey, u3_noun cor)
|
||||
|
||||
par = u3r_at(axe, cor);
|
||||
if ( u3_none == par || c3n == u3du(par) ) {
|
||||
u3l_log("fund: %s is bogus\r\n", u3r_string(nam));
|
||||
u3l_log("fund: %s is bogus", u3r_string(nam));
|
||||
return u3_none;
|
||||
}
|
||||
pel = _cj_spot(par, NULL);
|
||||
if ( u3_none == pel ) {
|
||||
u3l_log("fund: in %s, parent %x not found at %d\r\n",
|
||||
u3l_log("fund: in %s, parent %x not found at %d",
|
||||
u3r_string(nam),
|
||||
u3r_mug(u3h(par)),
|
||||
axe);
|
||||
@ -1822,7 +1822,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas)
|
||||
jax_l = _cj_hot_mean(par_l, nam);
|
||||
#if 0
|
||||
u3m_p("new jet", bal);
|
||||
u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l);
|
||||
u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l);
|
||||
#endif
|
||||
|
||||
if ( !(u3C.wag_w & u3o_hashless) ) {
|
||||
@ -1840,7 +1840,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas)
|
||||
for ( i_w = 32; i_w > 0; ) {
|
||||
u3l_log("%02x", dig_y[--i_w]);
|
||||
}
|
||||
u3l_log("\r\n");
|
||||
u3l_log("");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1870,7 +1870,7 @@ _cj_mine(u3_noun cey, u3_noun cor, u3_noun bas)
|
||||
|
||||
if ( c3n == hav_o ) {
|
||||
u3m_p("unregistered battery", bal);
|
||||
u3l_log("hash: %x\r\n", bas);
|
||||
u3l_log("hash: %x", bas);
|
||||
}
|
||||
u3z(bas);
|
||||
}
|
||||
@ -2093,7 +2093,7 @@ _cj_ream(u3_noun all)
|
||||
act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat));
|
||||
#if 0
|
||||
u3m_p("old jet", bal);
|
||||
u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l);
|
||||
u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l);
|
||||
#endif
|
||||
u3h_put(u3R->jed.war_p, loc, act);
|
||||
}
|
||||
@ -2132,7 +2132,7 @@ _cj_ream(u3_noun all)
|
||||
act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat));
|
||||
#if 0
|
||||
u3m_p("old jet", bal);
|
||||
u3l_log(" bat %x, jax %d\r\n", u3r_mug(bat), jax_l);
|
||||
u3l_log(" bat %x, jax %d", u3r_mug(bat), jax_l);
|
||||
#endif
|
||||
u3h_put(u3R->jed.war_p, loc, act);
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ u3l_log(const char* format, ...)
|
||||
// this process did not set a logging function, fallback to stderr
|
||||
//
|
||||
vfprintf(stderr, format, myargs);
|
||||
fprintf(stderr, "\r\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
va_end(myargs);
|
||||
@ -31,7 +33,7 @@ u3_weak
|
||||
u3l_punt(const char* name, u3_weak pro)
|
||||
{
|
||||
if ( u3_none == pro ) {
|
||||
u3l_log("%s-punt\r\n", name);
|
||||
u3l_log("%s-punt", name);
|
||||
}
|
||||
return pro;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user