From 5385889ebd79c46134430a932fbc18a105c67e10 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 24 Sep 2021 23:14:55 -0400 Subject: [PATCH 001/249] Revert "Revert "Merge pull request #4463 from urbit/m/next-gen-term"" This reverts commit 3fba32185dce321661647c5fe3a8a3be930aee32. --- bin/brass.pill | 4 +- bin/ivory.pill | 4 +- bin/solid.pill | 4 +- pkg/arvo/app/herm.hoon | 91 +-- pkg/arvo/app/hood.hoon | 25 +- pkg/arvo/gen/aqua/dojo.hoon | 4 +- pkg/arvo/lib/dill.hoon | 93 +++ pkg/arvo/lib/hood/drum.hoon | 391 ++++++------ pkg/arvo/lib/ph/util.hoon | 8 +- pkg/arvo/mar/belt.hoon | 15 +- pkg/arvo/mar/blit.hoon | 47 +- pkg/arvo/mar/dill/belt.hoon | 4 +- pkg/arvo/mar/dill/blit.hoon | 6 +- pkg/arvo/mar/herm/task.hoon | 46 ++ pkg/arvo/sur/herm.hoon | 9 + pkg/arvo/sys/lull.hoon | 86 ++- pkg/arvo/sys/vane/clay.hoon | 10 +- pkg/arvo/sys/vane/dill.hoon | 320 ++++++---- pkg/arvo/sys/vane/gall.hoon | 20 +- pkg/arvo/sys/vane/jael.hoon | 11 +- pkg/arvo/sys/zuse.hoon | 101 +++ pkg/arvo/ted/aqua/dill.hoon | 5 +- pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs | 37 +- pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs | 80 ++- pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs | 2 +- pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs | 295 ++++++--- pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs | 2 +- .../urbit-king/lib/Urbit/Vere/Term/Logic.hs | 61 +- .../urbit-king/lib/Urbit/Vere/Term/Render.hs | 34 +- pkg/interface/package-lock.json | Bin 882585 -> 1363532 bytes pkg/interface/package.json | 2 + pkg/interface/src/logic/lib/bel.js | 1 - pkg/interface/src/logic/lib/bel.ts | 1 + pkg/interface/src/logic/state/term.ts | 21 + pkg/interface/src/views/apps/term/api.tsx | 50 -- pkg/interface/src/views/apps/term/app.tsx | 526 +++++++++++++--- .../views/apps/term/components/history.tsx | 35 -- .../src/views/apps/term/components/line.tsx | 66 -- .../src/views/apps/term/css/custom.css | 16 - pkg/interface/src/views/apps/term/store.tsx | 94 --- .../src/views/apps/term/subscription.tsx | 87 --- pkg/npm/api/term/index.ts | 2 + pkg/npm/api/term/lib.ts | 22 + pkg/npm/api/term/types.ts | 60 ++ pkg/urbit/compat/posix/ptty.c | 3 + pkg/urbit/configure | 2 +- pkg/urbit/daemon/main.c | 4 +- pkg/urbit/include/c/motes.h | 3 + pkg/urbit/include/vere/vere.h | 49 +- pkg/urbit/jets/c/rep.c | 2 +- pkg/urbit/jets/c/rip.c | 2 +- pkg/urbit/jets/e/argon2.c | 2 +- pkg/urbit/jets/e/jam.c | 6 +- pkg/urbit/jets/e/rub.c | 2 +- pkg/urbit/jets/e/secp.c | 2 +- pkg/urbit/jets/f/core.c | 2 +- pkg/urbit/jets/f/look.c | 2 +- pkg/urbit/noun/allocate.c | 16 +- pkg/urbit/noun/events.c | 20 +- pkg/urbit/noun/jets.c | 42 +- pkg/urbit/noun/log.c | 2 + pkg/urbit/noun/manage.c | 36 +- pkg/urbit/noun/nock.c | 2 +- pkg/urbit/noun/trace.c | 6 +- pkg/urbit/noun/vortex.c | 8 +- pkg/urbit/vere/auto.c | 8 +- pkg/urbit/vere/dawn.c | 46 +- pkg/urbit/vere/disk.c | 10 +- pkg/urbit/vere/foil.c | 4 +- pkg/urbit/vere/io/ames.c | 96 +-- pkg/urbit/vere/io/behn.c | 4 +- pkg/urbit/vere/io/cttp.c | 10 +- pkg/urbit/vere/io/fore.c | 14 +- pkg/urbit/vere/io/hind.c | 4 +- pkg/urbit/vere/io/http.c | 74 +-- pkg/urbit/vere/io/term.c | 581 ++++++++++-------- pkg/urbit/vere/io/unix.c | 102 +-- pkg/urbit/vere/king.c | 46 +- pkg/urbit/vere/lord.c | 12 +- pkg/urbit/vere/newt.c | 2 +- pkg/urbit/vere/pier.c | 97 +-- pkg/urbit/vere/save.c | 2 +- pkg/urbit/vere/walk.c | 14 +- pkg/urbit/worker/serf.c | 14 +- 84 files changed, 2387 insertions(+), 1764 deletions(-) create mode 100644 pkg/arvo/lib/dill.hoon create mode 100644 pkg/arvo/mar/herm/task.hoon create mode 100644 pkg/arvo/sur/herm.hoon delete mode 100644 pkg/interface/src/logic/lib/bel.js create mode 100644 pkg/interface/src/logic/lib/bel.ts create mode 100644 pkg/interface/src/logic/state/term.ts delete mode 100644 pkg/interface/src/views/apps/term/api.tsx delete mode 100644 pkg/interface/src/views/apps/term/components/history.tsx delete mode 100644 pkg/interface/src/views/apps/term/components/line.tsx delete mode 100644 pkg/interface/src/views/apps/term/css/custom.css delete mode 100644 pkg/interface/src/views/apps/term/store.tsx delete mode 100644 pkg/interface/src/views/apps/term/subscription.tsx create mode 100644 pkg/npm/api/term/index.ts create mode 100644 pkg/npm/api/term/lib.ts create mode 100644 pkg/npm/api/term/types.ts diff --git a/bin/brass.pill b/bin/brass.pill index 6b9140a68..034893638 100644 --- a/bin/brass.pill +++ b/bin/brass.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8c497bba51152dc3e54463a9f33c02876345419457a2f0ce2f15810db9daac72 -size 5041231 +oid sha256:f70a6e20ac6fd7dfb620f7ace725c5b031d040c0fe97caab251233ba31bc9819 +size 5155717 diff --git a/bin/ivory.pill b/bin/ivory.pill index 86a18b8b4..0f3973589 100644 --- a/bin/ivory.pill +++ b/bin/ivory.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5c6ad04e9c83caf6667ef12f4ba9627e9d409381fc4cd151dd2964faed105f8a -size 1148833 +oid sha256:c871af4da5d779a2ccc8a8187ca06e2ccf19a984db9bede7f2d721fa43525210 +size 1259429 diff --git a/bin/solid.pill b/bin/solid.pill index a25dae6d3..2c88500aa 100644 --- a/bin/solid.pill +++ b/bin/solid.pill @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3cc76dec0e5110e35647a8a7341c5c1648d33eab636c067b4ce5893d13af86d8 -size 6755088 +oid sha256:5f97a6c105b89973b6f7ee2bace9f0aff018efb65db7a3b90948761abb8c6b18 +size 6876039 diff --git a/pkg/arvo/app/herm.hoon b/pkg/arvo/app/herm.hoon index cd791b2af..7be319b95 100644 --- a/pkg/arvo/app/herm.hoon +++ b/pkg/arvo/app/herm.hoon @@ -1,7 +1,13 @@ :: herm: stand-in for term.c with http interface :: +/- herm /+ default-agent, dbug, verb -=, jael +:: keep relevant mark conversions in cache for performance +:: +/$ bj %blit %json +/$ jb %json %belt +/$ jt %json %herm-task +:: |% +$ state-0 [%0 ~] -- @@ -12,17 +18,9 @@ %- agent:dbug ^- agent:gall => |% - ++ request-tube - |= [bowl:gall from=mark to=mark next=?] - ^- card:agent:gall - :* %pass /tube/[from]/[to] - %arvo %c %warp - our q.byk ~ - :: - ?: next - [%next %c da+now /[from]/[to]] - [%sing %c da+now /[from]/[to]] - == + ++ pass-session + |= [ses=@tas tas=session-task:dill] + [%pass /dill/[ses] %arvo %d %shot ses tas] -- |_ =bowl:gall +* this . @@ -30,14 +28,7 @@ :: ++ on-init ^- (quip card:agent:gall _this) - :_ this - :: set up dill session subscription, - :: and ensure the tubes we use are in cache - :: - :~ [%pass [%view %$ ~] %arvo %d %view ~] - (request-tube bowl %blit %json |) - (request-tube bowl %json %belt |) - == + [~ this] :: ++ on-save !>([%0 ~]) ++ on-load @@ -48,54 +39,70 @@ ++ on-watch |= =path ^- (quip card:agent:gall _this) - ?> ?=([%session @ ~] path) :_ this - :: scry prompt and cursor position out of dill for initial response - :: - =/ 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)))] + ?> ?=([%session @ ~] path) + =* ses i.t.path + :~ :: subscribe to the requested session + :: + ::NOTE multiple views do not result in multiple subscriptions + :: because they go over the same wire/duct + :: + (pass-session ses %view ~) + :: tell session to refresh, so new client knows what's on screen + ::TODO should client be responsible for this? + :: + (pass-session ses %hail ~) == :: ++ on-arvo |= [=wire =sign-arvo] ^- (quip card:agent:gall _this) + ~| wire ?+ wire !! :: 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 %$ ~]~ %blit !>(blit)] + [%give %fact [%session ses ~]~ %blit !>(blit)] :: - :: ensure the tubes we need remain in cache + :: clean up old-style subscriptions :: - [%tube @ @ ~] - =* from i.t.wire - =* to i.t.t.wire - ?. ?=([%clay %writ *] sign-arvo) - ~| [%unexpected-sign [- +<]:sign-arvo] - !! + [%view @ ~] + =* ses i.t.wire :_ this - [(request-tube bowl from to &)]~ + [%pass wire %arvo %d %shot ses %flee ~]~ == :: ++ on-poke |= [=mark =vase] ^- (quip card:agent:gall _this) - ?. ?=(%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 -- diff --git a/pkg/arvo/app/hood.hoon b/pkg/arvo/app/hood.hoon index 13410cda9..753560969 100644 --- a/pkg/arvo/app/hood.hoon +++ b/pkg/arvo/app/hood.hoon @@ -2,7 +2,7 @@ /+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln |% +$ state - $: %15 + $: %16 drum=state:drum helm=state:helm kiln=state:kiln @@ -10,14 +10,15 @@ +$ any-state $% state [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)] - [%7 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%8 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%9 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%10 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%11 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%12 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%13 drum=state:drum helm=state:helm kiln=state-1:kiln] - [%14 drum=state:drum helm=state:helm kiln=state:kiln] + [%7 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%8 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%9 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%10 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%11 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%12 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%13 drum=any-state:drum helm=state:helm kiln=state-1:kiln] + [%14 drum=any-state:drum helm=state:helm kiln=state:kiln] + [%15 drum=any-state:drum helm=state:helm kiln=state:kiln] == +$ any-state-tuple $: drum=any-state:drum @@ -83,8 +84,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) == @@ -97,7 +97,7 @@ |= =path ^- step:agent:gall ?+ path (on-watch:def +<) - [%drum *] =^(c drum.state (peer:drum-core +<) [c this]) + [%dill *] =^(c drum.state (peer:drum-core +<) [c this]) == :: ++ on-agent @@ -114,7 +114,6 @@ |= [=wire syn=sign-arvo] ^- step:agent:gall ?+ wire ~|([%hood-bad-wire wire] !!) - [%drum *] =^(c drum.state (take-arvo:drum-core t.wire syn) [c this]) [%helm *] =^(c helm.state (take-arvo:helm-core t.wire syn) [c this]) [%kiln *] =^(c kiln.state (take-arvo:kiln-core t.wire syn) [c this]) == diff --git a/pkg/arvo/gen/aqua/dojo.hoon b/pkg/arvo/gen/aqua/dojo.hoon index 03d63f505..d9ef58a1d 100644 --- a/pkg/arvo/gen/aqua/dojo.hoon +++ b/pkg/arvo/gen/aqua/dojo.hoon @@ -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 ~] == diff --git a/pkg/arvo/lib/dill.hoon b/pkg/arvo/lib/dill.hoon new file mode 100644 index 000000000..d4cecdf14 --- /dev/null +++ b/pkg/arvo/lib/dill.hoon @@ -0,0 +1,93 @@ +:: 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 'r'^(numb r.p.blit) 'c'^(numb c.p.blit) ~) + %put a+(turn p.blit |=(c=@c s+(tuft c))) + %nel b+& + %url s+p.blit + %wyp b+& + :: + %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 'r'^ni 'c'^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) + -- + -- +-- \ No newline at end of file diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 01b1b2919..1a3f3e73b 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -1,14 +1,14 @@ /- *sole /+ sole |% -+$ any-state $%(state) -+$ state [%2 pith-2] ++$ any-state $%(state state-2) ++$ state [%3 pith] :: -++ pith-2 :: +++ pith :: $: eel=(set gill:gall) :: connect to ray=(set well:gall) :: fur=(map dude:gall (unit server)) :: servers - bin=(map bone source) :: terminals + bin=(map @ source) :: terminals == :: :: :: ++ server :: running server @@ -49,6 +49,42 @@ pom=sole-prompt :: static prompt inp=sole-command :: input state == :: +:: +:: ++$ state-2 [%2 pith-2] +:: ++$ pith-2 + $: eel=(set gill:gall) + ray=(set well:gall) + fur=(map dude:gall (unit server)) + bin=(map bone source-2) + == +:: ++$ source-2 + $: edg=_80 + off=@ud + kil=kill + inx=@ud + fug=(map gill:gall (unit target-2)) + mir=(pair @ud stub) + == +:: ++$ target-2 + $: $= blt + %+ pair + (unit dill-belt-2) + (unit dill-belt-2) + ris=(unit search) + hit=history + pom=sole-prompt + inp=sole-command + == +:: ++$ dill-belt-2 + $% [%ctl p=@c] + [%met p=@c] + dill-belt:dill + == -- :: :: :: :::: :: :: @@ -121,26 +157,34 @@ ++ en-gill :: gill to wire |= gyl=gill:gall ^- wire + ::TODO include session? [%drum %phat (scot %p p.gyl) q.gyl ~] :: ++ de-gill :: gill from wire |= way=wire ^- gill:gall ?>(?=([@ @ ~] 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) |% ++ this . +++ klr klr:format +$ state ^state :: proxy +$ any-state ^any-state :: proxy ++ on-init se-abet:this(eel (deft-fish our.hid)) +:: +++ prep + |= s=@tas + =. ses ses + =. dev (~(gut by bin) ses *source) + this +:: ++ diff-sole-effect-phat :: app event |= [way=wire fec=sole-effect] =< se-abet =< se-view @@ -150,6 +194,8 @@ :: ++ 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 @@ -166,15 +212,15 @@ =. ray (deft-apes our.hid lit) [~ sat] :: +++ 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-belt bet) :: -++ poke-dill-blit :: terminal output - |= bit=dill-blit:dill - se-abet:(se-blit-sys bit) -:: ++ poke-start :: start app |= wel=well:gall =< se-abet =< se-view @@ -206,8 +252,7 @@ ++ poke |= [=mark =vase] ?+ 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) @@ -218,53 +263,89 @@ == :: ++ on-load - |= [hood-version=@ud old=any-state] - =< se-abet =< se-view - =. sat old - =. dev (~(gut by bin) ost *source) - =? ..on-load (lte hood-version %4) - ~> %slog.0^leaf+"drum: starting os1 agents" - => (se-born | %home %s3-store) - => (se-born | %home %contact-view) - => (se-born | %home %contact-hook) - => (se-born | %home %contact-store) - => (se-born | %home %metadata-hook) - => (se-born | %home %metadata-store) - => (se-born | %home %goad) - ~> %slog.0^leaf+"drum: resubscribing to %dojo and %chat-cli" - => (se-drop:(se-pull our.hid %dojo) | our.hid %dojo) - (se-drop:(se-pull our.hid %chat-cli) | our.hid %chat-cli) - =? ..on-load (lte hood-version %5) - (se-born | %home %file-server) - =? ..on-load (lte hood-version %7) - (se-born | %home %glob) - =? ..on-load (lte hood-version %8) - => (se-born | %home %group-push-hook) - (se-born | %home %group-pull-hook) - =? ..on-load (lte hood-version %9) - (se-born | %home %graph-store) - =? ..on-load (lte hood-version %10) - => (se-born | %home %graph-push-hook) - (se-born | %home %graph-pull-hook) - =? ..on-load (lte hood-version %11) - => (se-born | %home %hark-graph-hook) - => (se-born | %home %hark-group-hook) - => (se-born | %home %hark-chat-hook) - => (se-born | %home %hark-store) - => (se-born | %home %observe-hook) - => (se-born | %home %metadata-pull-hook) - => (se-born | %home %metadata-push-hook) - (se-born | %home %herm) - =? ..on-load (lte hood-version %12) - => (se-born | %home %contact-push-hook) - => (se-born | %home %contact-pull-hook) - => (se-born | %home %settings-store) - (se-born | %home %group-view) - =? ..on-load (lte hood-version %13) - (se-born | %home %dm-hook) - =? ..on-load (lte hood-version %15) - (se-born | %home %notify) - ..on-load + |^ |= [hood-version=@ud old=any-state] + =< se-abet =< se-view + =. sat (load-state old) + =. dev (~(gut by bin) ses *source) + (load-apps hood-version) + :: + ++ load-state + |= old=any-state + ^- state + ?- -.old + %3 old + %2 [%3 (pith-2-to-3 +.old)] + == + :: + ++ pith-2-to-3 + |= p=pith-2 + ^- pith + p(bin (~(run by bin.p) source-2-to-3)) + :: + ++ source-2-to-3 + |= s=source-2 + ^- source + s(fug (~(run by fug.s) |=(t=(unit target-2) (bind t target-2-to-3)))) + :: + ++ target-2-to-3 + |= t=target-2 + ^- target + :_ +.t + :- (bind p.blt.t belt-2-to-3) + (bind q.blt.t belt-2-to-3) + :: + ++ belt-2-to-3 + |= b=dill-belt-2 + ^- dill-belt:dill + ?. ?=(?(%ctl %met) -.b) b + [%mod -.b p.b] + :: + ++ load-apps + |= hood-version=@ud + =? ..on-load (lte hood-version %4) + ~> %slog.0^leaf+"drum: starting os1 agents" + => (se-born | %home %s3-store) + => (se-born | %home %contact-view) + => (se-born | %home %contact-hook) + => (se-born | %home %contact-store) + => (se-born | %home %metadata-hook) + => (se-born | %home %metadata-store) + => (se-born | %home %goad) + ~> %slog.0^leaf+"drum: resubscribing to %dojo and %chat-cli" + => (se-drop:(se-pull our.hid %dojo) | our.hid %dojo) + (se-drop:(se-pull our.hid %chat-cli) | our.hid %chat-cli) + =? ..on-load (lte hood-version %5) + (se-born | %home %file-server) + =? ..on-load (lte hood-version %7) + (se-born | %home %glob) + =? ..on-load (lte hood-version %8) + => (se-born | %home %group-push-hook) + (se-born | %home %group-pull-hook) + =? ..on-load (lte hood-version %9) + (se-born | %home %graph-store) + =? ..on-load (lte hood-version %10) + => (se-born | %home %graph-push-hook) + (se-born | %home %graph-pull-hook) + =? ..on-load (lte hood-version %11) + => (se-born | %home %hark-graph-hook) + => (se-born | %home %hark-group-hook) + => (se-born | %home %hark-chat-hook) + => (se-born | %home %hark-store) + => (se-born | %home %observe-hook) + => (se-born | %home %metadata-pull-hook) + => (se-born | %home %metadata-push-hook) + (se-born | %home %herm) + =? ..on-load (lte hood-version %12) + => (se-born | %home %contact-push-hook) + => (se-born | %home %contact-pull-hook) + => (se-born | %home %settings-store) + (se-born | %home %group-view) + =? ..on-load (lte hood-version %13) + (se-born | %home %dm-hook) + =? ..on-load (lte hood-version %15) + (se-born | %home %notify) + ..on-load + -- :: ++ reap-phat :: ack connect |= [way=wire saw=(unit tang)] @@ -277,12 +358,6 @@ :: (se-drop & gyl) :: -++ take-arvo - |= [=wire =sign-arvo] - %+ take-onto wire - ?> ?=(%onto +<.sign-arvo) - +>.sign-arvo -:: ++ take-coup-phat :: ack poke |= [way=wire saw=(unit tang)] =< se-abet =< se-view @@ -293,19 +368,6 @@ :_ u.saw >[%drum-coup-fail src.hid gyl]< :: -++ take-onto :: ack start - |= [way=wire saw=(each suss:gall tang)] - =< se-abet =< se-view - ?> ?=([@ @ ~] way) - ?> (~(has by fur) i.t.way) - =/ wel=well:gall [i.way i.t.way] - ?- saw - [%| *] (se-dump p.saw) - [%& *] ?> =(q.wel p.p.saw) - :: =. +>.$ (se-text "live {}") - +>.$(fur (~(put by fur) q.wel `[p.wel %da r.p.saw])) - == -:: ++ take-agent |= [=wire =sign:agent:gall] ?+ wire ~|([%drum-bad-take-agent wire -.sign] !!) @@ -333,12 +395,13 @@ ++ se-abet :: resolve ^- (quip card:agent:gall state) =. . se-subze:se-adze:se-subit:se-adit - :_ sat(bin (~(put by bin) ost dev)) + :_ 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)] + ::TODO remove /drum after dill cleans up + [%give %fact ~[/drum /dill/[ses]] %dill-blit !>(dill-blit)] :: ++ se-adit :: update servers ^+ this @@ -423,14 +486,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) ses dev.xeno)) :: ++ se-subze-local ^+ . @@ -445,7 +508,7 @@ ++ se-aint :: ignore result |= gyl=gill:gall ^- ? - ?. (~(has by bin) ost) & + ?. (~(has by bin) ses) & =+ gyr=(~(get by fug) gyl) |(?=(~ gyr) ?=(~ u.gyr)) :: @@ -554,6 +617,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) ^+ +> @@ -564,7 +642,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 @@ -597,15 +675,16 @@ :: ++ 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))] @@ -643,7 +722,7 @@ ?. ((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] @@ -651,6 +730,7 @@ :: ++ se-peer :: send a peer |= gyl=gill:gall + ::TODO include session =/ =path /sole/(cat 3 'drum_' (scot %p our.hid)) %- se-emit(fug (~(put by fug) gyl ~)) [%pass (en-gill gyl) %agent gyl %watch path] @@ -711,13 +791,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 @@ -741,7 +827,7 @@ (ta-hom %del (dec pos.inp)) :: ++ ta-ctl :: hear control - |= key=@ud + |= key=bolt:dill ^+ +> =. ris ?.(?=(?(%g %r) key) ~ ris) ?+ key ta-bel @@ -762,7 +848,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 @@ -795,6 +881,15 @@ ta-bel (ta-hom %del pos.inp) :: + ++ ta-hit :: hear click + |= [r=@ud c=@ud] + ^+ +> + ?. =(0 r) +> + =/ pol=@ud + (lent-char:klr (make:klr cad.pom)) + ?: (lth c pol) +>.$ + +>.$(pos.inp (min (sub c pol) (lent buf.say.inp))) + :: ++ ta-erl :: hear local error |= pos=@ud ta-bel(pos.inp (min pos (lent buf.say.inp))) @@ -806,14 +901,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)) @@ -821,10 +915,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 @@ -876,8 +968,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) @@ -894,17 +986,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]) @@ -960,8 +1053,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) @@ -1139,82 +1232,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)) - -- -- diff --git a/pkg/arvo/lib/ph/util.hoon b/pkg/arvo/lib/ph/util.hoon index 53979b425..46e47947e 100644 --- a/pkg/arvo/lib/ph/util.hoon +++ b/pkg/arvo/lib/ph/util.hoon @@ -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)) == diff --git a/pkg/arvo/mar/belt.hoon b/pkg/arvo/mar/belt.hoon index 1c5a6e1ea..acbf284c9 100644 --- a/pkg/arvo/mar/belt.hoon +++ b/pkg/arvo/mar/belt.hoon @@ -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 :: diff --git a/pkg/arvo/mar/blit.hoon b/pkg/arvo/mar/blit.hoon index 4c23c5705..4b852aa60 100644 --- a/pkg/arvo/mar/blit.hoon +++ b/pkg/arvo/mar/blit.hoon @@ -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) -- -- diff --git a/pkg/arvo/mar/dill/belt.hoon b/pkg/arvo/mar/dill/belt.hoon index 1677b6ef1..5d50dcd98 100644 --- a/pkg/arvo/mar/dill/belt.hoon +++ b/pkg/arvo/mar/dill/belt.hoon @@ -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))] diff --git a/pkg/arvo/mar/dill/blit.hoon b/pkg/arvo/mar/dill/blit.hoon index 77e5cecf4..5ec9b08cb 100644 --- a/pkg/arvo/mar/dill/blit.hoon +++ b/pkg/arvo/mar/dill/blit.hoon @@ -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 'r'^(numb r.p.dib) 'c'^(numb c.p.dib) ~) + %put (frond -.dib (tape (tufa p.dib))) ?(%bel %clr) (frond %act %s -.dib) == -- diff --git a/pkg/arvo/mar/herm/task.hoon b/pkg/arvo/mar/herm/task.hoon new file mode 100644 index 000000000..93757418e --- /dev/null +++ b/pkg/arvo/mar/herm/task.hoon @@ -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 + -- +-- diff --git a/pkg/arvo/sur/herm.hoon b/pkg/arvo/sur/herm.hoon new file mode 100644 index 000000000..eab8cbb1b --- /dev/null +++ b/pkg/arvo/sur/herm.hoon @@ -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) + == +-- diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index e20f41ec9..ea7757413 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -741,7 +741,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 [%writ p=riot] :: response @@ -1031,9 +1030,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 @@ -1041,29 +1038,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) @@ -1071,14 +1071,10 @@ +$ 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 @@ -1087,43 +1083,29 @@ [%hit r=@ud c=@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 [r=@ud c=@ud])] :: set cursor col/pos + [%klr p=stub] :: put styled + [%put p=(list @c)] :: put text at cursor + [%nel ~] :: newline [%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 + +$ dill-blit :: arvo output + $% blit :: client output [%mor p=(list dill-blit)] :: multiple blits - [%pom p=stub] :: styled prompt - [%pro p=(list @c)] :: show as cursor+line [%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 @@ -1134,6 +1116,11 @@ [%text p=tape] :: [%verb ~] :: verbose mode == :: + :: :: + +$ poke :: dill to userspace + $: ses=@tas :: target session + dill-belt :: input + == :: -- ::dill :: :::: :::: ++eyre :: (1e) http-server @@ -1634,7 +1621,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=sign:agent] :: == :: +$ task :: incoming request @@ -2163,9 +2149,6 @@ :: %ames: hear packet :: $>(%hear task:ames) - :: %dill: hangup - :: - $>(%hook task:dill) :: %clay: external edit :: $>(%into task:clay) @@ -2181,6 +2164,9 @@ :: %eyre: starts handling an backdoor http request :: $>(%request-local task:eyre) + :: %dill: close session + :: + $>(%shut task:dill) :: %behn: wakeup :: $>(%wake task:behn) diff --git a/pkg/arvo/sys/vane/clay.hoon b/pkg/arvo/sys/vane/clay.hoon index 2f2281e4b..06fecce26 100644 --- a/pkg/arvo/sys/vane/clay.hoon +++ b/pkg/arvo/sys/vane/clay.hoon @@ -319,7 +319,10 @@ task :: == :: $: %d :: to %dill - $>(%flog task:dill) :: + $> $? %flog :: + %text :: + == :: + task:dill :: == :: $: %g :: to %gall $>(%deal task:gall) :: @@ -343,7 +346,6 @@ == == :: $: %clay :: $> $? %mere :: - %note :: %writ :: == :: gift :: @@ -1890,7 +1892,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 @@ -4788,7 +4791,6 @@ q.p.p.+.hin [~ ..^$] :: - %note [[hen %give +.hin]~ ..^$] %wake :: TODO: handle behn errors :: diff --git a/pkg/arvo/sys/vane/dill.hoon b/pkg/arvo/sys/vane/dill.hoon index fa15461fe..5423e60d4 100644 --- a/pkg/arvo/sys/vane/dill.hoon +++ b/pkg/arvo/sys/vane/dill.hoon @@ -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 $-> @@ -72,7 +70,6 @@ == == :: $: %clay :: $> $? %mere :: - %note :: %writ :: == :: gift:clay :: @@ -81,10 +78,7 @@ $>(%blit gift:dill) :: == :: $: %gall :: - $> $? %onto :: - %unto :: - == :: - gift:gall :: + $>(%unto gift:gall) :: == == :: :::::::: :: dill tiles -- @@ -94,39 +88,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)) + %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 %rez p.p.kyz q.p.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) - :: - %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]) == :: ++ crud @@ -136,30 +118,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 @@ -170,6 +152,30 @@ |= [=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 ^+ +> @@ -177,34 +183,6 @@ |- ^+ +>.^$ ?~ 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 ~]) @@ -241,18 +219,33 @@ =. tem `(turn gyl |=(a=gill [%yow a])) (pass / [%c %warp our %home `[%sing %y [%ud 1] /]]) :: + ++ open + |= gyl=(list gill) + =. +> (pass / %g %conf ram) + =. +> peer + %+ roll gyl + |= [g=gill _..open] + (send [%yow g]) + :: + ++ shut + ::TODO send a %bye blit? + pull(eye.all (~(del by eye.all) ses)) + :: ++ 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])]]) :: ++ hood-set-boot-apps (deal / [%poke %drum-set-boot-apps !>(lit.all)]) :: ++ peer - (deal / [%watch /drum]) + (deal /peer/[ses] %watch /dill/[ses]) + :: + ++ pull + (deal /peer/[ses] %leave ~) :: ++ show :: permit reads on desk |= des=desk @@ -266,13 +259,6 @@ |= [tea=wire sih=sign] ^+ +> ?- sih - [%gall %onto *] - :: ~& [%take-gall-onto +>.sih] - ?- -.+>.sih - %| (crud %onto p.p.+>.sih) - %& (done %blit [%lin (tuba "{}")]~) - == - :: [%gall %unto *] :: ~& [%take-gall-unto +>.sih] ?- -.+>.sih @@ -288,9 +274,6 @@ +>.$ (from ;;(dill-blit q.q.cage.p.+>.sih)) == - :: - [%clay %note *] - (from %out (tuba p.sih ' ' ~(ram re q.sih))) :: [?(%behn %clay) %writ *] init @@ -305,12 +288,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 @@ -321,7 +312,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) @@ -351,10 +345,11 @@ :: =* duc (need hey.all) =/ app %hood - =/ see (tuba "") - =/ zon=axon [app input=[~ ~] width=80 cursor=(lent see) lin+see] + =/ say (tuba "") + =/ 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 :: @@ -375,35 +370,55 @@ ?: ?=(%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)) + =^ moz all abet:shut:nus + [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)) ~) ..^$] :: @@ -411,8 +426,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 @@ -441,19 +511,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 @@ -464,12 +527,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 ..^$] diff --git a/pkg/arvo/sys/vane/gall.hoon b/pkg/arvo/sys/vane/gall.hoon index a71b0dd8a..65fc1b266 100644 --- a/pkg/arvo/sys/vane/gall.hoon +++ b/pkg/arvo/sys/vane/gall.hoon @@ -266,12 +266,22 @@ :: +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-pass |=(p=[wire note-arvo] mo-core(moves [[hen pass+p] moves])) ++ 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-boot: ask %ford to build us a core for the specified agent. :: ++ mo-boot @@ -349,12 +359,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-subscribe-to-agent-builds: request agent update notices :: :: Also subscribe to our own source path, in case we get reloaded @@ -544,7 +554,7 @@ ++ fail |= =tang ^+ mo-core - =. mo-core (mo-give %onto |+tang) + =. mo-core (mo-pass (mo-talk |+tang)) =/ =case [%da tim] =/ =wire /sys/cor/[dap]/[her]/[desk]/(scot case) (mo-pass wire %c %warp p.beak desk ~ %next %a case /app/[dap]/hoon) @@ -1019,8 +1029,8 @@ :: =/ running (~(put by yokes.state) agent-name current-agent) =/ 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 diff --git a/pkg/arvo/sys/vane/jael.hoon b/pkg/arvo/sys/vane/jael.hoon index ddc225d03..f97f4cc46 100644 --- a/pkg/arvo/sys/vane/jael.hoon +++ b/pkg/arvo/sys/vane/jael.hoon @@ -107,11 +107,8 @@ $>(%wake gift:behn) :: == :: $: %gall :: - $> $? %onto :: - %unto :: - == :: - gift:gall :: - == + $>(%unto gift:gall) :: + == :: == :: -- :: :: :::: @@ -557,10 +554,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 diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 8a0056bcc..ee263eee5 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -3729,6 +3729,107 @@ ~ (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 + =+ c=(lnts-char b) + =+ i=(brek a c) + ?~ i ~ + =+ 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 + |= [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 + |= [[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 -- :: :: :::: ++differ :: (2d) hunt-mcilroy diff --git a/pkg/arvo/ted/aqua/dill.hoon b/pkg/arvo/ted/aqua/dill.hoon index 4d3b7b2e4..7ce9ff073 100644 --- a/pkg/arvo/ted/aqua/dill.hoon +++ b/pkg/arvo/ted/aqua/dill.hoon @@ -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 ~& "{}: {line}" "" + %nel ~& "{}: {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 ~ diff --git a/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs b/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs index 5a5782912..6037e0298 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Arvo/Effect.hs @@ -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 diff --git a/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs b/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs index d2f316a53..50ef1ac1f 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Arvo/Event.hs @@ -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 = diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs index 24e7bb7ff..a3b0f72a2 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Pier.hs @@ -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 diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs index dc49043fe..ccd4c676d 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term.hs @@ -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,31 +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 - "d" -> atomically doneSignal - 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 } @@ -644,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 () diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs index 7e65d49e5..d6b6fde60 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/API.hs @@ -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 diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs index 770742a68..748b3fa5a 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Logic.hs @@ -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 ()] diff --git a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs index 3765f9cb2..c3b778f43 100644 --- a/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs +++ b/pkg/hs/urbit-king/lib/Urbit/Vere/Term/Render.hs @@ -4,9 +4,12 @@ module Urbit.Vere.Term.Render ( clearScreen , clearLine - , cursorRight - , cursorLeft , soundBell + , cursorMove + , cursorSave + , cursorRestore + , putCsi + , hijack ) where import ClassyPrelude @@ -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 diff --git a/pkg/interface/package-lock.json b/pkg/interface/package-lock.json index 39a1f4c99d7bbff9730b3aebe548280fd4fbd553..9f6f63c6dd5b1b6323464554449ec93b41db9e35 100644 GIT binary patch literal 1363532 zcmeFaX_Knj(k}Y_{)!#ztG6bgqIe=s#1TQTK@p_U4=V!cmA+Bn#QE=c*kfB-vuf@Y z=dL$mzpJJ+Imjowkt0Wr|NZ~`=RbdWimU(iKmPNV?In6-D60O~|GWKptw*u#d)q6> zFZdU{|JCu;m0>%&c)E)0?vC^@wIe+SwF$5NCRjTV+&u!`>pN>*+m6Lbk|6#c5ESXA9Vb!#%M09P{L7C_=;F=L$Bw`U z@(aA`S7H{s@$X)@{ZKQqlYINW*iulW`jKUc40kq~wZMj|sU${!<*&jiHYnJ&+FNXf ztt=P{aLXHS@Iv8}h2g^5$Wvn$X6k8NAp@V)q`bLa6au>D$8>Yh2+aTaKhIP(eSKig zjt~E5%c3$nOgpjC#RG=aPY8U8A^Ud&mhAud*uCy^rjSc$RwXN<*oe87+zg~4+O3Hu zDMf8unO0j>f(tpJ!PPBqvSgDER1h^!F*8wBH3%%h$HT|JUDpsCMA~=Rg1F zKGv5Xas13{l|zuz2mn{!Q-Kl%0DI|QKq25?2=Y1jA~&O{iHJm@$Bp};#;hq}F@pvk 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%0DK0-=)ERyq8W% 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%0ABqp+DF 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 n6Sl<6|BxCQd9z5Kj=taO$oqy6ON)y0nzkKJ= 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 bxIfcA84l`m>YjI^7o!0F```ca-~aMImqcgt literal 882585 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

m)-o=I(DsV#=^Qeq}rNsYTyCt9~L^`2{T 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%0D(w+DMpc-V4sr8v?EDqV8ZB)zEW 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

Loading...

+ : + + + + + ); +} diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx new file mode 100644 index 000000000..0c3f14831 --- /dev/null +++ b/pkg/interface/webterm/Tab.tsx @@ -0,0 +1,44 @@ +import { DEFAULT_SESSION } from './constants'; +import React, { useCallback } from 'react'; +import useTermState from './state'; +import { style } from 'styled-system'; +import api from './api'; +import { pokeTask } from '@urbit/api/term'; + +export const Tab = ( { session, name } ) => { + + const isSelected = useTermState().selected === name; + + const onClick = () => { + console.log('click!', name); + useTermState.getState().set((state) => { + state.selected = name; + state.sessions[name].hasBell = false; + }); + useTermState.getState().sessions[name]?.term?.focus(); + } + + const onDelete = (e) => { + e.stopPropagation(); + api.poke(pokeTask(name, { shut: null })); + useTermState.getState().set(state => { + if (state.selected === name) { + state.selected = DEFAULT_SESSION; + } + state.names = state.names.filter(n => n !== name); + delete state.sessions[name]; + }); + //TODO clean up the subscription + } + + return ( + + ); +}; diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx new file mode 100644 index 000000000..37d64eed5 --- /dev/null +++ b/pkg/interface/webterm/Tabs.tsx @@ -0,0 +1,36 @@ +import { pokeTask } from '@urbit/api/term'; +import api from './api'; +import React from 'react'; +import useTermState from './state'; +import { Tab } from './Tab'; + +export const Tabs = () => { + const { sessions, names } = useTermState(); + + const onAddClick = () => { + const name = prompt('please entew a session name uwu'); + if (!name) { + return; + } + //TODO name must be @ta + api.poke(pokeTask(name, { open: { term: 'hood', apps: [{ who: '~'+(window as any).ship, app: 'dojo' }] } })); + useTermState.getState().set(state => { + state.names = [name, ...state.names].sort(); + state.selected = name; + state.sessions[name] = null; + }); + + + } + + return ( +
+ { names.map((n, i) => { + return ( + + ); + })} + +
+ ); +}; diff --git a/pkg/interface/webterm/app.tsx b/pkg/interface/webterm/app.tsx index 8b0dd65a6..d7c782f29 100644 --- a/pkg/interface/webterm/app.tsx +++ b/pkg/interface/webterm/app.tsx @@ -1,292 +1,42 @@ /* eslint-disable max-lines */ import React, { - useEffect, - useRef, - useCallback + useCallback, useEffect } from 'react'; -import useTermState from './state'; +import useTermState, { Sessions } 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 { Reset, _dark, _light } from '@tlon/indigo-react'; import 'xterm/css/xterm.css'; import { - Belt, Blit, Stye, Stub, Tint, Deco, - pokeTask, pokeBelt + scrySessions } from '@urbit/api/term'; -import bel from './lib/bel'; import { ThemeProvider } from 'styled-components'; +import { Tabs } from './Tabs'; +import Buffer from './Buffer'; +import { DEFAULT_SESSION } from './constants'; +import { showSlog } from './lib/blit'; 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 - }; -}; - -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 -}; - -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) { - 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); -}; - -// 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({ 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: { 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(null); - // TODO allow switching of selected - const { sessions, selected, slogstream, set } = useTermState(); - const session = sessions[selected]; + const { names, selected } = useTermState(); const dark = useDark(); + const initSessions = useCallback(async () => { + const response = await api.scry(scrySessions()); + + useTermState.getState().set((state) => { + state.names = response.sort(); + }); + }, []); + const setupSlog = useCallback(() => { console.log('slog: setting up...'); let available = false; @@ -298,9 +48,10 @@ export default function TermApp(props: TermAppProps) { }; slog.onmessage = (e) => { - const session = useTermState.getState().sessions['']; + const session = useTermState.getState().sessions[DEFAULT_SESSION]; if (!session) { - console.log('default session mia!', 'slog:', slog); + console.log('slog: default session mia!', 'msg:', e.data); + console.log(Object.keys(useTermState.getState().sessions), session); return; } showSlog(session.term, e.data); @@ -319,131 +70,26 @@ export default function TermApp(props: TermAppProps) { } }; - set((state) => { + useTermState.getState().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) => { - api.poke(pokeBelt(ses, 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) => { - 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]); + initSessions(); + setupSlog(); + }, []); return ( <> - - - - + +
+ {names.map(name => { + return ; + })} +
); diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts new file mode 100644 index 000000000..23cbd3497 --- /dev/null +++ b/pkg/interface/webterm/constants.ts @@ -0,0 +1 @@ +export const DEFAULT_SESSION = ''; diff --git a/pkg/interface/webterm/index.html b/pkg/interface/webterm/index.html index 5eaf05c35..ed7f86111 100644 --- a/pkg/interface/webterm/index.html +++ b/pkg/interface/webterm/index.html @@ -27,6 +27,44 @@ margin: 0; padding: 0; } + + .buffer-container { + height: calc(100% - 33px); + } + + div.tabs { + height: 33px; + display: flex; + flex-flow: row nowrap; + justify-content: flex-start; + padding: 5px 0; + border-bottom: 1px solid black; + } + + div.tabs > * { + margin-left: 5px; + margin-right: 5px; + border: solid 1px black; + padding: 7px; + cursor: pointer; + } + + div.tab { + text-align: center; + /* display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: space-between; */ + } + + div.tabs > div.selected > a.session-name { + font-weight: bold; + } + + div.tabs > a.delete-session { + padding: 5px; + } + diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts new file mode 100644 index 000000000..534328433 --- /dev/null +++ b/pkg/interface/webterm/lib/blit.ts @@ -0,0 +1,73 @@ +import { Terminal } from 'xterm'; +import { saveAs } from 'file-saver'; +import { Blit, Stub } 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 ('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) { + 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')); +}; diff --git a/pkg/interface/webterm/lib/stye.ts b/pkg/interface/webterm/lib/stye.ts new file mode 100644 index 000000000..bc2d99b5e --- /dev/null +++ b/pkg/interface/webterm/lib/stye.ts @@ -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'; +}; diff --git a/pkg/interface/webterm/lib/theme.ts b/pkg/interface/webterm/lib/theme.ts new file mode 100644 index 000000000..6044f1c30 --- /dev/null +++ b/pkg/interface/webterm/lib/theme.ts @@ -0,0 +1,21 @@ +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 + }; +}; diff --git a/pkg/interface/webterm/state.ts b/pkg/interface/webterm/state.ts index 253e7854f..2392db880 100644 --- a/pkg/interface/webterm/state.ts +++ b/pkg/interface/webterm/state.ts @@ -3,18 +3,22 @@ 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 } | 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, +} const useTermState = create((set, get) => ({ sessions: {} as Sessions, + names: [''], selected: '', // empty string is default session slogstream: null, theme: 'auto', diff --git a/pkg/interface/webterm/tsconfig.json b/pkg/interface/webterm/tsconfig.json new file mode 100644 index 000000000..9a8642966 --- /dev/null +++ b/pkg/interface/webterm/tsconfig.json @@ -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" + ] +} diff --git a/pkg/npm/api/term/lib.ts b/pkg/npm/api/term/lib.ts index 3d0424099..67e14175f 100644 --- a/pkg/npm/api/term/lib.ts +++ b/pkg/npm/api/term/lib.ts @@ -1,5 +1,5 @@ -import { Scry } from '../http-api/src' -import { Poke } from '../http-api/src/types'; +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 => ({ diff --git a/pkg/npm/api/term/types.ts b/pkg/npm/api/term/types.ts index 502df692f..df4767cff 100644 --- a/pkg/npm/api/term/types.ts +++ b/pkg/npm/api/term/types.ts @@ -53,8 +53,8 @@ export type Belt = 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 From e41263c6532637e641caa51fc23765e3154deb8a Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 2 Mar 2022 22:49:31 -0600 Subject: [PATCH 013/249] dojo: add missing nu-sole-id compatability Forgotten code. --- pkg/arvo/app/dojo.hoon | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index bf0c24dd4..691b30df1 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -1706,14 +1706,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 From 25a1c79aa3f4dd9fc2ce4ee129bb888274129e50 Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 2 Mar 2022 23:25:38 -0600 Subject: [PATCH 014/249] drum: properly hook up new |link More uncommitted code. --- pkg/arvo/lib/hood/drum.hoon | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index f62143e21..001e07324 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -171,21 +171,22 @@ se-abet:(se-blit-sys bit) :: ++ poke-link :: connect app - |= gyl=gill:gall + |= [ses=@tas gyl=gill:gall] =< se-abet - (se-link gyl) + (se-link:(prep ses) gyl) :: ++ poke-unlink :: disconnect app - |= gyl=gill:gall + |= [ses=@ta gyl=gill:gall] =< se-abet - (se-drop:(se-pull gyl) & gyl) + (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 @@ -368,7 +369,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)) From 1a50957950fa9bd972d5e5c00c64428c4f8f9319 Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 3 Mar 2022 16:58:48 -0600 Subject: [PATCH 015/249] ux: session ID input validation When creating a new session, validate that it meets the following conditions: - must start with an alphabetical - can be composed of alphanumerics with hyphens - can be length 1 or longer - cannot begin or end with a hyphen --- pkg/interface/webterm/Tabs.tsx | 11 +++++------ pkg/interface/webterm/constants.ts | 10 ++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx index 37d64eed5..bf3d32b64 100644 --- a/pkg/interface/webterm/Tabs.tsx +++ b/pkg/interface/webterm/Tabs.tsx @@ -3,29 +3,28 @@ import api from './api'; import React from 'react'; import useTermState from './state'; import { Tab } from './Tab'; +import { SESSION_ID_REGEX } from './constants'; export const Tabs = () => { const { sessions, names } = useTermState(); const onAddClick = () => { const name = prompt('please entew a session name uwu'); - if (!name) { + if (!name || !SESSION_ID_REGEX.test(name) || names.includes(name)) { + console.log('invalid session name:', name); return; } - //TODO name must be @ta - api.poke(pokeTask(name, { open: { term: 'hood', apps: [{ who: '~'+(window as any).ship, app: 'dojo' }] } })); + api.poke(pokeTask(name, { open: { term: 'hood', apps: [{ who: '~' + (window as any).ship, app: 'dojo' }] } })); useTermState.getState().set(state => { state.names = [name, ...state.names].sort(); state.selected = name; state.sessions[name] = null; }); - - } return (
- { names.map((n, i) => { + {names.map((n, i) => { return ( ); diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index 23cbd3497..7e173ac64 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -1 +1,11 @@ export const DEFAULT_SESSION = ''; + +/** + * Session ID validity: + * + * - must start with an alphabetical + * - can be composed of alphanumerics with hyphens + * - can be length 1 or longer + * - cannot begin or end with a hyphen + */ +export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d\-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; From fe1ece47d83a35d446722c7bfcc4181468c59a57 Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 3 Mar 2022 17:09:38 -0600 Subject: [PATCH 016/249] api: clean up subscriptions on deletion of session On subscribe, track the subcription ID in the Session state. On deletion, unsubscribe using the same ID. --- pkg/interface/webterm/Buffer.tsx | 6 +++--- pkg/interface/webterm/Tab.tsx | 26 +++++++++++++++++++------- pkg/interface/webterm/state.ts | 7 ++++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index d33b2e9ec..ef65c592b 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -162,7 +162,7 @@ export default function Buffer({ name, selected }: BufferProps) { // term.write(csi('?9h')); - const ses: Session = { term, fit, hasBell: false }; + const ses: Session = { term, fit, hasBell: false, subscriptionId: null }; // set up event handlers // @@ -174,7 +174,7 @@ export default function Buffer({ name, selected }: BufferProps) { // open subscription // - await api.subscribe({ app: 'herm', path: '/session/'+name+'/view', + ses.subscriptionId = await api.subscribe({ app: 'herm', path: '/session/'+name+'/view', event: (e) => { showBlit(ses.term, e); if (e.bel && !selected) { @@ -189,7 +189,7 @@ export default function Buffer({ name, selected }: BufferProps) { console.error('oops quit, pls handle'); } }); - + useTermState.getState().set((state) => { state.sessions[name] = ses; }); diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx index 0c3f14831..f55627f6d 100644 --- a/pkg/interface/webterm/Tab.tsx +++ b/pkg/interface/webterm/Tab.tsx @@ -1,16 +1,20 @@ import { DEFAULT_SESSION } from './constants'; import React, { useCallback } from 'react'; -import useTermState from './state'; +import useTermState, { Session } from './state'; import { style } from 'styled-system'; import api from './api'; import { pokeTask } from '@urbit/api/term'; -export const Tab = ( { session, name } ) => { +interface TabProps { + session: Session; + name: string; +} + +export const Tab = ( { session, name }: TabProps ) => { const isSelected = useTermState().selected === name; const onClick = () => { - console.log('click!', name); useTermState.getState().set((state) => { state.selected = name; state.sessions[name].hasBell = false; @@ -18,9 +22,18 @@ export const Tab = ( { session, name } ) => { useTermState.getState().sessions[name]?.term?.focus(); } - const onDelete = (e) => { + const onDelete = useCallback(async (e) => { e.stopPropagation(); - api.poke(pokeTask(name, { shut: null })); + + // 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; @@ -28,8 +41,7 @@ export const Tab = ( { session, name } ) => { state.names = state.names.filter(n => n !== name); delete state.sessions[name]; }); - //TODO clean up the subscription - } + }, [session]); return (
diff --git a/pkg/interface/webterm/state.ts b/pkg/interface/webterm/state.ts index 2392db880..b6ca56633 100644 --- a/pkg/interface/webterm/state.ts +++ b/pkg/interface/webterm/state.ts @@ -3,7 +3,12 @@ import { FitAddon } from 'xterm-addon-fit'; import create from 'zustand'; import produce from 'immer'; -export type Session = { term: Terminal, fit: FitAddon, hasBell: boolean } | null; +export type Session = { + term: Terminal, + fit: FitAddon, + hasBell: boolean, + subscriptionId: number | null, +} | null; export type Sessions = { [id: string]: Session; } export interface TermState { From 438e6d4df983aec7ab1fe1e5ff5a8e089900200e Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 3 Mar 2022 17:10:54 -0600 Subject: [PATCH 017/249] ui: style tabs also rename join --> useDark; clean up extraneous logging statements --- pkg/interface/webterm/{app.tsx => App.tsx} | 10 ++--- pkg/interface/webterm/Buffer.tsx | 11 ++--- pkg/interface/webterm/Tab.tsx | 2 +- pkg/interface/webterm/Tabs.tsx | 2 +- pkg/interface/webterm/index.html | 43 ++++++++++++++----- .../webterm/{join.ts => lib/useDark.ts} | 8 ++-- 6 files changed, 45 insertions(+), 31 deletions(-) rename pkg/interface/webterm/{app.tsx => App.tsx} (91%) rename pkg/interface/webterm/{join.ts => lib/useDark.ts} (75%) diff --git a/pkg/interface/webterm/app.tsx b/pkg/interface/webterm/App.tsx similarity index 91% rename from pkg/interface/webterm/app.tsx rename to pkg/interface/webterm/App.tsx index d7c782f29..9ad1d6185 100644 --- a/pkg/interface/webterm/app.tsx +++ b/pkg/interface/webterm/App.tsx @@ -1,13 +1,12 @@ -/* eslint-disable max-lines */ import React, { useCallback, useEffect } from 'react'; -import useTermState, { Sessions } from './state'; -import { useDark } from './join'; +import useTermState from './state'; +import { useDark } from './lib/useDark'; import api from './api'; -import { Reset, _dark, _light } from '@tlon/indigo-react'; +import { _dark, _light } from '@tlon/indigo-react'; import 'xterm/css/xterm.css'; @@ -83,11 +82,10 @@ export default function TermApp(props: TermAppProps) { return ( <> -
{names.map(name => { - return ; + return ; })}
diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index ef65c592b..8ef69e2e9 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -12,8 +12,7 @@ import useTermState from './state'; import React from 'react'; import { Box, Col } from '@tlon/indigo-react'; import { makeTheme } from './lib/theme'; -import { useDark } from './join'; -import { showBlit, csi, showSlog } from './lib/blit'; +import { showBlit, csi } from './lib/blit'; const termConfig: ITerminalOptions = { logLevel: 'warn', @@ -138,11 +137,11 @@ const onInput = (name: string, session: Session, e: string) => { interface BufferProps { name: string, selected: boolean, + dark: boolean, } -export default function Buffer({ name, selected }: BufferProps) { +export default function Buffer({ name, selected, dark }: BufferProps) { const container = useRef(null); - const dark = useDark(); const session: Session = useTermState(s => s.sessions[name]); @@ -210,10 +209,6 @@ export default function Buffer({ name, selected }: BufferProps) { let newContainer = containerRef || container.current; if(session && newContainer) { container.current = newContainer; - console.log('newcont', newContainer); - // session.term.open(newContainer); - } else { - console.log('kaboom', session); } }, [session]); diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx index f55627f6d..0813292bd 100644 --- a/pkg/interface/webterm/Tab.tsx +++ b/pkg/interface/webterm/Tab.tsx @@ -44,7 +44,7 @@ export const Tab = ( { session, name }: TabProps ) => { }, [session]); return ( -
+ ); }; diff --git a/pkg/interface/webterm/index.html b/pkg/interface/webterm/index.html index ed7f86111..e2f4a18c2 100644 --- a/pkg/interface/webterm/index.html +++ b/pkg/interface/webterm/index.html @@ -29,32 +29,38 @@ } .buffer-container { - height: calc(100% - 33px); + height: calc(100% - 40px); } div.tabs { - height: 33px; + height: 40px; display: flex; flex-flow: row nowrap; justify-content: flex-start; - padding: 5px 0; + 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: 7px; + padding: 10px; cursor: pointer; } - div.tab { - text-align: center; - /* display: flex; - flex-flow: row nowrap; - align-items: center; - justify-content: space-between; */ + 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 { @@ -65,6 +71,23 @@ padding: 5px; } + @media (prefers-color-scheme: dark) { + 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, button.tab { + background-color: rgb(26, 26, 26); + color: rgba(255, 255, 255, 0.9); + border-color: rgba(255, 255, 255, 0.9); + } + + div.tabs > div.selected { + border-bottom: black solid 1px; + } + } diff --git a/pkg/interface/webterm/join.ts b/pkg/interface/webterm/lib/useDark.ts similarity index 75% rename from pkg/interface/webterm/join.ts rename to pkg/interface/webterm/lib/useDark.ts index 957abbd3d..cd9625403 100644 --- a/pkg/interface/webterm/join.ts +++ b/pkg/interface/webterm/lib/useDark.ts @@ -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); From 87ac253b8d9dd6873129c83a4268623c040c2271 Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 3 Mar 2022 18:11:37 -0600 Subject: [PATCH 018/249] ux: default terminal sets correct theme onload also, increase size of Tab click target --- pkg/interface/webterm/Buffer.tsx | 5 +++-- pkg/interface/webterm/Tab.tsx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 8ef69e2e9..dca9d8d71 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -13,6 +13,7 @@ import React from 'react'; import { Box, Col } from '@tlon/indigo-react'; import { makeTheme } from './lib/theme'; import { showBlit, csi } from './lib/blit'; +import { DEFAULT_SESSION } from './constants'; const termConfig: ITerminalOptions = { logLevel: 'warn', @@ -146,7 +147,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { const session: Session = useTermState(s => s.sessions[name]); const initSession = useCallback(async (name: string, dark: boolean) => { - console.log('setting up', name); + console.log('setting up', name === DEFAULT_SESSION ? 'default' : name); // set up xterm terminal // @@ -234,7 +235,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { if (container.current) { container.current.style.backgroundColor = theme.background || ''; } - }, [dark]); + }, [session, dark]); useEffect(() => { if (session && selected && !session.term.isOpen) { diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx index 0813292bd..2fac14813 100644 --- a/pkg/interface/webterm/Tab.tsx +++ b/pkg/interface/webterm/Tab.tsx @@ -44,8 +44,8 @@ export const Tab = ( { session, name }: TabProps ) => { }, [session]); return ( -
- +
+ {session?.hasBell ? '🔔 ' : ''} {name === DEFAULT_SESSION ? 'default' : name} {' '} From 8906d1c17d581ef809bdd21049f255d42b1ca53e Mon Sep 17 00:00:00 2001 From: fang Date: Sat, 5 Mar 2022 18:17:48 -0600 Subject: [PATCH 019/249] dill: move %mor case into $blit This lets us send a single blit around, instead of sending facts for every individual blit in a draw event. --- pkg/arvo/lib/hood/drum.hoon | 10 +++++----- pkg/arvo/sys/lull.hoon | 5 +++-- pkg/arvo/sys/vane/dill.hoon | 7 ++----- pkg/base-dev/lib/dill.hoon | 1 + pkg/interface/webterm/lib/blit.ts | 4 +++- pkg/npm/api/term/types.ts | 3 ++- pkg/urbit/vere/io/term.c | 12 +++++++++++- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 001e07324..5399edeea 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -122,7 +122,7 @@ =+ (~(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 @@ -284,13 +284,13 @@ ^- (list card:agent:gall) ?~ biz (flop moz) :_ (flop moz) - =/ =dill-blit:dill ?~(t.biz i.biz [%mor (flop biz)]) + =/ =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 !>(dill-blit)] + [%give %fact to %dill-blit !>(blit)] :: ++ se-adze :: update connections ^+ . @@ -473,7 +473,7 @@ +>(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 @@ -640,7 +640,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) diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index d89745182..32a1de2c5 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -1088,8 +1088,9 @@ [%clr ~] :: clear the screen [%hop p=$@(@ud [r=@ud c=@ud])] :: set cursor col/pos [%klr p=stub] :: put styled - [%put p=(list @c)] :: put text at cursor + [%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 @@ -1099,12 +1100,12 @@ $% belt :: client input [%cru p=@tas q=(list tank)] :: echo error [%hey ~] :: refresh + ::TODO inconsistent with %hit and %hop [%rez p=@ud q=@ud] :: resize, cols, rows [%yow p=gill:gall] :: connect to app == :: +$ dill-blit :: arvo output $% blit :: client output - [%mor p=(list dill-blit)] :: multiple blits [%qit ~] :: close console == :: +$ flog :: sent to %dill diff --git a/pkg/arvo/sys/vane/dill.hoon b/pkg/arvo/sys/vane/dill.hoon index e2c1e4d2e..afb827c32 100644 --- a/pkg/arvo/sys/vane/dill.hoon +++ b/pkg/arvo/sys/vane/dill.hoon @@ -178,13 +178,10 @@ ++ from :: receive blit |= bit=dill-blit ^+ +> - ?: ?=(%mor -.bit) - |- ^+ +>.^$ - ?~ p.bit +>.^$ - $(p.bit t.p.bit, +>.^$ ^$(bit i.p.bit)) ?: ?=(%qit -.bit) (dump %logo ~) - (done %blit [bit ~]) + ::TODO so why is this a (list blit) again? + (done %blit bit ~) :: ++ sponsor ^- ship diff --git a/pkg/base-dev/lib/dill.hoon b/pkg/base-dev/lib/dill.hoon index d4cecdf14..d3592c07d 100644 --- a/pkg/base-dev/lib/dill.hoon +++ b/pkg/base-dev/lib/dill.hoon @@ -18,6 +18,7 @@ %nel b+& %url s+p.blit %wyp b+& + %mor a+(turn p.blit ^blit) :: %sag %- pairs diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts index 534328433..5285675f1 100644 --- a/pkg/interface/webterm/lib/blit.ts +++ b/pkg/interface/webterm/lib/blit.ts @@ -10,7 +10,9 @@ export const csi = (cmd: string, ...args: number[]) => { export const showBlit = (term: Terminal, blit: Blit) => { let out = ''; - if ('bel' in blit) { + 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(); diff --git a/pkg/npm/api/term/types.ts b/pkg/npm/api/term/types.ts index df4767cff..362973f31 100644 --- a/pkg/npm/api/term/types.ts +++ b/pkg/npm/api/term/types.ts @@ -27,8 +27,9 @@ export type Blit = | { clr: null } // clear the screen | { hop: number | { r: number, c: 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 diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index e2b6376ca..ba5775cbd 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -1353,7 +1353,17 @@ _term_ef_blit(u3_utty* uty_u, _term_it_show_tour(uty_u, u3k(u3t(blt))); } break; - case c3__mor: //TMP backwards compatibility + case c3__mor: { + if (u3_nul != u3t(blt)) { + u3_noun bis = u3t(blt); + while (u3_nul != bis) { + _term_ef_blit(uty_u, u3k(u3h(bis))); + bis = u3t(bis); + } + break; + } + //TMP fall through to nel for backwards compatibility + } case c3__nel: { _term_it_show_nel(uty_u); } break; From 8d9a59bfe4f67f7eeeb144c4580b7713e8d1d4ff Mon Sep 17 00:00:00 2001 From: tomholford Date: Wed, 9 Mar 2022 16:14:06 -0600 Subject: [PATCH 020/249] devex: eslint config --- pkg/interface/webterm/.eslintrc.js | 26 +++++++++++++++++++----- pkg/interface/webterm/package-lock.json | Bin 1275816 -> 1283742 bytes pkg/interface/webterm/package.json | 9 +++++--- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pkg/interface/webterm/.eslintrc.js b/pkg/interface/webterm/.eslintrc.js index 66d65c291..8f36013ed 100644 --- a/pkg/interface/webterm/.eslintrc.js +++ b/pkg/interface/webterm/.eslintrc.js @@ -1,7 +1,23 @@ -const config = { +module.exports = exports = { "rules": { - "spaced-comment": false, - } + "spaced-comment": 0, + }, + "extends": [ + "eslint:recommended", + "plugin:import/errors", + "plugin:react/recommended", + ], + "settings": { + "react": { + "version": "detect" + }, + "import/resolver": { + typescript: {} // this loads /tsconfig.json to eslint + }, + }, + "env": { + "browser": true, + "es6": true + }, + "plugins": ["import", "react-hooks"] } - -export default config; diff --git a/pkg/interface/webterm/package-lock.json b/pkg/interface/webterm/package-lock.json index 2e42a0ff018e73a5cc473e825008d4b7061dc56e..902930d988df8539a038394474507620face3d54 100644 GIT binary patch delta 7666 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 H9_PORH@`58 delta 5033 zcmdUyX^b1?8OP-vd+qi5&SrD%Cc8OSDVx}1dwh|!iO09c_xdg*@%mV=?_P>G{0pn{s+stGhzptBB12$kATr0EC0 z8olpp`I+bV|9^hwu;i&IPdLNhd zi(k`*^Q=1_1ftAVLFKNlZdh@@U^)D>%w83mNT!QQqJW2VNka`E4OI0Cwa-V?2~|E< zOvkWg z-3dE+JsaTYmagS6aERLr!>5FD_;H!v2M2#CmBNV^xO?bhv92c&cua>3Kxi8Wn~#kH zuTBfZoMNJ)SP#m(yA~qMBgj{Y*9L2bI64(8x2pCjE!t@K$0L?h)L|h_O}iCsw-S*| zscfiDMbjR8BhxOZ@p!d8QM65s>#ef+@b;3QCs>HMT-PNCMfT1hW z6>xSRR|K=qb2W%^A;mD9*F z=Gp%p@#;|Cn05rQWS-KbJuVLwBC>@dN#&J_U?AS`mt)CfNgMQ{$+2)Mqs&j?Xiztr zicw+0;EuR;g;9k@9Z~u9Zk0*C*J2w;Ihya-{+5AXN!Fxd1V!i9I4wt%@l(IPgp zuL0wutkoeOmNO8_l)Y??w#*(Msxgw2t)$b^a0InkQg6-1h2t`Sq?jO+*+ikx`B6-c?)LN5uyYRKgZwi@wM5+s0qd-q&Z_OK zI=F8RxucV8mI5SCGOx6Akf((inP>#wo8kAv8JTDsEN8RjF#EJ{Dfm?UbuhG%Jp%hb zLApC%q}_Vs#9QIIe~j=(z3oC;pD?Ja(QI;R zG-`~-_2Z7JDy5yoEZJ15q_s52QB)CX5_x$4C}$YZ-*gYc#!H9{(y#Hv@Y3_rLD;d4 zmxEa@yL)=?6@=bD zH#ImM(8$&XEslDTRD0EhTs@?%mq~>avnZ#`fmR0h)UvsDM&TuLg?6erVVNxYsi{)I zjYS%|&?uGmdYtaIrKF4mEGVH*Whd3CurV47s(>{nS`6r~kkzpHA~Pb`i?Tj=_vZpJ zJdPnM@VK9alF?Q(*#Jk!i*3m0Ybr*~8w6CTg^5bG3lg=JwfB8EP^W zKneaIL9b5uB;dBv0&0w2}CU3g1t1AjM$5Ktmd_a+I6BiRvPNLXtFi^KEiJ{FFwTF>T0_4nH`{YvR!?qy^#>|DZ3 z>H}{vGcmhI(hYmLJ-s8>tbnO!ow1qHguGHKlV!49Nz1RDt;e8B2uFf(O*|3xqV+}{ zb*ow_g%)qCtCciSaS(s=Dm9_-lE+DUY?hW=%>HP2*l~&Q>di<8g)2jw{Dd z(}WH4XlhEE!K1cxIOIApA$rEXhfWCpFx-0&g1rg@zbEqw8?>?g48Bd&0|oa|vfe7cce`wVJ0Arx_8XP=1kzlFV%Pw=&{=_0b|{}lH6Kypwx0Ka=mD22m!OPn-A za6K&g@^aAt3pRfu5yC5%5FYG!PRg42nq_ea<3zgnwI-+qRXxD>~EkHFEp=v#dq*-9E{I)-8cHFrHv0dY;;7hT7(= zw+*n}@DY}N_Z)9A?BGjpS3;W?ZxAn(+HNMas}s=)oW3BD3T`Ewb%gplU0h8eU0x{t zo97#B7W!7$3?6gHR(%uA7SqSm(pP?e`=i-aM7W;4|H@|T=*jQNb`jG@9+uHZ9$qlp F^DpHKxuF06 diff --git a/pkg/interface/webterm/package.json b/pkg/interface/webterm/package.json index e859b4825..856b29eed 100644 --- a/pkg/interface/webterm/package.json +++ b/pkg/interface/webterm/package.json @@ -36,7 +36,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 +45,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 +60,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", From e7e5c6340977abf15831f07831ac24e1ad69edd3 Mon Sep 17 00:00:00 2001 From: tomholford Date: Wed, 9 Mar 2022 16:15:24 -0600 Subject: [PATCH 021/249] ux: support `agent!session-name` syntax When adding a session, using this special syntax will create a new session for the indicated agent. E.g., `book!my-session` opens a new session for the %book agent. --- pkg/interface/webterm/Tabs.tsx | 21 ++------ pkg/interface/webterm/constants.ts | 15 ++++++ pkg/interface/webterm/lib/useAddSession.ts | 59 ++++++++++++++++++++++ 3 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 pkg/interface/webterm/lib/useAddSession.ts diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx index e98c38d3f..09751537a 100644 --- a/pkg/interface/webterm/Tabs.tsx +++ b/pkg/interface/webterm/Tabs.tsx @@ -1,26 +1,11 @@ -import { pokeTask } from '@urbit/api/term'; -import api from './api'; import React from 'react'; import useTermState from './state'; import { Tab } from './Tab'; -import { SESSION_ID_REGEX } from './constants'; +import { useAddSession } from './lib/useAddSession'; export const Tabs = () => { const { sessions, names } = useTermState(); - - const onAddClick = () => { - const name = prompt('please entew a session name uwu'); - if (!name || !SESSION_ID_REGEX.test(name) || names.includes(name)) { - console.log('invalid session name:', name); - return; - } - api.poke(pokeTask(name, { open: { term: 'hood', apps: [{ who: '~' + (window as any).ship, app: 'dojo' }] } })); - useTermState.getState().set(state => { - state.names = [name, ...state.names].sort(); - state.selected = name; - state.sessions[name] = null; - }); - } + const { addSession } = useAddSession(); return (
@@ -29,7 +14,7 @@ export const Tabs = () => { ); })} - +
); }; diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index 7e173ac64..cd80b9aa2 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -9,3 +9,18 @@ export const DEFAULT_SESSION = ''; * - cannot begin or end with a hyphen */ export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d\-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; + +/** + * 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]{4})\!(([a-z]{1}[a-z\d\-]*[a-z\d]{1}$)|(^[a-z]{1}))/; diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts new file mode 100644 index 000000000..5f06d5c8d --- /dev/null +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -0,0 +1,59 @@ +import { 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 = 'hood'; // default agent + let sessionName: string; + + const userInput = prompt('please entew a session name uwu'); + // user canceled or did not enter a value + if (!userInput) { + return; + } + + // check for custom agent session syntax + if (AGENT_SESSION_REGEX.test(userInput)) { + const match = AGENT_SESSION_REGEX.exec(userInput); + if (!match) { + 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) { + return; + } + sessionName = match[1]; + } else { + return; + } + + // avoid nil or duplicate sessions + if(!sessionName || names.includes(sessionName)) { + return; + } + + try { + 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 + }; +}; From ee492e6f8309cbba3d77dbd7fd258764f5d99679 Mon Sep 17 00:00:00 2001 From: tomholford Date: Wed, 9 Mar 2022 16:25:10 -0600 Subject: [PATCH 022/249] devex: cleaning up lint issues --- pkg/interface/webterm/App.tsx | 12 ++++-------- pkg/interface/webterm/Buffer.tsx | 19 +++++++++---------- pkg/interface/webterm/Tab.tsx | 6 ++---- pkg/interface/webterm/constants.ts | 14 +++++++------- pkg/interface/webterm/lib/useDark.ts | 2 +- pkg/interface/webterm/state.ts | 6 ++++-- 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/pkg/interface/webterm/App.tsx b/pkg/interface/webterm/App.tsx index 9ad1d6185..9ce3b0c00 100644 --- a/pkg/interface/webterm/App.tsx +++ b/pkg/interface/webterm/App.tsx @@ -20,11 +20,7 @@ import Buffer from './Buffer'; import { DEFAULT_SESSION } from './constants'; import { showSlog } from './lib/blit'; -type TermAppProps = { - ship: string; -} - -export default function TermApp(props: TermAppProps) { +export default function TermApp() { const { names, selected } = useTermState(); const dark = useDark(); @@ -41,7 +37,7 @@ export default function TermApp(props: TermAppProps) { let available = false; const slog = new EventSource('/~_~/slog', { withCredentials: true }); - slog.onopen = (e) => { + slog.onopen = () => { console.log('slog: opened stream'); available = true; }; @@ -84,8 +80,8 @@ export default function TermApp(props: TermAppProps) {
- {names.map(name => { - return ; + {names.map((name) => { + return ; })}
diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index dca9d8d71..063019ed2 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -62,7 +62,7 @@ const readInput = (term: Terminal, e: string): Belt[] => { } else if (13 === c) { belts.push({ ret: null }); } else if (c <= 26) { - let k = String.fromCharCode(96 + c); + const k = String.fromCharCode(96 + c); //NOTE prevent remote shut-downs if ('d' !== k) { belts.push({ mod: { mod: 'ctl', key: k } }); @@ -178,7 +178,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { event: (e) => { showBlit(ses.term, e); if (e.bel && !selected) { - useTermState.getState().set(state => { + useTermState.getState().set((state) => { state.sessions[name].hasBell = true; }); } @@ -189,7 +189,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { console.error('oops quit, pls handle'); } }); - + useTermState.getState().set((state) => { state.sessions[name] = ses; }); @@ -207,7 +207,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // on selected change, maybe setup the term, or put it into the container // const setContainer = useCallback((containerRef: HTMLDivElement | null) => { - let newContainer = containerRef || container.current; + const newContainer = containerRef || container.current; if(session && newContainer) { container.current = newContainer; } @@ -216,7 +216,6 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // on-init, open slogstream and fetch existing sessions // useEffect(() => { - window.addEventListener('resize', onResize(session)); return () => { @@ -239,10 +238,10 @@ export default function Buffer({ name, selected, dark }: BufferProps) { useEffect(() => { if (session && selected && !session.term.isOpen) { - session!.term.open(container.current); - session!.fit.fit(); - session!.term.focus(); - session!.term.isOpen = true; + session.term.open(container.current); + session.fit.fit(); + session.term.focus(); + session.term.isOpen = true; } }, [selected, session]); @@ -256,7 +255,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { bg='white' fontFamily='mono' overflow='hidden' - style={selected ? {} : {display: 'none'}} + style={selected ? {} : { display: 'none' }} > { - const isSelected = useTermState().selected === name; const onClick = () => { @@ -20,7 +18,7 @@ export const Tab = ( { session, name }: TabProps ) => { state.sessions[name].hasBell = false; }); useTermState.getState().sessions[name]?.term?.focus(); - } + }; const onDelete = useCallback(async (e) => { e.stopPropagation(); @@ -34,7 +32,7 @@ export const Tab = ( { session, name }: TabProps ) => { await api.poke(pokeTask(name, { shut: null })); // remove from zustand - useTermState.getState().set(state => { + useTermState.getState().set((state) => { if (state.selected === name) { state.selected = DEFAULT_SESSION; } diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index cd80b9aa2..61c11b13c 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -2,25 +2,25 @@ export const DEFAULT_SESSION = ''; /** * Session ID validity: - * + * * - must start with an alphabetical * - can be composed of alphanumerics with hyphens * - can be length 1 or longer * - cannot begin or end with a hyphen */ -export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d\-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; +export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; /** * 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 + * + * Note that the second capture group after the ! is composed of the session ID * regex above. */ -export const AGENT_SESSION_REGEX = /^([a-z]{4})\!(([a-z]{1}[a-z\d\-]*[a-z\d]{1}$)|(^[a-z]{1}))/; +export const AGENT_SESSION_REGEX = /^([a-z]{4})!(([a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}))/; diff --git a/pkg/interface/webterm/lib/useDark.ts b/pkg/interface/webterm/lib/useDark.ts index cd9625403..ddd9c10ae 100644 --- a/pkg/interface/webterm/lib/useDark.ts +++ b/pkg/interface/webterm/lib/useDark.ts @@ -14,7 +14,7 @@ export function useDark() { return () => { themeWatcher.removeEventListener('change', update); - } + }; }, []); const theme = useTermState(s => s.theme); diff --git a/pkg/interface/webterm/state.ts b/pkg/interface/webterm/state.ts index b6ca56633..e481e36e5 100644 --- a/pkg/interface/webterm/state.ts +++ b/pkg/interface/webterm/state.ts @@ -3,8 +3,8 @@ import { FitAddon } from 'xterm-addon-fit'; import create from 'zustand'; import produce from 'immer'; -export type Session = { - term: Terminal, +export type Session = { + term: Terminal, fit: FitAddon, hasBell: boolean, subscriptionId: number | null, @@ -21,12 +21,14 @@ export interface TermState { set: any, } +// eslint-disable-next-line no-unused-vars const useTermState = create((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)); } From 200b504c4e19ac76eada25fa48844d0dc2b9ce9c Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 10 Mar 2022 00:03:27 -0600 Subject: [PATCH 023/249] api: resubscribe after clog --- pkg/interface/webterm/Buffer.tsx | 37 +++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 063019ed2..eecadb9f1 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -174,21 +174,34 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // open subscription // - ses.subscriptionId = await api.subscribe({ app: 'herm', path: '/session/'+name+'/view', - event: (e) => { - showBlit(ses.term, e); - if (e.bel && !selected) { + const initSubscription = async () => { + const subscriptionId = await api.subscribe({ + app: 'herm', path: '/session/' + name + '/view', + event: (e) => { + showBlit(ses.term, e); + if (e.bel && !selected) { + 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('oops quit, reconnecting...'); + const newSubscriptionId = await initSubscription(); useTermState.getState().set((state) => { - state.sessions[name].hasBell = true; + state.sessions[name].subscriptionId = newSubscriptionId; }); } - //TODO should handle %bye on this higher level though, for deletion - }, - quit: () => { // quit - // TODO show user a message - console.error('oops quit, pls handle'); - } - }); + }); + + return subscriptionId; + }; + + ses.subscriptionId = await initSubscription(); useTermState.getState().set((state) => { state.sessions[name] = ses; From bf0f4e97c999256d1fcd2deaa12e452265a8bd93 Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 10 Mar 2022 22:54:30 -0600 Subject: [PATCH 024/249] api: exponential backoff when resubscribing Use the new `lib/retry` to attempt to reconnect when clogged. If unsucessful after 5 attempts, stop retrying and log an error. --- pkg/interface/webterm/Buffer.tsx | 15 +++++++++--- pkg/interface/webterm/constants.ts | 2 +- pkg/interface/webterm/lib/retry.ts | 39 ++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 pkg/interface/webterm/lib/retry.ts diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index eecadb9f1..f24d08bd4 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -14,6 +14,7 @@ import { Box, Col } from '@tlon/indigo-react'; import { makeTheme } from './lib/theme'; import { showBlit, csi } from './lib/blit'; import { DEFAULT_SESSION } from './constants'; +import { retry } from './lib/retry'; const termConfig: ITerminalOptions = { logLevel: 'warn', @@ -191,10 +192,16 @@ export default function Buffer({ name, selected, dark }: BufferProps) { }, quit: async () => { // quit console.error('oops quit, reconnecting...'); - const newSubscriptionId = await initSubscription(); - useTermState.getState().set((state) => { - state.sessions[name].subscriptionId = newSubscriptionId; - }); + 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); + } } }); diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index 61c11b13c..a96349bc1 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -11,7 +11,7 @@ export const DEFAULT_SESSION = ''; export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; /** - * Open a session with a given agent using `[agent]![session_name] + * Open a session with a given agent using `[agent]![session_name]` * * For example: * ``` diff --git a/pkg/interface/webterm/lib/retry.ts b/pkg/interface/webterm/lib/retry.ts new file mode 100644 index 000000000..dea78b0b2 --- /dev/null +++ b/pkg/interface/webterm/lib/retry.ts @@ -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); +} From cdaf23a184c8aa538974a38e3bd0ce76e659e959 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Fri, 25 Feb 2022 15:51:22 -0500 Subject: [PATCH 025/249] hoon: prefix and postfix doccords for ++ and +$ there's a stub for +* but its not working yet --- pkg/arvo/sys/hoon.hoon | 80 ++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 566010fbe..edc9572b3 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -13226,45 +13226,65 @@ :: ++ boog !: :: core arms %+ knee [p=*term q=*hoon] |. ~+ + %+ cook + |= [a=whit b=term c=whit d=hoon] + =+ e=(glom a c) + ?~ boy.e + [b d] + [b [%note [%help ~ [p.u.boy.e q.u.boy.e]] d]] ;~ pose - ;~ pfix (jest '++') - ;~ plug - ;~(pfix gap ;~(pose (cold %$ buc) sym)) - ;~(pfix gap loaf) + ;~ plug + apex:docs + ;~ pfix (jest '++') + ;~ plug + ;~(pfix gap ;~(pose (cold %$ buc) sym)) + apse:docs + ;~(pfix gap loaf) + == == == :: %+ cook - |= [b=term d=spec] - [b [%ktcl [%name b d]]] - ;~ pfix (jest '+$') - ;~ plug - ;~(pfix gap sym) - ;~(pfix gap loan) + |= [a=whit b=term c=whit d=spec] + [a b c [%ktcl [%name b d]]] + ;~ plug + apex:docs + ;~ pfix (jest '+$') + ;~ plug + ;~(pfix gap sym) + apse:docs + ;~(pfix gap loan) + == == == :: %+ cook - |= [b=term c=(list term) e=spec] - ^- [term hoon] - :- b - :+ %brtr - :- %bccl - =- ?>(?=(^ -) -) - :: for each .term in .c, produce $=(term $~(* $-(* *))) - :: ie {term}=mold - :: - %+ turn c - |= =term - ^- spec - =/ tar [%base %noun] - [%bcts term [%bcsg tar [%bchp tar tar]]] - [%ktcl [%made [b c] e]] - ;~ pfix (jest '+*') - ;~ plug - ;~(pfix gap sym) - ;~(pfix gap (ifix [sel ser] (most ace sym))) - ;~(pfix gap loan) + |= [a=whit b=term d=hoon] + [a b *whit d] + ;~ plug + apex:docs :: this doesn't work, not sure why yet + %+ cook + |= [b=term c=(list term) e=spec] + ^- [term hoon] + :- b + :+ %brtr + :- %bccl + =- ?>(?=(^ -) -) + :: for each .term in .c, produce $=(term $~(* $-(* *))) + :: ie {term}=mold + :: + %+ turn c + |= =term + ^- spec + =/ tar [%base %noun] + [%bcts term [%bcsg tar [%bchp tar tar]]] + [%ktcl [%made [b c] e]] + ;~ pfix (jest '+*') + ;~ plug + ;~(pfix gap sym) + ;~(pfix gap (ifix [sel ser] (most ace sym))) + ;~(pfix gap loan) + == == == == From 336817d5bc318204fb86640cf551ae2a9ac63e3c Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Fri, 25 Feb 2022 15:52:23 -0500 Subject: [PATCH 026/249] hoon: doccords for core chapters this populates the $what in $tome --- pkg/arvo/sys/hoon.hoon | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index edc9572b3..d6f8f31ca 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -13336,31 +13336,32 @@ ++ wisp !: :: core tail ?. tol fail %+ cook - |= a=(list (pair term (map term hoon))) + |= a=(list [wit=whit wap=(pair term (map term hoon))]) ^- (map term tome) =< p |- ^- (pair (map term tome) (map term hoon)) ?~ a [~ ~] =/ mor $(a t.a) - =. q.i.a - %- ~(urn by q.i.a) + =. q.wap.i.a + %- ~(urn by q.wap.i.a) |= b=(pair term hoon) ^+ +.b + :: tests for duplicate arms between two chapters ?. (~(has by q.mor) p.b) +.b [%eror (weld "duplicate arm: +" (trip p.b))] - :_ (~(uni by q.mor) q.i.a) + :_ (~(uni by q.mor) q.wap.i.a) %+ ~(put by p.mor) - p.i.a - :- *what - ?. (~(has by p.mor) p.i.a) - q.i.a - [[%$ [%eror (weld "duplicate chapter: |" (trip p.i.a))]] ~ ~] + p.wap.i.a + :- boy.wit.i.a :: body of the whit set as the what + ?. (~(has by p.mor) p.wap.i.a) + q.wap.i.a + [[%$ [%eror (weld "duplicate chapter: |" (trip p.wap.i.a))]] ~ ~] :: ;~ pose dun ;~ sfix ;~ pose - (most muck ;~(pfix (jest '+|') ;~(pfix gap whip))) - ;~(plug (stag %$ whap) (easy ~)) + (most muck ;~(plug apex:docs ;~(pfix (jest '+|') ;~(pfix gap whip)))) + ;~(plug (stag *whit (stag %$ whap)) (easy ~)) == gap dun From 0a3ec9a92d1d5cffe243006c3b0e2c3877d1739f Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 1 Mar 2022 16:35:47 -0500 Subject: [PATCH 027/249] hoon: doccords cleanup %note tag for +boog --- pkg/arvo/sys/hoon.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index d6f8f31ca..fd6c0fe30 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -13231,7 +13231,7 @@ =+ e=(glom a c) ?~ boy.e [b d] - [b [%note [%help ~ [p.u.boy.e q.u.boy.e]] d]] + [b [%note help+`[u.boy.e] d]] ;~ pose ;~ plug apex:docs From 41a796d2d1465d934edd9cb7305a274bb813b72f Mon Sep 17 00:00:00 2001 From: fang Date: Thu, 10 Mar 2022 01:40:02 +0100 Subject: [PATCH 028/249] hoon: hook up $+ for shorthand type rendering Too often when dealing with big types the compiler traces and other such outputs become hard to read. Wrapping a type as $+(shorthand big-type) will now print #shorthand in place of the type. --- pkg/arvo/app/dojo.hoon | 4 +++- pkg/arvo/sys/hoon.hoon | 21 +++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index 938d9f25a..b127a3ce0 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -679,7 +679,9 @@ [%face ^] a(q $(a q.a)) [%cell ^] a(p $(a p.a), q $(a q.a)) [%fork *] a(p (silt (turn ~(tap in p.a) |=(b=type ^$(a b))))) - [%hint *] !! + [%hint *] ?. ?=(%know -.q.p.a) $(a q.a) + ?@ p.q.p.a [(cat 3 '#' mark.p.q.p.a)]~ + [(rap 3 '#' auth.p.q.p.a (spat type.p.q.p.a) ~)]~ [%core ^] `wain`/core [%hold *] a(p $(a p.a)) == diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index fd6c0fe30..ec4a6fa26 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -7781,7 +7781,7 @@ [%bcgl *] $(mod q.mod) [%bcgr *] $(mod q.mod) [%bckt *] $(mod q.mod) - [%bcls *] $(mod q.mod) + [%bcls *] [%note [%know p.mod] $(mod q.mod)] [%bcmc *] :: borrow sample :: [%tsgl [%$ 6] p.mod] @@ -7832,7 +7832,7 @@ [%bchp *] (decorate (function:clear p.mod q.mod)) [%bcmc *] (decorate (home [%tsgl [%limb %$] p.mod])) [%bcsg *] [%ktls example(mod q.mod) (home p.mod)] - [%bcls *] (decorate example(mod q.mod)) + [%bcls *] (decorate [%note [%know p.mod] example(mod q.mod)]) [%bcts *] (decorate [%ktts p.mod example:clear(mod q.mod)]) [%bcdt *] (decorate (home (interface %gold p.mod q.mod))) [%bcfs *] (decorate (home (interface %iron p.mod q.mod))) @@ -8189,7 +8189,7 @@ relative:clear(mod q.mod) relative:clear(mod p.mod) :: - [%bcls *] relative(mod q.mod) + [%bcls *] [%note [%know p.mod] relative(mod q.mod)] [%bcdt *] (decorate (home (interface %gold p.mod q.mod))) [%bcfs *] (decorate (home (interface %iron p.mod q.mod))) [%bczp *] (decorate (home (interface %lead p.mod q.mod))) @@ -10914,6 +10914,7 @@ [%stop p=@ud] :: [%tree p=term q=wine] :: [%unit p=term q=wine] :: + [%name p=stud q=wine] :: == :: -- |_ sut=type @@ -11004,6 +11005,11 @@ [%unit *] =^ cox gid $(q.ham q.q.ham) :_(gid [%rose [" " (weld (trip p.q.ham) "(") ")"] cox ~]) + :: + [%name *] + :_ gid + ?@ p.q.ham (cat 3 '#' mark.p.q.ham) + (rap 3 '#' auth.p.q.ham (spat type.p.q.ham) ~) == -- :: @@ -11191,6 +11197,9 @@ ?~ wal ~ [~ %rose [[' ' ~] ['[' ~] [']' ~]] [%leaf '~' ~] u.wal ~] + :: + [%name *] + $(q.ham q.q.ham) == :: ++ doge @@ -11295,7 +11304,9 @@ == :: [%hint *] - $(sut q.sut) + =+ yad=$(sut q.sut) + ?. ?=(%know -.q.p.sut) yad + [p.yad [%name p.q.p.sut q.yad]] :: [%face *] =+ yad=$(sut q.sut) @@ -13010,6 +13021,7 @@ ['=' (rune tis %bcts exqg)] ['?' (rune wut %bcwt exqs)] [';' (rune mic %bcmc expa)] + ['+' (rune lus %bcls exqg)] == == :- '%' @@ -13080,6 +13092,7 @@ ['-' (stag %ktcl (rune hep %bchp exqb))] ['=' (stag %ktcl (rune tis %bcts exqg))] ['?' (stag %ktcl (rune wut %bcwt exqs))] + ['+' (stag %ktcl (rune lus %bcls exqg))] ['.' (rune dot %kttr exqa)] [',' (rune com %ktcl exqa)] == From f08b613416f9da8529ca4188b16a2e67bc332f08 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Mon, 14 Mar 2022 17:00:04 -0400 Subject: [PATCH 029/249] hoon: populate label for %brcn doccords This changes the parser for +tall so that it looks before and after a hoon for doccords, and then extracts a label for %brcn if it exists. +wrap will be used to annotating most hoons, but this commit only covers %brcn --- pkg/arvo/sys/hoon.hoon | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index ec4a6fa26..6e6bacc7e 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8207,6 +8207,21 @@ == |_ gen=hoon :: + :: This door takes in a whit and annotates gen as appropriate + ++ docs-engine + |_ wit=whit + :: + ++ apply-whit + ^- hoon + ?: =([~ ~ ~ ~] wit) + gen + ?+ gen gen + :: + [%brcn *] + [%brcn lab.wit q.gen] + == + -- + :: ++ grip |= =skin =| rel=wing @@ -13673,9 +13688,26 @@ [%spec spec %base %noun] wyde == + :: + :: +wrap is for tagging arbitrary hoons. This is where most of the doccords + :: logic lives - the modifications to +boog and +wisp are for tagging arms + :: and chapter labels, while +wrap handles hoons inside of arms and cores. + ++ wrap + |* fel=rule + %+ cook + |= [a=whit b=hoon c=whit] + ^- hoon + ~(apply-whit ~(docs-engine ap b) (glom a c)) + :: + ;~ plug + apex:docs + fel + apse:docs + == + :: ++ tall :: full tall form %+ knee *hoon - |.(~+((wart ;~(pose expression:(norm &) long lute apex:(sail &))))) + |.(~+((wart (wrap ;~(pose expression:(norm &) long lute apex:(sail &)))))) ++ till :: mold tall form %+ knee *spec |.(~+((wert ;~(pose structure:(norm &) scad)))) From 0dc3498a6f2b0bbc63b367031720e56a5221d76d Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Mon, 14 Mar 2022 17:08:49 -0400 Subject: [PATCH 030/249] hoon: change %brdt AST to support doccords label --- pkg/arvo/sys/hoon.hoon | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 6e6bacc7e..81bef0a17 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -6440,7 +6440,7 @@ [%brcb p=spec q=alas r=(map term tome)] :: |_ [%brcl p=hoon q=hoon] :: |: [%brcn p=(unit term) q=(map term tome)] :: |% - [%brdt p=hoon] :: |. + [%brdt p=(unit term) q=hoon] :: |. [%brkt p=hoon q=(map term tome)] :: |^ [%brhp p=hoon] :: |- [%brsg p=spec q=hoon] :: |~ @@ -8213,12 +8213,16 @@ :: ++ apply-whit ^- hoon + :: if wit is empty, just return the hoon ?: =([~ ~ ~ ~] wit) gen ?+ gen gen :: [%brcn *] - [%brcn lab.wit q.gen] + [%brcn lab.wit q.gen] :: populate (unit term) with lab.wit + :: + [%brdt *] + [%brdt lab.wit q.gen] == -- :: @@ -8439,10 +8443,10 @@ |= =hoon ?~ q.gen hoon [%tstr [p.i.q.gen ~] q.i.q.gen $(q.gen t.q.gen)] - [%brcl *] [%tsls p.gen [%brdt q.gen]] - [%brdt *] :+ %brcn ~ + [%brcl *] [%tsls p.gen [%brdt ~ q.gen]] ::TODO ~ added when modifying %brdt, change to be appropriate docs + [%brdt *] :+ %brcn p.gen :: (docs) ~ changed to p.gen. builds a |% with an arm named $ =- [[%$ ~ -] ~ ~] - (~(put by *(map term hoon)) %$ p.gen) + (~(put by *(map term hoon)) %$ q.gen) [%brkt *] :+ %tsgl [%limb %$] :+ %brcn ~ =+ zil=(~(get by q.gen) %$) @@ -8451,7 +8455,7 @@ [*what [[%$ p.gen] ~ ~]] %+ ~(put by q.gen) %$ [p.u.zil (~(put by q.u.zil) %$ p.gen)] - [%brhp *] [%tsgl [%limb %$] [%brdt p.gen]] + [%brhp *] [%tsgl [%limb %$] [%brdt ~ p.gen]] :: TODO ~ added when modifying %brdt. change to appropriate docs [%brsg *] [%ktbr [%brts p.gen q.gen]] [%brtr *] :+ %tsls [%kttr p.gen] :+ %brpt ~ @@ -8460,7 +8464,7 @@ [%brts *] :+ %brcb p.gen =- [~ [[%$ ~ -] ~ ~]] (~(put by *(map term hoon)) %$ q.gen) - [%brwt *] [%ktwt %brdt p.gen] + [%brwt *] [%ktwt %brdt ~ p.gen] :: TODO ~ added when modifying %brdt. change to appropriate docs :: [%clkt *] [p.gen q.gen r.gen s.gen] [%clls *] [p.gen q.gen r.gen] @@ -8521,10 +8525,10 @@ :- %mean =+ fek=~(feck ap p.gen) ?^ fek [%rock %tas u.fek] - [%brdt [%cncl [%limb %cain] [%zpgr [%tsgr [%$ 3] p.gen]] ~]] + [%brdt ~ [%cncl [%limb %cain] [%zpgr [%tsgr [%$ 3] p.gen]] ~]] :: (doccords) added ~ for %brdt q.gen :: - [%sgcb *] [%sggr [%mean [%brdt p.gen]] q.gen] + [%sgcb *] [%sggr [%mean [%brdt ~ p.gen]] q.gen] :: (doccords) added ~ for %brdt [%sgcn *] :+ %sggl :- %fast @@ -8622,7 +8626,7 @@ :+ %tsgl :: [%wing [%| 0 ~] [%& 6] ~] :: [%limb %b] :: - :- %brdt :: |. + :+ %brdt ~ :: |. (doccords) added ~ for %brdt :^ %cnls :: %+ [%tsgr [%limb %v] p.gen] :: =>(v {p.gen}) [%cncl [%limb %b] [%limb %c] ~] :: (b c) @@ -13080,7 +13084,7 @@ ['%' (runo cen %brcn ~ expe)] ['@' (runo pat %brpt ~ expe)] [':' (rune col %brcl expb)] - ['.' (rune dot %brdt expa)] + ['.' (runo dot %brdt ~ expa)] ['-' (rune hep %brhp expa)] ['^' (rune ket %brkt expx)] ['~' (rune sig %brsg exqc)] From 643700546f2d1ecf00bd33e5b3c726b18a51c980 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Mon, 14 Mar 2022 17:09:41 -0400 Subject: [PATCH 031/249] hoon: populate %brpt doccords label --- pkg/arvo/sys/hoon.hoon | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 81bef0a17..8307566eb 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8220,6 +8220,9 @@ :: [%brcn *] [%brcn lab.wit q.gen] :: populate (unit term) with lab.wit + :: + [%brpt *] + [%brpt lab.wit q.gen] :: populate (unit term) with lab.wit :: [%brdt *] [%brdt lab.wit q.gen] From 586c2da857b7ce56e55c73bcd235cfa8c0e69427 Mon Sep 17 00:00:00 2001 From: fang Date: Tue, 15 Mar 2022 01:24:16 +0100 Subject: [PATCH 032/249] webterm: improve session creation regexes Trailing dashes are, in fact, allowed. As are numerics in the agent name. --- pkg/interface/webterm/constants.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index a96349bc1..deaf08db6 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -6,9 +6,8 @@ export const DEFAULT_SESSION = ''; * - must start with an alphabetical * - can be composed of alphanumerics with hyphens * - can be length 1 or longer - * - cannot begin or end with a hyphen */ -export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; +export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*$)/; /** * Open a session with a given agent using `[agent]![session_name]` @@ -23,4 +22,4 @@ export const SESSION_ID_REGEX = /(^[a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}$)/; * Note that the second capture group after the ! is composed of the session ID * regex above. */ -export const AGENT_SESSION_REGEX = /^([a-z]{4})!(([a-z]{1}[a-z\d-]*[a-z\d]{1}$)|(^[a-z]{1}))/; +export const AGENT_SESSION_REGEX = /^([a-z]{1}[a-z\d-]*)!([a-z]{1}[a-z\d-]*$)/; From 0d2c135959e1c634f8c69c4a45390005c0fb8d89 Mon Sep 17 00:00:00 2001 From: fang Date: Tue, 15 Mar 2022 01:34:19 +0100 Subject: [PATCH 033/249] webterm: small cleanup, comments Also includes a more-sane prompt() description. --- pkg/interface/webterm/Buffer.tsx | 2 +- pkg/interface/webterm/constants.ts | 1 + pkg/interface/webterm/lib/useAddSession.ts | 11 ++++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index f24d08bd4..067fd0cf9 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -191,7 +191,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { console.log(`subscription error, id ${id}:`, e); }, quit: async () => { // quit - console.error('oops quit, reconnecting...'); + console.error('quit, reconnecting...'); try { const newSubscriptionId = await retry(initSubscription, () => { console.log('attempting to reconnect ...'); diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index deaf08db6..66d4b0ecc 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -1,4 +1,5 @@ export const DEFAULT_SESSION = ''; +export const DEFAULT_HANDLER = 'hood'; /** * Session ID validity: diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts index 5f06d5c8d..f25c13b2b 100644 --- a/pkg/interface/webterm/lib/useAddSession.ts +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -1,4 +1,8 @@ -import { AGENT_SESSION_REGEX, SESSION_ID_REGEX } from '../constants'; +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'; @@ -8,10 +12,10 @@ export const useAddSession = () => { const { names } = useTermState(); const addSession = useCallback(async () => { - let agent = 'hood'; // default agent + let agent = DEFAULT_HANDLER; let sessionName: string; - const userInput = prompt('please entew a session name uwu'); + const userInput = prompt('Please enter an alpha-numeric session name.'); // user canceled or did not enter a value if (!userInput) { return; @@ -42,6 +46,7 @@ export const useAddSession = () => { } 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(); From 6256a0a6647fd20b4b03c57eaa4c8a2cded3c0cd Mon Sep 17 00:00:00 2001 From: tomholford Date: Tue, 15 Mar 2022 11:16:44 -0600 Subject: [PATCH 034/249] ux: inform user when session input is invalid Show a helpful error message via `alert` instead of failing silently. --- pkg/interface/webterm/lib/useAddSession.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts index f25c13b2b..b740ebcc4 100644 --- a/pkg/interface/webterm/lib/useAddSession.ts +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -18,6 +18,7 @@ export const useAddSession = () => { const userInput = prompt('Please enter an alpha-numeric session name.'); // user canceled or did not enter a value if (!userInput) { + alert('A valid name is required to create a new session'); return; } @@ -25,6 +26,7 @@ export const useAddSession = () => { 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]; @@ -33,15 +35,18 @@ export const useAddSession = () => { } 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; } - // avoid nil or duplicate sessions - if(!sessionName || names.includes(sessionName)) { + // prevent duplicate sessions + if(names.includes(sessionName)) { + alert(`Session name must be unique ("${sessionName}" already in use)`); return; } From 1c72ff610312af50d1b3f4058674c6e7a10a249b Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 16 Mar 2022 12:12:39 -0400 Subject: [PATCH 035/249] Revert "hoon: change %brdt AST to support doccords label" This reverts commit 0dc3498a6f2b0bbc63b367031720e56a5221d76d. --- pkg/arvo/sys/hoon.hoon | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 8307566eb..b4ef91597 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -6440,7 +6440,7 @@ [%brcb p=spec q=alas r=(map term tome)] :: |_ [%brcl p=hoon q=hoon] :: |: [%brcn p=(unit term) q=(map term tome)] :: |% - [%brdt p=(unit term) q=hoon] :: |. + [%brdt p=hoon] :: |. [%brkt p=hoon q=(map term tome)] :: |^ [%brhp p=hoon] :: |- [%brsg p=spec q=hoon] :: |~ @@ -8213,12 +8213,12 @@ :: ++ apply-whit ^- hoon - :: if wit is empty, just return the hoon ?: =([~ ~ ~ ~] wit) gen ?+ gen gen :: [%brcn *] +<<<<<<< HEAD [%brcn lab.wit q.gen] :: populate (unit term) with lab.wit :: [%brpt *] @@ -8226,6 +8226,9 @@ :: [%brdt *] [%brdt lab.wit q.gen] +======= + [%brcn lab.wit q.gen] +>>>>>>> parent of 0dc3498a6f (hoon: change %brdt AST to support doccords label) == -- :: @@ -8446,10 +8449,10 @@ |= =hoon ?~ q.gen hoon [%tstr [p.i.q.gen ~] q.i.q.gen $(q.gen t.q.gen)] - [%brcl *] [%tsls p.gen [%brdt ~ q.gen]] ::TODO ~ added when modifying %brdt, change to be appropriate docs - [%brdt *] :+ %brcn p.gen :: (docs) ~ changed to p.gen. builds a |% with an arm named $ + [%brcl *] [%tsls p.gen [%brdt q.gen]] + [%brdt *] :+ %brcn ~ =- [[%$ ~ -] ~ ~] - (~(put by *(map term hoon)) %$ q.gen) + (~(put by *(map term hoon)) %$ p.gen) [%brkt *] :+ %tsgl [%limb %$] :+ %brcn ~ =+ zil=(~(get by q.gen) %$) @@ -8458,7 +8461,7 @@ [*what [[%$ p.gen] ~ ~]] %+ ~(put by q.gen) %$ [p.u.zil (~(put by q.u.zil) %$ p.gen)] - [%brhp *] [%tsgl [%limb %$] [%brdt ~ p.gen]] :: TODO ~ added when modifying %brdt. change to appropriate docs + [%brhp *] [%tsgl [%limb %$] [%brdt p.gen]] [%brsg *] [%ktbr [%brts p.gen q.gen]] [%brtr *] :+ %tsls [%kttr p.gen] :+ %brpt ~ @@ -8467,7 +8470,7 @@ [%brts *] :+ %brcb p.gen =- [~ [[%$ ~ -] ~ ~]] (~(put by *(map term hoon)) %$ q.gen) - [%brwt *] [%ktwt %brdt ~ p.gen] :: TODO ~ added when modifying %brdt. change to appropriate docs + [%brwt *] [%ktwt %brdt p.gen] :: [%clkt *] [p.gen q.gen r.gen s.gen] [%clls *] [p.gen q.gen r.gen] @@ -8528,10 +8531,10 @@ :- %mean =+ fek=~(feck ap p.gen) ?^ fek [%rock %tas u.fek] - [%brdt ~ [%cncl [%limb %cain] [%zpgr [%tsgr [%$ 3] p.gen]] ~]] :: (doccords) added ~ for %brdt + [%brdt [%cncl [%limb %cain] [%zpgr [%tsgr [%$ 3] p.gen]] ~]] q.gen :: - [%sgcb *] [%sggr [%mean [%brdt ~ p.gen]] q.gen] :: (doccords) added ~ for %brdt + [%sgcb *] [%sggr [%mean [%brdt p.gen]] q.gen] [%sgcn *] :+ %sggl :- %fast @@ -8629,7 +8632,7 @@ :+ %tsgl :: [%wing [%| 0 ~] [%& 6] ~] :: [%limb %b] :: - :+ %brdt ~ :: |. (doccords) added ~ for %brdt + :- %brdt :: |. :^ %cnls :: %+ [%tsgr [%limb %v] p.gen] :: =>(v {p.gen}) [%cncl [%limb %b] [%limb %c] ~] :: (b c) @@ -13087,7 +13090,7 @@ ['%' (runo cen %brcn ~ expe)] ['@' (runo pat %brpt ~ expe)] [':' (rune col %brcl expb)] - ['.' (runo dot %brdt ~ expa)] + ['.' (rune dot %brdt expa)] ['-' (rune hep %brhp expa)] ['^' (rune ket %brkt expx)] ['~' (rune sig %brsg exqc)] From ff81189823098c15fdb0deca5e8daea8043962af Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 16 Mar 2022 12:13:39 -0400 Subject: [PATCH 036/249] hoon: doccords %brdt cleanup revert --- pkg/arvo/sys/hoon.hoon | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index b4ef91597..44ee27616 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8218,17 +8218,11 @@ ?+ gen gen :: [%brcn *] -<<<<<<< HEAD [%brcn lab.wit q.gen] :: populate (unit term) with lab.wit :: [%brpt *] [%brpt lab.wit q.gen] :: populate (unit term) with lab.wit :: - [%brdt *] - [%brdt lab.wit q.gen] -======= - [%brcn lab.wit q.gen] ->>>>>>> parent of 0dc3498a6f (hoon: change %brdt AST to support doccords label) == -- :: From c01732de1608702a775d2d4a8f1e0c38b770d1f2 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 16 Mar 2022 13:05:58 -0400 Subject: [PATCH 037/249] hoon: doccords wrap bar runes with %notes this changes the parser to take any bar runes surrounded by formal comments and wraps them with %note tags containing those comments --- pkg/arvo/sys/hoon.hoon | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 44ee27616..531d89fcb 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8216,13 +8216,22 @@ ?: =([~ ~ ~ ~] wit) gen ?+ gen gen + :: + $? [%brbc *] [%brcb *] [%brcl *] [%brdt *] [%brkt *] + [%brhp *] [%brsg *] [%brtr *] [%brts *] [%brwt *] == + ?~ boy.wit + gen + [%note help+`u.boy.wit gen] :: [%brcn *] - [%brcn lab.wit q.gen] :: populate (unit term) with lab.wit + ?~ boy.wit + [%brcn lab.wit q.gen] + [%note help+`u.boy.wit [%brcn lab.wit q.gen]] :: [%brpt *] - [%brpt lab.wit q.gen] :: populate (unit term) with lab.wit - :: + ?~ boy.wit + [%brcn lab.wit q.gen] + [%note help+`u.boy.wit [%brpt lab.wit q.gen]] == -- :: From 2fa0bd364479da9c5b2415e9492dfd9d7fd9a345 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 16 Mar 2022 13:43:55 -0400 Subject: [PATCH 038/249] squash! hoon: doccords wrap bar runes with %notes --- pkg/arvo/sys/hoon.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 531d89fcb..c962ec606 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8217,8 +8217,8 @@ gen ?+ gen gen :: - $? [%brbc *] [%brcb *] [%brcl *] [%brdt *] [%brkt *] - [%brhp *] [%brsg *] [%brtr *] [%brts *] [%brwt *] == + $? [%brbc *] [%brcb *] [%brcl *] [%brdt *] [%brkt *] + [%brhp *] [%brsg *] [%brtr *] [%brts *] [%brwt *] == ?~ boy.wit gen [%note help+`u.boy.wit gen] From 37580fa7221ff727c61a09e2b39364144e3f9f6f Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Fri, 18 Mar 2022 17:03:02 -0400 Subject: [PATCH 039/249] hoon: doccords for tisfas wraps the skin in tisface with a %help skin --- pkg/arvo/sys/hoon.hoon | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index c962ec606..35f4bb258 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8216,7 +8216,7 @@ ?: =([~ ~ ~ ~] wit) gen ?+ gen gen - :: + :: bar runes $? [%brbc *] [%brcb *] [%brcl *] [%brdt *] [%brkt *] [%brhp *] [%brsg *] [%brtr *] [%brts *] [%brwt *] == ?~ boy.wit @@ -8232,6 +8232,13 @@ ?~ boy.wit [%brcn lab.wit q.gen] [%note help+`u.boy.wit [%brpt lab.wit q.gen]] + :: + :: tis runes + [%tsfs *] + ?~ boy.wit + gen + [%tsfs [%help `u.boy.wit p.gen] q.gen r.gen] +:: [%tsfs help+`u.boy.wit p.gen q.gen r.gen] == -- :: From e50635babd25fbabf70fa88183c835d2ed204bfb Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Fri, 18 Mar 2022 18:22:26 -0400 Subject: [PATCH 040/249] hoon: doccords wrap %rock %sand %wing %knit %bust wraps them in %note hoons --- pkg/arvo/sys/hoon.hoon | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 35f4bb258..42d15e896 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8215,10 +8215,18 @@ ^- hoon ?: =([~ ~ ~ ~] wit) gen + |^ ?+ gen gen + :: non-recursive hoons + :: %knit can contain hoons, but since its supposed to be printed as a + :: string, I think I can ignore the recursion? + $? [%rock *] [%sand *] [%wing *] [%knit *] [%bust *] == + wrap-boy + :: :: bar runes $? [%brbc *] [%brcb *] [%brcl *] [%brdt *] [%brkt *] [%brhp *] [%brsg *] [%brtr *] [%brts *] [%brwt *] == + :: TODO: handle recursion ?~ boy.wit gen [%note help+`u.boy.wit gen] @@ -8240,6 +8248,11 @@ [%tsfs [%help `u.boy.wit p.gen] q.gen r.gen] :: [%tsfs help+`u.boy.wit p.gen q.gen r.gen] == + :: + ++ wrap-boy + ?~ boy.wit gen + [%note help+`u.boy.wit gen] + -- -- :: ++ grip From 01de5a06b0aebe797570e4f137ee2b3e1eb24c18 Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 25 Mar 2022 13:45:29 +0100 Subject: [PATCH 041/249] term: consistently use x/y coordinate ordering %rez has always used "width & height". Certainly, "x & y" is more standard than "row & column". As such, we settle on making %hop and %hit respect the more natural ordering. This change is safe because these interfaces haven't made it to livenet yet. --- pkg/arvo/lib/hood/drum.hoon | 8 ++++---- pkg/arvo/mar/dill/blit.hoon | 2 +- pkg/arvo/sys/lull.hoon | 5 ++--- pkg/base-dev/lib/dill.hoon | 4 ++-- pkg/interface/webterm/Buffer.tsx | 2 +- pkg/interface/webterm/lib/blit.ts | 2 +- pkg/npm/api/term/types.ts | 4 ++-- pkg/urbit/vere/io/term.c | 8 +++++--- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 5399edeea..39ceb90db 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -685,13 +685,13 @@ (ta-hom %del pos.inp) :: ++ ta-hit :: hear click - |= [r=@ud c=@ud] + |= [x=@ud y=@ud] ^+ +> - ?. =(0 r) +> + ?. =(0 y) +> =/ pol=@ud (lent-char:klr (make:klr cad.pom)) - ?: (lth c pol) +>.$ - +>.$(pos.inp (min (sub c pol) (lent buf.say.inp))) + ?: (lth x pol) +>.$ + +>.$(pos.inp (min (sub x pol) (lent buf.say.inp))) :: ++ ta-erl :: hear local error |= pos=@ud diff --git a/pkg/arvo/mar/dill/blit.hoon b/pkg/arvo/mar/dill/blit.hoon index 5ec9b08cb..3ba85e3dc 100644 --- a/pkg/arvo/mar/dill/blit.hoon +++ b/pkg/arvo/mar/dill/blit.hoon @@ -21,7 +21,7 @@ %mor [%a (turn p.dib |=(a=dill-blit:dill json(dib a)))] %hop %+ frond %hop ?@ p.dib (numb p.dib) - (pairs 'r'^(numb r.p.dib) 'c'^(numb c.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) == diff --git a/pkg/arvo/sys/lull.hoon b/pkg/arvo/sys/lull.hoon index 32a1de2c5..3caace4f6 100644 --- a/pkg/arvo/sys/lull.hoon +++ b/pkg/arvo/sys/lull.hoon @@ -1080,13 +1080,13 @@ $% [%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 :: client output $% [%bel ~] :: make a noise [%clr ~] :: clear the screen - [%hop p=$@(@ud [r=@ud c=@ud])] :: set cursor col/pos + [%hop p=$@(@ud [x=@ud y=@ud])] :: set cursor col/pos [%klr p=stub] :: put styled [%mor p=(list blit)] :: multiple blits [%nel ~] :: newline @@ -1100,7 +1100,6 @@ $% belt :: client input [%cru p=@tas q=(list tank)] :: echo error [%hey ~] :: refresh - ::TODO inconsistent with %hit and %hop [%rez p=@ud q=@ud] :: resize, cols, rows [%yow p=gill:gall] :: connect to app == :: diff --git a/pkg/base-dev/lib/dill.hoon b/pkg/base-dev/lib/dill.hoon index d3592c07d..41608b263 100644 --- a/pkg/base-dev/lib/dill.hoon +++ b/pkg/base-dev/lib/dill.hoon @@ -13,7 +13,7 @@ %bel b+& %clr b+& %hop ?@ p.blit (numb p.blit) - (pairs 'r'^(numb r.p.blit) 'c'^(numb c.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 @@ -74,7 +74,7 @@ :~ aro+(su (perk %d %l %r %u ~)) bac+ul del+ul - hit+(ot 'r'^ni 'c'^ni ~) + hit+(ot 'x'^ni 'y'^ni ~) ret+ul == :: diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 067fd0cf9..67b8f03c6 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -90,7 +90,7 @@ const readInput = (term: Terminal, e: string): Belt[] => { if (1 === m) { const c = e.charCodeAt(2) - 32; const r = e.charCodeAt(3) - 32; - belts.push({ hit: { r: term.rows - r, c: c - 1 } }); + belts.push({ hit: { y: term.rows - r, x: c - 1 } }); } e = e.slice(3); break; diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts index 5285675f1..cd25de168 100644 --- a/pkg/interface/webterm/lib/blit.ts +++ b/pkg/interface/webterm/lib/blit.ts @@ -21,7 +21,7 @@ export const showBlit = (term: Terminal, blit: 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('H', term.rows - blit.hop.y, blit.hop.x + 1); } out += csi('s'); // save cursor position } else if ('put' in blit) { diff --git a/pkg/npm/api/term/types.ts b/pkg/npm/api/term/types.ts index 362973f31..2f352a728 100644 --- a/pkg/npm/api/term/types.ts +++ b/pkg/npm/api/term/types.ts @@ -25,7 +25,7 @@ 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 | { mor: Blit[] } // multiple blits | { nel: null } // newline @@ -43,7 +43,7 @@ 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 = diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index ba5775cbd..387e939ea 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -405,7 +405,7 @@ _term_it_show_blank(u3_utty* uty_u) * it is clipped to stay within the window. */ static void -_term_it_move_cursor(u3_utty* uty_u, c3_w row_w, c3_w col_w) +_term_it_move_cursor(u3_utty* uty_u, c3_w col_w, c3_w row_w) { c3_l row_l = uty_u->tat_u.siz.row_l; c3_l col_l = uty_u->tat_u.siz.col_l; @@ -698,7 +698,9 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) c3_y row_y = cay_y - 32; // only acknowledge button 1 presses within our window if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { - _term_io_belt(uty_u, u3nt(c3__hit, tat_u->siz.row_l - row_y, tat_u->esc.col_y - 1)); + _term_io_belt(uty_u, u3nt(c3__hit, + tat_u->esc.col_y - 1, + tat_u->siz.row_l - row_y)); } tat_u->esc.mou = c3n; tat_u->esc.ton_y = tat_u->esc.col_y = 0; @@ -1334,7 +1336,7 @@ _term_ef_blit(u3_utty* uty_u, case c3__hop: { u3_noun pos = u3t(blt); if ( c3y == u3r_ud(pos) ) { - _term_it_move_cursor(uty_u, 0, pos); + _term_it_move_cursor(uty_u, pos, 0); } else { _term_it_move_cursor(uty_u, u3h(pos), u3t(pos)); From 890e5f1e9b2b1a1128dd81c5492fd3b73315badc Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 25 Mar 2022 14:41:53 +0100 Subject: [PATCH 042/249] webterm: do not warn on session creation cancel --- pkg/interface/webterm/lib/useAddSession.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts index b740ebcc4..25a5fc0c2 100644 --- a/pkg/interface/webterm/lib/useAddSession.ts +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -17,8 +17,7 @@ export const useAddSession = () => { const userInput = prompt('Please enter an alpha-numeric session name.'); // user canceled or did not enter a value - if (!userInput) { - alert('A valid name is required to create a new session'); + if (null === userInput) { return; } From 8da6c20f700772af7c65825d1a1cf9f5b3179407 Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 25 Mar 2022 15:08:50 +0100 Subject: [PATCH 043/249] herm: stop sending %hail on-connect Client will probably want to send a %blew first anyway. By not doing any screen refreshed in herm, we avoid doing unnecessary redraws on-connect. --- pkg/arvo/app/herm.hoon | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/pkg/arvo/app/herm.hoon b/pkg/arvo/app/herm.hoon index 0d7f45a65..aefe6c8df 100644 --- a/pkg/arvo/app/herm.hoon +++ b/pkg/arvo/app/herm.hoon @@ -44,17 +44,12 @@ ~| path ?> ?=([%session @ %view ~] path) =* ses i.t.path - :~ :: subscribe to the requested session - :: - ::NOTE multiple views do not result in multiple subscriptions - :: because they go over the same wire/duct - :: - (pass-session ses %view ~) - :: tell session to refresh, so new client knows what's on screen - ::TODO should client be responsible for this? - :: - (pass-session ses %hail ~) - == + :: subscribe to the requested session + :: + ::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] From 60ed368bc4752b7244eb7d8bf6074f5b26699fa9 Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 25 Mar 2022 15:38:56 +0100 Subject: [PATCH 044/249] webterm: fix bell icon in tabs Presumably due to how js non-objects work in closures, the selected prop we were reading out whenever a blit came in was stale. Also, it was possible that a bell was hiding inside a %mor blit, so we add a small helper for checking properly. --- pkg/interface/webterm/Buffer.tsx | 5 +++-- pkg/interface/webterm/lib/blit.ts | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 67b8f03c6..8d5ae2ce7 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -12,7 +12,7 @@ import useTermState from './state'; import React from 'react'; import { Box, Col } from '@tlon/indigo-react'; import { makeTheme } from './lib/theme'; -import { showBlit, csi } from './lib/blit'; +import { showBlit, csi, hasBell } from './lib/blit'; import { DEFAULT_SESSION } from './constants'; import { retry } from './lib/retry'; @@ -180,7 +180,8 @@ export default function Buffer({ name, selected, dark }: BufferProps) { app: 'herm', path: '/session/' + name + '/view', event: (e) => { showBlit(ses.term, e); - if (e.bel && !selected) { + //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; }); diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts index cd25de168..e98f8fe75 100644 --- a/pkg/interface/webterm/lib/blit.ts +++ b/pkg/interface/webterm/lib/blit.ts @@ -73,3 +73,13 @@ export const showSlog = (term: Terminal, slog: string) => { + 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; + } +} From af7d38124be14d6f66f3486ea9a70b9853ef3cc6 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 30 Mar 2022 14:51:40 -0400 Subject: [PATCH 045/249] doccords: finding and print doccords library initial commit for library for finding and printing doccords. has some basic functionality for looking through a type and finding the docs within it and printing them, but is mostly unfinished --- pkg/arvo/lib/dprint.hoon | 204 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 pkg/arvo/lib/dprint.hoon diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon new file mode 100644 index 000000000..6695cad0d --- /dev/null +++ b/pkg/arvo/lib/dprint.hoon @@ -0,0 +1,204 @@ +:: A library for printing doccords +=> + |% + :> an overview of all named things in the type. + :> + :> each element in the overview list is either a documentation for a sublist + :> or an association betwen a term and documentation for it + +$ overview (list overview-item) + :: + :> an element of an overview + +$ overview-item + $% [%header doc=what children=overview] + [%item name=tape doc=what] + == + :: + :> the part of a type being inspected + +$ item + $% + :: overview of a type + :: + [%view items=overview] + :: inspecting a full core + $: %core + name=tape + docs=what + sut=type + con=coil + children=(unit item) + == + :: inspecting a single arm on a core + $: %arm + name=tape + docs=what + gen=hoon + sut=type + == + :: inspecting a face and what's behind it + $: %face + name=tape + docs=what + children=(unit item) + == + :: inspecting a single chapter on a core + $: %chapter + name=tape + docs=what + sut=type + con=coil + chapter-id=@ + == + == + :: + -- +|% +:: arms for finding docs in types +::+| %searching +:> returns the item to print while searching through topic +:> +:> this gate is called recursively to find the path (topic) in the type +:> (sut). once it finds the correct part of the type, it switches to +:> +build-inspectable-recursively to describe that part of the type +++ find-item-in-type + |= [topics=(list term) sut=type] + ^- (unit item) + ?~ topics + ~ ::(build-inspectable-recursively sut) + ?- sut + [%atom *] ~ + :: + [%cell *] + =+ lhs=$(sut p.sut) + ?~ lhs + $(sut q.sut) + lhs + :: + [%core *] + :: cores don't have any doc structure inside of them. i probably need to + :: check that they're wrapped with a %hint type. so this just looks for + :: docs on the arms + =+ arm=(find-arm-in-coil i.topics q.sut) + ?~ arm + :: the current topic is not an arm in the core + $(sut p.sut) + :: check to see if the arm is wrapped with a note + =+ wat=(unwrap-note u.arm) + `[%arm (trip i.topics) wat u.arm p.sut] + :: TODO: check for chapter docs + :: + [%face *] + ?. ?=(term p.sut) + :: TODO: handle tune case + ~ + ?. =(i.topics p.sut) + :: this face has a name, but not the one we're looking for + ~ + :: faces need to be checked to see if they're wrapped + ~ + :: + [%fork *] + =/ types=(list type) ~(tap in p.sut) + |- + ?~ types + ~ + =+ res=^$(sut i.types) + ?~ res + $(types t.types) + res + :: + [%hint *] + :: this is probably where most of the action should take place. it should + :: grab the docs from the hint and then look inside of the type to see where + :: it ought to go + ~ + :: + [%hold *] $(sut (~(play ut p.sut) q.sut)) + :: + %noun ~ + %void ~ + == +:: +:> checks if a hoon is wrapped with a help note, and returns it if so +++ unwrap-note + |= gen=hoon + ^- what + ?: ?=([%note *] gen) + ?: ?=([%help *] p.gen) + `crib.p.p.gen + ~ + ~ +:: +:> if arm-name is an arm in con, return its hoon and potentially the note wrapping it (?) +++ find-arm-in-coil + |= [arm-name=term con=coil] + ^- (unit hoon) + :: + =/ tomes=(list [p=term q=tome]) ~(tap by q.r.con) + |- + ?~ tomes + ~ + =+ item=(~(get by q.q.i.tomes) arm-name) + ?~ item + $(tomes t.tomes) +:: ?: =([%note *] u.item) :: the arm is wrapped with a %note +:: [~ p.u.item u.item] :: maybe i should check for the note later + `u.item +:: +:> gets the documentation inside of a type +++ docs-from-type + |= sut=type + ^- what + ?+ sut ~ + [%core *] ~ :: should this get the chapter docs? + [%hint *] ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) + [%hold *] $(sut (~(play ut p.sut) q.sut)) + == +:> grabs the docs for an arm. +++ select-arm-docs + |= [arm-doc=what fot=foot sut=type] + ^- [what what what] + =+ foot-type=(~(play ut sut) p.fot) + =/ raw-doc=what (docs-from-type foot-type) + :: if the arm builds a core, get the docs for the default arm + :: in that core + =/ core-doc=what + ?. ?=([%core *] foot-type) + ~ + (docs-from-type (~(play ut foot-type) [%limb %$])) + :: i think at least one of these will always be empty + :+ arm-doc raw-doc core-doc +:: +:: :> # +:: :> # %printing +:: :> # +:: :> functions which display output of various types +:: +| %printing +:: +:> renders a list of sections as tang +:> +:> prints the longform documentation +++ print-sections + |= sections=(list sect) + ^- tang + =| out=tang + |- + ?~ sections out + =. out + ;: weld + out + `tang`[%leaf ""]~ + (print-section i.sections) + == + $(sections t.sections) +:: +:> renders a sect as a tang +++ print-section + |= section=sect + ^- tang + %+ turn section + |= =pica + ^- tank + ?: p.pica + [%leaf (trip q.pica)] + [%leaf " {(trip q.pica)}"] +-- From 91aeb0fdbff20ab209284238de7478919209f895 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 30 Mar 2022 15:36:30 -0400 Subject: [PATCH 046/249] doccords: more printing tools --- pkg/arvo/lib/dprint.hoon | 110 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 6695cad0d..1cc1710e5 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -46,7 +46,7 @@ docs=what sut=type con=coil - chapter-id=@ + chapter-id=term == == :: @@ -155,9 +155,9 @@ == :> grabs the docs for an arm. ++ select-arm-docs - |= [arm-doc=what fot=foot sut=type] + |= [arm-doc=what gen=hoon sut=type] ^- [what what what] - =+ foot-type=(~(play ut sut) p.fot) + =+ foot-type=(~(play ut sut) gen) =/ raw-doc=what (docs-from-type foot-type) :: if the arm builds a core, get the docs for the default arm :: in that core @@ -168,11 +168,115 @@ :: i think at least one of these will always be empty :+ arm-doc raw-doc core-doc :: +:> returns an overview of the arms in a specific chapter +++ arms-in-chapter + |= [sut=type con=coil chapter-id=term] + ^- overview + =/ chapter-tome (~(got by q.r.con) chapter-id) + (sort-overview (arms-as-overview q.chapter-tome sut)) +:: +:> sort items in an overview in alphabetical order +++ sort-overview + |= ovr=overview + ^- overview + %+ sort ovr + |= [lhs=overview-item rhs=overview-item] + (aor (get-overview-name lhs) (get-overview-name rhs)) +:: +:> returns the name of an overview +++ get-overview-name + |= ovr=overview-item + ?- ovr + [%header *] "" + [%item *] name.ovr + == +:: +:> translate a tome into an overview +++ arms-as-overview + |= [a=(map term hoon) sut=type] + ^- overview + *overview +:: :: :> # :: :> # %printing :: :> # :: :> functions which display output of various types :: +| %printing +:> prints a doccords item +++ print-item + |= =item + ^- tang + ?- item + [%view *] (print-overview items.item) + [%core *] (print-core +.item) + [%arm *] (print-arm +.item) + [%chapter *] (print-chapter +.item) + [%face *] (print-face +.item) + == +:: +:> renders documentation for a full core +++ print-core + |= [name=tape docs=what sut=type con=coil uit=(unit item)] + ^- tang + *tang +:: +++ print-chapter + |= [name=tape doc=what sut=type con=coil chapter-id=term] + ^- tang + ;: weld + (print-header name doc) + :: + ?~ doc + ~ + (print-sections q.u.doc) + :: + =+ arms=(arms-in-chapter sut con chapter-id) + ?~ arms + ~ + (print-overview [%header `['arms:' ~] arms]~) + == +:: +:> renders documentation for a single arm in a core +++ print-arm + |= [name=tape docs=what gen=hoon sut=type] + ^- tang + =+ [main-doc raw-doc product-doc]=(select-arm-docs docs gen sut) + %+ weld + (print-header name main-doc) + ?~ product-doc + ~ + %+ weld + `tang`[[%leaf ""] [%leaf "product:"] ~] + (print-header "" product-doc) +:: +++ print-face + |= [name=tape doc=what children=(unit item)] + ^- tang + %+ weld + (print-header name doc) + ?~ children + ~ + (print-item u.children) +:: +++ print-header + |= [name=tape doc=what] + ^- tang + ?~ name + ?~ doc + [%leaf "(undocumented)"]~ + %+ weld + `tang`[%leaf "{(trip p.u.doc)}"]~ + (print-sections q.u.doc) + ?~ doc + [%leaf name]~ + %+ weld + `tang`[%leaf "{name}: {(trip p.u.doc)}"]~ + (print-sections q.u.doc) +:: +++ print-overview + |= ovr=overview + ^- tang + *tang :: :> renders a list of sections as tang :> From 1af2e8fdae68ce39703fb9bcb76421d8c9508ba3 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 14:39:09 -0400 Subject: [PATCH 047/249] doccords: dprint library unwrapping hints doesn't totally work yet --- pkg/arvo/lib/dprint.hoon | 244 ++++++++++++++++++++++++++++++++++----- 1 file changed, 215 insertions(+), 29 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 1cc1710e5..ee0d9fce5 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -1,4 +1,5 @@ :: A library for printing doccords +=/ debug & => |% :> an overview of all named things in the type. @@ -58,13 +59,17 @@ :> :> this gate is called recursively to find the path (topic) in the type :> (sut). once it finds the correct part of the type, it switches to -:> +build-inspectable-recursively to describe that part of the type +:> +signify to describe that part of the type ++ find-item-in-type - |= [topics=(list term) sut=type] + :: TODO make this work with a list of topics + |= [topic=term sut=type] ^- (unit item) - ?~ topics - ~ ::(build-inspectable-recursively sut) + :: ?~ topics + :: :: we have no more search paths TODO: return the rest as an overview + :: (signify sut) ?- sut + %noun ~ + %void ~ [%atom *] ~ :: [%cell *] @@ -77,20 +82,21 @@ :: cores don't have any doc structure inside of them. i probably need to :: check that they're wrapped with a %hint type. so this just looks for :: docs on the arms - =+ arm=(find-arm-in-coil i.topics q.sut) + =+ arm=(find-arm-in-coil topic q.sut) ?~ arm :: the current topic is not an arm in the core $(sut p.sut) :: check to see if the arm is wrapped with a note =+ wat=(unwrap-note u.arm) - `[%arm (trip i.topics) wat u.arm p.sut] + `[%arm (trip topic) wat u.arm p.sut] + :: `[%arm (trip topic) wat u.arm q.q.sut] :: what's the difference if i use the type in the coil? :: TODO: check for chapter docs :: [%face *] ?. ?=(term p.sut) :: TODO: handle tune case ~ - ?. =(i.topics p.sut) + ?. =(topic p.sut) :: this face has a name, but not the one we're looking for ~ :: faces need to be checked to see if they're wrapped @@ -107,18 +113,88 @@ res :: [%hint *] - :: this is probably where most of the action should take place. it should - :: grab the docs from the hint and then look inside of the type to see where - :: it ought to go - ~ + :: If we found a help hint, it is wrapping a type for which we might want to + :: produce an item, so we should peek inside of it to see what type it is + :: and grab the docs from +signify + :: + :: check to see if type inside the hint is a match + :: TODO: should i be trying to match both types in the hint? + :: TODO: actually hints can be nested, if e.g. an arm has a product with a hint, whose + :: product also has a hint. so this won't actually work for nested hints as written + ?: (shallow-match topic q.sut) + =/ wat=what (unwrap-hint sut) + =/ itm=(unit item) (signify q.sut) + ?~ itm + ~ + `(emblazen u.itm wat) +:: (emblazen (need (signify q.sut)) (unwrap-hint sut)) + $(sut q.sut) :: [%hold *] $(sut (~(play ut p.sut) q.sut)) :: - %noun ~ - %void ~ == :: -:> checks if a hoon is wrapped with a help note, and returns it if so +:> non-recursive check to see if type matches search +:> +:> this is for applying help hints to types when searching for a match. hints +:> are only for the type theyre immediately wrapping, not something nested +:> deeper, so we dont always want to recurse +++ shallow-match + |= [topic=term sut=type] + ^- ? + ?+ sut %.n + [%atom *] %.n :: should we allow doccords on individual atoms? i think they should be for faces + [%core *] !=(~ (find ~[topic] (sloe sut))) + [%face *] ?. ?=(term p.sut) + %.n :: TODO: handle tune case + =(topic p.sut) + == +:: +:> changes a type into a item +:> +:> this does not actually assign the docs, since they usually come from a hint +:> wrapping the type. +++ signify + |= sut=type + ^- (unit item) + ?- sut + :: + [%atom *] ~ + :: + [%cell *] + %+ join-items + $(sut p.sut) + $(sut q.sut) + :: + [%core *] + =/ name ~ :: should check if core is built with an arm and use that name? + =* compiled-against $(sut p.sut) + `[%core (trip name) *what p.sut q.sut compiled-against] + :: + [%face *] + ?. ?=(term p.sut) + :: TODO: handle tune case + ~ + =* compiled-against $(sut q.sut) + `[%face (trip p.sut) *what compiled-against] + :: + [%fork *] + =* types ~(tap in p.sut) + =* items (turn types signify) + (roll items join-items) + :: + [%hint *] + =* rest-type $(sut q.sut) + :: check to see if it is a help hint + ?> ?=(%help -.q.p.sut) + `[%view [%header `crib.p.q.p.sut (item-as-overview rest-type)]~] + :: + [%hold *] $(sut (~(play ut p.sut) q.sut)) + %noun ~ + %void ~ + == + +:> checks if a hoon is wrapped with a help note, and returns it if so ++ unwrap-note |= gen=hoon ^- what @@ -128,11 +204,41 @@ ~ ~ :: +:> checks if a hint type is a help hint and returns the docs if so +++ unwrap-hint + |= sut=type + ^- what + :: should I care what the type in the (pair type note) is? + ?. ?=([%hint *] sut) + ~? > debug %not-hint-type + ~ + ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) +:: +:> inserts docs into an item +:> +:> most docs are going to be found in hint types wrapping another type. when +:> we come across a hint, we grab the docs from the hint and then build the +:> item for the type it wrapped. since building an item is handled separately, +:> this item will initially have no docs in it, so we add it in after with this +:> +:> the exceptions to this are %chapter and %view items. chapters have an axis +:> for docs in their $tome structure, and %views are summaries of several types +++ emblazen + |= [=item =what] + ~? >> debug %emblazen + ^+ item + ?+ item item :: no-op on %chapter and %view + ?([%core *] [%arm *] [%face *]) ?~ docs.item + item(docs what) + ~? > debug %docs-in-item + item(docs what) + == +:: :> if arm-name is an arm in con, return its hoon and potentially the note wrapping it (?) ++ find-arm-in-coil |= [arm-name=term con=coil] + ~? >> debug %find-arm-in-coil ^- (unit hoon) - :: =/ tomes=(list [p=term q=tome]) ~(tap by q.r.con) |- ?~ tomes @@ -140,34 +246,73 @@ =+ item=(~(get by q.q.i.tomes) arm-name) ?~ item $(tomes t.tomes) -:: ?: =([%note *] u.item) :: the arm is wrapped with a %note -:: [~ p.u.item u.item] :: maybe i should check for the note later `u.item :: :> gets the documentation inside of a type ++ docs-from-type + :: TODO: the following comment doesn't appear because of some issue with product + :: docs, unless i erase the arm-doc + :> testing |= sut=type ^- what ?+ sut ~ - [%core *] ~ :: should this get the chapter docs? - [%hint *] ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) + [%core *] ~? >> debug %docs-from-type-core ~ :: should this get the chapter docs? + [%hint *] ~? >> debug %docs-from-type-hint ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) [%hold *] $(sut (~(play ut p.sut) q.sut)) == +:: :> grabs the docs for an arm. +:> +:> there are three possible places with relevant docs for an arm: +:> docs for the arm itself, docs for the product of the arm, and +:> if the arm builds a core, docs for the default arm of that core. +:> arm-doc: docs wrapping the arm - this should have already been found +:> raw-doc: docs for the product of the arm +:> core-doc: docs for the default arm of the core produced by the arm ++ select-arm-docs |= [arm-doc=what gen=hoon sut=type] + ~? >> debug %select-arm-docs ^- [what what what] - =+ foot-type=(~(play ut sut) gen) - =/ raw-doc=what (docs-from-type foot-type) + =+ hoon-type=(~(play ut sut) gen) + ~? >>> debug hoon-type + =/ raw-doc=what (docs-from-type hoon-type) + ~? > debug raw-doc :: if the arm builds a core, get the docs for the default arm :: in that core =/ core-doc=what - ?. ?=([%core *] foot-type) + ?. ?=([%core *] hoon-type) + ~? > debug %no-core-product ~ - (docs-from-type (~(play ut foot-type) [%limb %$])) - :: i think at least one of these will always be empty + (docs-from-type (~(play ut hoon-type) [%limb %$])) + :: i think arm-doc and raw-doc might always be the same + ~? > debug :+ arm-doc raw-doc core-doc :+ arm-doc raw-doc core-doc :: +:> returns an overview for a cores arms and chapters +:> +:> returns an overview for arms which are part of unnamed chapters, and +:> an overview of the named chapters +++ arm-and-chapter-overviews + |= [sut=type con=coil core-name=tape] + ^- [overview overview] + =| arm-docs=overview + =| chapter-docs=overview + =/ tomes ~(tap by q.r.con) + |- + ?~ tomes + [(sort-overview arm-docs) (sort-overview chapter-docs)] + =* current i.tomes ::[term tome] + ?~ p.current + :: chapter has no name. add documentation for its arms to arm-docs + =. arm-docs (weld arm-docs (arms-as-overview q.q.current sut)) + $(tomes t.tomes) + :: chapter has a name. add to list of chapters + =. chapter-docs + %+ weld chapter-docs + ^- overview + [%item :(weld (trip -.current) ":" core-name) p.q.current]~ + $(tomes t.tomes) +:: :> returns an overview of the arms in a specific chapter ++ arms-in-chapter |= [sut=type con=coil chapter-id=term] @@ -180,8 +325,8 @@ |= ovr=overview ^- overview %+ sort ovr - |= [lhs=overview-item rhs=overview-item] - (aor (get-overview-name lhs) (get-overview-name rhs)) + |= [lhs=overview-item rhs=overview-item] + (aor (get-overview-name lhs) (get-overview-name rhs)) :: :> returns the name of an overview ++ get-overview-name @@ -193,10 +338,49 @@ :: :> translate a tome into an overview ++ arms-as-overview + :: currently this doesn't do anything until i implement arm-doc |= [a=(map term hoon) sut=type] ^- overview - *overview + %+ turn ~(tap by a) + |= ar=(pair term hoon) + =/ doc (select-arm-docs *what q.ar sut) :: *what should be from the hint wrapper + [%item (weld "++" (trip p.ar)) -.doc] :: +:> changes an item into an overview +++ item-as-overview + |= uit=(unit item) + ^- overview + ?~ uit ~ + =+ itm=(need uit) + ?- itm + :: + [%view *] items.itm + :: + [%core *] + ?~ name.itm + (item-as-overview children.itm) + :- [%item name.itm docs.itm] + (item-as-overview children.itm) + :: + [%arm *] + [%item name.itm docs.itm]~ + :: + [%chapter *] + [%item name.itm docs.itm]~ + :: + [%face *] + ?~ name.itm + ~ + [%item name.itm docs.itm]~ + == +:: +:> combines two (unit items) together +++ join-items + |= [lhs=(unit item) rhs=(unit item)] + ^- (unit item) + ?~ lhs rhs + ?~ rhs lhs + `[%view (weld (item-as-overview lhs) (item-as-overview rhs))] :: :> # :: :> # %printing :: :> # @@ -240,15 +424,17 @@ ++ print-arm |= [name=tape docs=what gen=hoon sut=type] ^- tang + ~? >> debug %print-arm =+ [main-doc raw-doc product-doc]=(select-arm-docs docs gen sut) %+ weld (print-header name main-doc) - ?~ product-doc - ~ + :: ?~ product-doc + :: ~ %+ weld `tang`[[%leaf ""] [%leaf "product:"] ~] (print-header "" product-doc) :: +:> renders documentation for a face ++ print-face |= [name=tape doc=what children=(unit item)] ^- tang From 752182f0bf76e438e05f2d814e47ea9791e3bdce Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 17:33:59 -0400 Subject: [PATCH 048/249] doccords: dprint fix default core arm printing if the product had its own docs, it wouldn't also get the docs for a the default arm produced by the core. this fixes that. also misc style fixes --- pkg/arvo/lib/dprint.hoon | 103 ++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 39 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index ee0d9fce5..12c30c4b7 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -81,12 +81,19 @@ [%core *] :: cores don't have any doc structure inside of them. i probably need to :: check that they're wrapped with a %hint type. so this just looks for - :: docs on the arms + :: docs on the arms. + :: + :: cores also can't have names right now. %brcn and %brpt have a slot in + :: their AST for the name, but it doesn't end up in the their type. so + :: if i want core names right now, i'd have to look inside their AST, and + :: only |% and |@ cores would have names, which is silly. =+ arm=(find-arm-in-coil topic q.sut) ?~ arm :: the current topic is not an arm in the core $(sut p.sut) :: check to see if the arm is wrapped with a note + :: TODO: this is taking docs from the AST rather than the type. is that + :: the right thing to do here? =+ wat=(unwrap-note u.arm) `[%arm (trip topic) wat u.arm p.sut] :: `[%arm (trip topic) wat u.arm q.q.sut] :: what's the difference if i use the type in the coil? @@ -126,8 +133,8 @@ =/ itm=(unit item) (signify q.sut) ?~ itm ~ - `(emblazen u.itm wat) -:: (emblazen (need (signify q.sut)) (unwrap-hint sut)) + `(emblazon u.itm wat) +:: (emblazon (need (signify q.sut)) (unwrap-hint sut)) $(sut q.sut) :: [%hold *] $(sut (~(play ut p.sut) q.sut)) @@ -157,10 +164,10 @@ ++ signify |= sut=type ^- (unit item) - ?- sut + ?- sut :: [%atom *] ~ - :: + :: [%cell *] %+ join-items $(sut p.sut) @@ -171,27 +178,26 @@ =* compiled-against $(sut p.sut) `[%core (trip name) *what p.sut q.sut compiled-against] :: - [%face *] + [%face *] ?. ?=(term p.sut) - :: TODO: handle tune case - ~ + ~ :: TODO: handle tune case =* compiled-against $(sut q.sut) `[%face (trip p.sut) *what compiled-against] :: - [%fork *] - =* types ~(tap in p.sut) - =* items (turn types signify) - (roll items join-items) - :: - [%hint *] - =* rest-type $(sut q.sut) - :: check to see if it is a help hint - ?> ?=(%help -.q.p.sut) - `[%view [%header `crib.p.q.p.sut (item-as-overview rest-type)]~] - :: - [%hold *] $(sut (~(play ut p.sut) q.sut)) - %noun ~ - %void ~ + [%fork *] + =* types ~(tap in p.sut) + =* items (turn types signify) + (roll items join-items) + :: + [%hint *] + =* rest-type $(sut q.sut) + :: check to see if it is a help hint + ?> ?=(%help -.q.p.sut) + `[%view [%header `crib.p.q.p.sut (item-as-overview rest-type)]~] + :: + [%hold *] $(sut (~(play ut p.sut) q.sut)) + %noun ~ + %void ~ == :> checks if a hoon is wrapped with a help note, and returns it if so @@ -223,9 +229,9 @@ :> :> the exceptions to this are %chapter and %view items. chapters have an axis :> for docs in their $tome structure, and %views are summaries of several types -++ emblazen +++ emblazon |= [=item =what] - ~? >> debug %emblazen + ~? >> debug %emblazon ^+ item ?+ item item :: no-op on %chapter and %view ?([%core *] [%arm *] [%face *]) ?~ docs.item @@ -234,7 +240,7 @@ item(docs what) == :: -:> if arm-name is an arm in con, return its hoon and potentially the note wrapping it (?) +:> looks for an arm in a coil and returns its hoon ++ find-arm-in-coil |= [arm-name=term con=coil] ~? >> debug %find-arm-in-coil @@ -243,10 +249,10 @@ |- ?~ tomes ~ - =+ item=(~(get by q.q.i.tomes) arm-name) - ?~ item + =+ gen=(~(get by q.q.i.tomes) arm-name) + ?~ gen $(tomes t.tomes) - `u.item + `u.gen :: :> gets the documentation inside of a type ++ docs-from-type @@ -258,7 +264,7 @@ ?+ sut ~ [%core *] ~? >> debug %docs-from-type-core ~ :: should this get the chapter docs? [%hint *] ~? >> debug %docs-from-type-hint ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) - [%hold *] $(sut (~(play ut p.sut) q.sut)) + [%hold *] ~? >> debug %docs-from-type-hold $(sut (~(play ut p.sut) q.sut)) == :: :> grabs the docs for an arm. @@ -266,8 +272,9 @@ :> there are three possible places with relevant docs for an arm: :> docs for the arm itself, docs for the product of the arm, and :> if the arm builds a core, docs for the default arm of that core. +:> :> arm-doc: docs wrapping the arm - this should have already been found -:> raw-doc: docs for the product of the arm +:> product-doc: docs for the product of the arm :> core-doc: docs for the default arm of the core produced by the arm ++ select-arm-docs |= [arm-doc=what gen=hoon sut=type] @@ -275,18 +282,36 @@ ^- [what what what] =+ hoon-type=(~(play ut sut) gen) ~? >>> debug hoon-type - =/ raw-doc=what (docs-from-type hoon-type) - ~? > debug raw-doc + =/ product-doc=what (docs-from-type hoon-type) + ~? > debug product-doc :: if the arm builds a core, get the docs for the default arm :: in that core + :: + :: this is broken if it also has an arm-doc. if i have an arm-doc, i + :: need to strip off the first hint and then check if i have a core, i think =/ core-doc=what - ?. ?=([%core *] hoon-type) - ~? > debug %no-core-product - ~ - (docs-from-type (~(play ut hoon-type) [%limb %$])) - :: i think arm-doc and raw-doc might always be the same - ~? > debug :+ arm-doc raw-doc core-doc - :+ arm-doc raw-doc core-doc + :: if product-doc is empty, just go right on and check if its a core + ?~ product-doc + ?. ?=([%core *] hoon-type) + ~? > debug %no-core-product + ~ + (docs-from-type (~(play ut hoon-type) [%limb %$])) + :: if there is a product doc, then step through the hint and check for a core + ?: ?=([%hint *] hoon-type) + ~? > debug %step-through-hint + =+ inner-type=(~(play ut q.hoon-type) gen) + :: using mule since it crashes if there's not a core + =/ res (mule |.((~(play ut inner-type) [%limb %$]))) + ?- -.res + %| ~ + %& (docs-from-type p.res) + == + ~ + :: i think arm-doc and product-doc might always be the same + :: upon further reflection, i think this is a limitation of the wrapping + :: approach + ~? > debug :* %arm-doc arm-doc %product-doc product-doc %core-doc core-doc == + :+ arm-doc product-doc core-doc :: :> returns an overview for a cores arms and chapters :> From d9e44e9e761f3b41152c7e6a85b70a9b69801ebe Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 17:35:50 -0400 Subject: [PATCH 049/249] doccords: dprint print core routine --- pkg/arvo/lib/dprint.hoon | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 12c30c4b7..68dabe63c 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -427,7 +427,24 @@ ++ print-core |= [name=tape docs=what sut=type con=coil uit=(unit item)] ^- tang - *tang + =+ [arms chapters]=(arm-and-chapter-overviews sut con name) + ;: weld + :: cores don't have names + (print-header *tape *what) + :: + ?~ arms + ~ + (print-overview [%header `['arms:' ~] arms]~) + :: + ?~ chapters + ~ + (print-overview [%header `['chapters:' ~] chapters]~) + :: + =+ compiled=(item-as-overview uit) + ?~ compiled + ~ + (print-overview [%header `['compiled against: ' ~] compiled]~) + == :: ++ print-chapter |= [name=tape doc=what sut=type con=coil chapter-id=term] From f9dfb590d6c8b30dc15777ad8ddc0e5fe4c57aa2 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 17:41:48 -0400 Subject: [PATCH 050/249] hoon: turn on hints for %noun types --- pkg/arvo/sys/hoon.hoon | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 42d15e896..04607d81b 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -7199,7 +7199,6 @@ |= [p=(pair type note) q=type] ^- type ?: =(%void q) %void - ?: =(%noun q) %noun [%hint p q] :: ++ face :: make %face type From a15711c74d95d3eb3294df9cee080e48ddb39288 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 17:59:45 -0400 Subject: [PATCH 051/249] doccords: dprint fix crash on non-help %hint --- pkg/arvo/lib/dprint.hoon | 45 ++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 68dabe63c..b2b0272f0 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -255,16 +255,22 @@ `u.gen :: :> gets the documentation inside of a type -++ docs-from-type - :: TODO: the following comment doesn't appear because of some issue with product - :: docs, unless i erase the arm-doc +++ what-from-type :> testing |= sut=type ^- what - ?+ sut ~ - [%core *] ~? >> debug %docs-from-type-core ~ :: should this get the chapter docs? - [%hint *] ~? >> debug %docs-from-type-hint ?>(?=(%help -.q.p.sut) `crib.p.q.p.sut) - [%hold *] ~? >> debug %docs-from-type-hold $(sut (~(play ut p.sut) q.sut)) + ?+ sut + ~ + :: + [%core *] + ~? >> debug %what-from-type-core ~ :: should this get the chapter docs? + :: + [%hold *] + ~? >> debug %what-from-type-hold $(sut (~(play ut p.sut) q.sut)) + :: + [%hint *] + ~? >> debug :- %what-from-type-hint -.q.p.sut + ?: ?=(%help -.q.p.sut) `crib.p.q.p.sut ~ == :: :> grabs the docs for an arm. @@ -282,7 +288,7 @@ ^- [what what what] =+ hoon-type=(~(play ut sut) gen) ~? >>> debug hoon-type - =/ product-doc=what (docs-from-type hoon-type) + =/ product-doc=what (what-from-type hoon-type) ~? > debug product-doc :: if the arm builds a core, get the docs for the default arm :: in that core @@ -295,7 +301,7 @@ ?. ?=([%core *] hoon-type) ~? > debug %no-core-product ~ - (docs-from-type (~(play ut hoon-type) [%limb %$])) + (what-from-type (~(play ut hoon-type) [%limb %$])) :: if there is a product doc, then step through the hint and check for a core ?: ?=([%hint *] hoon-type) ~? > debug %step-through-hint @@ -304,13 +310,16 @@ =/ res (mule |.((~(play ut inner-type) [%limb %$]))) ?- -.res %| ~ - %& (docs-from-type p.res) + %& (what-from-type p.res) == ~ :: i think arm-doc and product-doc might always be the same :: upon further reflection, i think this is a limitation of the wrapping :: approach - ~? > debug :* %arm-doc arm-doc %product-doc product-doc %core-doc core-doc == + ~? > debug :* %arm-doc arm-doc + %product-doc product-doc + %core-doc core-doc + == :+ arm-doc product-doc core-doc :: :> returns an overview for a cores arms and chapters @@ -467,14 +476,14 @@ |= [name=tape docs=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm - =+ [main-doc raw-doc product-doc]=(select-arm-docs docs gen sut) - %+ weld + =+ [main-doc product-doc core-doc]=(select-arm-docs docs gen sut) + ;: weld (print-header name main-doc) - :: ?~ product-doc - :: ~ - %+ weld - `tang`[[%leaf ""] [%leaf "product:"] ~] - (print-header "" product-doc) + `tang`[[%leaf ""] [%leaf "product:"] ~] + (print-header "" product-doc) + `tang`[[%leaf ""] [%leaf "default arm in core:"] ~] + (print-header "" core-doc) + == :: :> renders documentation for a face ++ print-face From edfcceb1d950a65409c48e7a3e29cbdfed4cb7f4 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 31 Mar 2022 18:45:28 -0400 Subject: [PATCH 052/249] doccords: dprint print overview also adds another mule to a play:ut call to avoid another crash that i'm not sure yet why it is happening --- pkg/arvo/lib/dprint.hoon | 61 ++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index b2b0272f0..243e06953 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -287,7 +287,7 @@ ~? >> debug %select-arm-docs ^- [what what what] =+ hoon-type=(~(play ut sut) gen) - ~? >>> debug hoon-type + ::~? >>> debug hoon-type =/ product-doc=what (what-from-type hoon-type) ~? > debug product-doc :: if the arm builds a core, get the docs for the default arm @@ -305,20 +305,28 @@ :: if there is a product doc, then step through the hint and check for a core ?: ?=([%hint *] hoon-type) ~? > debug %step-through-hint - =+ inner-type=(~(play ut q.hoon-type) gen) - :: using mule since it crashes if there's not a core - =/ res (mule |.((~(play ut inner-type) [%limb %$]))) - ?- -.res - %| ~ - %& (what-from-type p.res) + ::=+ inner-type=(~(play ut q.hoon-type) gen) + ::=/ res (mule |.((~(play ut inner-type) [%limb %$]))) + :: pretty sure having to use mule twice here means im doing something wrong + =/ h-res (mule |.((~(play ut q.hoon-type) gen))) + ?- -.h-res + %| + ~ + :: + %& + =/ in-res (mule |.((~(play ut p.h-res) [%limb %$]))) + ?- -.in-res + %| ~ + %& (what-from-type p.in-res) + == == ~ :: i think arm-doc and product-doc might always be the same :: upon further reflection, i think this is a limitation of the wrapping :: approach - ~? > debug :* %arm-doc arm-doc + ~? > debug :* %arm-doc arm-doc %product-doc product-doc - %core-doc core-doc + %core-doc core-doc == :+ arm-doc product-doc core-doc :: @@ -495,6 +503,7 @@ ~ (print-item u.children) :: +:> prints name and docs only ++ print-header |= [name=tape doc=what] ^- tang @@ -511,9 +520,39 @@ (print-sections q.u.doc) :: ++ print-overview - |= ovr=overview + |= =overview ^- tang - *tang + =| out=tang + |- + ?~ overview out + =/ oitem i.overview + ?- oitem + [%header *] + %= $ + overview t.overview + out ;: weld + out + ?~ doc.oitem ~ + `tang`[[%leaf ""] [%leaf "{(trip p.u.doc.oitem)}"] ~] + ?~ doc.oitem ~ + (print-sections q.u.doc.oitem) + ^$(overview children.oitem) + == + == + :: + [%item *] + %= $ + overview t.overview + out ;: weld + out + `tang`[[%leaf ""] [%leaf name.oitem] ~] + ?~ doc.oitem ~ + `tang`[[%leaf ""] [%leaf "{(trip p.u.doc.oitem)}"] ~] + ?~ doc.oitem ~ + (print-sections q.u.doc.oitem) + == + == + == :: :> renders a list of sections as tang :> From 531fd61ace550154ff8dfb1e2d8f1ebc96477a4f Mon Sep 17 00:00:00 2001 From: tomholford Date: Fri, 1 Apr 2022 06:59:39 -0700 Subject: [PATCH 053/249] ux: add info modal Add a new tab to the top bar that shows an alert with a brief usage guide. --- pkg/interface/webterm/App.tsx | 6 ++++- pkg/interface/webterm/InfoButton.tsx | 19 ++++++++++++++++ pkg/interface/webterm/Tabs.tsx | 8 ++++++- pkg/interface/webterm/index.html | 34 +++++++++++++++++++++++++++- 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 pkg/interface/webterm/InfoButton.tsx diff --git a/pkg/interface/webterm/App.tsx b/pkg/interface/webterm/App.tsx index 9ce3b0c00..c8dee297c 100644 --- a/pkg/interface/webterm/App.tsx +++ b/pkg/interface/webterm/App.tsx @@ -19,6 +19,7 @@ import { Tabs } from './Tabs'; import Buffer from './Buffer'; import { DEFAULT_SESSION } from './constants'; import { showSlog } from './lib/blit'; +import { InfoButton } from './InfoButton'; export default function TermApp() { const { names, selected } = useTermState(); @@ -78,7 +79,10 @@ export default function TermApp() { return ( <> - +
+ + +
{names.map((name) => { return ; diff --git a/pkg/interface/webterm/InfoButton.tsx b/pkg/interface/webterm/InfoButton.tsx new file mode 100644 index 000000000..4ec3a3347 --- /dev/null +++ b/pkg/interface/webterm/InfoButton.tsx @@ -0,0 +1,19 @@ +import React, { useCallback } from 'react'; +import { Icon } from '@tlon/indigo-react'; + +export const InfoButton = () => { + const onInfoClick = useCallback(() => { + alert('To select text in the terminal, hold down the alt key.'); + }, []); + + return ( + <> + + + ); +}; diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx index 09751537a..3b0cd0a0f 100644 --- a/pkg/interface/webterm/Tabs.tsx +++ b/pkg/interface/webterm/Tabs.tsx @@ -2,6 +2,7 @@ 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(); @@ -14,7 +15,12 @@ export const Tabs = () => { ); })} - +
); }; diff --git a/pkg/interface/webterm/index.html b/pkg/interface/webterm/index.html index e2f4a18c2..1ab870732 100644 --- a/pkg/interface/webterm/index.html +++ b/pkg/interface/webterm/index.html @@ -32,7 +32,19 @@ height: calc(100% - 40px); } + 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; @@ -71,6 +83,15 @@ 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) { div.tabs { background-color: rgb(26, 26, 26); @@ -78,14 +99,25 @@ border-bottom-color: rgba(255, 255, 255, 0.9); } - div.tab, button.tab { + 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: black solid 1px; + } + + button.info-btn { + border-bottom: solid rgba(255, 255, 255, 0.9) 1px; + background: rgb(26, 26, 26); } } From c5b07f520379614e183285cd437763bf4146ab2a Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 1 Apr 2022 22:15:34 +0200 Subject: [PATCH 054/249] term: batch simple input events into a single %txt By accumulating %txt events until we reach a more complex event or reach the end of the input buffer, we can significantly reduce the "overhead" of pasting text into the terminal. Instead of an event for each character, we now inject up to a buffer's worth of characters (currently, 123 bytes) at a time. This makes pasting process much faster. Incidentally, the behavior for pasting text with syntax errors into the dojo may be a little bit surprising: after every buffer boundary, the dojo will complain about the syntax error, moving the cursor to its location, and causing the remainder of the text to be inserted in that position. This may result in garbled-looking input in some cases. This ux problem should be resolved on dojo's end, perhaps by highlighting syntax errors with color, instead of the cursor. Alleviates most of the need for #5687. --- pkg/urbit/include/vere/vere.h | 9 ++++--- pkg/urbit/vere/io/term.c | 47 +++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index 023635f35..3d7c0b030 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -158,10 +158,11 @@ c3_y col_y; // column coordinate } 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 { diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index 387e939ea..f4039bf8b 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -147,6 +147,7 @@ u3_term_log_init(void) uty_u->tat_u.fut.len_w = 0; uty_u->tat_u.fut.wid_w = 0; + uty_u->tat_u.fut.imp = u3_nul; } // default size @@ -636,9 +637,28 @@ _term_io_belt(u3_utty* uty_u, u3_noun blb) } } -/* _term_io_suck_char(): process a single character. +/* _term_io_spit(): input the buffer (if any), then input the belt (if any) */ static void +_term_io_spit(u3_utty* uty_u, u3_noun bet) { + u3_utat* tat_u = &uty_u->tat_u; + if (u3_nul != tat_u->fut.imp) { + _term_io_belt(uty_u, u3nc(c3__txt, u3kb_flop(tat_u->fut.imp))); + tat_u->fut.imp = u3_nul; + } + if (u3_none != bet) { + _term_io_belt(uty_u, bet); + } +} + +/* _term_io_suck_char(): process a single character. + * + * Note that this accumulates simple inputs in a buffer, and is not + * guaranteed to flush it fully. After a call (or sequence of calls) + * to this function, please call _term_io_spit(uty_u, u3_none) to + * flush any remainder. + */ +static void _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) { u3_utat* tat_u = &uty_u->tat_u; @@ -652,10 +672,10 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); break; } - case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break; - case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break; - case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break; - case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break; + case 'A': _term_io_spit(uty_u, u3nc(c3__aro, 'u')); break; + case 'B': _term_io_spit(uty_u, u3nc(c3__aro, 'd')); break; + case 'C': _term_io_spit(uty_u, u3nc(c3__aro, 'r')); break; + case 'D': _term_io_spit(uty_u, u3nc(c3__aro, 'l')); break; // case 'M': tat_u->esc.mou = c3y; break; } @@ -667,13 +687,13 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) // XX for backwards compatibility, check kelvin version // and fallback to [%met @c] // - _term_io_belt(uty_u, u3nt(c3__mod, c3__met, cay_y)); + _term_io_spit(uty_u, u3nt(c3__mod, c3__met, cay_y)); } else if ( 8 == cay_y || 127 == cay_y ) { tat_u->esc.ape = c3n; // XX backwards compatibility [%met @c] // - _term_io_belt(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); + _term_io_spit(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); } else if ( ('[' == cay_y) || ('O' == cay_y) ) { tat_u->esc.bra = c3y; @@ -698,7 +718,7 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) c3_y row_y = cay_y - 32; // only acknowledge button 1 presses within our window if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { - _term_io_belt(uty_u, u3nt(c3__hit, + _term_io_spit(uty_u, u3nt(c3__hit, tat_u->esc.col_y - 1, tat_u->siz.row_l - row_y)); } @@ -720,28 +740,28 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) wug = u3do("taft", huv); tat_u->fut.len_w = tat_u->fut.wid_w = 0; - _term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul)); + tat_u->fut.imp = u3nc(wug, tat_u->fut.imp); } } // individual characters // else { if ( (cay_y >= 32) && (cay_y < 127) ) { // visual ascii - _term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul)); + tat_u->fut.imp = u3nc(cay_y, tat_u->fut.imp); } else if ( 0 == cay_y ) { // null _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } else if ( 8 == cay_y || 127 == cay_y ) { // backspace & delete - _term_io_belt(uty_u, u3nc(c3__bac, u3_nul)); + _term_io_spit(uty_u, u3nc(c3__bac, u3_nul)); } else if ( 10 == cay_y || 13 == cay_y ) { // newline & carriage return - _term_io_belt(uty_u, u3nc(c3__ret, u3_nul)); + _term_io_spit(uty_u, u3nc(c3__ret, u3_nul)); } else if ( cay_y <= 26 ) { // XX backwards compatibility [%ctl @c] // - _term_io_belt(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); + _term_io_spit(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); } else if ( 27 == cay_y ) { tat_u->esc.ape = c3y; @@ -799,6 +819,7 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i) for ( i=0; i < siz_i; i++ ) { _term_io_suck_char(uty_u, buf[i]); } + _term_io_spit(uty_u, u3_none); } } } From 064b15e5a01e3f466f33bd8bc87a00a9d838834c Mon Sep 17 00:00:00 2001 From: fang Date: Sun, 3 Apr 2022 21:38:09 +0200 Subject: [PATCH 055/249] term: move coordinate origin to top left Having the origin at the top left instead of the bottom left is more conventional and ergonomic. The only thing this complicates is prompt-specific logic, where we care about the coordinates of the bottom-most line on the screen. For that reason, the bulk of the changes here are in vere, where we treat the bottom-most line specially, drawing the spinner onto it. Webterm is likewise updated to account for the new coordinate system. Drum now opts to accept clicks anywhere on the screen, and does its best to move the cursor as close to the clicked location as possible (within the confines of the prompt). --- pkg/arvo/lib/hood/drum.hoon | 3 +-- pkg/interface/webterm/Buffer.tsx | 2 +- pkg/interface/webterm/lib/blit.ts | 2 +- pkg/urbit/vere/io/term.c | 29 ++++++++++++++--------------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 39ceb90db..1914b69fa 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -687,10 +687,9 @@ ++ ta-hit :: hear click |= [x=@ud y=@ud] ^+ +> - ?. =(0 y) +> =/ pol=@ud (lent-char:klr (make:klr cad.pom)) - ?: (lth x pol) +>.$ + =? x (lth x pol) pol +>.$(pos.inp (min (sub x pol) (lent buf.say.inp))) :: ++ ta-erl :: hear local error diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 8d5ae2ce7..da4a8e8a6 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -90,7 +90,7 @@ const readInput = (term: Terminal, e: string): Belt[] => { if (1 === m) { const c = e.charCodeAt(2) - 32; const r = e.charCodeAt(3) - 32; - belts.push({ hit: { y: term.rows - r, x: c - 1 } }); + belts.push({ hit: { y: r - 1, x: c - 1 } }); } e = e.slice(3); break; diff --git a/pkg/interface/webterm/lib/blit.ts b/pkg/interface/webterm/lib/blit.ts index e98f8fe75..a34e75900 100644 --- a/pkg/interface/webterm/lib/blit.ts +++ b/pkg/interface/webterm/lib/blit.ts @@ -21,7 +21,7 @@ export const showBlit = (term: Terminal, blit: Blit) => { if (typeof blit.hop === 'number') { out += csi('H', term.rows, blit.hop + 1); } else { - out += csi('H', term.rows - blit.hop.y, blit.hop.x + 1); + out += csi('H', blit.hop.y + 1, blit.hop.x + 1); } out += csi('s'); // save cursor position } else if ('put' in blit) { diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index f4039bf8b..a653a6bcb 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -385,7 +385,7 @@ _term_it_clear_line(u3_utty* uty_u) // if we're clearing the bottom line, clear our mirror of it too // - if ( 0 == uty_u->tat_u.mir.rus_w ) { + if ( uty_u->tat_u.siz.row_l - 1 == uty_u->tat_u.mir.rus_w ) { _term_it_free_line(uty_u); } } @@ -401,7 +401,7 @@ _term_it_show_blank(u3_utty* uty_u) /* _term_it_move_cursor(): move cursor to row & column * - * row 0 is at the bottom, col 0 is to the left. + * row 0 is at the top, col 0 is to the left. * if the given position exceeds the known window size, * it is clipped to stay within the window. */ @@ -413,7 +413,7 @@ _term_it_move_cursor(u3_utty* uty_u, c3_w col_w, c3_w row_w) if ( row_w >= row_l ) { row_w = row_l - 1; } if ( col_w >= col_l ) { col_w = col_l - 1; } - _term_it_send_csi(uty_u, 'H', 2, row_l - row_w, col_w + 1); + _term_it_send_csi(uty_u, 'H', 2, row_w + 1, col_w + 1); _term_it_dump_buf(uty_u, &uty_u->ufo_u.suc_u); uty_u->tat_u.mir.rus_w = row_w; @@ -473,7 +473,7 @@ _term_it_restore_line(u3_utty* uty_u) { u3_utat* tat_u = &uty_u->tat_u; - _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 0); + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 1); _term_it_dump_buf(uty_u, &uty_u->ufo_u.cel_u); _term_it_send_stub(uty_u, u3k(tat_u->mir.lin)); //NOTE send_stub restores cursor position @@ -490,7 +490,8 @@ _term_it_save_stub(u3_utty* uty_u, u3_noun tub) // keep track of changes to bottom-most line, to aid spinner drawing logic. // -t mode doesn't need this logic, because it doesn't render the spinner. // - if ( (0 == tat_u->mir.rus_w) && (c3n == u3_Host.ops_u.tem)) { + if ( ( tat_u->siz.row_l - 1 == tat_u->mir.rus_w ) && + ( c3n == u3_Host.ops_u.tem ) ) { lin = u3dq("wail:klr:format", lin, tat_u->mir.cus_w, u3k(tub), ' '); lin = u3do("pact:klr:format", lin); } @@ -513,8 +514,8 @@ _term_it_show_nel(u3_utty* uty_u) } uty_u->tat_u.mir.cus_w = 0; - if ( uty_u->tat_u.mir.rus_w > 0 ) { - uty_u->tat_u.mir.rus_w--; + if ( uty_u->tat_u.mir.rus_w < uty_u->tat_u.siz.row_l - 1 ) { + uty_u->tat_u.mir.rus_w++; } else { // newline at bottom of screen, so bottom line is now empty @@ -716,11 +717,9 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) } else { c3_y row_y = cay_y - 32; - // only acknowledge button 1 presses within our window + // only acknowledge button 1 presses within our known window if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { - _term_io_spit(uty_u, u3nt(c3__hit, - tat_u->esc.col_y - 1, - tat_u->siz.row_l - row_y)); + _term_io_spit(uty_u, u3nt(c3__hit, tat_u->esc.col_y - 1, row_y - 1)); } tat_u->esc.mou = c3n; tat_u->esc.ton_y = tat_u->esc.col_y = 0; @@ -907,8 +906,8 @@ _term_spin_step(u3_utty* uty_u) // if we know where the bottom line is, and the cursor is not on it, // move it to the bottom left // - if ( tat_u->siz.row_l && tat_u->mir.rus_w > 0 ) { - _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 0); + if ( tat_u->siz.row_l && tat_u->mir.rus_w < tat_u->siz.row_l - 1 ) { + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 1); } c3_w i_w; @@ -1357,7 +1356,7 @@ _term_ef_blit(u3_utty* uty_u, case c3__hop: { u3_noun pos = u3t(blt); if ( c3y == u3r_ud(pos) ) { - _term_it_move_cursor(uty_u, pos, 0); + _term_it_move_cursor(uty_u, pos, uty_u->tat_u.siz.row_l - 1); } else { _term_it_move_cursor(uty_u, u3h(pos), u3t(pos)); @@ -1369,7 +1368,7 @@ _term_ef_blit(u3_utty* uty_u, } break; case c3__lin: { //TMP backwards compatibility - _term_it_move_cursor(uty_u, 0, 0); + _term_it_move_cursor(uty_u, 0, uty_u->tat_u.siz.row_l - 1); _term_it_clear_line(uty_u); } // case c3__put: { From d3f9d7621799a57844469d097dfed2941bd0bd62 Mon Sep 17 00:00:00 2001 From: fang Date: Sun, 3 Apr 2022 21:44:05 +0200 Subject: [PATCH 056/249] term: move cursor to end before exit When urbit exits, the host shell it was running in takes over, often re-prints its own prompt. Here, we move the cursor to the bottom of the screen right before exiting, so that any subsequent output doesn't destroy whatever we had on-screen when we closed. --- pkg/urbit/vere/io/term.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index a653a6bcb..7b3f7720e 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -1762,6 +1762,10 @@ _term_io_exit(u3_auto* car_u) // _term_it_dump_buf(uty_u, &uty_u->ufo_u.mof_u); + // move cursor to the end + // + _term_it_move_cursor(uty_u, 0, uty_u->tat_u.siz.row_l - 1); + // NB, closed in u3_term_log_exit() // uv_read_stop((uv_stream_t*)&(uty_u->pin_u)); From 0c255c1294b924c871179be553a24c3de2cd0604 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 25 Mar 2022 10:27:32 -0400 Subject: [PATCH 057/249] hoon: plug type leak in vase literals by properly burping %hint --- pkg/arvo/sys/hoon.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 04607d81b..216642b53 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -9121,7 +9121,7 @@ == [%face *] [%face p.sut burp(sut q.sut)] [%fork *] [%fork (~(run in p.sut) |=(type burp(sut +<)))] - [%hint *] (hint p.sut burp(sut q.sut)) + [%hint *] (hint [burp(sut p.p.sut) q.p.sut] burp(sut q.sut)) [%hold *] [%hold burp(sut p.sut) q.sut] == :: From f7f4b3e7487364c7cff00d56cba5b18098fa2844 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Fri, 25 Mar 2022 10:28:05 -0400 Subject: [PATCH 058/249] hoon: preserve structural sharing by testing subject/product equality in +burp --- pkg/arvo/sys/hoon.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 216642b53..59a4b2d4d 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -9107,7 +9107,7 @@ :: ^- type ~+ - ~= sut + =- ?.(=(sut -) - sut) ?+ sut sut [%cell *] [%cell burp(sut p.sut) burp(sut q.sut)] [%core *] :+ %core From 6a6078b5548d01fe3245a3756e69ce4bb59221db Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Mon, 4 Apr 2022 16:23:27 -0400 Subject: [PATCH 059/249] doccords: dprint core and chapter items adds the ability to find cores and chapters and produce an item from them --- pkg/arvo/lib/dprint.hoon | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 243e06953..4b83d8d4a 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -52,9 +52,9 @@ == :: -- +:> # %dprint |% -:: arms for finding docs in types -::+| %searching ++| %searching :> returns the item to print while searching through topic :> :> this gate is called recursively to find the path (topic) in the type @@ -83,21 +83,22 @@ :: check that they're wrapped with a %hint type. so this just looks for :: docs on the arms. :: - :: cores also can't have names right now. %brcn and %brpt have a slot in - :: their AST for the name, but it doesn't end up in the their type. so - :: if i want core names right now, i'd have to look inside their AST, and - :: only |% and |@ cores would have names, which is silly. + =+ core-name=p.p.q.sut + ?: =(`topic core-name) + :: if core-name matches topic, return the core as a (unit item) + (signify sut) + =+ chapters=~(key by q.r.q.sut) + ?: (~(has in chapters) topic) + :: if there is a chapter with a name matching the topic, return chapter + :: as a (unit item) + =/ docs=what p:(~(got by q.r.q.sut) topic) + `[%chapter (trip topic) docs sut q.sut topic] =+ arm=(find-arm-in-coil topic q.sut) ?~ arm - :: the current topic is not an arm in the core + :: the current topic is not an arm in the core, recurse into type $(sut p.sut) - :: check to see if the arm is wrapped with a note - :: TODO: this is taking docs from the AST rather than the type. is that - :: the right thing to do here? =+ wat=(unwrap-note u.arm) `[%arm (trip topic) wat u.arm p.sut] - :: `[%arm (trip topic) wat u.arm q.q.sut] :: what's the difference if i use the type in the coil? - :: TODO: check for chapter docs :: [%face *] ?. ?=(term p.sut) @@ -174,9 +175,11 @@ $(sut q.sut) :: [%core *] - =/ name ~ :: should check if core is built with an arm and use that name? + =/ name=(unit term) p.p.q.sut :: should check if core is built with an arm and use that name? =* compiled-against $(sut p.sut) - `[%core (trip name) *what p.sut q.sut compiled-against] + ?~ name + `[%core ~ *what p.sut q.sut compiled-against] + `[%core (trip u.name) *what p.sut q.sut compiled-against] :: [%face *] ?. ?=(term p.sut) @@ -427,7 +430,7 @@ :: :> # %printing :: :> # :: :> functions which display output of various types -:: +| %printing ++| %printing :> prints a doccords item ++ print-item |= =item From 063e3ed716b1bae15a408461e16f5668e8c47dc6 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 12:35:53 -0400 Subject: [PATCH 060/249] hoon: doccords dist. between arm-doc and prod-doc docs written above an arm are now distinguishable in the AST from docs written above the product of the arm, by tagging docs written above the arm with a %funk link --- pkg/arvo/sys/hoon.hoon | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index 59a4b2d4d..b114ceeb8 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -13288,10 +13288,15 @@ %+ knee [p=*term q=*hoon] |. ~+ %+ cook |= [a=whit b=term c=whit d=hoon] - =+ e=(glom a c) - ?~ boy.e - [b d] - [b [%note help+`[u.boy.e] d]] + ?~ boy.a :: no arm docs + ?~ boy.c :: no product docs + [b d] + :: product docs, no arm docs + [b [%note help+`[u.boy.c] d]] + ?~ boy.c :: arm docs, no product docs + [b [%note help+[[%funk b]~ u.boy.a] d]] + :: arm docs and product docs + [b [%note help+[[%funk b]~ u.boy.a] [%note help+`[u.boy.c] d]]] ;~ pose ;~ plug apex:docs From eb4b996420896815070c80df70ec99b207e6f063 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 12:38:02 -0400 Subject: [PATCH 061/249] doccords: dprint can dist. arm-doc and prod-doc rewrites select-arm-docs so that it checks for nested hint types and sees if the outermost help hint has a %funk link with the name of the arm in order to tell that its an arm-doc --- pkg/arvo/lib/dprint.hoon | 115 ++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 4b83d8d4a..ca3c87e82 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -95,7 +95,7 @@ `[%chapter (trip topic) docs sut q.sut topic] =+ arm=(find-arm-in-coil topic q.sut) ?~ arm - :: the current topic is not an arm in the core, recurse into type + :: the current topic is not an arm in the core, recurse into sut $(sut p.sut) =+ wat=(unwrap-note u.arm) `[%arm (trip topic) wat u.arm p.sut] @@ -135,7 +135,6 @@ ?~ itm ~ `(emblazon u.itm wat) -:: (emblazon (need (signify q.sut)) (unwrap-hint sut)) $(sut q.sut) :: [%hold *] $(sut (~(play ut p.sut) q.sut)) @@ -276,62 +275,79 @@ ?: ?=(%help -.q.p.sut) `crib.p.q.p.sut ~ == :: +:> returns 0, 1, or 2 whats for an arm +++ arm-product-docs + |= [sut=type name=tape] + ^- (unit [what what]) + =/ doc-one=(unit help) + ?: ?=([%hint [* [%help ^]] *] sut) + `p.q.p.sut + ~ + ?~ doc-one + :: no need to look for a second doc if there is no first one + ~ + =/ doc-two=(unit help) + ?> ?=([%hint *] sut) + ?: ?=([%hint [* [%help ^]] *] q.sut) + `p.q.p.q.sut + ~ + ?~ doc-two + ?~ links.u.doc-one + :: if links are empty, doc-one is a product-doc + [~ [~ `crib.u.doc-one]] + ?: =([%funk `@tas`(crip name)] i.links.u.doc-one) + :: if links are non-empty, check that the link is for the arm + [~ [`crib.u.doc-one ~]] + ~? > debug %link-doesnt-match-arm + :: this shouldn't happen at this point in time + [~ [`crib.u.doc-one ~]] + :: doc-two is non-empty. make sure that doc-one is an arm-doc + ?~ links.u.doc-one + ~? > debug %doc-one-empty-link + [~ [`crib.u.doc-one `crib.u.doc-two]] + [~ [`crib.u.doc-one `crib.u.doc-two]] +:: :> grabs the docs for an arm. :> :> there are three possible places with relevant docs for an arm: :> docs for the arm itself, docs for the product of the arm, and :> if the arm builds a core, docs for the default arm of that core. :> -:> arm-doc: docs wrapping the arm - this should have already been found +:> arm-doc: docs wrapping the arm :> product-doc: docs for the product of the arm :> core-doc: docs for the default arm of the core produced by the arm ++ select-arm-docs - |= [arm-doc=what gen=hoon sut=type] - ~? >> debug %select-arm-docs + |= [gen=hoon sut=type name=tape] + ~? > debug %select-arm-docs ^- [what what what] =+ hoon-type=(~(play ut sut) gen) - ::~? >>> debug hoon-type - =/ product-doc=what (what-from-type hoon-type) - ~? > debug product-doc - :: if the arm builds a core, get the docs for the default arm - :: in that core - :: - :: this is broken if it also has an arm-doc. if i have an arm-doc, i - :: need to strip off the first hint and then check if i have a core, i think - =/ core-doc=what - :: if product-doc is empty, just go right on and check if its a core - ?~ product-doc - ?. ?=([%core *] hoon-type) - ~? > debug %no-core-product - ~ - (what-from-type (~(play ut hoon-type) [%limb %$])) - :: if there is a product doc, then step through the hint and check for a core - ?: ?=([%hint *] hoon-type) - ~? > debug %step-through-hint - ::=+ inner-type=(~(play ut q.hoon-type) gen) - ::=/ res (mule |.((~(play ut inner-type) [%limb %$]))) - :: pretty sure having to use mule twice here means im doing something wrong - =/ h-res (mule |.((~(play ut q.hoon-type) gen))) - ?- -.h-res - %| - ~ - :: - %& - =/ in-res (mule |.((~(play ut p.h-res) [%limb %$]))) - ?- -.in-res - %| ~ - %& (what-from-type p.in-res) - == - == + =+ arm-prod=(arm-product-docs hoon-type name) + ~? >> debug arm-prod + ^- [what what what] + |^ + :: use arm-prod to determine how many layers to look into the type + :: for core docs + =/ depth=@ (add !=(~ +<.arm-prod) !=(~ +>.arm-prod)) + ^- [what what what] + ?+ depth [~ ~ ~] + %0 [~ ~ (check-core hoon-type)] + %1 :+ +<.arm-prod + +>.arm-prod + ?> ?=([%hint *] hoon-type) + (check-core q.hoon-type) + %2 :+ +<.arm-prod + +>.arm-prod + ?> ?=([%hint *] hoon-type) + ?> ?=([%hint *] q.hoon-type) + (check-core q.q.hoon-type) + == + ++ check-core + |= sut=type + ^- what + ?: ?=([%core *] sut) + (what-from-type (~(play ut sut) [%limb %$])) ~ - :: i think arm-doc and product-doc might always be the same - :: upon further reflection, i think this is a limitation of the wrapping - :: approach - ~? > debug :* %arm-doc arm-doc - %product-doc product-doc - %core-doc core-doc - == - :+ arm-doc product-doc core-doc + -- :: :> returns an overview for a cores arms and chapters :> @@ -383,13 +399,12 @@ :: :> translate a tome into an overview ++ arms-as-overview - :: currently this doesn't do anything until i implement arm-doc |= [a=(map term hoon) sut=type] ^- overview %+ turn ~(tap by a) |= ar=(pair term hoon) - =/ doc (select-arm-docs *what q.ar sut) :: *what should be from the hint wrapper - [%item (weld "++" (trip p.ar)) -.doc] + =+ [adoc pdoc cdoc]=(select-arm-docs q.ar sut (trip p.ar)) + [%item (weld "++" (trip p.ar)) adoc] :: :> changes an item into an overview ++ item-as-overview @@ -487,7 +502,7 @@ |= [name=tape docs=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm - =+ [main-doc product-doc core-doc]=(select-arm-docs docs gen sut) + =+ [main-doc product-doc core-doc]=(select-arm-docs gen sut name) ;: weld (print-header name main-doc) `tang`[[%leaf ""] [%leaf "product:"] ~] From 151608d583ffb41df5ae5e50c7fca2240276899d Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 14:44:47 -0400 Subject: [PATCH 062/249] doccords: dprint fix depth calculation stupid loobeans tripping me up --- pkg/arvo/lib/dprint.hoon | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index ca3c87e82..64cccc183 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -323,12 +323,11 @@ =+ hoon-type=(~(play ut sut) gen) =+ arm-prod=(arm-product-docs hoon-type name) ~? >> debug arm-prod - ^- [what what what] |^ - :: use arm-prod to determine how many layers to look into the type + :: check arm-prod to determine how many layers to look into the type :: for core docs - =/ depth=@ (add !=(~ +<.arm-prod) !=(~ +>.arm-prod)) - ^- [what what what] + =/ depth=@ ?~ arm-prod 0 + (add =(~ +<.arm-prod) =(~ +>.arm-prod)) ?+ depth [~ ~ ~] %0 [~ ~ (check-core hoon-type)] %1 :+ +<.arm-prod From 6f32d107fc737bf1f39e7e5605aa4d8dec71633b Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 14:45:51 -0400 Subject: [PATCH 063/249] hoon: doccords wrap tisfas fix I didn't know what I was doing before, I think this is the right way to wrap tisfas with a %note hoon. --- pkg/arvo/sys/hoon.hoon | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index b114ceeb8..b1698487a 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8242,10 +8242,7 @@ :: :: tis runes [%tsfs *] - ?~ boy.wit - gen - [%tsfs [%help `u.boy.wit p.gen] q.gen r.gen] -:: [%tsfs help+`u.boy.wit p.gen q.gen r.gen] + wrap-boy == :: ++ wrap-boy From 37a787970ca5876fa27f54b926fa0683d5382fde Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 15:17:57 -0400 Subject: [PATCH 064/249] doccords: dprint refactoring and renaming --- pkg/arvo/lib/dprint.hoon | 105 +++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 42 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 64cccc183..5b854fbb6 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -256,56 +256,76 @@ $(tomes t.tomes) `u.gen :: -:> gets the documentation inside of a type -++ what-from-type - :> testing +:> gets the documentation inside of a hint, or a hold that plays to a hint +++ what-from-hint |= sut=type ^- what ?+ sut ~ - :: - [%core *] - ~? >> debug %what-from-type-core ~ :: should this get the chapter docs? :: [%hold *] - ~? >> debug %what-from-type-hold $(sut (~(play ut p.sut) q.sut)) + ~? >> debug %what-from-hint-hold $(sut (~(play ut p.sut) q.sut)) :: [%hint *] - ~? >> debug :- %what-from-type-hint -.q.p.sut + ~? >> debug :- %what-from-hint-hint -.q.p.sut ?: ?=(%help -.q.p.sut) `crib.p.q.p.sut ~ == +:> gets the $help from a %help %hint type and returns it as a unit +++ help-from-hint + |= sut=type + ^- (unit help) + ?+ sut ~ + [%hold *] + ~? >> debug %help-from-hold $(sut (~(play ut p.sut) q.sut)) + :: + [%hint *] + ~? >> debug %help-from-hint + ?. ?=(%help -.q.p.sut) + ~ + (some p.q.p.sut) + == :: :> returns 0, 1, or 2 whats for an arm +:> +:> this arm should be handed the compiled type of the hoon of an arm, as well +:> as the name of that arm. it checks for up to 2 nested hints on the outermost +:> layer of the type. if you have 2, it is presumed to be arm-doc followed by +:> product-doc. if you only have one, we check links in the $help of the hint +:> to determine whether it is an arm doc or product doc. +:> +:> this returns ~ if there are no docs. if there are docs, the first one is the +:> arm-doc, and the second one is the product-doc. ++ arm-product-docs - |= [sut=type name=tape] + |= [sut=type name=term] ^- (unit [what what]) =/ doc-one=(unit help) - ?: ?=([%hint [* [%help ^]] *] sut) - `p.q.p.sut - ~ + (help-from-hint sut) ?~ doc-one - :: no need to look for a second doc if there is no first one - ~ + ~? > debug %doc-one-empty + ~ :: no need to look for a second doc if there is no first one + :: technically doc-two doesn't need to be a help, i could just grab the what + :: directly since we aren't testing it to see if its an arm-doc, but it makes + :: the code more confusing to use a different structure. =/ doc-two=(unit help) ?> ?=([%hint *] sut) - ?: ?=([%hint [* [%help ^]] *] q.sut) - `p.q.p.q.sut - ~ + (help-from-hint q.sut) ?~ doc-two + ~? > debug %doc-two-empty ?~ links.u.doc-one :: if links are empty, doc-one is a product-doc - [~ [~ `crib.u.doc-one]] - ?: =([%funk `@tas`(crip name)] i.links.u.doc-one) + [~ [~ (some crib.u.doc-one)]] + ?: =([%funk name] i.links.u.doc-one) :: if links are non-empty, check that the link is for the arm - [~ [`crib.u.doc-one ~]] + ~? > debug %link-match + [~ [(some crib.u.doc-one) ~]] ~? > debug %link-doesnt-match-arm :: this shouldn't happen at this point in time - [~ [`crib.u.doc-one ~]] + [~ [(some crib.u.doc-one) ~]] :: doc-two is non-empty. make sure that doc-one is an arm-doc ?~ links.u.doc-one ~? > debug %doc-one-empty-link - [~ [`crib.u.doc-one `crib.u.doc-two]] - [~ [`crib.u.doc-one `crib.u.doc-two]] + [~ [(some crib.u.doc-one) (some crib.u.doc-two)]] + [~ [(some crib.u.doc-one) (some crib.u.doc-two)]] :: :> grabs the docs for an arm. :> @@ -313,38 +333,42 @@ :> docs for the arm itself, docs for the product of the arm, and :> if the arm builds a core, docs for the default arm of that core. :> -:> arm-doc: docs wrapping the arm +:> arm-doc: docs written above the the arm :> product-doc: docs for the product of the arm :> core-doc: docs for the default arm of the core produced by the arm -++ select-arm-docs +++ all-arm-docs |= [gen=hoon sut=type name=tape] - ~? > debug %select-arm-docs + ~? > debug %all-arm-docs ^- [what what what] =+ hoon-type=(~(play ut sut) gen) - =+ arm-prod=(arm-product-docs hoon-type name) + =+ arm-prod=(arm-product-docs hoon-type `@tas`(crip name)) ~? >> debug arm-prod |^ :: check arm-prod to determine how many layers to look into the type :: for core docs =/ depth=@ ?~ arm-prod 0 (add =(~ +<.arm-prod) =(~ +>.arm-prod)) - ?+ depth [~ ~ ~] - %0 [~ ~ (check-core hoon-type)] + ?+ depth ``~ + %0 ``(extract hoon-type) %1 :+ +<.arm-prod +>.arm-prod ?> ?=([%hint *] hoon-type) - (check-core q.hoon-type) + (extract q.hoon-type) %2 :+ +<.arm-prod +>.arm-prod ?> ?=([%hint *] hoon-type) ?> ?=([%hint *] q.hoon-type) - (check-core q.q.hoon-type) + (extract q.q.hoon-type) == - ++ check-core + :> grabs the first doc for the default arm of a core + :> + :> this could end up being an arm doc or a product doc. or it might even + :> produce another core with docs in that. should I care? + ++ extract |= sut=type ^- what ?: ?=([%core *] sut) - (what-from-type (~(play ut sut) [%limb %$])) + (what-from-hint (~(play ut sut) [%limb %$])) ~ -- :: @@ -402,7 +426,7 @@ ^- overview %+ turn ~(tap by a) |= ar=(pair term hoon) - =+ [adoc pdoc cdoc]=(select-arm-docs q.ar sut (trip p.ar)) + =+ [adoc pdoc cdoc]=(all-arm-docs q.ar sut (trip p.ar)) [%item (weld "++" (trip p.ar)) adoc] :: :> changes an item into an overview @@ -440,10 +464,7 @@ ?~ lhs rhs ?~ rhs lhs `[%view (weld (item-as-overview lhs) (item-as-overview rhs))] -:: :> # -:: :> # %printing -:: :> # -:: :> functions which display output of various types +:: +| %printing :> prints a doccords item ++ print-item @@ -501,13 +522,13 @@ |= [name=tape docs=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm - =+ [main-doc product-doc core-doc]=(select-arm-docs gen sut name) + =+ [adoc pdoc cdoc]=(all-arm-docs gen sut name) ;: weld - (print-header name main-doc) + (print-header name adoc) `tang`[[%leaf ""] [%leaf "product:"] ~] - (print-header "" product-doc) + (print-header "" pdoc) `tang`[[%leaf ""] [%leaf "default arm in core:"] ~] - (print-header "" core-doc) + (print-header "" cdoc) == :: :> renders documentation for a face From 3afc9b6899ae32ff0aa3f130f60140147c850fd7 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 15:52:35 -0400 Subject: [PATCH 065/249] doccords: dprint all docs in %arm items from type before this, it was grabbing the initial arm-doc from the AST rather than the type. now %arm items have all 3 types of docs available. the interface has been degraded somewhat though, as %arm items no longer have a single docs field. more refactoring will be needed to figure out the best way to do this. --- pkg/arvo/lib/dprint.hoon | 54 +++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 5b854fbb6..bf95e6012 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -31,7 +31,9 @@ :: inspecting a single arm on a core $: %arm name=tape - docs=what + adoc=what + pdoc=what + cdoc=what gen=hoon sut=type == @@ -97,8 +99,8 @@ ?~ arm :: the current topic is not an arm in the core, recurse into sut $(sut p.sut) - =+ wat=(unwrap-note u.arm) - `[%arm (trip topic) wat u.arm p.sut] + =+ [adoc pdoc cdoc]=(all-arm-docs u.arm p.sut (trip topic)) + `[%arm (trip topic) adoc pdoc cdoc u.arm p.sut] :: [%face *] ?. ?=(term p.sut) @@ -129,12 +131,15 @@ :: TODO: should i be trying to match both types in the hint? :: TODO: actually hints can be nested, if e.g. an arm has a product with a hint, whose :: product also has a hint. so this won't actually work for nested hints as written + :: + :: this should only be doing something for cores right now. you run into an + :: arm's name before you run into its docs ?: (shallow-match topic q.sut) =/ wat=what (unwrap-hint sut) - =/ itm=(unit item) (signify q.sut) - ?~ itm + =/ uitm=(unit item) (signify q.sut) + ?~ uitm ~ - `(emblazon u.itm wat) + `(emblazon u.uitm wat) $(sut q.sut) :: [%hold *] $(sut (~(play ut p.sut) q.sut)) @@ -224,22 +229,15 @@ :: :> inserts docs into an item :> -:> most docs are going to be found in hint types wrapping another type. when -:> we come across a hint, we grab the docs from the hint and then build the -:> item for the type it wrapped. since building an item is handled separately, -:> this item will initially have no docs in it, so we add it in after with this -:> -:> the exceptions to this are %chapter and %view items. chapters have an axis -:> for docs in their $tome structure, and %views are summaries of several types +:> when matching for a core or a face type, the docs for that type will be in +:> a hint that wraps it. thus we end up producing an item for that type, then +:> need to add the docs to it. ++ emblazon |= [=item =what] ~? >> debug %emblazon ^+ item - ?+ item item :: no-op on %chapter and %view - ?([%core *] [%arm *] [%face *]) ?~ docs.item - item(docs what) - ~? > debug %docs-in-item - item(docs what) + ?+ item item :: no-op on %chapter, %arm, $view + ?([%core *] [%face *]) item(docs what) == :: :> looks for an arm in a coil and returns its hoon @@ -282,7 +280,7 @@ ~? >> debug %help-from-hint ?. ?=(%help -.q.p.sut) ~ - (some p.q.p.sut) + `p.q.p.sut == :: :> returns 0, 1, or 2 whats for an arm @@ -313,19 +311,19 @@ ~? > debug %doc-two-empty ?~ links.u.doc-one :: if links are empty, doc-one is a product-doc - [~ [~ (some crib.u.doc-one)]] + [~ [~ `crib.u.doc-one]] ?: =([%funk name] i.links.u.doc-one) :: if links are non-empty, check that the link is for the arm ~? > debug %link-match - [~ [(some crib.u.doc-one) ~]] + [~ [`crib.u.doc-one ~]] ~? > debug %link-doesnt-match-arm :: this shouldn't happen at this point in time - [~ [(some crib.u.doc-one) ~]] + [~ [`crib.u.doc-one ~]] :: doc-two is non-empty. make sure that doc-one is an arm-doc ?~ links.u.doc-one ~? > debug %doc-one-empty-link - [~ [(some crib.u.doc-one) (some crib.u.doc-two)]] - [~ [(some crib.u.doc-one) (some crib.u.doc-two)]] + [~ [`crib.u.doc-one `crib.u.doc-two]] + [~ [`crib.u.doc-one `crib.u.doc-two]] :: :> grabs the docs for an arm. :> @@ -446,7 +444,7 @@ (item-as-overview children.itm) :: [%arm *] - [%item name.itm docs.itm]~ + [%item name.itm adoc.itm]~ :: [%chapter *] [%item name.itm docs.itm]~ @@ -484,8 +482,7 @@ ^- tang =+ [arms chapters]=(arm-and-chapter-overviews sut con name) ;: weld - :: cores don't have names - (print-header *tape *what) + (print-header name docs) :: ?~ arms ~ @@ -519,10 +516,9 @@ :: :> renders documentation for a single arm in a core ++ print-arm - |= [name=tape docs=what gen=hoon sut=type] + |= [name=tape adoc=what pdoc=what cdoc=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm - =+ [adoc pdoc cdoc]=(all-arm-docs gen sut name) ;: weld (print-header name adoc) `tang`[[%leaf ""] [%leaf "product:"] ~] From 69399c4153075317a9121ac4941486cecbff4e63 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Tue, 5 Apr 2022 15:55:42 -0400 Subject: [PATCH 066/249] doccords: remove unwrap-note from dprint we shouldn't be getting docs from the AST, so this should never be needed --- pkg/arvo/lib/dprint.hoon | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index bf95e6012..34bacf745 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -206,16 +206,6 @@ %noun ~ %void ~ == - -:> checks if a hoon is wrapped with a help note, and returns it if so -++ unwrap-note - |= gen=hoon - ^- what - ?: ?=([%note *] gen) - ?: ?=([%help *] p.gen) - `crib.p.p.gen - ~ - ~ :: :> checks if a hint type is a help hint and returns the docs if so ++ unwrap-hint From 877fe0059e7aec696510f0b85434d907b03a25f8 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 14:02:25 -0400 Subject: [PATCH 067/249] dojo: add command to lookup doccords syntax: `# foo` to look up foo. this is not the final form - it does not support `# foo:bar` yet. the dprint library needs some changes first. --- pkg/arvo/app/dojo.hoon | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index b127a3ce0..8b6674f60 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -3,7 +3,7 @@ :: :: :: /? 309 :: arvo kelvin /- *sole, lens :: console structures -/+ sole, pprint, :: +/+ sole, pprint, dprint, :: auto=language-server-complete, :: easy-print=language-server-easy-print :: :: :: :: @@ -54,6 +54,7 @@ r=@t == [%poke p=goal] :: poke app + [%help p=term] :: doccords [%show p=?(%0 %1 %2 %3 %4 %5)] :: val/type/hoon/xray [%verb p=term] :: store variable == :: @@ -178,6 +179,18 @@ (parse-variable (cold %lib lus) ;~(pfix gap parse-cables)) == == + :: + ;~ pfix hax + ;~ pose + ;~ pfix ace + %+ cook + |= a=term + [[%help a] 0 %ex [%cnts p=~[[%.y p=1]] q=~]] + sym :: should be (most col sym) once i switch to (list term) + == + (easy [[%help %$] 0 %ex [%cnts p=~[[%.y p=1]] q=~]]) + == + == :: ;~((glue ace) parse-sink parse-source) (stag [%show %0] parse-source) @@ -624,6 +637,9 @@ ++ maar ?: =(%noun p.cay) ~ [[%rose [~ " " ~] >p.cay< ~] ~] -- + :: + %help + (dy-inspect p.p.mad p.q.cay) == :: ++ dy-show |=(cay=cage (dy-print cay ~)) @@ -663,6 +679,15 @@ :- i="" t=(turn `wain`?~(r.hit ~ (to-wain:format q.u.r.hit)) trip) == + :: + ++ dy-inspect + |= [topic=term sut=type] + %+ dy-rash %tan + =+ to-display=(find-item-in-type:dprint topic sut) + ?~ to-display + [%leaf "Could not find help"]~ + (print-item:dprint u.to-display) + :: ++ dy-show-type-noun |= a=type ^- tank =- >[-]< From 912a5023bbecc4ce41ae6eafcc2e96b8d8b0c66a Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 14:58:28 -0400 Subject: [PATCH 068/249] doccords: flop order of +print-arm results --- pkg/arvo/lib/dprint.hoon | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 34bacf745..eac96902a 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -509,6 +509,7 @@ |= [name=tape adoc=what pdoc=what cdoc=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm + %- flop ;: weld (print-header name adoc) `tang`[[%leaf ""] [%leaf "product:"] ~] From 33b2761b39ce94962129ffc771ea4e4e470cc97b Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 15:50:23 -0400 Subject: [PATCH 069/249] doccords, dojo: move flop print-arm -> dy-inspect this looks more sensible --- pkg/arvo/app/dojo.hoon | 2 +- pkg/arvo/lib/dprint.hoon | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index 8b6674f60..c5a00ba46 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -686,7 +686,7 @@ =+ to-display=(find-item-in-type:dprint topic sut) ?~ to-display [%leaf "Could not find help"]~ - (print-item:dprint u.to-display) + (flop (print-item:dprint u.to-display)) :: ++ dy-show-type-noun |= a=type ^- tank diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index eac96902a..34bacf745 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -509,7 +509,6 @@ |= [name=tape adoc=what pdoc=what cdoc=what gen=hoon sut=type] ^- tang ~? >> debug %print-arm - %- flop ;: weld (print-header name adoc) `tang`[[%leaf ""] [%leaf "product:"] ~] From 2a57e85a091d0406a1bd17ad942ea62134d4f9a9 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 16:27:07 -0400 Subject: [PATCH 070/249] hoon: comment out %note entry in +open this was wiping out some comments buried that weren't written at the top of an arm. not sure if this is used in another fashion that will create issues, so I just commented it out to help remember that it used to be there in case it needs further changes, like if I should actually skip %know and %made notes but not %help notes --- pkg/arvo/sys/hoon.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/sys/hoon.hoon b/pkg/arvo/sys/hoon.hoon index b1698487a..ad1d68ff6 100644 --- a/pkg/arvo/sys/hoon.hoon +++ b/pkg/arvo/sys/hoon.hoon @@ -8450,7 +8450,7 @@ [%tell *] [%cncl [%limb %noah] [%zpgr [%cltr p.gen]] ~] [%wing *] [%cnts p.gen ~] [%yell *] [%cncl [%limb %cain] [%zpgr [%cltr p.gen]] ~] - [%note *] q.gen + ::[%note *] q.gen :: [%brbc *] =- ?~ - !! [%brtr [%bccl -] [%ktcl body.gen]] From 0e8cf3bbfa5d300cff3ae9b03bbd6e7ab8d5e220 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 16:34:02 -0400 Subject: [PATCH 071/249] doccords: dprint improve default arm core docs the logic for getting the docs on the default arm of a core is now more similar to how other arm docs are gotten, rather than having its own system. there is still more room for improvement --- pkg/arvo/lib/dprint.hoon | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 34bacf745..f465ac2a9 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -324,13 +324,16 @@ :> arm-doc: docs written above the the arm :> product-doc: docs for the product of the arm :> core-doc: docs for the default arm of the core produced by the arm +:> this will be the first of the arm-doc or product-doc on the default +:> arm. maybe this should be recursive and/or give both but its a decision +:> ill leave for later ++ all-arm-docs |= [gen=hoon sut=type name=tape] ~? > debug %all-arm-docs ^- [what what what] =+ hoon-type=(~(play ut sut) gen) =+ arm-prod=(arm-product-docs hoon-type `@tas`(crip name)) - ~? >> debug arm-prod + ~? >> debug :- %arm-prod arm-prod |^ :: check arm-prod to determine how many layers to look into the type :: for core docs @@ -350,14 +353,18 @@ == :> grabs the first doc for the default arm of a core :> - :> this could end up being an arm doc or a product doc. or it might even - :> produce another core with docs in that. should I care? + :> this could end up being an arm doc or a product doc. ++ extract |= sut=type ^- what - ?: ?=([%core *] sut) - (what-from-hint (~(play ut sut) [%limb %$])) - ~ + ?. ?=([%core *] sut) + ~? > debug %no-nested-core ~ + ~? > debug %found-nested-core + =+ carm=(find-arm-in-coil %$ q.sut) + ?~ carm ~? > debug %empty-carm ~ + ~? > debug %found-default-arm + =+ carm-type=(~(play ut p.sut) u.carm) + (what-from-hint carm-type) -- :: :> returns an overview for a cores arms and chapters From 7a94319af3933c025974e6e73bbb268d590344e3 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Wed, 6 Apr 2022 17:37:55 -0400 Subject: [PATCH 072/249] dojo, doccords: dprint library can take list term this allows you to search for foo:bar instead of just foo --- pkg/arvo/app/dojo.hoon | 12 +++--- pkg/arvo/lib/dprint.hoon | 85 +++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index c5a00ba46..9363ab4b7 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -54,7 +54,7 @@ r=@t == [%poke p=goal] :: poke app - [%help p=term] :: doccords + [%help p=(list term)] :: doccords [%show p=?(%0 %1 %2 %3 %4 %5)] :: val/type/hoon/xray [%verb p=term] :: store variable == :: @@ -184,11 +184,11 @@ ;~ pose ;~ pfix ace %+ cook - |= a=term + |= a=(list term) [[%help a] 0 %ex [%cnts p=~[[%.y p=1]] q=~]] - sym :: should be (most col sym) once i switch to (list term) + (most col sym) == - (easy [[%help %$] 0 %ex [%cnts p=~[[%.y p=1]] q=~]]) + (easy [[%help ~[%$]] 0 %ex [%cnts p=~[[%.y p=1]] q=~]]) == == :: @@ -681,9 +681,9 @@ == :: ++ dy-inspect - |= [topic=term sut=type] + |= [topics=(list term) sut=type] %+ dy-rash %tan - =+ to-display=(find-item-in-type:dprint topic sut) + =+ to-display=(find-item-in-type:dprint topics sut %.y) ?~ to-display [%leaf "Could not find help"]~ (flop (print-item:dprint u.to-display)) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index f465ac2a9..b409978fc 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -59,16 +59,17 @@ +| %searching :> returns the item to print while searching through topic :> -:> this gate is called recursively to find the path (topic) in the type -:> (sut). once it finds the correct part of the type, it switches to -:> +signify to describe that part of the type +:> this gate is optionally called recursively to find the path (topic) in the +:> type (sut). once it finds the correct part of the type, it switches to +:> +signify to describe that part of the type. recursion is turned off (for some +:> cases) when a hint type is found, in case it is wrapping a match. ++ find-item-in-type :: TODO make this work with a list of topics - |= [topic=term sut=type] + |= [topics=(list term) sut=type rec=?] ^- (unit item) - :: ?~ topics - :: :: we have no more search paths TODO: return the rest as an overview - :: (signify sut) + ?~ topics + :: we have no more search paths, return an overview of what remains + (signify sut) ?- sut %noun ~ %void ~ @@ -77,6 +78,7 @@ [%cell *] =+ lhs=$(sut p.sut) ?~ lhs + :: not sure if this should recurse when rec=%.n $(sut q.sut) lhs :: @@ -86,31 +88,47 @@ :: docs on the arms. :: =+ core-name=p.p.q.sut - ?: =(`topic core-name) - :: if core-name matches topic, return the core as a (unit item) - (signify sut) + ?: !=(`i.topics core-name) + :: the current topic isn't the top level core name + :: else, look for an arm matching the name + =+ arm=(find-arm-in-coil i.topics q.sut) + ?~ arm + :: the current topic is not an arm in the core, recurse into sut + ?:(rec $(sut p.sut) ~) + ::$(sut p.sut) + :: else, return the arm as docs + =+ [adoc pdoc cdoc]=(all-arm-docs u.arm p.sut (trip i.topics)) + `[%arm (trip i.topics) adoc pdoc cdoc u.arm p.sut] + :: the core name matches. check to see if there are any topics left + ?~ t.topics + :: we matched the core name and have no further topics. return the core + =* compiled-against (signify p.sut) + `[%core (trip i.topics) *what p.sut q.sut compiled-against] + :: we matched the core name, but there are still topics left + :: check to see if one the chapters matches the next topic =+ chapters=~(key by q.r.q.sut) - ?: (~(has in chapters) topic) - :: if there is a chapter with a name matching the topic, return chapter - :: as a (unit item) - =/ docs=what p:(~(got by q.r.q.sut) topic) - `[%chapter (trip topic) docs sut q.sut topic] - =+ arm=(find-arm-in-coil topic q.sut) - ?~ arm - :: the current topic is not an arm in the core, recurse into sut - $(sut p.sut) - =+ [adoc pdoc cdoc]=(all-arm-docs u.arm p.sut (trip topic)) - `[%arm (trip topic) adoc pdoc cdoc u.arm p.sut] + ?. (~(has in chapters) i.t.topics) + :: the core name matched, but nothing inside of it did. return null + ~ + :: if there is a chapter with a name matching the topic, return chapter + :: as a (unit item) + =/ docs=what p:(~(got by q.r.q.sut) i.topics) + `[%chapter (trip i.topics) docs sut q.sut i.topics] :: [%face *] ?. ?=(term p.sut) :: TODO: handle tune case ~ - ?. =(topic p.sut) + ?. =(i.topics p.sut) :: this face has a name, but not the one we're looking for ~ - :: faces need to be checked to see if they're wrapped - ~ + ?~ t.topics + :: we found a match, and there are no further topics + :: this might have been wrapped with a hint type, that case will handle + :: docs for this face + `[%face (trip p.sut) *what (signify q.sut)] + :: the first topic matched the face, but there are more left. + ?:(rec $(topics t.topics, sut q.sut) ~) :: [%fork *] =/ types=(list type) ~(tap in p.sut) @@ -134,13 +152,18 @@ :: :: this should only be doing something for cores right now. you run into an :: arm's name before you run into its docs - ?: (shallow-match topic q.sut) - =/ wat=what (unwrap-hint sut) - =/ uitm=(unit item) (signify q.sut) - ?~ uitm - ~ - `(emblazon u.uitm wat) - $(sut q.sut) + :: + ::?: (shallow-match i.topics q.sut) + =/ shallow-match=(unit item) $(sut q.sut, rec %.n) + ?~ shallow-match + :: hint isn't wrapping a match, so step through it + $(sut q.sut, rec %.y) + :: hint was wrapping a match, so signify the type and emblazon it + :: =/ wat=what (unwrap-hint sut) + `(emblazon u.shallow-match (unwrap-hint sut)) + ::=/ uitm=(unit item) (signify q.sut) + ::?~ uitm + :: ~ :: [%hold *] $(sut (~(play ut p.sut) q.sut)) :: From 7d8fabe6cff150a05081c15e55c2b40de086334e Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 7 Apr 2022 11:54:33 -0400 Subject: [PATCH 073/249] doccords: dprint remove +shallow-match it was factored into +find-item-in-type --- pkg/arvo/lib/dprint.hoon | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index b409978fc..5ae38811c 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -169,22 +169,6 @@ :: == :: -:> non-recursive check to see if type matches search -:> -:> this is for applying help hints to types when searching for a match. hints -:> are only for the type theyre immediately wrapping, not something nested -:> deeper, so we dont always want to recurse -++ shallow-match - |= [topic=term sut=type] - ^- ? - ?+ sut %.n - [%atom *] %.n :: should we allow doccords on individual atoms? i think they should be for faces - [%core *] !=(~ (find ~[topic] (sloe sut))) - [%face *] ?. ?=(term p.sut) - %.n :: TODO: handle tune case - =(topic p.sut) - == -:: :> changes a type into a item :> :> this does not actually assign the docs, since they usually come from a hint From b41b22ab70941eb5fdcf040df20b189740df30e8 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 7 Apr 2022 12:42:55 -0400 Subject: [PATCH 074/249] doccords: dprint fix chapter printing --- pkg/arvo/lib/dprint.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 5ae38811c..377d74903 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -112,8 +112,8 @@ ~ :: if there is a chapter with a name matching the topic, return chapter :: as a (unit item) - =/ docs=what p:(~(got by q.r.q.sut) i.topics) - `[%chapter (trip i.topics) docs sut q.sut i.topics] + =/ docs=what p:(~(got by q.r.q.sut) i.t.topics) + `[%chapter (trip i.t.topics) docs sut q.sut i.t.topics] :: [%face *] ?. ?=(term p.sut) From b0230086ce4db18c209ae4e7e98b67c5a88ca22c Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 7 Apr 2022 12:55:30 -0400 Subject: [PATCH 075/249] doccords: dprint chapter and overview print tweak printing an overview only gives the summary now, not the details. also fixed chapter printing so that it doesn't print the details twice --- pkg/arvo/lib/dprint.hoon | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index 377d74903..f4bd522c7 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -56,6 +56,9 @@ -- :> # %dprint |% +:> contains arms used for looking for docs inside of a type +:> +:> the entrypoint for finding docs within a type is +find-item-in-type. +| %searching :> returns the item to print while searching through topic :> @@ -505,12 +508,13 @@ ++ print-chapter |= [name=tape doc=what sut=type con=coil chapter-id=term] ^- tang + ~? > debug %print-chapter ;: weld (print-header name doc) :: - ?~ doc - ~ - (print-sections q.u.doc) + ::?~ doc + :: ~ + ::(print-sections q.u.doc) :: =+ arms=(arms-in-chapter sut con chapter-id) ?~ arms @@ -572,8 +576,8 @@ out ?~ doc.oitem ~ `tang`[[%leaf ""] [%leaf "{(trip p.u.doc.oitem)}"] ~] - ?~ doc.oitem ~ - (print-sections q.u.doc.oitem) + ::?~ doc.oitem ~ + ::(print-sections q.u.doc.oitem) ^$(overview children.oitem) == == @@ -586,8 +590,8 @@ `tang`[[%leaf ""] [%leaf name.oitem] ~] ?~ doc.oitem ~ `tang`[[%leaf ""] [%leaf "{(trip p.u.doc.oitem)}"] ~] - ?~ doc.oitem ~ - (print-sections q.u.doc.oitem) + ::?~ doc.oitem ~ + ::(print-sections q.u.doc.oitem) == == == From 24a175a803d8dea51bd29f0bf5d347ffa877aa71 Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 7 Apr 2022 13:05:15 -0400 Subject: [PATCH 076/249] dojo: flop order of topics for dy-inspect you had to search for core:arm instead of arm:core before --- pkg/arvo/app/dojo.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index 9363ab4b7..7fc5ed3b3 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -683,7 +683,7 @@ ++ dy-inspect |= [topics=(list term) sut=type] %+ dy-rash %tan - =+ to-display=(find-item-in-type:dprint topics sut %.y) + =+ to-display=(find-item-in-type:dprint (flop topics) sut %.y) ?~ to-display [%leaf "Could not find help"]~ (flop (print-item:dprint u.to-display)) From dd71b7c788730f49e29d3b75f7185676616de4fe Mon Sep 17 00:00:00 2001 From: drbeefsupreme Date: Thu, 7 Apr 2022 13:05:58 -0400 Subject: [PATCH 077/249] doccords: dprint debug printfs --- pkg/arvo/lib/dprint.hoon | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/pkg/arvo/lib/dprint.hoon b/pkg/arvo/lib/dprint.hoon index f4bd522c7..6b9664565 100644 --- a/pkg/arvo/lib/dprint.hoon +++ b/pkg/arvo/lib/dprint.hoon @@ -70,6 +70,7 @@ :: TODO make this work with a list of topics |= [topics=(list term) sut=type rec=?] ^- (unit item) + ~? > debug topics ?~ topics :: we have no more search paths, return an overview of what remains (signify sut) @@ -258,8 +259,25 @@ ++ what-from-hint |= sut=type ^- what - ?+ sut - ~ + ?- sut + :: ~? > debug %what-from-hint-miss ~ + %noun ~? >> debug %what-from-hint-noun-miss ~ + %void ~? >> debug %what-from-hint-void-miss ~ + :: + [%core *] + ~? >> debug %what-from-hint-core-miss ~ + :: + [%cell *] + ~? >> debug %what-from-hint-cell-miss ~ + :: + [%face *] + ~? >> debug %what-from-hint-face-miss ~ + :: + [%fork *] + ~? >> debug %what-from-hint-fork-miss ~ + :: + [%atom *] + ~? >> debug %what-from-hint-atom-miss ~ :: [%hold *] ~? >> debug %what-from-hint-hold $(sut (~(play ut p.sut) q.sut)) @@ -311,6 +329,7 @@ ~? > debug %doc-two-empty ?~ links.u.doc-one :: if links are empty, doc-one is a product-doc + ~? > debug %link-empty [~ [~ `crib.u.doc-one]] ?: =([%funk name] i.links.u.doc-one) :: if links are non-empty, check that the link is for the arm @@ -343,7 +362,7 @@ ^- [what what what] =+ hoon-type=(~(play ut sut) gen) =+ arm-prod=(arm-product-docs hoon-type `@tas`(crip name)) - ~? >> debug :- %arm-prod arm-prod + ::~? >> debug :- %arm-prod arm-prod |^ :: check arm-prod to determine how many layers to look into the type :: for core docs @@ -373,6 +392,7 @@ =+ carm=(find-arm-in-coil %$ q.sut) ?~ carm ~? > debug %empty-carm ~ ~? > debug %found-default-arm + ::~? >>> debug u.carm =+ carm-type=(~(play ut p.sut) u.carm) (what-from-hint carm-type) -- @@ -474,6 +494,7 @@ :> prints a doccords item ++ print-item |= =item + ~? >> debug %print-item ^- tang ?- item [%view *] (print-overview items.item) @@ -539,6 +560,7 @@ ++ print-face |= [name=tape doc=what children=(unit item)] ^- tang + ~? >> debug %print-face %+ weld (print-header name doc) ?~ children @@ -549,6 +571,7 @@ ++ print-header |= [name=tape doc=what] ^- tang + ~? >> debug %print-header ?~ name ?~ doc [%leaf "(undocumented)"]~ @@ -564,6 +587,7 @@ ++ print-overview |= =overview ^- tang + ~? >> debug %print-overview =| out=tang |- ?~ overview out From 50d120e3c166410f9d1646b17a537b8e93653f18 Mon Sep 17 00:00:00 2001 From: tomholford Date: Mon, 11 Apr 2022 12:05:25 -0700 Subject: [PATCH 078/249] devex: address PR feedback - move App#initSessions definition outside function component closure - enhance useAddSessions performance --- pkg/interface/webterm/App.tsx | 16 ++++++++-------- pkg/interface/webterm/Tabs.tsx | 2 +- pkg/interface/webterm/lib/useAddSession.ts | 4 +--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/interface/webterm/App.tsx b/pkg/interface/webterm/App.tsx index c8dee297c..211066b74 100644 --- a/pkg/interface/webterm/App.tsx +++ b/pkg/interface/webterm/App.tsx @@ -21,18 +21,18 @@ 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 initSessions = useCallback(async () => { - const response = await api.scry(scrySessions()); - - useTermState.getState().set((state) => { - state.names = response.sort(); - }); - }, []); - const setupSlog = useCallback(() => { console.log('slog: setting up...'); let available = false; diff --git a/pkg/interface/webterm/Tabs.tsx b/pkg/interface/webterm/Tabs.tsx index 3b0cd0a0f..ed583635a 100644 --- a/pkg/interface/webterm/Tabs.tsx +++ b/pkg/interface/webterm/Tabs.tsx @@ -6,7 +6,7 @@ import { Icon } from '@tlon/indigo-react'; export const Tabs = () => { const { sessions, names } = useTermState(); - const { addSession } = useAddSession(); + const addSession = useAddSession(); return (
diff --git a/pkg/interface/webterm/lib/useAddSession.ts b/pkg/interface/webterm/lib/useAddSession.ts index 25a5fc0c2..c5556c14b 100644 --- a/pkg/interface/webterm/lib/useAddSession.ts +++ b/pkg/interface/webterm/lib/useAddSession.ts @@ -62,7 +62,5 @@ export const useAddSession = () => { } }, [names]); - return { - addSession - }; + return addSession; }; From 349033fb121aa39b77e8846b974f3a64115f6192 Mon Sep 17 00:00:00 2001 From: tomholford Date: Wed, 13 Apr 2022 08:47:30 -0700 Subject: [PATCH 079/249] ux: detect OS for hotkey instructions Also, ensure changes from this PR are included in the session branch: https://github.com/urbit/urbit/pull/5529 --- pkg/interface/webterm/Buffer.tsx | 4 ++- pkg/interface/webterm/InfoButton.tsx | 9 +++-- pkg/interface/webterm/lib/theme.ts | 3 +- pkg/interface/webterm/lib/useDetectOS.ts | 44 ++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 pkg/interface/webterm/lib/useDetectOS.ts diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index da4a8e8a6..e0ce5e143 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -33,7 +33,9 @@ const termConfig: ITerminalOptions = { bellSound: bel, // // allows text selection by holding modifier (option, or shift) - macOptionClickForcesSelection: true + macOptionClickForcesSelection: true, + // prevent insertion of simulated arrow keys on-altclick + altClickMovesCursor: false }; const readInput = (term: Terminal, e: string): Belt[] => { diff --git a/pkg/interface/webterm/InfoButton.tsx b/pkg/interface/webterm/InfoButton.tsx index 4ec3a3347..b0ba22953 100644 --- a/pkg/interface/webterm/InfoButton.tsx +++ b/pkg/interface/webterm/InfoButton.tsx @@ -1,10 +1,15 @@ 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(() => { - alert('To select text in the terminal, hold down the alt key.'); - }, []); + const key = isMacOS ? 'alt' : 'shift'; + + alert(`To select text in the terminal, hold down the ${key} key.`); + }, [isMacOS]); return ( <> diff --git a/pkg/interface/webterm/lib/theme.ts b/pkg/interface/webterm/lib/theme.ts index 6044f1c30..9b97806d4 100644 --- a/pkg/interface/webterm/lib/theme.ts +++ b/pkg/interface/webterm/lib/theme.ts @@ -16,6 +16,7 @@ export const makeTheme = (dark: boolean): ITheme => { foreground: fg, background: bg, brightBlack: '#7f7f7f', // NOTE slogs - cursor: fg + cursor: fg, + selection: fg }; }; diff --git a/pkg/interface/webterm/lib/useDetectOS.ts b/pkg/interface/webterm/lib/useDetectOS.ts new file mode 100644 index 000000000..7b8f915f9 --- /dev/null +++ b/pkg/interface/webterm/lib/useDetectOS.ts @@ -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 + }; +}; From 37ce741a77898d0bdd99fff497699e622bea6146 Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 14 Apr 2022 04:52:43 -0700 Subject: [PATCH 080/249] deps: replace deprecated xterm#setOption See: https://github.com/xtermjs/xterm.js/blob/4.15.0/typings/xterm.d.ts#L1053 --- pkg/interface/webterm/Buffer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index e0ce5e143..f18f0ab6e 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -155,7 +155,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // set up xterm terminal // const term = new Terminal(termConfig); - term.setOption('theme', makeTheme(dark)); + term.options.theme = makeTheme(dark); const fit = new FitAddon(); term.loadAddon(fit); fit.fit(); @@ -252,7 +252,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { useEffect(() => { const theme = makeTheme(dark); if (session) { - session.term.setOption('theme', theme); + session.term.options.theme = theme; } if (container.current) { container.current.style.backgroundColor = theme.background || ''; From dfded5e592a7e4f27272733c455896f4709fecba Mon Sep 17 00:00:00 2001 From: tomholford Date: Thu, 14 Apr 2022 07:13:09 -0700 Subject: [PATCH 081/249] ux: refactor resize behavior - debounced resize event listener - new Buffer#onSelect: resize, focus, and pokes `herm` with updated rows / cols - simplify container ref implementation (no need for a callback ref), remove isOpen hack - add lodash for debounce - Tab#onClick no longer handles focus (it's now handled by Buffer#onSelect) --- pkg/interface/webterm/Buffer.tsx | 87 +++++++++++++----------- pkg/interface/webterm/Tab.tsx | 1 - pkg/interface/webterm/constants.ts | 1 + pkg/interface/webterm/package-lock.json | Bin 1283742 -> 1283772 bytes pkg/interface/webterm/package.json | 1 + 5 files changed, 49 insertions(+), 41 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index f18f0ab6e..4fb21b775 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -1,5 +1,6 @@ import { Terminal, ITerminalOptions } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; +import { debounce } from 'lodash'; import bel from './lib/bel'; import api from './api'; @@ -13,7 +14,7 @@ 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 } from './constants'; +import { DEFAULT_SESSION, RESIZE_DEBOUNCE_MS } from './constants'; import { retry } from './lib/retry'; const termConfig: ITerminalOptions = { @@ -120,11 +121,10 @@ const readInput = (term: Terminal, e: string): Belt[] => { return belts; }; -const onResize = (session: Session) => () => { - //TODO debounce, if it ever becomes a problem - //TODO test that we only send this to the selected session, - // and that we *do* send it on-selected-change if necessary. - session?.fit.fit(); +const onResize = async (name: string, session: Session) => { + if (session) { + session.fit.fit(); + } }; const onInput = (name: string, session: Session, e: string) => { @@ -145,7 +145,7 @@ interface BufferProps { } export default function Buffer({ name, selected, dark }: BufferProps) { - const container = useRef(null); + const containerRef = useRef(null); const session: Session = useTermState(s => s.sessions[name]); @@ -165,7 +165,7 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // term.write(csi('?9h')); - const ses: Session = { term, fit, hasBell: false, subscriptionId: null }; + const ses: Session = { term, fit, hasBell: false, subscriptionId: null }; // set up event handlers // @@ -218,6 +218,15 @@ export default function Buffer({ name, selected, dark }: BufferProps) { }); }, []); + const onSelect = useCallback(async () => { + if (session && selected) { + session.fit.fit(); + session.term.focus(); + await api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })); + } + }, [session, selected]); + + // Effects // init session useEffect(() => { if(session) { @@ -227,25 +236,27 @@ export default function Buffer({ name, selected, dark }: BufferProps) { initSession(name, dark); }, [name]); - // on selected change, maybe setup the term, or put it into the container - // - const setContainer = useCallback((containerRef: HTMLDivElement | null) => { - const newContainer = containerRef || container.current; - if(session && newContainer) { - container.current = newContainer; + // attach to DOM when ref is available + useEffect(() => { + if(session && containerRef.current && !session.term.element) { + session.term.open(containerRef.current); } - }, [session]); + }, [session, containerRef]); - // on-init, open slogstream and fetch existing sessions + // on-init, open slogstream and fetch existing sessions // useEffect(() => { - window.addEventListener('resize', onResize(session)); + if(!session) { + return; + } + + const debouncedResize = debounce(() => onResize(name, session), RESIZE_DEBOUNCE_MS); + window.addEventListener('resize', debouncedResize); return () => { - // TODO clean up subs? - window.removeEventListener('resize', onResize(session)); + window.removeEventListener('resize', debouncedResize); }; - }, []); + }, [session]); // on dark mode change, change terminals' theme // @@ -254,24 +265,20 @@ export default function Buffer({ name, selected, dark }: BufferProps) { if (session) { session.term.options.theme = theme; } - if (container.current) { - container.current.style.backgroundColor = theme.background || ''; + if (containerRef.current) { + containerRef.current.style.backgroundColor = theme.background || ''; } }, [session, dark]); + // On select, resize, focus, and poke herm with updated cols and rows useEffect(() => { - if (session && selected && !session.term.isOpen) { - session.term.open(container.current); - session.fit.fit(); - session.term.focus(); - session.term.isOpen = true; - } - }, [selected, session]); + onSelect(); + }, [onSelect]); return ( !session && !selected ?

Loading...

- : + : - - - + + + ); } diff --git a/pkg/interface/webterm/Tab.tsx b/pkg/interface/webterm/Tab.tsx index 209d408e5..6f15e9f59 100644 --- a/pkg/interface/webterm/Tab.tsx +++ b/pkg/interface/webterm/Tab.tsx @@ -17,7 +17,6 @@ export const Tab = ( { session, name }: TabProps ) => { state.selected = name; state.sessions[name].hasBell = false; }); - useTermState.getState().sessions[name]?.term?.focus(); }; const onDelete = useCallback(async (e) => { diff --git a/pkg/interface/webterm/constants.ts b/pkg/interface/webterm/constants.ts index 66d4b0ecc..549f4bd94 100644 --- a/pkg/interface/webterm/constants.ts +++ b/pkg/interface/webterm/constants.ts @@ -1,5 +1,6 @@ export const DEFAULT_SESSION = ''; export const DEFAULT_HANDLER = 'hood'; +export const RESIZE_DEBOUNCE_MS = 100; /** * Session ID validity: diff --git a/pkg/interface/webterm/package-lock.json b/pkg/interface/webterm/package-lock.json index 902930d988df8539a038394474507620face3d54..4e617d5f3024df6fc15133e3af632b343071f301 100644 GIT binary patch delta 109 zcmWl|OA0_x7=Y1!@AorPOJY$57C_yZY~YrO6gG5~J@}kDi|%gSZI>v$maTeE$)-md j)hmeyBcqYOMVk&?dh{7EWW<;WQ)bLruw-=@srUHz delta 104 zcmWl~y9t0W06;+!KZ!=;57){}f`tPpq!8R7kVY(YGAp0OaZhkZaPby?dW~JR9DUq{ gnU!3W6!=e&B0~-ZjRGYMD%7xO(4s?sDLI_m2aMVl`Tzg` diff --git a/pkg/interface/webterm/package.json b/pkg/interface/webterm/package.json index 856b29eed..0e58cc608 100644 --- a/pkg/interface/webterm/package.json +++ b/pkg/interface/webterm/package.json @@ -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", From 65f9f904c73becdc0e7c656b8a5c217f0a6a5c6c Mon Sep 17 00:00:00 2001 From: fang Date: Fri, 15 Apr 2022 18:02:42 +0200 Subject: [PATCH 082/249] zuse: rewrite klr:format's +scag and +slag The previous implementation was counting the full length of the stub unnecessarily. Doing a single "dumb" traversal is ~40% faster. --- pkg/arvo/sys/zuse.hoon | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 1d465267e..a1895c0ee 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -3788,29 +3788,24 @@ ++ slag :: slag stub |= [a=@ b=stub] ^- stub - =+ c=(lnts-char b) - =+ i=(brek a c) - ?~ i ~ - =+ 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) + ?: =(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 - =+ 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) + ?: =(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] From 2d3e803704af38e761f014ff612d8097494ee2f8 Mon Sep 17 00:00:00 2001 From: tomholford Date: Tue, 19 Apr 2022 03:41:40 -0700 Subject: [PATCH 083/249] devex: improved resize behavior - only resize when necessary (check the container's height) - refactor CSS: use position relative / absolute to stack Buffers instead of display:none; this affects the calcuations used by fit() - fix dark mode styles, tweak viewport height (100vh --> 99vh) to prevent overflow scroller --- pkg/interface/webterm/Buffer.tsx | 27 +++++++++++++++++++-------- pkg/interface/webterm/constants.ts | 1 + pkg/interface/webterm/index.html | 14 ++++++++++++-- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx index 4fb21b775..3e1be2bb3 100644 --- a/pkg/interface/webterm/Buffer.tsx +++ b/pkg/interface/webterm/Buffer.tsx @@ -14,7 +14,7 @@ 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 } from './constants'; +import { DEFAULT_SESSION, RESIZE_DEBOUNCE_MS, RESIZE_THRESHOLD_PX } from './constants'; import { retry } from './lib/retry'; const termConfig: ITerminalOptions = { @@ -124,6 +124,7 @@ const readInput = (term: Terminal, e: string): Belt[] => { const onResize = async (name: string, session: Session) => { if (session) { session.fit.fit(); + api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })); } }; @@ -171,9 +172,6 @@ export default function Buffer({ name, selected, dark }: BufferProps) { // term.onData(e => onInput(name, ses, e)); term.onBinary(e => onInput(name, ses, e)); - term.onResize((e) => { - api.poke(pokeTask(name, { blew: { w: e.cols, h: e.rows } })); - }); // open subscription // @@ -218,11 +216,22 @@ export default function Buffer({ name, selected, dark }: BufferProps) { }); }, []); + 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) { + if (session && selected && shouldResize()) { session.fit.fit(); - session.term.focus(); await api.poke(pokeTask(name, { blew: { w: session.term.cols, h: session.term.rows } })); + session.term.focus(); } }, [session, selected]); @@ -243,13 +252,14 @@ export default function Buffer({ name, selected, dark }: BufferProps) { } }, [session, containerRef]); - // on-init, open slogstream and fetch existing sessions + // 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); @@ -285,7 +295,8 @@ export default function Buffer({ name, selected, dark }: BufferProps) { bg='white' fontFamily='mono' overflow='hidden' - style={selected ? {} : { display: 'none' }} + className="terminal-container" + style={selected ? { zIndex: 999 } : {}} >

^5)W6WX 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 diff --git a/pkg/interface/package.json b/pkg/interface/package.json index 00207a538..0a2191f8b 100644 --- a/pkg/interface/package.json +++ b/pkg/interface/package.json @@ -53,6 +53,8 @@ "suncalc": "^1.8.0", "unist-util-visit": "^3.0.0", "urbit-ob": "^5.0.1", + "xterm": "^4.10.0", + "xterm-addon-fit": "^0.5.0", "workbox-core": "^6.0.2", "workbox-precaching": "^6.0.2", "workbox-recipes": "^6.0.2", diff --git a/pkg/interface/src/logic/lib/bel.js b/pkg/interface/src/logic/lib/bel.js deleted file mode 100644 index 77ee14507..000000000 --- a/pkg/interface/src/logic/lib/bel.js +++ /dev/null @@ -1 +0,0 @@ -export default new Audio('data:@file/ogg;base64,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'); diff --git a/pkg/interface/src/logic/lib/bel.ts b/pkg/interface/src/logic/lib/bel.ts new file mode 100644 index 000000000..6de9d6ee3 --- /dev/null +++ b/pkg/interface/src/logic/lib/bel.ts @@ -0,0 +1 @@ +export default 'data:@file/ogg;base64,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'; diff --git a/pkg/interface/src/logic/state/term.ts b/pkg/interface/src/logic/state/term.ts new file mode 100644 index 000000000..d0820cd87 --- /dev/null +++ b/pkg/interface/src/logic/state/term.ts @@ -0,0 +1,21 @@ +import { Terminal } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; + +import { createState } from "./base"; + +type Session = { term: Terminal, fit: FitAddon }; +type Sessions = { [id: string]: Session; } + +export interface TermState { + sessions: Sessions, + selected: string, + slogstream: null | EventSource, +}; + +const useTermState = createState('Term', { + sessions: {}, + selected: '', // empty string is default session + slogstream: null, +}, ['sessions', 'slogstream']); //TODO consider persisting + +export default useTermState; \ No newline at end of file diff --git a/pkg/interface/src/views/apps/term/api.tsx b/pkg/interface/src/views/apps/term/api.tsx deleted file mode 100644 index 077263efc..000000000 --- a/pkg/interface/src/views/apps/term/api.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import _ from 'lodash'; - -export default class Api { - ship: any; - channel: any; - bindPaths: any[]; - constructor(ship, channel) { - this.ship = ship; - this.channel = channel; - this.bindPaths = []; - } - - bind(path, method, ship = this.ship, appl = 'herm', success, fail) { - this.bindPaths = _.uniq([...this.bindPaths, path]); - - (window as any).subscriptionId = this.channel.subscribe(ship, appl, path, - (err) => { - fail(err); - }, - (event) => { - success({ - data: event, - from: { - ship, - path - } - }); - }, - (err) => { - fail(err); - }); - } - - belt(belt) { - return this.action('herm', 'belt', belt); - } - - action(appl, mark, data) { - return new Promise((resolve, reject) => { - this.channel.poke(window.ship, appl, mark, data, - (json) => { - resolve(json); - }, - (err) => { - reject(err); - }); - }); - } -} - diff --git a/pkg/interface/src/views/apps/term/app.tsx b/pkg/interface/src/views/apps/term/app.tsx index 7db2c96a6..071aa5cc6 100644 --- a/pkg/interface/src/views/apps/term/app.tsx +++ b/pkg/interface/src/views/apps/term/app.tsx @@ -1,100 +1,444 @@ -import { Box, Col } from '@tlon/indigo-react'; -import React, { Component } from 'react'; +import React, { + useEffect, + useRef, + useCallback +} from 'react'; import Helmet from 'react-helmet'; -import { Route } from 'react-router-dom'; -import withState from '~/logic/lib/withState'; -import useHarkState from '~/logic/state/hark'; -import Api from './api'; -import { History } from './components/history'; -import { Input } from './components/input'; -import './css/custom.css'; -import Store from './store'; -import Subscription from './subscription'; -class TermApp extends Component { - store: Store; - api: any; - subscription: any; - constructor(props) { - super(props); - this.store = new Store(); - this.store.setStateHandler(this.setState.bind(this)); +import useTermState from '~/logic/state/term'; +import { useDark } from '~/logic/state/join'; - this.state = this.store.state; - } +import { Terminal, ITerminalOptions, ITheme } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; +import { saveAs } from 'file-saver'; - resetControllers() { - this.api = null; - this.subscription = null; - } +import { Box, Col } from '@tlon/indigo-react'; - componentDidMount() { - this.resetControllers(); - // eslint-disable-next-line new-cap - const channel = new (window as any).channel(); - this.api = new Api(this.props.ship, channel); - this.store.api = this.api; +import '../../../../node_modules/xterm/css/xterm.css'; +import api from '~/logic/api/index'; +import { + Belt, Blit, Stye, Stub, Tint, Deco, + pokeTask, pokeBelt +} from '@urbit/api/term'; - this.subscription = new Subscription(this.store, this.api, channel); - this.subscription.start(); - } +import bel from '~/logic/lib/bel'; - componentWillUnmount() { - this.subscription.delete(); - this.store.clear(); - this.resetControllers(); - } - - render() { - return ( - <> - - { this.props.notificationsCount ? `(${String(this.props.notificationsCount) }) `: '' }Landscape - - - { - return ( - - - {/* @ts-ignore declare props in later pass */} - - - - - ); - }} - /> - - - ); - } +type TermAppProps = { + ship: string; + notificationsCount: number; } -export default withState(TermApp, [[useHarkState]]); +const makeTheme = (dark: boolean): ITheme => { + let fg, bg: string; + if (dark) { + fg = 'white'; + bg = 'black'; + } 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 + }; +}; + +const termConfig: ITerminalOptions = { + logLevel: 'warn', + // + convertEol: true, + // + rows: 24, + cols: 80, + scrollback: 10000, + // + fontFamily: '"Source Code Pro","Roboto mono","Courier New",monospace', + // NOTE theme colors configured dynamically + // + bellStyle: 'sound', + bellSound: bel, + // + // allows text selection by holding modifier (option, or shift) + macOptionClickForcesSelection: true +}; + +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) { + 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); +}; + +// 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) { + belts.push({ mod: { mod: 'ctl', key: String.fromCharCode(96 + c) } }); + } + + // 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: { 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(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! + api.poke(pokeBelt(ses, 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) => { + api.poke(pokeTask(selected, { blew: { w: e.cols, h: e.rows } })); + }); + + ses = { term, fit }; + + // open subscription + // + api.subscribe({ app: 'herm', path: '/session/'+selected, + 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 ( + <> + + { props.notificationsCount ? `(${String(props.notificationsCount) }) `: '' }Landscape + + + + + + + ); +} diff --git a/pkg/interface/src/views/apps/term/components/history.tsx b/pkg/interface/src/views/apps/term/components/history.tsx deleted file mode 100644 index 814d417dc..000000000 --- a/pkg/interface/src/views/apps/term/components/history.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Box } from '@tlon/indigo-react'; -import React, { Component } from 'react'; -import Line from './line'; - -export class History extends Component { - constructor(props) { - super(props); - } - - render() { - return ( - - - {/* @ts-ignore declare props in later pass */} - {this.props.log.map((line, i) => { - // @ts-ignore react memo not passing props - return ; - })} - - - ); - } - } - -export default History; diff --git a/pkg/interface/src/views/apps/term/components/line.tsx b/pkg/interface/src/views/apps/term/components/line.tsx deleted file mode 100644 index 5f8f5c131..000000000 --- a/pkg/interface/src/views/apps/term/components/line.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { Text } from '@tlon/indigo-react'; -import React from 'react'; -// @ts-ignore line isn't in props? -export default React.memo(({ line }) => { - // line body to jsx - // NOTE lines are lists of characters that might span multiple codepoints - // - let text = ''; - if (line.lin) { - text = line.lin.join(''); - } else if (line.klr) { - text = line.klr.map((part, i) => { - const prop = part.stye.deco.reduce((prop, deco) => { - switch (deco) { - case null: return prop; - case 'br': return { bold: true, ...prop }; - case 'bl': return { className: 'blink', ...prop }; - case 'un': return { style: { textDecoration: 'underline' }, ...prop }; - default: console.log('weird deco', deco); return prop; - } - }, {}); - switch (part.stye.fore) { - case null: break; - case 'r': prop.color = 'red'; break; - case 'g': prop.color = 'green'; break; - case 'b': prop.color = 'blue'; break; - case 'c': prop.color = 'cyan'; break; - case 'm': prop.color = 'purple'; break; - case 'y': prop.color = 'yellow'; break; - case 'k': prop.color = 'black'; break; - case 'w': prop.color = 'white'; break; - default: prop.color = '#' + part.stye.fore; - } - switch (part.stye.back) { - case null: break; - case 'r': prop.backgroundColor = 'red'; break; - case 'g': prop.backgroundColor = 'green'; break; - case 'b': prop.backgroundColor = 'blue'; break; - case 'c': prop.backgroundColor = 'cyan'; break; - case 'm': prop.backgroundColor = 'purple'; break; - case 'y': prop.backgroundColor = 'yellow'; break; - case 'k': prop.backgroundColor = 'black'; break; - case 'w': prop.backgroundColor = 'white'; break; - default: prop.backgroundColor = '#' + part.stye.back; - } - if (Object.keys(prop).length === 0) { - return part.text; - } else { - return ( - {part.text.join('')} - ); - } - }); - } - - // render line - // - return ( - - {text} - - ); -}); diff --git a/pkg/interface/src/views/apps/term/css/custom.css b/pkg/interface/src/views/apps/term/css/custom.css deleted file mode 100644 index b25bcdbd9..000000000 --- a/pkg/interface/src/views/apps/term/css/custom.css +++ /dev/null @@ -1,16 +0,0 @@ -input#term { - background-color: inherit; - color: inherit; -} - -.blink { - animation: 4s ease-in-out infinite opacity_blink; -} - -@keyframes opacity_blink { - 0% { opacity: 0; } - 10% { opacity: 1; } - 80% { opacity: 1; } - 90% { opacity: 0; } - 100% { opacity: 0; } -} diff --git a/pkg/interface/src/views/apps/term/store.tsx b/pkg/interface/src/views/apps/term/store.tsx deleted file mode 100644 index d2166083a..000000000 --- a/pkg/interface/src/views/apps/term/store.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { saveAs } from 'file-saver'; -import bel from '../../../logic/lib/bel'; - -export default class Store { - state: any; - api: any; - setState: any; - constructor() { - this.state = this.initialState(); - } - - initialState() { - return { - lines: [''], - cursor: 0 - }; - } - - clear() { - this.setState(this.initialState()); - } - - handleEvent(data) { - // process slogs - // - if (data.slog) { - this.state.lines.splice(this.state.lines.length-1, 0, { lin: [data.slog] }); - this.setState({ lines: this.state.lines }); - return; - } - - // process blits - // - const blit = data.data; - switch (Object.keys(blit)[0]) { - case 'bel': - bel.play(); - break; - case 'clr': - this.state.lines = this.state.lines.slice(-1); - this.setState({ lines: this.state.lines }); - break; - case 'hop': - // since lines are lists of characters that might span multiple - // codepoints, we need to calculate the byte-wise cursor position - // to avoid incorrect cursor rendering. - // - const line = this.state.lines[this.state.lines.length - 1]; - let hops; - if (line.lin) { - hops = line.lin.slice(0, blit.hop); - } else if (line.klr) { - hops = line.klr.reduce((h, p) => { - if (h.length >= blit.hop) -return h; - return [...h, ...p.text.slice(0, blit.hop - h.length)]; - }, []); - } - this.setState({ cursor: hops.join('').length }); - break; - case 'lin': - this.state.lines[this.state.lines.length - 1] = blit; - this.setState({ lines: this.state.lines }); - break; - case 'klr': - this.state.lines[this.state.lines.length - 1] = blit; - this.setState({ lines: this.state.lines }); - break; - case 'mor': - this.state.lines.push(''); - this.setState({ lines: this.state.lines }); - break; - case 'sag': - blit.sav = blit.sag; - break; - case 'sav': - const name = blit.sav.path.split('/').slice(-2).join('.'); - const buff = new Buffer(blit.sav.file, 'base64'); - const blob = new Blob([buff], { type: 'application/octet-stream' }); - saveAs(blob, name); - break; - case 'url': - // TODO too invasive? just print as ? - window.open(blit.url); - break; - default: console.log('weird blit', blit); - } - } - - setStateHandler(setState) { - this.setState = setState; - } -} - diff --git a/pkg/interface/src/views/apps/term/subscription.tsx b/pkg/interface/src/views/apps/term/subscription.tsx deleted file mode 100644 index 178246e43..000000000 --- a/pkg/interface/src/views/apps/term/subscription.tsx +++ /dev/null @@ -1,87 +0,0 @@ -export default class Subscription { - store: any; - api: any; - channel: any; - firstRoundComplete: boolean; - constructor(store, api, channel) { - this.store = store; - this.api = api; - this.channel = channel; - - this.channel.setOnChannelError(this.onChannelError.bind(this)); - this.firstRoundComplete = false; - } - - start() { - if (this.api.ship) { - this.firstRound(); - } else { - console.error('~~~ ERROR: Must set api.ship before operation ~~~'); - } - this.setupSlog(); - } - - setupSlog() { - let available = false; - const slog = new EventSource('/~_~/slog', { withCredentials: true }); - - slog.onopen = (e) => { - console.log('slog: opened stream'); - available = true; - }; - - slog.onmessage = (e) => { - this.handleEvent({ slog: 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...'); - this.setupSlog(); - }, 10000); - } - }; - } - - delete() { - this.channel.delete(); - } - - onChannelError(err) { - console.error('event source error: ', err); - console.log('initiating new channel'); - this.firstRoundComplete = false; - setTimeout(() => { - this.store.handleEvent({ - data: { clear : true } - }); - - this.start(); - }, 2000); - } - - subscribe(path, app) { - this.api.bind(path, 'PUT', this.api.ship, app, - this.handleEvent.bind(this), - (err) => { - console.log(err); - this.subscribe(path, app); - }, - () => { - this.subscribe(path, app); - }); - } - - firstRound() { - this.subscribe('/session/', 'herm'); - } - - handleEvent(diff) { - this.store.handleEvent(diff); - } -} - diff --git a/pkg/npm/api/term/index.ts b/pkg/npm/api/term/index.ts new file mode 100644 index 000000000..341e81711 --- /dev/null +++ b/pkg/npm/api/term/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * from './lib'; \ No newline at end of file diff --git a/pkg/npm/api/term/lib.ts b/pkg/npm/api/term/lib.ts new file mode 100644 index 000000000..e6ae877ea --- /dev/null +++ b/pkg/npm/api/term/lib.ts @@ -0,0 +1,22 @@ +import _ from 'lodash'; + +import { Scry } from '../lib' +import { Poke } from '../lib/types'; +import { Belt, Task, SessionTask } from './types'; + +export const pokeTask = (session: string, task: Task): Poke => ({ + app: 'herm', + mark: 'herm-task', + json: { session, ...task } +}); + +export const pokeBelt = ( + session: string, + belt: Belt +): Poke => pokeTask(session, { belt }); + +//NOTE scry will return string[] +export const scrySessions = (): Scry => ({ + app: 'herm', + path: `/sessions` +}); diff --git a/pkg/npm/api/term/types.ts b/pkg/npm/api/term/types.ts new file mode 100644 index 000000000..8bcdd302f --- /dev/null +++ b/pkg/npm/api/term/types.ts @@ -0,0 +1,60 @@ +// outputs +// + +export type TermUpdate = + | Blit; + +export type Tint = + | null + | 'r' | 'g' | 'b' | 'c' | 'm' | 'y' | 'k' | 'w' + | { r: number, g: number, b: number }; + +export type Deco = null | 'br' | 'un' | 'bl'; + +export type Stye = { + deco: Deco[], + back: Tint, + fore: Tint +}; + +export type Stub = { + stye: Stye, + text: string[] +} + +export type Blit = + | { bel: null } // make a noise + | { clr: null } // clear the screen + | { hop: number | { r: number, c: number } } // set cursor col/pos + | { klr: Stub[] } // put styled + | { put: string[] } // put text at cursor + | { nel: null } // newline + | { 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 + +// inputs +// + +export type Bolt = + | string + | { aro: 'd' | 'l' | 'r' | 'u' } + | { bac: null } + | { del: null } + | { hit: { r: number, c: number } } + | { ret: null } + +export type Belt = + | Bolt + | { mod: { mod: 'ctl' | 'met' | 'hyp', key: Bolt } } + | { txt: Array }; + +export type Task = + | { belt: Belt } + | { blew: { w: number, h: number } } + | { flow: { term: string, apps: Array<{ who: string, app: string }> } } + | { hail: null } + | { hook: null } + +export type SessionTask = { session: string } & Task diff --git a/pkg/urbit/compat/posix/ptty.c b/pkg/urbit/compat/posix/ptty.c index ff42abff9..7c1a17f00 100644 --- a/pkg/urbit/compat/posix/ptty.c +++ b/pkg/urbit/compat/posix/ptty.c @@ -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; diff --git a/pkg/urbit/configure b/pkg/urbit/configure index ab5b3a3df..138f52a85 100755 --- a/pkg/urbit/configure +++ b/pkg/urbit/configure @@ -195,7 +195,7 @@ for citem in $compat; do done cat >config.mk <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; } diff --git a/pkg/urbit/jets/e/rub.c b/pkg/urbit/jets/e/rub.c index 641e53035..48a1116b3 100644 --- a/pkg/urbit/jets/e/rub.c +++ b/pkg/urbit/jets/e/rub.c @@ -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); } diff --git a/pkg/urbit/jets/e/secp.c b/pkg/urbit/jets/e/secp.c index 6a4c6ce63..537606adf 100644 --- a/pkg/urbit/jets/e/secp.c +++ b/pkg/urbit/jets/e/secp.c @@ -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(); } } diff --git a/pkg/urbit/jets/f/core.c b/pkg/urbit/jets/f/core.c index 753ea74de..5d7ef8015 100644 --- a/pkg/urbit/jets/f/core.c +++ b/pkg/urbit/jets/f/core.c @@ -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(); } } diff --git a/pkg/urbit/jets/f/look.c b/pkg/urbit/jets/f/look.c index e54091b0b..038f7a522 100644 --- a/pkg/urbit/jets/f/look.c +++ b/pkg/urbit/jets/f/look.c @@ -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 { diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index 4536069a6..1737890be 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -433,7 +433,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]; @@ -568,7 +568,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); @@ -684,7 +684,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++; } @@ -917,7 +917,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); } @@ -1065,7 +1065,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, @@ -1103,7 +1103,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, @@ -1162,7 +1162,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() @@ -1218,7 +1218,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() diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 224eb86d9..92b94edec 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -63,7 +63,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); } } @@ -136,7 +136,7 @@ u3e_fault(void* adr_v, c3_i ser_i) #if 0 if ( pag_w == 131041 ) { - u3l_log("dirty page %d (at %p); unprotecting %p to %p\r\n", + u3l_log("dirty page %d (at %p); unprotecting %p to %p", pag_w, adr_v, (u3_Loom + (pag_w << u3a_page)), @@ -341,7 +341,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 } @@ -458,7 +458,7 @@ _ce_patch_save_page(u3_ce_patch* pat_u, (1 << u3a_page)); #if 0 - u3l_log("protect a: page %d\r\n", pag_w); + u3l_log("protect a: page %d", pag_w); #endif _ce_patch_write_page(pat_u, pgc_w, mem_w); @@ -484,7 +484,7 @@ _ce_patch_junk_page(u3_ce_patch* pat_u, c3_w blk_w = (pag_w >> 5); c3_w bit_w = (pag_w & 31); - // u3l_log("protect b: page %d\r\n", pag_w); + // u3l_log("protect b: page %d", pag_w); if ( -1 == mprotect(u3_Loom + (pag_w << u3a_page), (1 << (u3a_page + 2)), PROT_READ) ) @@ -688,7 +688,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } } #if 0 - u3l_log("apply: %d, %x\n", pag_w, u3r_mug_words(mem_w, (1 << u3a_page))); + u3l_log("apply: %d, %x", pag_w, u3r_mug_words(mem_w, (1 << u3a_page))); #endif } } @@ -713,7 +713,7 @@ _ce_image_blit(u3e_image* img_u, c3_w off_w = (ptr_w - u3_Loom); c3_w pag_w = (off_w >> u3a_page); - u3l_log("blit: page %d, mug %x\r\n", pag_w, + u3l_log("blit: page %d, mug %x", pag_w, u3r_mug_words(ptr_w, (1 << u3a_page))); } #endif @@ -868,17 +868,17 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) -(1 << u3a_page)); if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, PROT_READ) ) { - u3l_log("loom: live mprotect: %s\r\n", strerror(errno)); + u3l_log("loom: live mprotect: %s", strerror(errno)); c3_assert(0); } - 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 { diff --git a/pkg/urbit/noun/jets.c b/pkg/urbit/noun/jets.c index 357e94bd8..c60badf5d 100644 --- a/pkg/urbit/noun/jets.c +++ b/pkg/urbit/noun/jets.c @@ -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); } diff --git a/pkg/urbit/noun/log.c b/pkg/urbit/noun/log.c index 866a7430e..f1a7c1b38 100644 --- a/pkg/urbit/noun/log.c +++ b/pkg/urbit/noun/log.c @@ -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); diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index f6e692824..14f83c852 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -318,7 +318,7 @@ _cm_signal_recover(c3_l sig_l, u3_noun arg) while ( rod_u->kid_p ) { #if 0 - u3l_log("collecting %d frames\r\n", + u3l_log("collecting %d frames", u3kb_lent((u3to(u3_road, rod_u->kid_p)->bug.tax)); #endif tax = u3kb_weld(_cm_stack_recover(u3to(u3_road, rod_u->kid_p)), tax); @@ -372,7 +372,7 @@ _cm_signal_deep(c3_w mil_w) itm_u.it_value.tv_usec = 1000 * (mil_w % 1000); if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) { - u3l_log("loom: set timer failed %s\r\n", strerror(errno)); + u3l_log("loom: set timer failed %s", strerror(errno)); } else { rsignal_install_handler(SIGVTALRM, _cm_signal_handle_alrm); @@ -405,7 +405,7 @@ _cm_signal_done() timerclear(&itm_u.it_value); if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) { - u3l_log("loom: clear timer failed %s\r\n", strerror(errno)); + u3l_log("loom: clear timer failed %s", strerror(errno)); } } @@ -437,7 +437,7 @@ u3m_file(c3_c* pas_c) c3_y* pad_y; if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - u3l_log("%s: %s\r\n", pas_c, strerror(errno)); + u3l_log("%s: %s", pas_c, strerror(errno)); return u3m_bail(c3__fail); } fln_w = buf_b.st_size; @@ -632,7 +632,7 @@ u3m_dump(void) fre_u = fre_u->nex_u; } } - u3l_log("dump: hat_w %x, fre_w %x, allocated %x\n", + u3l_log("dump: hat_w %x, fre_w %x, allocated %x", hat_w, fre_w, (hat_w - fre_w)); if ( 0 != (hat_w - fre_w) ) { @@ -644,14 +644,14 @@ u3m_dump(void) if ( 0 != box_u->use_w ) { #ifdef U3_MEMORY_DEBUG - // u3l_log("live %d words, code %x\n", box_u->siz_w, box_u->cod_w); + // u3l_log("live %d words, code %x", box_u->siz_w, box_u->cod_w); #endif mem_w += box_u->siz_w; } box_w += box_u->siz_w; } - u3l_log("second count: %x\n", mem_w); + u3l_log("second count: %x", mem_w); } } #endif @@ -1548,7 +1548,7 @@ u3m_p(const c3_c* cap_c, u3_noun som) { c3_c* pre_c = u3m_pretty(som); - u3l_log("%s: %s\r\n", cap_c, pre_c); + u3l_log("%s: %s", cap_c, pre_c); c3_free(pre_c); } @@ -1609,7 +1609,7 @@ _cm_limits(void) rlm.rlim_cur = c3_min(rlm.rlim_max, (65536 << 10)); if ( 0 != setrlimit(RLIMIT_STACK, &rlm) ) { - u3l_log("boot: stack size: %s\r\n", strerror(errno)); + u3l_log("boot: stack size: %s", strerror(errno)); exit(1); } } @@ -1628,7 +1628,7 @@ _cm_limits(void) // no exit, not a critical limit // if ( 0 != setrlimit(RLIMIT_NOFILE, &rlm) ) { - u3l_log("boot: open file limit: %s\r\n", strerror(errno)); + u3l_log("boot: open file limit: %s", strerror(errno)); } } @@ -1642,7 +1642,7 @@ _cm_limits(void) // no exit, not a critical limit // if ( 0 != setrlimit(RLIMIT_CORE, &rlm) ) { - u3l_log("boot: core limit: %s\r\n", strerror(errno)); + u3l_log("boot: core limit: %s", strerror(errno)); } } # endif @@ -1665,7 +1665,7 @@ _cm_signals(void) // access and stack overflow exceptions. It calls u3e_fault directly. # else if ( 0 != sigsegv_install_handler(u3e_fault) ) { - u3l_log("boot: sigsegv install failed\n"); + u3l_log("boot: sigsegv install failed"); exit(1); } # endif @@ -1681,7 +1681,7 @@ _cm_signals(void) 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); } } @@ -1737,17 +1737,17 @@ u3m_init(void) MAP_ANON | MAP_PRIVATE, -1, 0); - u3l_log("boot: mapping %dMB failed\r\n", (len_w / (1024 * 1024))); + u3l_log("boot: mapping %dMB failed", (len_w / (1024 * 1024))); u3l_log("see urbit.org/using/install/#about-swap-space" " for adding swap space\r\n"); - if ( -1 != (c3_ps)dyn_v ) { - u3l_log("if porting to a new platform, try U3_OS_LoomBase %p\r\n", + if ( -1 != (c3_ps)map_v ) { + u3l_log("if porting to a new platform, try U3_OS_LoomBase %p", dyn_v); } exit(1); } - u3l_log("loom: mapped %dMB\r\n", len_w >> 20); + u3l_log("loom: mapped %dMB", len_w >> 20); } } @@ -1788,7 +1788,7 @@ u3m_boot(c3_c* dir_c) */ { c3_w len_w = u3j_boot(nuu_o); - u3l_log("boot: installed %d jets\r\n", len_w); + u3l_log("boot: installed %d jets", len_w); } /* Reactivate jets on old kernel. diff --git a/pkg/urbit/noun/nock.c b/pkg/urbit/noun/nock.c index bc41e5ddd..22e08e1db 100644 --- a/pkg/urbit/noun/nock.c +++ b/pkg/urbit/noun/nock.c @@ -44,7 +44,7 @@ _n_hint(u3_noun zep, low_i = 1; if ( 0 == (u3R->pro.nox_d % 65536ULL) ) { if ( c3__spot == zep ) { - u3l_log("spot %d/%d : %d/%d\r\n", + u3l_log("spot %d/%d : %d/%d", u3h(u3h(u3t(hod))), u3t(u3h(u3t(hod))), u3h(u3t(u3t(hod))), diff --git a/pkg/urbit/noun/trace.c b/pkg/urbit/noun/trace.c index 1ee8168c7..5d93db13d 100644 --- a/pkg/urbit/noun/trace.c +++ b/pkg/urbit/noun/trace.c @@ -167,7 +167,7 @@ _t_samp_process(u3_road* rod_u) pef = t_pef; } - // u3l_log("sample: stack length %d\r\n", u3kb_lent(u3k(pal))); + // u3l_log("sample: stack length %d", u3kb_lent(u3k(pal))); return pal; } } @@ -540,7 +540,7 @@ u3t_boot(void) sigemptyset(&set); sigaddset(&set, SIGPROF); if ( 0 != pthread_sigmask(SIG_UNBLOCK, &set, NULL) ) { - u3l_log("trace: thread mask SIGPROF: %s\r\n", strerror(errno)); + u3l_log("trace: thread mask SIGPROF: %s", strerror(errno)); } } @@ -569,7 +569,7 @@ u3t_boff(void) sigemptyset(&set); sigaddset(&set, SIGPROF); if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) { - u3l_log("trace: thread mask SIGPROF: %s\r\n", strerror(errno)); + u3l_log("trace: thread mask SIGPROF: %s", strerror(errno)); } } diff --git a/pkg/urbit/noun/vortex.c b/pkg/urbit/noun/vortex.c index acf7eea9d..820216b2f 100644 --- a/pkg/urbit/noun/vortex.c +++ b/pkg/urbit/noun/vortex.c @@ -60,9 +60,9 @@ _cv_lite(u3_noun pil) eve = tal; } - u3l_log("lite: arvo formula %x\r\n", u3r_mug(pil)); + u3l_log("lite: arvo formula %x", u3r_mug(pil)); pro = u3v_life(u3k(eve)); - u3l_log("lite: core %x\r\n", u3r_mug(pro)); + u3l_log("lite: core %x", u3r_mug(pro)); u3z(pil); return pro; @@ -89,7 +89,7 @@ u3v_boot_lite(u3_noun pil) u3z(pro); } - u3l_log("lite: final state %x\r\n", u3r_mug(u3A->roc)); + u3l_log("lite: final state %x", u3r_mug(u3A->roc)); return c3y; } @@ -209,7 +209,7 @@ _cv_mole(u3_noun fot, (0 != q_uco) || (c3n == u3r_sing(fot, r_uco)) ) { - u3l_log("strange mole %s\n", u3r_string(san))); + u3l_log("strange mole %s", u3r_string(san))); u3z(fot); u3z(uco); return c3n; } diff --git a/pkg/urbit/vere/auto.c b/pkg/urbit/vere/auto.c index 5a56d22bc..c02d7aabe 100644 --- a/pkg/urbit/vere/auto.c +++ b/pkg/urbit/vere/auto.c @@ -91,7 +91,7 @@ u3_auto_bail_slog(u3_ovum* egg_u, u3_noun lud) c3_w len_w = 1; while ( u3_nul != dul ) { - u3l_log("%s: bail %u\r\n", car_c, len_w++); + u3l_log("%s: bail %u", car_c, len_w++); u3_pier_punt_goof(car_c, u3k(u3h(dul))); dul = u3t(dul); @@ -240,7 +240,7 @@ _auto_kick_lost(u3_noun pax, u3_noun fav) c3_c* tag_c = u3r_string(u3h(fav)); c3_c* pax_c = u3r_string(tox); - u3l_log("kick: lost %%%s on %s\n", tag_c, pax_c); + u3l_log("kick: lost %%%s on %s", tag_c, pax_c); c3_free(pax_c); c3_free(tag_c); @@ -360,12 +360,12 @@ u3_auto_info(u3_auto* car_u) { u3_auto* nex_u; - u3l_log(" drivers:\n"); + u3l_log(" drivers:"); while ( car_u ) { nex_u = car_u->nex_u; - u3l_log(" %.*s: live=%s, queue=%u\n", + u3l_log(" %.*s: live=%s, queue=%u", u3r_met(3, car_u->nam_m), (c3_c*)&car_u->nam_m, ( c3y == car_u->liv_o ) ? "&" : "|", diff --git a/pkg/urbit/vere/dawn.c b/pkg/urbit/vere/dawn.c index 9c4cd9959..f11b3c608 100644 --- a/pkg/urbit/vere/dawn.c +++ b/pkg/urbit/vere/dawn.c @@ -71,7 +71,7 @@ _dawn_post_json(c3_c* url_c, uv_buf_t lod_u) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(curl = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -95,12 +95,12 @@ _dawn_post_json(c3_c* url_c, uv_buf_t lod_u) // XX retry? if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", + u3l_log("failed to fetch %s: %s", url_c, curl_easy_strerror(result)); exit(1); } if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + u3l_log("error fetching %s: HTTP %ld", url_c, cod_l); exit(1); } @@ -122,7 +122,7 @@ _dawn_get_jam(c3_c* url_c) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(curl = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -138,12 +138,12 @@ _dawn_get_jam(c3_c* url_c) // XX retry? if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", + u3l_log("failed to fetch %s: %s", url_c, curl_easy_strerror(result)); exit(1); } if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + u3l_log("error fetching %s: HTTP %ld", url_c, cod_l); exit(1); } @@ -207,7 +207,7 @@ _dawn_fail(u3_noun who, u3_noun rac, u3_noun sas) } } - u3l_log("boot: invalid keys for %s '%s'\r\n", rac_c, how_c); + u3l_log("boot: invalid keys for %s '%s'", rac_c, how_c); // XX deconstruct sas, print helpful error messages while ( u3_nul != sas ) { @@ -226,7 +226,7 @@ static u3_noun _dawn_need_unit(u3_noun nit, c3_c* msg_c) { if ( u3_nul == nit ) { - u3l_log("%s\r\n", msg_c); + u3l_log("%s", msg_c); exit(1); } else { @@ -245,7 +245,7 @@ _dawn_purl(u3_noun rac) if ( 0 == u3_Host.ops_u.eth_c ) { if ( c3__czar == rac ) { - u3l_log("boot: galaxy requires ethereum gateway via -e\r\n"); + u3l_log("boot: galaxy requires ethereum gateway via -e"); exit(1); } @@ -260,7 +260,7 @@ _dawn_purl(u3_noun rac) if ( u3_nul == rul ) { if ( c3__czar == rac ) { - u3l_log("boot: galaxy requires ethereum gateway via -e\r\n"); + u3l_log("boot: galaxy requires ethereum gateway via -e"); exit(1); } @@ -292,11 +292,11 @@ _dawn_turf(c3_c* dns_c) u3_noun rul = u3dc("rush", u3k(dns), u3k(par)); if ( (u3_nul == rul) || (c3n == u3h(u3t(rul))) ) { - u3l_log("boot: invalid domain specified with -H %s\r\n", dns_c); + u3l_log("boot: invalid domain specified with -H %s", dns_c); exit(1); } else { - u3l_log("boot: overriding network domains with %s\r\n", dns_c); + u3l_log("boot: overriding network domains with %s", dns_c); u3_noun dom = u3t(u3t(rul)); tuf = u3nc(u3k(dom), u3_nul); } @@ -345,7 +345,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) // pin block number // { - u3l_log("boot: retrieving latest block\r\n"); + u3l_log("boot: retrieving latest block"); u3_noun oct = u3v_wish("bloq:give:dawn"); u3_noun kob = _dawn_eth_rpc(url_c, u3k(oct)); @@ -369,7 +369,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) pot = u3v_wish("*point:azimuth"); } else { - u3l_log("boot: retrieving %s's public keys\r\n", + u3l_log("boot: retrieving %s's public keys", u3_Host.ops_u.who_c); { @@ -388,7 +388,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) u3_noun liv = u3_nul; // u3_noun liv = _dawn_get_json(parent, /some/url) - u3l_log("boot: verifying keys\r\n"); + u3l_log("boot: verifying keys"); // (each seed (lest error=@tas)) // @@ -400,7 +400,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) return u3_none; } - u3l_log("boot: getting sponsor\r\n"); + u3l_log("boot: getting sponsor"); pos = _dawn_sponsor(u3k(ship), u3k(rank), u3k(pot)); u3z(pot); u3z(liv); } @@ -409,7 +409,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) // (map ship [=life =pass]): galaxy table // { - u3l_log("boot: retrieving galaxy table\r\n"); + u3l_log("boot: retrieving galaxy table"); u3_noun oct = u3do("czar:give:dawn", u3k(bok)); u3_noun raz = _dawn_eth_rpc(url_c, u3k(oct)); @@ -425,7 +425,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) tuf = _dawn_turf(u3_Host.ops_u.dns_c); } else { - u3l_log("boot: retrieving network domains\r\n"); + u3l_log("boot: retrieving network domains"); u3_noun oct = u3do("turf:give:dawn", u3k(bok)); u3_noun fut = _dawn_eth_rpc(url_c, u3k(oct)); @@ -443,7 +443,7 @@ u3_dawn_vent(u3_noun ship, u3_noun feed) { u3_noun who = u3dc("scot", 'p', u3k(pos)); c3_c* who_c = u3r_string(who); - u3l_log("boot: retrieving keys for sponsor %s\r\n", who_c); + u3l_log("boot: retrieving keys for sponsor %s", who_c); u3z(who); c3_free(who_c); } @@ -495,8 +495,8 @@ _dawn_come(u3_noun stars) c3_rand(eny_w); eny = u3i_words(16, eny_w); - u3l_log("boot: mining a comet. May take up to an hour.\r\n"); - u3l_log("If you want to boot faster, get an Urbit identity.\r\n"); + u3l_log("boot: mining a comet. May take up to an hour."); + u3l_log("If you want to boot faster, get an Urbit identity."); seed = u3dc("come:dawn", u3k(stars), u3k(eny)); u3z(eny); @@ -506,7 +506,7 @@ _dawn_come(u3_noun stars) u3_noun who = u3dc("scot", 'p', u3k(u3h(seed))); c3_c* who_c = u3r_string(who); - u3l_log("boot: found comet %s\r\n", who_c); + u3l_log("boot: found comet %s", who_c); // enable to print and save comet private key for future reuse // @@ -515,7 +515,7 @@ _dawn_come(u3_noun stars) u3_noun key = u3dc("scot", c3__uw, u3qe_jam(seed)); c3_c* key_c = u3r_string(key); - u3l_log("boot: comet private key\n %s\n", key_c); + u3l_log("boot: comet private key\n %s", key_c); { c3_c pat_c[64]; diff --git a/pkg/urbit/vere/disk.c b/pkg/urbit/vere/disk.c index 6f8240daa..5d308ae4d 100644 --- a/pkg/urbit/vere/disk.c +++ b/pkg/urbit/vere/disk.c @@ -242,7 +242,7 @@ u3_disk_plan(u3_disk* log_u, u3_fact* tac_u) { c3_assert( (1ULL + log_u->sen_d) == tac_u->eve_d ); log_u->sen_d++; - + if ( !log_u->put_u.ent_u ) { c3_assert( !log_u->put_u.ext_u ); log_u->put_u.ent_u = log_u->put_u.ext_u = tac_u; @@ -649,7 +649,7 @@ u3_disk_exit(u3_disk* log_u) void u3_disk_info(u3_disk* log_u) { - u3l_log(" disk: live=%s, event=%" PRIu64 "\n", + u3l_log(" disk: live=%s, event=%" PRIu64, ( c3y == log_u->liv_o ) ? "&" : "|", log_u->dun_d); @@ -657,7 +657,7 @@ u3_disk_info(u3_disk* log_u) u3_read* red_u = log_u->red_u; while ( red_u ) { - u3l_log(" read: %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" read: %" PRIu64 "-%" PRIu64, red_u->eve_d, (red_u->eve_d + red_u->len_d) - 1); } @@ -665,12 +665,12 @@ u3_disk_info(u3_disk* log_u) if ( log_u->put_u.ext_u ) { if ( log_u->put_u.ext_u != log_u->put_u.ent_u ) { - u3l_log(" save: %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" save: %" PRIu64 "-%" PRIu64, log_u->put_u.ext_u->eve_d, log_u->put_u.ent_u->eve_d); } else { - u3l_log(" save: %" PRIu64 "\n", log_u->put_u.ext_u->eve_d); + u3l_log(" save: %" PRIu64, log_u->put_u.ext_u->eve_d); } } } diff --git a/pkg/urbit/vere/foil.c b/pkg/urbit/vere/foil.c index 1d844f5d4..186c8fdec 100644 --- a/pkg/urbit/vere/foil.c +++ b/pkg/urbit/vere/foil.c @@ -36,10 +36,10 @@ static void _foil_fail(const c3_c* why_c, c3_i err_i) { if ( err_i ) { - u3l_log("%s: error: %s\r\n", why_c, uv_strerror(err_i)); + u3l_log("%s: error: %s", why_c, uv_strerror(err_i)); c3_assert(0); } else { - u3l_log("%s: file error\r\n", why_c); + u3l_log("%s: file error", why_c); } exit(1); } diff --git a/pkg/urbit/vere/io/ames.c b/pkg/urbit/vere/io/ames.c index 1773e02ed..79c5beb9e 100644 --- a/pkg/urbit/vere/io/ames.c +++ b/pkg/urbit/vere/io/ames.c @@ -340,7 +340,7 @@ _ames_send_cb(uv_udp_send_t* req_u, c3_i sas_i) u3_ames* sam_u = pac_u->sam_u; if ( sas_i && (c3y == sam_u->fig_u.net_o) ) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + u3l_log("ames: send fail: %s", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } else { @@ -379,7 +379,7 @@ _ames_send(u3_pact* pac_u) if ( sas_i ) { if ( c3y == sam_u->fig_u.net_o ) { - u3l_log("ames: send fail: %s\n", uv_strerror(sas_i)); + u3l_log("ames: send fail: %s", uv_strerror(sas_i)); sam_u->fig_u.net_o = c3n; } @@ -516,7 +516,7 @@ _ames_czar_gone(u3_pact* pac_u, time_t now) u3_ames* sam_u = pac_u->sam_u; if ( c3y == sam_u->imp_o[pac_u->imp_y] ) { - u3l_log("ames: czar at %s: not found (b)\n", pac_u->dns_c); + u3l_log("ames: czar at %s: not found (b)", pac_u->dns_c); sam_u->imp_o[pac_u->imp_y] = c3n; } @@ -546,7 +546,7 @@ _ames_czar_here(u3_pact* pac_u, time_t now, struct sockaddr_in* add_u) u3_noun nam = u3dc("scot", c3__if, u3i_word(pip_w)); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: czar %s: ip %s\n", pac_u->dns_c, nam_c); + u3l_log("ames: czar %s: ip %s", pac_u->dns_c, nam_c); c3_free(nam_c); u3z(nam); @@ -611,7 +611,7 @@ _ames_czar(u3_pact* pac_u) if ( !sam_u->dns_c ) { u3_noun nam = u3dc("scot", 'p', pac_u->imp_y); c3_c* nam_c = u3r_string(nam); - u3l_log("ames: no galaxy domain for %s, no-op\r\n", nam_c); + u3l_log("ames: no galaxy domain for %s, no-op", nam_c); c3_free(nam_c); u3z(nam); @@ -656,7 +656,7 @@ _ames_czar(u3_pact* pac_u) } if ( 255 <= sas_i ) { - u3l_log("ames: czar: galaxy domain %s truncated\n", sam_u->dns_c); + u3l_log("ames: czar: galaxy domain %s truncated", sam_u->dns_c); _ames_pact_free(pac_u); return; } @@ -669,7 +669,7 @@ _ames_czar(u3_pact* pac_u) _ames_czar_cb, pac_u->dns_c, 0, 0)) ) { - u3l_log("ames: %s\n", uv_strerror(sas_i)); + u3l_log("ames: %s", uv_strerror(sas_i)); _ames_czar_gone(pac_u, now); return; } @@ -684,7 +684,7 @@ static void _ames_ef_send(u3_ames* sam_u, u3_noun lan, u3_noun pac) { if ( c3n == sam_u->car_u.liv_o ) { - u3l_log("ames: not yet live, dropping outbound\r\n"); + u3l_log("ames: not yet live, dropping outbound"); u3z(lan); u3z(pac); return; } @@ -754,7 +754,7 @@ _ames_cap_queue(u3_ames* sam_u) sam_u->sat_u.dop_d++; if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); } } @@ -764,7 +764,7 @@ _ames_cap_queue(u3_ames* sam_u) if ( (sam_u->sat_u.dop_d && (0 == (sam_u->sat_u.dop_d % 1000))) && !(u3C.wag_w & u3o_verbose) ) { - u3l_log("ames: packet dropped (%" PRIu64 " total)\n", sam_u->sat_u.dop_d); + u3l_log("ames: packet dropped (%" PRIu64 " total)", sam_u->sat_u.dop_d); } } @@ -782,7 +782,7 @@ _ames_punt_goof(u3_noun lud) c3_w len_w = 1; while ( u3_nul != dul ) { - u3l_log("ames: bail %u\r\n", len_w++); + u3l_log("ames: bail %u", len_w++); u3_pier_punt_goof("ames", u3k(u3h(dul))); dul = u3t(dul); } @@ -803,13 +803,13 @@ _ames_hear_bail(u3_ovum* egg_u, u3_noun lud) || (0 == (sam_u->sat_u.fal_d % 1000)) ) { _ames_punt_goof(lud); - u3l_log("ames: packet failed (%" PRIu64 " total)\n\n", sam_u->sat_u.fal_d); + u3l_log("ames: packet failed (%" PRIu64 " total)", sam_u->sat_u.fal_d); } else { u3z(lud); if ( 0 == (sam_u->sat_u.fal_d % 1000) ) { - u3l_log("ames: packet failed (%" PRIu64 " total)\n\n", sam_u->sat_u.fal_d); + u3l_log("ames: packet failed (%" PRIu64 " total)", sam_u->sat_u.fal_d); } } @@ -843,7 +843,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) sam_u->sat_u.fow_d++; if ( 0 == (sam_u->sat_u.fow_d % 1000000) ) { - u3l_log("ames: forwarded %" PRIu64 " total\n", sam_u->sat_u.fow_d); + u3l_log("ames: forwarded %" PRIu64 " total", sam_u->sat_u.fow_d); } if ( u3C.wag_w & u3o_verbose ) { @@ -853,7 +853,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) c3_c* rec_c = u3r_string(rec); c3_y* pip_y = (c3_y*)&pac_u->ore_u.pip_w; - u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d\n", + u3l_log("ames: forwarding for %s to %s from %d.%d.%d.%d:%d", sen_c, rec_c, pip_y[0], pip_y[1], pip_y[2], pip_y[3], pac_u->ore_u.por_s); @@ -872,7 +872,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) // validate lane and skip self if galaxy // if ( c3n == u3r_cell(lan, &tag, &dat) ) { - u3l_log("ames: bogus lane\n"); + u3l_log("ames: bogus lane"); u3m_p("lan", lan); } else { @@ -887,7 +887,7 @@ _ames_forward(u3_panc* pac_u, u3_noun las) { sen_o = c3n; if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: forward skipping self\n"); + u3l_log("ames: forward skipping self"); } } } @@ -920,7 +920,7 @@ _ames_lane_scry_cb(void* vod_p, u3_noun nun) // if ( u3_none == las ) { if ( 5 < ++sam_u->sat_u.saw_d ) { - u3l_log("ames: giving up scry\n"); + u3l_log("ames: giving up scry"); sam_u->fig_u.see_o = c3n; } _ames_put_packet(sam_u, _ames_serialize_packet(pac_u, c3n), pac_u->ore_u); @@ -984,7 +984,7 @@ _ames_try_forward(u3_ames* sam_u, if ( (u3_none == lac) && (1000 < sam_u->sat_u.foq_d) ) { sam_u->sat_u.fod_d++; if ( 0 == (sam_u->sat_u.fod_d % 10000) ) { - u3l_log("ames: dropped %" PRIu64 " forwards total\n", + u3l_log("ames: dropped %" PRIu64 " forwards total", sam_u->sat_u.fod_d); } @@ -1088,7 +1088,7 @@ _ames_hear(u3_ames* sam_u, { sam_u->sat_u.hed_d++; if ( 0 == (sam_u->sat_u.hed_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read header\n", + u3l_log("ames: %" PRIu64 " dropped, failed to read header", sam_u->sat_u.hed_d); } @@ -1105,7 +1105,7 @@ _ames_hear(u3_ames* sam_u, { sam_u->sat_u.vet_d++; if ( 0 == (sam_u->sat_u.vet_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for version mismatch\n", + u3l_log("ames: %" PRIu64 " dropped for version mismatch", sam_u->sat_u.vet_d); } @@ -1122,7 +1122,7 @@ _ames_hear(u3_ames* sam_u, if ( (c3n == _ames_sift_body(&hed_u, &bod_u, bod_w, bod_y)) ) { sam_u->sat_u.bod_d++; if ( 0 == (sam_u->sat_u.bod_d % 100) ) { - u3l_log("ames: %" PRIu64 " dropped, failed to read body\n", + u3l_log("ames: %" PRIu64 " dropped, failed to read body", sam_u->sat_u.bod_d); } @@ -1135,7 +1135,7 @@ _ames_hear(u3_ames* sam_u, if ( bod_u.mug_l != hed_u.mug_l ) { sam_u->sat_u.mut_d++; if ( 0 == (sam_u->sat_u.mut_d % 100000) ) { - u3l_log("ames: %" PRIu64 " dropped for invalid mug\n", + u3l_log("ames: %" PRIu64 " dropped for invalid mug", sam_u->sat_u.mut_d); } @@ -1183,7 +1183,7 @@ _ames_recv_cb(uv_udp_t* wax_u, { if ( 0 > nrd_i ) { if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: recv: fail: %s\n", uv_strerror(nrd_i)); + u3l_log("ames: recv: fail: %s", uv_strerror(nrd_i)); } c3_free(buf_u->base); } @@ -1192,7 +1192,7 @@ _ames_recv_cb(uv_udp_t* wax_u, } else if ( flg_i & UV_UDP_PARTIAL ) { if ( u3C.wag_w & u3o_verbose ) { - u3l_log("ames: recv: fail: message truncated\n"); + u3l_log("ames: recv: fail: message truncated"); } c3_free(buf_u->base); } @@ -1228,8 +1228,8 @@ _ames_io_start(u3_ames* sam_u) por_s = zar_s; } else if ( por_s != zar_s ) { - u3l_log("ames: czar: overriding port %d with -p %d\n", zar_s, por_s); - u3l_log("ames: czar: WARNING: %d required for discoverability\n", zar_s); + u3l_log("ames: czar: overriding port %d with -p %d", zar_s, por_s); + u3l_log("ames: czar: WARNING: %d required for discoverability", zar_s); } } @@ -1248,12 +1248,12 @@ _ames_io_start(u3_ames* sam_u) if ( (ret_i = uv_udp_bind(&sam_u->wax_u, (const struct sockaddr*)&add_u, 0)) != 0 ) { - u3l_log("ames: bind: %s\n", uv_strerror(ret_i)); + u3l_log("ames: bind: %s", uv_strerror(ret_i)); if ( (c3__czar == rac) && (UV_EADDRINUSE == ret_i) ) { - u3l_log(" ...perhaps you've got two copies of vere running?\n"); + u3l_log(" ...perhaps you've got two copies of vere running?"); } // XX revise @@ -1268,10 +1268,10 @@ _ames_io_start(u3_ames* sam_u) } if ( c3y == u3_Host.ops_u.net ) { - u3l_log("ames: live on %d\n", sam_u->pir_u->por_s); + u3l_log("ames: live on %d", sam_u->pir_u->por_s); } else { - u3l_log("ames: live on %d (localhost only)\n", sam_u->pir_u->por_s); + u3l_log("ames: live on %d (localhost only)", sam_u->pir_u->por_s); } uv_udp_recv_start(&sam_u->wax_u, _ames_alloc, _ames_recv_cb); @@ -1302,7 +1302,7 @@ _ames_ef_turf(u3_ames* sam_u, u3_noun tuf) u3z(tuf); } else if ( (c3n == sam_u->pir_u->fak_o) && (0 == sam_u->dns_c) ) { - u3l_log("ames: turf: no domains\n"); + u3l_log("ames: turf: no domains"); } // XX is this ever necessary? @@ -1446,7 +1446,7 @@ _ames_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) ret_o = c3n; } else { - u3l_log("kick: strange send\r\n"); + u3l_log("kick: strange send"); ret_o = _ames_kick_newt(sam_u, u3k(tag), u3k(dat)); } } break; @@ -1497,21 +1497,21 @@ _ames_io_info(u3_auto* car_u) # define FLAG(a) ( (c3y == a) ? "&" : "|" ) - u3l_log(" config:\n"); - u3l_log(" filtering: %s\n", FLAG(sam_u->fig_u.fit_o)); - u3l_log(" can send: %s\n", FLAG(sam_u->fig_u.net_o)); - u3l_log(" can scry: %s\n", FLAG(sam_u->fig_u.see_o)); - u3l_log(" counters:\n"); - u3l_log(" dropped: %" PRIu64 "\n", sam_u->sat_u.dop_d); - u3l_log(" forwards dropped: %" PRIu64 "\n", sam_u->sat_u.fod_d); - u3l_log(" forwards pending: %" PRIu64 "\n", sam_u->sat_u.foq_d); - u3l_log(" forwarded: %" PRIu64 "\n", sam_u->sat_u.fow_d); - u3l_log(" filtered (hed): %" PRIu64 "\n", sam_u->sat_u.hed_d); - u3l_log(" filtered (ver): %" PRIu64 "\n", sam_u->sat_u.vet_d); - u3l_log(" filtered (mug): %" PRIu64 "\n", sam_u->sat_u.mut_d); - u3l_log(" filtered (bod): %" PRIu64 "\n", sam_u->sat_u.bod_d); - u3l_log(" crashed: %" PRIu64 "\n", sam_u->sat_u.fal_d); - u3l_log(" cached lanes: %u\n", u3h_wyt(sam_u->lax_p)); + u3l_log(" config:"); + u3l_log(" filtering: %s", FLAG(sam_u->fig_u.fit_o)); + u3l_log(" can send: %s", FLAG(sam_u->fig_u.net_o)); + u3l_log(" can scry: %s", FLAG(sam_u->fig_u.see_o)); + u3l_log(" counters:"); + u3l_log(" dropped: %" PRIu64, sam_u->sat_u.dop_d); + u3l_log(" forwards dropped: %" PRIu64, sam_u->sat_u.fod_d); + u3l_log(" forwards pending: %" PRIu64, sam_u->sat_u.foq_d); + u3l_log(" forwarded: %" PRIu64, sam_u->sat_u.fow_d); + u3l_log(" filtered (hed): %" PRIu64, sam_u->sat_u.hed_d); + u3l_log(" filtered (ver): %" PRIu64, sam_u->sat_u.vet_d); + u3l_log(" filtered (mug): %" PRIu64, sam_u->sat_u.mut_d); + u3l_log(" filtered (bod): %" PRIu64, sam_u->sat_u.bod_d); + u3l_log(" crashed: %" PRIu64, sam_u->sat_u.fal_d); + u3l_log(" cached lanes: %u", u3h_wyt(sam_u->lax_p)); } /* u3_ames_io_init(): initialize ames I/O. diff --git a/pkg/urbit/vere/io/behn.c b/pkg/urbit/vere/io/behn.c index c9394564e..a4f6a5618 100644 --- a/pkg/urbit/vere/io/behn.c +++ b/pkg/urbit/vere/io/behn.c @@ -48,7 +48,7 @@ _behn_wake_bail(u3_ovum* egg_u, u3_noun lud) u3_auto_bail_slog(egg_u, lud); u3_ovum_free(egg_u); - u3l_log("behn: timer failed; queue blocked\n"); + u3l_log("behn: timer failed; queue blocked"); // XX review, add flag to continue? // @@ -149,7 +149,7 @@ _behn_born_bail(u3_ovum* egg_u, u3_noun lud) u3_auto_bail_slog(egg_u, lud); u3_ovum_free(egg_u); - u3l_log("behn: initialization failed\n"); + u3l_log("behn: initialization failed"); // XX review, add flag to continue? // diff --git a/pkg/urbit/vere/io/cttp.c b/pkg/urbit/vere/io/cttp.c index 1f19c3e41..76c1dd396 100644 --- a/pkg/urbit/vere/io/cttp.c +++ b/pkg/urbit/vere/io/cttp.c @@ -558,7 +558,7 @@ _cttp_creq_new(u3_cttp* ctp_u, c3_l num_l, u3_noun hes) if ( c3n == u3r_du(unit_pul) ) { c3_c* url_c = u3r_string(url); - u3l_log("cttp: unable to parse url:\n %s\n", url_c); + u3l_log("cttp: unable to parse url:\n %s", url_c); c3_free(url_c); u3z(hes); return 0; @@ -735,7 +735,7 @@ _cttp_creq_fail(u3_creq* ceq_u, const c3_c* err_c) // XX anything other than a 504? c3_w cod_w = 504; - u3l_log("http: fail (%d, %d): %s\r\n", ceq_u->num_l, cod_w, err_c); + u3l_log("http: fail (%d, %d): %s", ceq_u->num_l, cod_w, err_c); // XX include err_c as response body? _cttp_http_client_receive(ceq_u, cod_w, u3_nul, u3_nul); @@ -1003,7 +1003,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) if ( (c3n == u3r_cell(dat, &num, &req)) || (c3n == u3r_safe_word(num, &num_l)) ) { - u3l_log("cttp: strange request\n"); + u3l_log("cttp: strange request"); ret_o = c3n; } else if ( (ceq_u = _cttp_creq_new(ctp_u, num_l, u3k(req))) ) { @@ -1018,7 +1018,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) c3_l num_l; if ( c3n == u3r_safe_word(dat, &num_l) ) { - u3l_log("cttp: strange cancel-request\n"); + u3l_log("cttp: strange cancel-request"); ret_o = c3n; } else if ( (ceq_u =_cttp_creq_find(ctp_u, num_l)) ) { @@ -1032,7 +1032,7 @@ _cttp_ef_http_client(u3_cttp* ctp_u, u3_noun tag, u3_noun dat) } } else { - u3l_log("cttp: strange effect (unknown type)\n"); + u3l_log("cttp: strange effect (unknown type)"); ret_o = c3n; } diff --git a/pkg/urbit/vere/io/fore.c b/pkg/urbit/vere/io/fore.c index 81476d92a..4582cab46 100644 --- a/pkg/urbit/vere/io/fore.c +++ b/pkg/urbit/vere/io/fore.c @@ -10,7 +10,7 @@ static void _fore_inject_bail(u3_ovum* egg_u, u3_noun lud) { u3_auto_bail_slog(egg_u, lud); - u3l_log("pier: injected event failed\n"); + u3l_log("pier: injected event failed"); u3_ovum_free(egg_u); } @@ -21,7 +21,7 @@ static void _fore_import_bail(u3_ovum* egg_u, u3_noun lud) { u3_auto_bail_slog(egg_u, lud); - u3l_log("pier: import failed\n"); + u3l_log("pier: import failed"); u3_ovum_free(egg_u); } @@ -37,20 +37,20 @@ _fore_inject(u3_auto* car_u, c3_c* pax_c) u3_noun riw, cad, tar, wir; if ( c3n == u3r_cell(ovo, &riw, &cad) ) { - u3l_log("pier: invalid ovum in -I\n"); + u3l_log("pier: invalid ovum in -I"); } else if ( (c3n == u3a_is_cell(cad)) || (c3n == u3a_is_atom(u3h(cad))) ) { - u3l_log("pier: invalid card in -I ovum\n"); + u3l_log("pier: invalid card in -I ovum"); } else if ( c3n == u3r_cell(riw, &tar, &wir) ) { - u3l_log("pier: invalid wire in -I ovum\n"); + u3l_log("pier: invalid wire in -I ovum"); } else if ( (c3n == u3a_is_atom(tar)) || (1 < u3r_met(3, tar)) ) { - u3l_log("pier: invalid target in -I wire\n"); + u3l_log("pier: invalid target in -I wire"); } else { { @@ -58,7 +58,7 @@ _fore_inject(u3_auto* car_u, c3_c* pax_c) u3_noun ser = u3do("spat", u3k(riw)); c3_c* wir_c = u3r_string(ser); - u3l_log("pier: injecting %%%s event on %s\n", tag_c, wir_c); + u3l_log("pier: injecting %%%s event on %s", tag_c, wir_c); c3_free(tag_c); c3_free(wir_c); diff --git a/pkg/urbit/vere/io/hind.c b/pkg/urbit/vere/io/hind.c index b0d207e83..d15534806 100644 --- a/pkg/urbit/vere/io/hind.c +++ b/pkg/urbit/vere/io/hind.c @@ -30,7 +30,7 @@ _hind_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) case c3__exit: { ret_o = c3y; - u3l_log("<<>>\n"); + u3l_log("<<>>"); u3_pier_exit(car_u->pir_u); } break; @@ -44,7 +44,7 @@ _hind_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) case c3__vega: { ret_o = c3y; - u3l_log("<<>>\n"); + u3l_log("<<>>"); } break; // NB: startup explicitly handled in pier.c diff --git a/pkg/urbit/vere/io/http.c b/pkg/urbit/vere/io/http.c index f0d2f0ea2..d53bff384 100644 --- a/pkg/urbit/vere/io/http.c +++ b/pkg/urbit/vere/io/http.c @@ -33,7 +33,7 @@ typedef struct _u3_h2o_serv { void* gen_u; // response generator struct _u3_hcon* hon_u; // connection backlink struct _u3_hreq* nex_u; // next in connection's list - struct _u3_hreq* pre_u; // next in connection's list + struct _u3_hreq* pre_u; // prev in connection's list } u3_hreq; /* u3_hcon: incoming http connection. @@ -48,7 +48,7 @@ typedef struct _u3_h2o_serv { struct _u3_http* htp_u; // server backlink struct _u3_hreq* req_u; // request list struct _u3_hcon* nex_u; // next in server's list - struct _u3_hcon* pre_u; // next in server's list + struct _u3_hcon* pre_u; // prev in server's list } u3_hcon; /* u3_http: http server. @@ -639,10 +639,10 @@ _http_start_respond(u3_hreq* req_u, u3_noun data, u3_noun complete) { - // u3l_log("start\n"); + // u3l_log("start"); if ( u3_rsat_plan != req_u->sat_e ) { - //u3l_log("duplicate response\n"); + //u3l_log("duplicate response"); return; } @@ -715,14 +715,14 @@ _http_continue_respond(u3_hreq* req_u, u3_noun data, u3_noun complete) { - // u3l_log("continue\n"); + // u3l_log("continue"); // XX add sequence numbers for %continue effects? // Arvo does not (currently) guarantee effect idempotence!! // response has not yet been started if ( u3_rsat_ripe != req_u->sat_e ) { - // u3l_log("duplicate response\n"); + // u3l_log("duplicate response"); return; } @@ -855,7 +855,7 @@ _http_seq_continue(void* vod_p, u3_noun nun) _http_start_respond(req_u, 403, u3_nul, u3_nul, c3y); } else if ( u3_none == aut ) { - u3l_log("http: authentication scry failed\n"); + u3l_log("http: authentication scry failed"); _http_start_respond(req_u, 500, u3_nul, u3_nul, c3y); } else { @@ -917,7 +917,7 @@ _http_rec_accept(h2o_handler_t* han_u, h2o_req_t* rec_u) if ( u3_none == req ) { if ( (u3C.wag_w & u3o_verbose) ) { - u3l_log("strange %.*s request\n", (int)rec_u->method.len, + u3l_log("strange %.*s request", (int)rec_u->method.len, rec_u->method.base); } c3_c* msg_c = "bad request"; @@ -1007,7 +1007,7 @@ _http_conn_free(uv_handle_t* han_t) noh_u = noh_u->nex_u; } - u3l_log("http conn free %d of %u server %d\n", hon_u->coq_l, len_w, htp_u->sev_l); + u3l_log("http conn free %d of %u server %d", hon_u->coq_l, len_w, htp_u->sev_l); } #endif @@ -1024,13 +1024,13 @@ _http_conn_free(uv_handle_t* han_t) noh_u = noh_u->nex_u; } - u3l_log("http conn free %u remaining\n", len_w); + u3l_log("http conn free %u remaining", len_w); } #endif if ( (0 == htp_u->hon_u) && (0 != h2o_u->ctx_u.shutdown_requested) ) { #if 0 - u3l_log("http conn free %d free server %d\n", hon_u->coq_l, htp_u->sev_l); + u3l_log("http conn free %d free server %d", hon_u->coq_l, htp_u->sev_l); #endif _http_serv_free(htp_u); } @@ -1054,7 +1054,7 @@ _http_conn_new(u3_http* htp_u) _http_conn_link(htp_u, hon_u); #if 0 - u3l_log("http conn neww %d server %d\n", hon_u->coq_l, htp_u->sev_l); + u3l_log("http conn neww %d server %d", hon_u->coq_l, htp_u->sev_l); #endif return hon_u; @@ -1104,7 +1104,7 @@ _http_serv_unlink(u3_http* htp_u) { // XX link elsewhere initially, relink on start? #if 0 - u3l_log("http serv unlink %d\n", htp_u->sev_l); + u3l_log("http serv unlink %d", htp_u->sev_l); #endif u3_http* pre_u = htp_u->htd_u->htp_u; @@ -1213,7 +1213,7 @@ http_serv_free_cb(uv_timer_t* tim_u) u3_http* htp_u = tim_u->data; #if 0 - u3l_log("http serv free cb %d\n", htp_u->sev_l); + u3l_log("http serv free cb %d", htp_u->sev_l); #endif _http_serv_really_free(htp_u); @@ -1227,7 +1227,7 @@ static void _http_serv_free(u3_http* htp_u) { #if 0 - u3l_log("http serv free %d\n", htp_u->sev_l); + u3l_log("http serv free %d", htp_u->sev_l); #endif c3_assert( 0 == htp_u->hon_u ); @@ -1297,7 +1297,7 @@ _http_serv_close(u3_http* htp_u) h2o_context_request_shutdown(&h2o_u->ctx_u); #if 0 - u3l_log("http serv close %d %p\n", htp_u->sev_l, &htp_u->wax_u); + u3l_log("http serv close %d %p", htp_u->sev_l, &htp_u->wax_u); #endif uv_close((uv_handle_t*)&htp_u->wax_u, _http_serv_close_cb); @@ -1338,7 +1338,7 @@ _http_serv_accept(u3_http* htp_u) if ( 0 != (sas_i = uv_accept((uv_stream_t*)&htp_u->wax_u, (uv_stream_t*)&hon_u->wax_u)) ) { if ( (u3C.wag_w & u3o_verbose) ) { - u3l_log("http: accept: %s\n", uv_strerror(sas_i)); + u3l_log("http: accept: %s", uv_strerror(sas_i)); } uv_close((uv_handle_t*)&hon_u->wax_u, _http_conn_free); @@ -1367,7 +1367,7 @@ _http_serv_listen_cb(uv_stream_t* str_u, c3_i sas_i) u3_http* htp_u = (u3_http*)str_u; if ( 0 != sas_i ) { - u3l_log("http: listen_cb: %s\n", uv_strerror(sas_i)); + u3l_log("http: listen_cb: %s", uv_strerror(sas_i)); } else { _http_serv_accept(htp_u); @@ -1493,13 +1493,13 @@ _http_serv_start(u3_http* htp_u) continue; } - u3l_log("http: listen: %s\n", uv_strerror(sas_i)); + u3l_log("http: listen: %s", uv_strerror(sas_i)); _http_serv_free(htp_u); return; } - u3l_log("http: %s live on %s://localhost:%d\n", + u3l_log("http: %s live on %s://localhost:%d", (c3y == htp_u->lop) ? "loopback" : "web interface", (c3y == htp_u->sec) ? "https" : "http", htp_u->por_s); @@ -1557,9 +1557,10 @@ _http_init_tls(uv_buf_t key_u, uv_buf_t cer_u) BIO_free(bio_u); if( 0 == sas_i ) { - u3l_log("http: load private key failed:\n"); - ERR_print_errors_fp(u3_term_io_hija()); - u3_term_io_loja(1); + u3l_log("http: load private key failed:"); + FILE* fil_u = u3_term_io_hija(); + ERR_print_errors_fp(fil_u); + u3_term_io_loja(1, fil_u); SSL_CTX_free(tls_u); @@ -1575,9 +1576,10 @@ _http_init_tls(uv_buf_t key_u, uv_buf_t cer_u) X509_free(xer_u); if( 0 == sas_i ) { - u3l_log("http: load certificate failed:\n"); - ERR_print_errors_fp(u3_term_io_hija()); - u3_term_io_loja(1); + u3l_log("http: load certificate failed:"); + FILE* fil_u = u3_term_io_hija(); + ERR_print_errors_fp(fil_u); + u3_term_io_loja(1,fil_u); BIO_free(bio_u); SSL_CTX_free(tls_u); @@ -1656,19 +1658,19 @@ _http_search_req(u3_httd* htd_u, if ( !(htp_u = _http_serv_find(htd_u, sev_l)) ) { if ( bug_w ) { - u3l_log("http: server not found: %x\r\n", sev_l); + u3l_log("http: server not found: %x", sev_l); } return 0; } else if ( !(hon_u = _http_conn_find(htp_u, coq_l)) ) { if ( bug_w ) { - u3l_log("http: connection not found: %x/%d\r\n", sev_l, coq_l); + u3l_log("http: connection not found: %x/%d", sev_l, coq_l); } return 0; } else if ( !(req_u = _http_req_find(hon_u, seq_l)) ) { if ( bug_w ) { - u3l_log("http: request not found: %x/%d/%d\r\n", + u3l_log("http: request not found: %x/%d/%d", sev_l, coq_l, seq_l); } return 0; @@ -1760,7 +1762,7 @@ _http_serv_restart(u3_httd* htd_u) _http_serv_start_all(htd_u); } else { - u3l_log("http: restarting servers to apply configuration\n"); + u3l_log("http: restarting servers to apply configuration"); while ( 0 != htp_u ) { if ( c3y == htp_u->liv ) { @@ -1812,7 +1814,7 @@ u3_http_ef_form(u3_httd* htd_u, u3_noun fig) !( c3y == pro || c3n == pro ) || !( c3y == log || c3n == log ) || !( c3y == red || c3n == red ) ) { - u3l_log("http: form: invalid card\n"); + u3l_log("http: form: invalid card"); u3z(fig); return; } @@ -1907,14 +1909,14 @@ _http_ef_http_server(u3_httd* htd_u, _http_continue_respond(req_u, u3k(data), u3k(complete)); } else if (c3y == u3r_sing_c("cancel", u3h(response))) { - u3l_log("http: %%cancel not handled yet\n"); + u3l_log("http: %%cancel not handled yet"); } else { - u3l_log("http: strange response\n"); + u3l_log("http: strange response"); } } else { - u3l_log("http: strange response\n"); + u3l_log("http: strange response"); } } @@ -2028,7 +2030,7 @@ _reck_mole(u3_noun fot, if ( (c3n == u3r_cell(uco, &p_uco, &q_uco)) || (u3_nul != p_uco) ) { - u3l_log("strange mole %s\n", u3r_string(san)); + u3l_log("strange mole %s", u3r_string(san)); u3z(fot); u3z(uco); return c3n; } @@ -2166,7 +2168,7 @@ _http_io_info(u3_auto* car_u) sec_y++; seq_u = seq_u->nex_u; } - u3l_log(" open slogstreams: %d\n", sec_y); + u3l_log(" open slogstreams: %d", sec_y); } /* u3_http_io_init(): initialize http I/O. diff --git a/pkg/urbit/vere/io/term.c b/pkg/urbit/vere/io/term.c index fcccf748a..e2b6376ca 100644 --- a/pkg/urbit/vere/io/term.c +++ b/pkg/urbit/vere/io/term.c @@ -16,6 +16,7 @@ static u3_utty* _term_main(); static void _term_read_cb(uv_stream_t* tcp_u, ssize_t siz_i, const uv_buf_t* buf_u); +static void _term_it_send_stub(u3_utty* uty_u, u3_noun tub); /* u3_write_fd(): retry interrupts, continue partial writes, assert errors. */ @@ -85,39 +86,6 @@ _term_alloc(uv_handle_t* had_u, *buf = uv_buf_init(ptr_v, 123); } -// XX unused, but %hook is in %zuse. -// implement or remove -// -#if 0 -/* _term_close_cb(): free terminal. -*/ -static void -_term_close_cb(uv_handle_t* han_t) -{ - u3_utty* tty_u = (void*) han_t; - if ( u3_Host.uty_u == tty_u ) { - u3_Host.uty_u = tty_u->nex_u; - } - else { - u3_utty* uty_u; - for (uty_u = u3_Host.uty_u; uty_u; uty_u = uty_u->nex_u ) { - if ( uty_u->nex_u == tty_u ) { - uty_u->nex_u = tty_u->nex_u; - break; - } - } - } - - { - u3_noun tid = u3dc("scot", c3__ud, tty_u->tid_l); - u3_noun pax = u3nq(u3_blip, c3__term, tid, u3_nul); - u3_pier_plan(u3k(pax), u3nc(c3__hook, u3_nul)); - u3z(pax); - } - c3_free(tty_u); -} -#endif - /* u3_term_log_init(): initialize terminal for logging */ void @@ -149,41 +117,33 @@ u3_term_log_init(void) // and simply use constant sequences. // { - uty_u->ufo_u.out.clear_u = TERM_LIT_BUF("\033[H\033[2J"); - uty_u->ufo_u.out.el_u = TERM_LIT_BUF("\033[K"); - // uty_u->ufo_u.out.el1_u = TERM_LIT_BUF("\033[1K"); - uty_u->ufo_u.out.ed_u = TERM_LIT_BUF("\033[J"); - uty_u->ufo_u.out.bel_u = TERM_LIT_BUF("\x7"); - uty_u->ufo_u.out.cub1_u = TERM_LIT_BUF("\x8"); - uty_u->ufo_u.out.cuf1_u = TERM_LIT_BUF("\033[C"); - uty_u->ufo_u.out.cuu1_u = TERM_LIT_BUF("\033[A"); - uty_u->ufo_u.out.cud1_u = TERM_LIT_BUF("\xa"); - // uty_u->ufo_u.out.cub_u = TERM_LIT_BUF("\033[%p1%dD"); - // uty_u->ufo_u.out.cuf_u = TERM_LIT_BUF("\033[%p1%dC"); - } + uty_u->ufo_u.mon_u = TERM_LIT_BUF("\033[?9h"); + uty_u->ufo_u.mof_u = TERM_LIT_BUF("\033[?9l"); - // configure input escape sequences - // - // NB: terminfo reports the wrong sequence for arrow keys on xterms. - // disabled, currently unused - // { - // uty_u->ufo_u.inn.kcuu1_u = TERM_LIT_BUF("\033[A"); // terminfo reports "\033OA" - // uty_u->ufo_u.inn.kcud1_u = TERM_LIT_BUF("\033[B"); // terminfo reports "\033OB" - // uty_u->ufo_u.inn.kcuf1_u = TERM_LIT_BUF("\033[C"); // terminfo reports "\033OC" - // uty_u->ufo_u.inn.kcub1_u = TERM_LIT_BUF("\033[D"); // terminfo reports "\033OD" - // } + uty_u->ufo_u.reg_u = TERM_LIT_BUF("\033[r"); + + uty_u->ufo_u.suc_u = TERM_LIT_BUF("\033[s"); + uty_u->ufo_u.ruc_u = TERM_LIT_BUF("\033[u"); + uty_u->ufo_u.cub_u = TERM_LIT_BUF("\x8"); + + uty_u->ufo_u.clr_u = TERM_LIT_BUF("\033[H\033[2J"); + uty_u->ufo_u.cel_u = TERM_LIT_BUF("\033[K"); + + uty_u->ufo_u.bel_u = TERM_LIT_BUF("\x7"); + } // Initialize mirror and accumulator state. // { - uty_u->tat_u.mir.lin_y = 0; - uty_u->tat_u.mir.byt_w = 0; - uty_u->tat_u.mir.wor_w = 0; - uty_u->tat_u.mir.sap_w = 0; + uty_u->tat_u.mir.lin = u3_nul; + uty_u->tat_u.mir.rus_w = 0; uty_u->tat_u.mir.cus_w = 0; uty_u->tat_u.esc.ape = c3n; uty_u->tat_u.esc.bra = c3n; + uty_u->tat_u.esc.mou = c3n; + uty_u->tat_u.esc.ton_y = 0; + uty_u->tat_u.esc.col_y = 0; uty_u->tat_u.fut.len_w = 0; uty_u->tat_u.fut.wid_w = 0; @@ -193,7 +153,7 @@ u3_term_log_init(void) // { uty_u->tat_u.siz.col_l = 80; - uty_u->tat_u.siz.row_l = 24; + uty_u->tat_u.siz.row_l = 0; } // initialize spinner state @@ -273,7 +233,7 @@ _term_it_write_cb(uv_write_t* wri_u, c3_i sas_i) // write failure is logged, but otherwise ignored. // if ( 0 != sas_i ) { - u3l_log("term: write: %s\n", uv_strerror(sas_i)); + u3l_log("term: write: %s", uv_strerror(sas_i)); } c3_free(wri_u->data); @@ -325,7 +285,7 @@ _term_it_write(u3_utty* uty_u, // synchronous write failure is logged, but otherwise ignored // if ( ret_i < 0 ) { - u3l_log("term: write: %s\n", uv_strerror(ret_i)); + u3l_log("term: write: %s", uv_strerror(ret_i)); } c3_free(ptr_v); @@ -370,32 +330,62 @@ _term_it_send(u3_utty* uty_u, } } -/* _term_it_send_cord(): write a cord. +/* _term_it_send_csi(): send csi escape sequence */ static void -_term_it_send_cord(u3_utty* uty_u, - u3_atom txt) +_term_it_send_csi(u3_utty *uty_u, c3_c cmd_c, c3_w num_w, ...) { - c3_w len_w = u3r_met(3, txt); - c3_y* hun_y = c3_malloc(len_w); - u3r_bytes(0, len_w, hun_y, txt); + va_list ap; + va_start(ap, num_w); - _term_it_send(uty_u, len_w, hun_y); + // allocate for escape sequence (2), command char (1), + // argument digits (5 per arg) and separators (1 per arg, minus 1). + // freed via _term_it_write. + // + c3_c* pas_c = c3_malloc( 2 + num_w * 6 ); + c3_y len_y = 0; - u3z(txt); + pas_c[len_y++] = '\033'; + pas_c[len_y++] = '['; + + while ( num_w-- ) { + c3_w par_w = va_arg(ap, c3_w); + len_y += sprintf(pas_c+len_y, "%d", par_w); + + if ( num_w ) { + pas_c[len_y++] = ';'; + } + } + + pas_c[len_y++] = cmd_c; + + _term_it_send(uty_u, len_y, (c3_y*)pas_c); + + va_end(ap); } -/* _term_it_show_clear(): clear to the beginning of the current line. +/* _term_it_free_line(): wipe line stored by _term_it_save_stub */ static void -_term_it_show_clear(u3_utty* uty_u) +_term_it_free_line(u3_utty* uty_u) { - if ( uty_u->tat_u.siz.col_l ) { - _term_it_dump(uty_u, TERM_LIT("\r")); - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.el_u); + u3z(uty_u->tat_u.mir.lin); + uty_u->tat_u.mir.lin = u3_nul; +} - uty_u->tat_u.mir.wor_w = 0; - uty_u->tat_u.mir.cus_w = 0; +/* _term_it_clear_line(): clear line of cursor +*/ +static void +_term_it_clear_line(u3_utty* uty_u) +{ + _term_it_dump(uty_u, TERM_LIT("\r")); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.cel_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); + + // if we're clearing the bottom line, clear our mirror of it too + // + if ( 0 == uty_u->tat_u.mir.rus_w ) { + _term_it_free_line(uty_u); } } @@ -404,87 +394,35 @@ _term_it_show_clear(u3_utty* uty_u) static void _term_it_show_blank(u3_utty* uty_u) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.clear_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.clr_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } -/* _term_it_show_cursor(): set current line, transferring pointer. -*/ +/* _term_it_move_cursor(): move cursor to row & column + * + * row 0 is at the bottom, col 0 is to the left. + * if the given position exceeds the known window size, + * it is clipped to stay within the window. + */ static void -_term_it_show_cursor(u3_utty* uty_u, c3_w cur_w) +_term_it_move_cursor(u3_utty* uty_u, c3_w row_w, c3_w col_w) { - c3_w cus_w = uty_u->tat_u.mir.cus_w; - c3_w dif_w; + c3_l row_l = uty_u->tat_u.siz.row_l; + c3_l col_l = uty_u->tat_u.siz.col_l; + if ( row_w >= row_l ) { row_w = row_l - 1; } + if ( col_w >= col_l ) { col_w = col_l - 1; } - //NOTE assumes all styled text precedes the cursor. drum enforces this. - // - cur_w += uty_u->tat_u.mir.sap_w; + _term_it_send_csi(uty_u, 'H', 2, row_l - row_w, col_w + 1); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.suc_u); - if ( cur_w < cus_w ) { - dif_w = cus_w - cur_w; - - while ( dif_w-- ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.cub1_u); - } - } - else if ( cur_w > cus_w ) { - dif_w = cur_w - cus_w; - - while ( dif_w-- ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.cuf1_u); - } - } - - uty_u->tat_u.mir.cus_w = cur_w; + uty_u->tat_u.mir.rus_w = row_w; + uty_u->tat_u.mir.cus_w = col_w; } -/* _term_it_show_line(): render current line. +/* _term_it_show_line(): print at cursor */ static void -_term_it_show_line(u3_utty* uty_u, c3_w wor_w, c3_w sap_w) -{ - u3_utat* tat_u = &uty_u->tat_u; - - // we have to reallocate the current line on write, - // or we have a data race if a) the write is async, - // and b) a new output line arrives before the write completes. - // - { - c3_w len_w = tat_u->mir.byt_w; - c3_y* hun_y = c3_malloc(len_w); - memcpy(hun_y, tat_u->mir.lin_y, len_w); - - _term_it_send(uty_u, len_w, hun_y); - } - - // XX refactor to avoid updating state - // - tat_u->mir.cus_w += wor_w; - tat_u->mir.wor_w = wor_w; - tat_u->mir.sap_w = sap_w; -} - -/* _term_it_refresh_line(): refresh current line. -*/ -static void -_term_it_refresh_line(u3_utty* uty_u) -{ - u3_utat* tat_u = &uty_u->tat_u; - c3_w wor_w = tat_u->mir.wor_w; - c3_w sap_w = tat_u->mir.sap_w; - c3_w cus_w = tat_u->mir.cus_w; - - _term_it_show_clear(uty_u); - _term_it_show_line(uty_u, wor_w, sap_w); - _term_it_show_cursor(uty_u, cus_w); -} - -/* _term_it_set_line(): set current line. -*/ -static void -_term_it_set_line(u3_utty* uty_u, - c3_w* lin_w, - c3_w wor_w, - c3_w sap_w) +_term_it_show_line(u3_utty* uty_u, c3_w* lin_w, c3_w wor_w) { u3_utat* tat_u = &uty_u->tat_u; c3_y* hun_y = (c3_y*)lin_w; @@ -522,28 +460,66 @@ _term_it_set_line(u3_utty* uty_u, } } - c3_free(tat_u->mir.lin_y); - tat_u->mir.lin_y = hun_y; - tat_u->mir.byt_w = byt_w; - tat_u->mir.wor_w = wor_w; - tat_u->mir.sap_w = sap_w; - - _term_it_show_line(uty_u, wor_w, sap_w); + //NOTE lin_w freed through hun_y by _send + _term_it_send(uty_u, byt_w, hun_y); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } -/* _term_it_show_more(): new current line. +/* _term_it_restore_line(): re-render original line at bottom of screen */ static void -_term_it_show_more(u3_utty* uty_u) +_term_it_restore_line(u3_utty* uty_u) +{ + u3_utat* tat_u = &uty_u->tat_u; + + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 0); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.cel_u); + _term_it_send_stub(uty_u, u3k(tat_u->mir.lin)); + //NOTE send_stub restores cursor position +} + +/* _term_it_save_stub(): store line if relevant to internal logic + */ +static void +_term_it_save_stub(u3_utty* uty_u, u3_noun tub) +{ + u3_utat* tat_u = &uty_u->tat_u; + u3_noun lin = tat_u->mir.lin; + + // keep track of changes to bottom-most line, to aid spinner drawing logic. + // -t mode doesn't need this logic, because it doesn't render the spinner. + // + if ( (0 == tat_u->mir.rus_w) && (c3n == u3_Host.ops_u.tem)) { + lin = u3dq("wail:klr:format", lin, tat_u->mir.cus_w, u3k(tub), ' '); + lin = u3do("pact:klr:format", lin); + } + + tat_u->mir.lin = lin; + u3z(tub); +} + +/* _term_it_show_nel(): render newline, moving cursor down +*/ +static void +_term_it_show_nel(u3_utty* uty_u) { if ( c3y == u3_Host.ops_u.tem ) { _term_it_dump(uty_u, TERM_LIT("\n")); } else { _term_it_dump(uty_u, TERM_LIT("\r\n")); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.suc_u); } uty_u->tat_u.mir.cus_w = 0; + if ( uty_u->tat_u.mir.rus_w > 0 ) { + uty_u->tat_u.mir.rus_w--; + } + else { + // newline at bottom of screen, so bottom line is now empty + // + _term_it_free_line(uty_u); + } } /* _term_it_path(): path for console file. @@ -667,32 +643,37 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) { u3_utat* tat_u = &uty_u->tat_u; + // escape sequences + // if ( c3y == tat_u->esc.ape ) { if ( c3y == tat_u->esc.bra ) { switch ( cay_y ) { default: { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); break; } case 'A': _term_io_belt(uty_u, u3nc(c3__aro, 'u')); break; case 'B': _term_io_belt(uty_u, u3nc(c3__aro, 'd')); break; case 'C': _term_io_belt(uty_u, u3nc(c3__aro, 'r')); break; case 'D': _term_io_belt(uty_u, u3nc(c3__aro, 'l')); break; + // + case 'M': tat_u->esc.mou = c3y; break; } tat_u->esc.ape = tat_u->esc.bra = c3n; } else { if ( (cay_y >= 'a') && (cay_y <= 'z') ) { tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, cay_y)); - } - else if ( '.' == cay_y ) { - tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, c3__dot)); + // XX for backwards compatibility, check kelvin version + // and fallback to [%met @c] + // + _term_io_belt(uty_u, u3nt(c3__mod, c3__met, cay_y)); } else if ( 8 == cay_y || 127 == cay_y ) { tat_u->esc.ape = c3n; - _term_io_belt(uty_u, u3nc(c3__met, c3__bac)); + // XX backwards compatibility [%met @c] + // + _term_io_belt(uty_u, u3nq(c3__mod, c3__met, c3__bac, u3_nul)); } else if ( ('[' == cay_y) || ('O' == cay_y) ) { tat_u->esc.bra = c3y; @@ -700,10 +681,31 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) else { tat_u->esc.ape = c3n; - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } } } + // mouse input + // + else if ( c3y == tat_u->esc.mou ) { + if ( 0 == tat_u->esc.ton_y ) { + tat_u->esc.ton_y = cay_y - 31; + } + else if ( 0 == tat_u->esc.col_y ) { + tat_u->esc.col_y = cay_y - 32; + } + else { + c3_y row_y = cay_y - 32; + // only acknowledge button 1 presses within our window + if ( 1 != tat_u->esc.ton_y && row_y <= tat_u->siz.row_l ) { + _term_io_belt(uty_u, u3nt(c3__hit, tat_u->siz.row_l - row_y, tat_u->esc.col_y - 1)); + } + tat_u->esc.mou = c3n; + tat_u->esc.ton_y = tat_u->esc.col_y = 0; + } + } + // unicode inputs + // else if ( 0 != tat_u->fut.wid_w ) { tat_u->fut.syb_y[tat_u->fut.len_w++] = cay_y; @@ -719,26 +721,25 @@ _term_io_suck_char(u3_utty* uty_u, c3_y cay_y) _term_io_belt(uty_u, u3nt(c3__txt, wug, u3_nul)); } } + // individual characters + // else { - if ( (cay_y >= 32) && (cay_y < 127) ) { + if ( (cay_y >= 32) && (cay_y < 127) ) { // visual ascii _term_io_belt(uty_u, u3nt(c3__txt, cay_y, u3_nul)); } - else if ( 0 == cay_y ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); + else if ( 0 == cay_y ) { // null + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } - else if ( 8 == cay_y || 127 == cay_y ) { + else if ( 8 == cay_y || 127 == cay_y ) { // backspace & delete _term_io_belt(uty_u, u3nc(c3__bac, u3_nul)); } - else if ( 13 == cay_y || 10 == cay_y ) { + else if ( 10 == cay_y || 13 == cay_y ) { // newline & carriage return _term_io_belt(uty_u, u3nc(c3__ret, u3_nul)); } -#if 0 - else if ( 6 == cay_y ) { - _term_io_flow(uty_u); // XX hack - } -#endif else if ( cay_y <= 26 ) { - _term_io_belt(uty_u, u3nc(c3__ctl, ('a' + (cay_y - 1)))); + // XX backwards compatibility [%ctl @c] + // + _term_io_belt(uty_u, u3nt(c3__mod, c3__ctl, ('a' + (cay_y - 1)))); } else if ( 27 == cay_y ) { tat_u->esc.ape = c3y; @@ -781,14 +782,14 @@ _term_suck(u3_utty* uty_u, const c3_y* buf, ssize_t siz_i) // The process hangs if we do nothing (and ctrl-z // then corrupts the event log), so we force shutdown. // - u3l_log("term: hangup (EOF)\r\n"); + u3l_log("term: hangup (EOF)"); // XX revise // u3_pier_bail(u3_king_stub()); } else if ( siz_i < 0 ) { - u3l_log("term %d: read: %s\n", uty_u->tid_l, uv_strerror(siz_i)); + u3l_log("term %d: read: %s", uty_u->tid_l, uv_strerror(siz_i)); } else { c3_i i; @@ -874,14 +875,20 @@ _term_spin_step(u3_utty* uty_u) // NB: we simply bail out if anything goes wrong // { - uv_buf_t lef_u = uty_u->ufo_u.out.cub1_u; + uv_buf_t lef_u = uty_u->ufo_u.cub_u; c3_i fid_i = uty_u->fid_i; // One-time cursor backoff. // if ( c3n == tat_u->sun_u.diz_o ) { - c3_w i_w; + // if we know where the bottom line is, and the cursor is not on it, + // move it to the bottom left + // + if ( tat_u->siz.row_l && tat_u->mir.rus_w > 0 ) { + _term_it_send_csi(uty_u, 'H', 2, tat_u->siz.row_l, 0); + } + c3_w i_w; for ( i_w = bac_w; i_w < sol_w; i_w++ ) { if ( lef_u.len != write(fid_i, lef_u.base, lef_u.len) ) { return; @@ -917,6 +924,7 @@ _term_spin_timer_cb(uv_timer_t* tim_u) _term_spin_step(uty_u); } +#define _SPIN_FAST_US 100UL // spinner activation delay when expected #define _SPIN_COOL_US 500UL // spinner activation delay when cool #define _SPIN_WARM_US 50UL // spinner activation delay when warm #define _SPIN_RATE_US 250UL // spinner rate (ms/frame) @@ -941,7 +949,7 @@ u3_term_start_spinner(u3_atom say, c3_o del_o) { c3_d now_d = _term_msc_out_host(); c3_d end_d = tat_u->sun_u.end_d; - c3_d wen_d = (c3n == del_o) ? 0UL : + c3_d wen_d = (c3n == del_o) ? _SPIN_FAST_US : (now_d - end_d < _SPIN_IDLE_US) ? _SPIN_WARM_US : _SPIN_COOL_US; @@ -966,7 +974,7 @@ u3_term_stop_spinner(void) uv_timer_stop(&tat_u->sun_u.tim_u); if ( c3y == tat_u->sun_u.diz_o ) { - _term_it_refresh_line(uty_u); + _term_it_restore_line(uty_u); tat_u->sun_u.end_d = _term_msc_out_host(); tat_u->sun_u.diz_o = c3n; } @@ -1057,15 +1065,13 @@ u3_term_ef_ctlc(void) { u3_noun wir = u3nt(c3__term, '1', u3_nul); - u3_noun cad = u3nt(c3__belt, c3__ctl, 'c'); + u3_noun cad = u3nq(c3__belt, c3__mod, c3__ctl, 'c'); c3_assert( 1 == uty_u->tid_l ); c3_assert( uty_u->car_u ); _term_ovum_plan(uty_u->car_u, wir, cad); } - - _term_it_refresh_line(uty_u); } /* _term_it_put_value(): put numeric color value on lin_w. @@ -1152,10 +1158,10 @@ _term_it_put_deco(c3_w* lin_w, } } -/* _term_it_show_stub(): send styled text to terminal as ansi escape sequences +/* _term_it_send_stub(): send styled text, without saving */ static void -_term_it_show_stub(u3_utty* uty_u, +_term_it_send_stub(u3_utty* uty_u, u3_noun tub) { c3_w tuc_w = u3qb_lent(tub); @@ -1174,17 +1180,16 @@ _term_it_show_stub(u3_utty* uty_u, // allocate enough memory for every display character, plus styles // - //NOTE we use max 31 characters per styl for escape codes: - // 3 for opening, 4 for decorations, 15 for colors, 4 for closing, - // and 5 as separators between decorations and colors. + //NOTE we use max 48 characters per styl for escape codes: + // 2 for opening, 7 for decorations, 2x16 for colors, 4 for closing, + // and 3 as separators between decorations and colors. // - c3_w* lin_w = c3_malloc( sizeof(c3_w) * (lec_w + (31 * tuc_w)) ); + c3_w* lin_w = c3_malloc( sizeof(c3_w) * (lec_w + (48 * tuc_w)) ); // write the contents to the buffer, // tracking total and escape characters written // c3_w i_w = 0; - c3_w sap_w = 0; { u3_noun nub = tub; while ( u3_nul != nub ) { @@ -1204,7 +1209,6 @@ _term_it_show_stub(u3_utty* uty_u, c3_o mor_o = c3n; lin_w[i_w++] = 27; lin_w[i_w++] = '['; - sap_w += 2; // text decorations // @@ -1214,10 +1218,8 @@ _term_it_show_stub(u3_utty* uty_u, while ( u3_nul != des ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } _term_it_put_deco(&lin_w[i_w++], u3h(des)); - sap_w++; mor_o = c3y; des = u3t(des); } @@ -1229,12 +1231,10 @@ _term_it_show_stub(u3_utty* uty_u, if ( u3_nul != bag ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } lin_w[i_w++] = '4'; c3_w put_w = _term_it_put_tint(&lin_w[i_w], bag); i_w += put_w; - sap_w += ++put_w; mor_o = c3y; } @@ -1243,17 +1243,14 @@ _term_it_show_stub(u3_utty* uty_u, if ( u3_nul != fog ) { if ( c3y == mor_o ) { lin_w[i_w++] = ';'; - sap_w++; } lin_w[i_w++] = '3'; c3_w put_w = _term_it_put_tint(&lin_w[i_w], fog); i_w += put_w; - sap_w += ++put_w; mor_o = c3y; } lin_w[i_w++] = 'm'; - sap_w++; } // write the text itself @@ -1269,18 +1266,27 @@ _term_it_show_stub(u3_utty* uty_u, lin_w[i_w++] = '['; lin_w[i_w++] = '0'; lin_w[i_w++] = 'm'; - sap_w += 4; } nub = u3t(nub); } } - _term_it_set_line(uty_u, lin_w, i_w, sap_w); + _term_it_show_line(uty_u, lin_w, i_w); u3z(tub); } +/* _term_it_send_stub(): send styled text to terminal as ansi escape sequences +*/ +static void +_term_it_show_stub(u3_utty* uty_u, + u3_noun tub) +{ + _term_it_send_stub(uty_u, u3k(tub)); + _term_it_save_stub(uty_u, tub); +} + /* _term_it_show_tour(): send utf32 to terminal. */ static void @@ -1298,9 +1304,14 @@ _term_it_show_tour(u3_utty* uty_u, } } - _term_it_set_line(uty_u, lin_w, len_w, 0); + _term_it_show_line(uty_u, lin_w, len_w); - u3z(lin); + { + u3_noun tub = u3i_list(u3nc(u3nt(u3_nul, u3_nul, u3_nul), lin), u3_none); + _term_it_save_stub(uty_u, tub); + } + + //NOTE lin transferred to tub above } /* _term_ef_blit(): send blit to terminal. @@ -1313,40 +1324,38 @@ _term_ef_blit(u3_utty* uty_u, default: break; case c3__bel: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_dump_buf(uty_u, &uty_u->ufo_u.out.bel_u); - } + _term_it_dump_buf(uty_u, &uty_u->ufo_u.bel_u); } break; case c3__clr: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_blank(uty_u); - _term_it_refresh_line(uty_u); - } + _term_it_show_blank(uty_u); } break; case c3__hop: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_cursor(uty_u, u3t(blt)); + u3_noun pos = u3t(blt); + if ( c3y == u3r_ud(pos) ) { + _term_it_move_cursor(uty_u, 0, pos); + } + else { + _term_it_move_cursor(uty_u, u3h(pos), u3t(pos)); } } break; case c3__klr: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_clear(uty_u); - } _term_it_show_stub(uty_u, u3k(u3t(blt))); } break; - case c3__lin: { - if ( c3n == u3_Host.ops_u.tem ) { - _term_it_show_clear(uty_u); - } + case c3__lin: { //TMP backwards compatibility + _term_it_move_cursor(uty_u, 0, 0); + _term_it_clear_line(uty_u); + } // + case c3__put: { _term_it_show_tour(uty_u, u3k(u3t(blt))); } break; - case c3__mor: { - _term_it_show_more(uty_u); + case c3__mor: //TMP backwards compatibility + case c3__nel: { + _term_it_show_nel(uty_u); } break; case c3__sav: { @@ -1364,20 +1373,50 @@ _term_ef_blit(u3_utty* uty_u, } break; case c3__url: { - u3_noun txt = u3t(blt); + // platform-agnostically opening the default web browser from within a + // c program is an unsolved problem. + } break; - // XX check u3_Host.ops_u.tem ? - // XX this looks to be broken, - // multiple calls to _show_clear will discard the mirror state - // - if ( c3y == u3a_is_atom(txt) ) { - _term_it_show_clear(uty_u); + case c3__wyp: { + _term_it_clear_line(uty_u); + } break; + } - _term_it_send_cord(uty_u, u3k(txt)); + u3z(blt); +} - _term_it_show_more(uty_u); - _term_it_refresh_line(uty_u); - } +/* _term_ef_blit_lame(): simplified output handling for -t +*/ +static void +_term_ef_blit_lame(u3_utty* uty_u, + u3_noun blt) +{ + switch ( u3h(blt) ) { + default: break; + + case c3__klr: { + _term_it_show_stub(uty_u, u3k(u3t(blt))); + _term_it_show_nel(uty_u); + } break; + + case c3__lin: //TMP backwards compatibility + case c3__put: { + _term_it_show_tour(uty_u, u3k(u3t(blt))); + _term_it_show_nel(uty_u); + } break; + + case c3__sav: { + u3_noun pax, dat; + u3x_cell(u3t(blt), &pax, &dat); + + _term_it_save(u3k(pax), u3k(dat)); + } break; + + case c3__sag: { + u3_noun pax, dat; + u3x_cell(u3t(blt), &pax, &dat); + + _term_it_save(u3k(pax), u3qe_jam(dat)); } break; } @@ -1391,7 +1430,7 @@ u3_term_io_hija(void) { u3_utty* uty_u = _term_main(); - if ( uty_u ) { + if ( uty_u && uty_u->tat_u.siz.row_l ) { if ( uty_u->fid_i > 2 ) { // We *should* in fact, produce some kind of fake FILE* for // non-console terminals. If we use this interface enough... @@ -1403,11 +1442,14 @@ u3_term_io_hija(void) if ( c3y != uty_u->hij_f(uty_u) ) { c3_assert(!"hija-tcsetattr"); } - u3_write_fd(uty_u->fid_i, "\r", 1); - { - uv_buf_t* buf_u = &uty_u->ufo_u.out.el_u; - u3_write_fd(uty_u->fid_i, buf_u->base, buf_u->len); - } + + // set scroll region to exclude the prompt, + // scroll up one line to make space, + // and move the cursor onto that space. + // + _term_it_send_csi(uty_u, 'r', 2, 1, uty_u->tat_u.siz.row_l - 1); + _term_it_send_csi(uty_u, 'S', 1, 1); + _term_it_send_csi(uty_u, 'H', 2, uty_u->tat_u.siz.row_l - 1, 1); } } } @@ -1417,11 +1459,11 @@ u3_term_io_hija(void) /* u3_term_io_loja(): release console from fprintf. */ void -u3_term_io_loja(int x) +u3_term_io_loja(int x, FILE* f) { u3_utty* uty_u = _term_main(); - if ( uty_u ) { + if ( uty_u && uty_u->tat_u.siz.row_l ) { if ( uty_u->fid_i > 2 ) { // We *should* in fact, produce some kind of fake FILE* for // non-console terminals. If we use this interface enough... @@ -1430,15 +1472,25 @@ u3_term_io_loja(int x) } else { if ( c3y == u3_Host.ops_u.tem ) { - fflush(stdout); - } else { + fprintf(f, "\n"); + fflush(f); + } + else { if ( c3y != uty_u->loj_f(uty_u) ) { c3_assert(!"loja-tcsetattr"); } - _term_it_refresh_line(uty_u); + + // clear the scrolling region we set previously, + // and restore cursor to its original position. + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.reg_u); + _term_it_dump_buf(uty_u, &uty_u->ufo_u.ruc_u); } } } + else { + fprintf(f, "\r\n"); + } } /* u3_term_it_log(): writes a log message @@ -1447,7 +1499,9 @@ void u3_term_io_log(c3_c* line) { FILE* stream = u3_term_io_hija(); - u3_term_io_loja(fprintf(stream, "%s", line)); + int x = fprintf(stream, "%s", line); + fflush(stream); + u3_term_io_loja(x, stream); //TODO remove arg? unused... } /* u3_term_tape_to(): dump a tape to a file. @@ -1479,7 +1533,7 @@ u3_term_tape(u3_noun tep) u3_term_tape_to(fil_f, tep); - u3_term_io_loja(0); + u3_term_io_loja(0, fil_f); } /* u3_term_wall(): dump a wall to stdout. @@ -1498,7 +1552,7 @@ u3_term_wall(u3_noun wol) wal = u3t(wal); } - u3_term_io_loja(0); + u3_term_io_loja(0, fil_f); u3z(wol); } @@ -1511,12 +1565,16 @@ _term_io_talk(u3_auto* car_u) if ( c3n == u3_Host.ops_u.tem ) { u3_utty* uty_u = _term_main(); + // start mouse handling + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.mon_u); + uv_read_start((uv_stream_t*)&(uty_u->pin_u), _term_alloc, _term_read_cb); } - // XX groace hardcoded terminal number + //TODO reevaluate wrt dill sessions // u3_noun wir = u3nt(c3__term, '1', u3_nul); u3_noun cad; @@ -1528,10 +1586,6 @@ _term_io_talk(u3_auto* car_u) _term_ovum_plan(car_u, u3k(wir), cad); } - // NB, term.c used to also start :dojo - // - // u3nq(c3__flow, c3__seat, c3__dojo, u3_nul) - // refresh terminal state // { @@ -1584,7 +1638,7 @@ _term_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) || (u3_nul != q_pud) || (c3n == _reck_orchid(c3__ud, u3k(p_pud), &tid_l)) ) { - u3l_log("term: bad tire\n"); + u3l_log("term: bad tire"); ret_o = c3n; } else { @@ -1593,26 +1647,25 @@ _term_io_kick(u3_auto* car_u, u3_noun wir, u3_noun cad) ret_o = c3n; } break; - // XX review, accepted and ignored - // - case c3__bbye: { - ret_o = c3y; - } break; - case c3__blit: { ret_o = c3y; { u3_utty* uty_u = _term_ef_get(tid_l); if ( 0 == uty_u ) { - // u3l_log("no terminal %d\n", tid_l); - // u3l_log("uty_u %p\n", u3_Host.uty_u); + // u3l_log("no terminal %d", tid_l); + // u3l_log("uty_u %p", u3_Host.uty_u); } else { u3_noun bis = dat; while ( c3y == u3du(bis) ) { - _term_ef_blit(uty_u, u3k(u3h(bis))); + if (c3n == u3_Host.ops_u.tem) { + _term_ef_blit(uty_u, u3k(u3h(bis))); + } + else { + _term_ef_blit_lame(uty_u, u3k(u3h(bis))); + } bis = u3t(bis); } } @@ -1673,6 +1726,10 @@ _term_io_exit(u3_auto* car_u) u3_utty* uty_u = _term_main(); if ( c3n == u3_Host.ops_u.tem ) { + // stop mouse handling + // + _term_it_dump_buf(uty_u, &uty_u->ufo_u.mof_u); + // NB, closed in u3_term_log_exit() // uv_read_stop((uv_stream_t*)&(uty_u->pin_u)); diff --git a/pkg/urbit/vere/io/unix.c b/pkg/urbit/vere/io/unix.c index 4526298bc..e38ac6b15 100644 --- a/pkg/urbit/vere/io/unix.c +++ b/pkg/urbit/vere/io/unix.c @@ -162,35 +162,35 @@ _unix_rm_r_cb(const c3_c* pax_c, { switch ( typeflag ) { default: - u3l_log("bad file type in rm_r: %s\r\n", pax_c); + u3l_log("bad file type in rm_r: %s", pax_c); break; case FTW_F: if ( 0 != unlink(pax_c) && ENOENT != errno ) { - u3l_log("error unlinking (in rm_r) %s: %s\n", + u3l_log("error unlinking (in rm_r) %s: %s", pax_c, strerror(errno)); c3_assert(0); } break; case FTW_D: - u3l_log("shouldn't have gotten pure directory: %s\r\n", pax_c); + u3l_log("shouldn't have gotten pure directory: %s", pax_c); break; case FTW_DNR: - u3l_log("couldn't read directory: %s\r\n", pax_c); + u3l_log("couldn't read directory: %s", pax_c); break; case FTW_NS: - u3l_log("couldn't stat path: %s\r\n", pax_c); + u3l_log("couldn't stat path: %s", pax_c); break; case FTW_DP: if ( 0 != rmdir(pax_c) && ENOENT != errno ) { - u3l_log("error rmdiring %s: %s\n", pax_c, strerror(errno)); + u3l_log("error rmdiring %s: %s", pax_c, strerror(errno)); c3_assert(0); } break; case FTW_SL: - u3l_log("got symbolic link: %s\r\n", pax_c); + u3l_log("got symbolic link: %s", pax_c); break; case FTW_SLN: - u3l_log("got nonexistent symbolic link: %s\r\n", pax_c); + u3l_log("got nonexistent symbolic link: %s", pax_c); break; } @@ -204,7 +204,7 @@ _unix_rm_r(c3_c* pax_c) { if ( 0 > nftw(pax_c, _unix_rm_r_cb, 100, FTW_DEPTH | FTW_PHYS ) && ENOENT != errno) { - u3l_log("rm_r error on %s: %s\r\n", pax_c, strerror(errno)); + u3l_log("rm_r error on %s: %s", pax_c, strerror(errno)); } } @@ -214,7 +214,7 @@ static void _unix_mkdir(c3_c* pax_c) { if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno) { - u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); + u3l_log("error mkdiring %s: %s", pax_c, strerror(errno)); c3_assert(0); } } @@ -231,7 +231,7 @@ _unix_write_file_hard(c3_c* pax_c, u3_noun mim) u3_noun dat = u3t(u3t(mim)); if ( fid_i < 0 ) { - u3l_log("error opening %s for writing: %s\r\n", + u3l_log("error opening %s for writing: %s", pax_c, strerror(errno)); u3z(mim); return 0; @@ -247,7 +247,7 @@ _unix_write_file_hard(c3_c* pax_c, u3_noun mim) rit_w = write(fid_i, dat_y, siz_w); if ( rit_w != siz_w ) { - u3l_log("error writing %s: %s\r\n", + u3l_log("error writing %s: %s", pax_c, strerror(errno)); mug_w = 0; } @@ -277,7 +277,7 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) goto _unix_write_file_soft_go; } else { - u3l_log("error opening file (soft) %s: %s\r\n", + u3l_log("error opening file (soft) %s: %s", fil_u->pax_c, strerror(errno)); u3z(mim); return; @@ -290,17 +290,17 @@ _unix_write_file_soft(u3_ufil* fil_u, u3_noun mim) red_ws = read(fid_i, old_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing file (soft) %s: %s\r\n", + u3l_log("error closing file (soft) %s: %s", fil_u->pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading file (soft) %s: %s\r\n", + u3l_log("error reading file (soft) %s: %s", fil_u->pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in file %s: %d %d", fil_u->pax_c, len_ws, red_ws); } c3_free(old_y); @@ -376,7 +376,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) { DIR* rid_u = opendir(mon_u->dir_u.pax_c); if ( !rid_u ) { - u3l_log("error opening pier directory: %s: %s\r\n", + u3l_log("error opening pier directory: %s: %s", mon_u->dir_u.pax_c, strerror(errno)); return; } @@ -389,7 +389,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) c3_w err_w; if ( 0 != (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) ) { - u3l_log("erroring loading pier directory %s: %s\r\n", + u3l_log("erroring loading pier directory %s: %s", mon_u->dir_u.pax_c, strerror(errno)); c3_assert(0); @@ -409,7 +409,7 @@ _unix_scan_mount_point(u3_unix* unx_u, u3_umon* mon_u) struct stat buf_u; if ( 0 != stat(pax_c, &buf_u) ) { - u3l_log("can't stat pier directory %s: %s\r\n", + u3l_log("can't stat pier directory %s: %s", mon_u->dir_u.pax_c, strerror(errno)); c3_free(pax_c); continue; @@ -453,7 +453,7 @@ static void _unix_free_file(u3_ufil *fil_u) { if ( 0 != unlink(fil_u->pax_c) && ENOENT != errno ) { - u3l_log("error unlinking %s: %s\n", fil_u->pax_c, strerror(errno)); + u3l_log("error unlinking %s: %s", fil_u->pax_c, strerror(errno)); c3_assert(0); } @@ -565,7 +565,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) mon_u = unx_u->mon_u; if ( !mon_u ) { - u3l_log("mount point already gone: %s\r\n", nam_c); + u3l_log("mount point already gone: %s", nam_c); goto _delete_mount_point_out; } if ( 0 == strcmp(nam_c, mon_u->nam_c) ) { @@ -581,7 +581,7 @@ _unix_delete_mount_point(u3_unix* unx_u, u3_noun mon) } if ( !mon_u->nex_u ) { - u3l_log("mount point already gone: %s\r\n", nam_c); + u3l_log("mount point already gone: %s", nam_c); goto _delete_mount_point_out; } @@ -699,7 +699,7 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) return u3nc(u3nc(_unix_string_to_path(unx_u, fil_u->pax_c), u3_nul), u3_nul); } else { - u3l_log("error opening file %s: %s\r\n", + u3l_log("error opening file %s: %s", fil_u->pax_c, strerror(errno)); return u3_nul; } @@ -711,17 +711,17 @@ _unix_update_file(u3_unix* unx_u, u3_ufil* fil_u) red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing file %s: %s\r\n", + u3l_log("error closing file %s: %s", fil_u->pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading file %s: %s\r\n", + u3l_log("error reading file %s: %s", fil_u->pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in file %s: %d %d", fil_u->pax_c, len_ws, red_ws); } c3_free(dat_y); @@ -790,7 +790,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( (fid_i < 0) || (fstat(fid_i, &buf_u) < 0) ) { if ( ENOENT != errno ) { - u3l_log("_unix_update_dir: error opening file %s: %s\r\n", + u3l_log("_unix_update_dir: error opening file %s: %s", nod_u->pax_c, strerror(errno)); } @@ -800,7 +800,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } else { if ( close(fid_i) < 0 ) { - u3l_log("_unix_update_dir: error closing file %s: %s\r\n", + u3l_log("_unix_update_dir: error closing file %s: %s", nod_u->pax_c, strerror(errno)); } @@ -815,7 +815,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) DIR* rid_u = opendir(dir_u->pax_c); if ( !rid_u ) { - u3l_log("error opening directory %s: %s\r\n", + u3l_log("error opening directory %s: %s", dir_u->pax_c, strerror(errno)); c3_assert(0); } @@ -827,7 +827,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) != 0 ) { - u3l_log("error loading directory %s: %s\r\n", + u3l_log("error loading directory %s: %s", dir_u->pax_c, strerror(err_w)); c3_assert(0); } @@ -843,7 +843,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) struct stat buf_u; if ( 0 != stat(pax_c, &buf_u) ) { - u3l_log("can't stat %s: %s\r\n", pax_c, strerror(errno)); + u3l_log("can't stat %s: %s", pax_c, strerror(errno)); c3_free(pax_c); continue; } @@ -853,13 +853,13 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) if ( 0 == strcmp(pax_c, nod_u->pax_c) ) { if ( S_ISDIR(buf_u.st_mode) ) { if ( c3n == nod_u->dir ) { - u3l_log("not a directory: %s\r\n", nod_u->pax_c); + u3l_log("not a directory: %s", nod_u->pax_c); c3_assert(0); } } else { if ( c3y == nod_u->dir ) { - u3l_log("not a file: %s\r\n", nod_u->pax_c); + u3l_log("not a file: %s", nod_u->pax_c); c3_assert(0); } } @@ -894,7 +894,7 @@ _unix_update_dir(u3_unix* unx_u, u3_udir* dir_u) } if ( closedir(rid_u) < 0 ) { - u3l_log("error closing directory %s: %s\r\n", + u3l_log("error closing directory %s: %s", dir_u->pax_c, strerror(errno)); } @@ -965,7 +965,7 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) return u3_nul; } else { - u3l_log("error opening initial file %s: %s\r\n", + u3l_log("error opening initial file %s: %s", pax_c, strerror(errno)); return u3_nul; } @@ -977,17 +977,17 @@ _unix_initial_update_file(c3_c* pax_c, c3_c* bas_c) red_ws = read(fid_i, dat_y, len_ws); if ( close(fid_i) < 0 ) { - u3l_log("error closing initial file %s: %s\r\n", + u3l_log("error closing initial file %s: %s", pax_c, strerror(errno)); } if ( len_ws != red_ws ) { if ( red_ws < 0 ) { - u3l_log("error reading initial file %s: %s\r\n", + u3l_log("error reading initial file %s: %s", pax_c, strerror(errno)); } else { - u3l_log("wrong # of bytes read in initial file %s: %d %d\r\n", + u3l_log("wrong # of bytes read in initial file %s: %d %d", pax_c, len_ws, red_ws); } c3_free(dat_y); @@ -1015,7 +1015,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) DIR* rid_u = opendir(pax_c); if ( !rid_u ) { - u3l_log("error opening initial directory: %s: %s\r\n", + u3l_log("error opening initial directory: %s: %s", pax_c, strerror(errno)); return u3_nul; } @@ -1026,7 +1026,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) c3_w err_w; if ( 0 != (err_w = u3_readdir_r(rid_u, &ent_u, &out_u)) ) { - u3l_log("error loading initial directory %s: %s\r\n", + u3l_log("error loading initial directory %s: %s", pax_c, strerror(errno)); c3_assert(0); @@ -1043,7 +1043,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) struct stat buf_u; if ( 0 != stat(pox_c, &buf_u) ) { - u3l_log("initial can't stat %s: %s\r\n", + u3l_log("initial can't stat %s: %s", pox_c, strerror(errno)); c3_free(pox_c); continue; @@ -1061,7 +1061,7 @@ _unix_initial_update_dir(c3_c* pax_c, c3_c* bas_c) } if ( closedir(rid_u) < 0 ) { - u3l_log("error closing initial directory %s: %s\r\n", + u3l_log("error closing initial directory %s: %s", pax_c, strerror(errno)); } @@ -1152,16 +1152,16 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) if ( c3n == u3du(pax) ) { if ( u3_nul == pax ) { - u3l_log("can't sync out file as top-level, strange\r\n"); + u3l_log("can't sync out file as top-level, strange"); } else { - u3l_log("sync out: bad path\r\n"); + u3l_log("sync out: bad path"); } u3z(pax); u3z(mim); return; } else if ( c3n == u3du(u3t(pax)) ) { - u3l_log("can't sync out file as top-level, strangely\r\n"); + u3l_log("can't sync out file as top-level, strangely"); u3z(pax); u3z(mim); } else { @@ -1191,7 +1191,7 @@ _unix_sync_change(u3_unix* unx_u, u3_udir* dir_u, u3_noun pax, u3_noun mim) } if ( c3n == nod_u->dir ) { - u3l_log("weird, we got a file when we weren't expecting to\r\n"); + u3l_log("weird, we got a file when we weren't expecting to"); c3_assert(0); } @@ -1274,7 +1274,7 @@ u3_unix_acquire(c3_c* pax_c) if ( NULL != (loq_u = fopen(paf_c, "r")) ) { if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) { - u3l_log("lockfile %s is corrupt!\n", paf_c); + u3l_log("lockfile %s is corrupt!", paf_c); kill(getpid(), SIGTERM); sleep(1); c3_assert(0); } @@ -1282,7 +1282,7 @@ u3_unix_acquire(c3_c* pax_c) c3_w i_w; if ( -1 != kill(pid_w, SIGTERM) ) { - u3l_log("unix: stopping process %d, live in %s...\n", + u3l_log("unix: stopping process %d, live in %s...", pid_w, pax_c); for ( i_w = 0; i_w < 16; i_w++ ) { @@ -1300,10 +1300,10 @@ u3_unix_acquire(c3_c* pax_c) } } if ( 16 == i_w ) { - u3l_log("unix: process %d seems unkillable!\n", pid_w); + u3l_log("unix: process %d seems unkillable!", pid_w); c3_assert(0); } - u3l_log("unix: stopped old process %u\n", pid_w); + u3l_log("unix: stopped old process %u", pid_w); } } fclose(loq_u); @@ -1311,7 +1311,7 @@ u3_unix_acquire(c3_c* pax_c) } if ( NULL == (loq_u = fopen(paf_c, "w")) ) { - u3l_log("unix: unable to open %s\n", paf_c); + u3l_log("unix: unable to open %s", paf_c); c3_assert(0); } diff --git a/pkg/urbit/vere/king.c b/pkg/urbit/vere/king.c index e857d6040..c9587fad2 100644 --- a/pkg/urbit/vere/king.c +++ b/pkg/urbit/vere/king.c @@ -245,7 +245,7 @@ _king_get_atom(c3_c* url_c) uv_buf_t buf_u = uv_buf_init(c3_malloc(1), 0); if ( !(curl = curl_easy_init()) ) { - u3l_log("failed to initialize libcurl\n"); + u3l_log("failed to initialize libcurl"); exit(1); } @@ -260,13 +260,13 @@ _king_get_atom(c3_c* url_c) // XX retry? // if ( CURLE_OK != result ) { - u3l_log("failed to fetch %s: %s\n", + u3l_log("failed to fetch %s: %s", url_c, curl_easy_strerror(result)); u3_king_bail(); exit(1); } if ( 300 <= cod_l ) { - u3l_log("error fetching %s: HTTP %ld\n", url_c, cod_l); + u3l_log("error fetching %s: HTTP %ld", url_c, cod_l); u3_king_bail(); exit(1); } @@ -292,12 +292,12 @@ _get_cmd_output(c3_c *cmd_c, c3_c *out_c, c3_w len_c) { FILE *fp = popen(cmd_c, "r"); if ( NULL == fp ) { - u3l_log("'%s' failed\n", cmd_c); + u3l_log("'%s' failed", cmd_c); exit(1); } if ( NULL == fgets(out_c, len_c, fp) ) { - u3l_log("'%s' produced no output\n", cmd_c); + u3l_log("'%s' produced no output", cmd_c); exit(1); } @@ -330,7 +330,7 @@ _git_pill_url(c3_c *out_c, c3_c *arv_c) assert(NULL != arv_c); if ( 0 != system("which git >> /dev/null") ) { - u3l_log("boot: could not find git executable\r\n"); + u3l_log("boot: could not find git executable"); exit(1); } @@ -347,7 +347,7 @@ _boothack_pill(void) u3_noun pil; if ( 0 != u3_Host.ops_u.pil_c ) { - u3l_log("boot: loading pill %s\r\n", u3_Host.ops_u.pil_c); + u3l_log("boot: loading pill %s", u3_Host.ops_u.pil_c); pil = u3m_file(u3_Host.ops_u.pil_c); } else { @@ -363,12 +363,12 @@ _boothack_pill(void) strcpy(url_c, u3_Host.ops_u.url_c); } - u3l_log("boot: downloading pill %s\r\n", url_c); + u3l_log("boot: downloading pill %s", url_c); pil = _king_get_atom(url_c); } if ( 0 != u3_Host.ops_u.arv_c ) { - u3l_log("boot: preparing filesystem from %s\r\n", + u3l_log("boot: preparing filesystem from %s", u3_Host.ops_u.arv_c); arv = u3nc(u3_nul, u3_unix_initial_into_card(u3_Host.ops_u.arv_c)); } @@ -389,7 +389,7 @@ _boothack_key(u3_noun kef) if ( u3_nul == des ) { c3_c* kef_c = u3r_string(kef); - u3l_log("dawn: invalid private keys: %s\r\n", kef_c); + u3l_log("dawn: invalid private keys: %s", kef_c); c3_free(kef_c); exit(1); } @@ -398,7 +398,7 @@ _boothack_key(u3_noun kef) // u3_noun pro = u3m_soft(0, u3ke_cue, u3k(u3t(des))); if ( u3_blip != u3h(pro) ) { - u3l_log("dawn: unable to cue keyfile\r\n"); + u3l_log("dawn: unable to cue keyfile"); exit(1); } seed = u3k(u3t(pro)); @@ -421,7 +421,7 @@ _boothack_key(u3_noun kef) u3_noun whu = u3dc("slaw", 'p', u3k(woh)); if ( u3_nul == whu ) { - u3l_log("dawn: invalid ship specified with -w %s\r\n", + u3l_log("dawn: invalid ship specified with -w %s", u3_Host.ops_u.who_c); exit(1); } @@ -431,7 +431,7 @@ _boothack_key(u3_noun kef) { u3_noun how = u3dc("scot", 'p', u3k(ship)); c3_c* how_c = u3r_string(u3k(how)); - u3l_log("dawn: mismatch between -w %s and -K %s\r\n", + u3l_log("dawn: mismatch between -w %s and -K %s", u3_Host.ops_u.who_c, how_c); u3z(how); @@ -462,7 +462,7 @@ _boothack_doom(void) u3_noun whu = u3dc("slaw", 'p', u3k(fak)); if ( u3_nul == whu ) { - u3l_log("boot: malformed -F ship %s\r\n", u3_Host.ops_u.fak_c); + u3l_log("boot: malformed -F ship %s", u3_Host.ops_u.fak_c); exit(1); } @@ -496,7 +496,7 @@ _boothack_doom(void) kef = u3i_string(u3_Host.ops_u.gen_c); } else { - u3l_log("boot: must specify a key with -k or -G\r\n"); + u3l_log("boot: must specify a key with -k or -G"); exit(1); } @@ -591,7 +591,7 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) { switch ( num_i ) { default: { - u3l_log("\r\nmysterious signal %d\r\n", num_i); + u3l_log("\r\nmysterious signal %d", num_i); break; } @@ -601,7 +601,7 @@ _king_sign_cb(uv_signal_t* sil_u, c3_i num_i) } case SIGINT: { - u3l_log("\r\ninterrupt\r\n"); + u3l_log("\r\ninterrupt"); u3_term_ef_ctlc(); #if defined(U3_OS_mingw) @@ -704,7 +704,7 @@ _king_boot_ivory(void) if ( u3_Host.ops_u.lit_c ) { if ( c3n == u3u_mmap_read("lite", u3_Host.ops_u.lit_c, &len_d, &byt_y) ) { - u3l_log("lite: unable to load ivory pill at %s\n", + u3l_log("lite: unable to load ivory pill at %s", u3_Host.ops_u.lit_c); exit(1); } @@ -719,21 +719,21 @@ _king_boot_ivory(void) u3_weak pil; if ( u3_none == (pil = u3s_cue_xeno_with(sil_u, len_d, byt_y)) ) { - u3l_log("lite: unable to cue ivory pill\r\n"); + u3l_log("lite: unable to cue ivory pill"); exit(1); } 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); } } if ( u3_Host.ops_u.lit_c ) { if ( c3n == u3u_munmap(len_d, byt_y) ) { - u3l_log("lite: unable to unmap ivory pill at %s\n", + u3l_log("lite: unable to unmap ivory pill at %s", u3_Host.ops_u.lit_c); exit(1); } @@ -787,7 +787,7 @@ u3_king_commence() rlm.rlim_cur = 0; if ( 0 != setrlimit(RLIMIT_CORE, &rlm) ) { - u3l_log("king: unable to disable core dumps: %s\r\n", strerror(errno)); + u3l_log("king: unable to disable core dumps: %s", strerror(errno)); exit(1); } } @@ -955,7 +955,7 @@ u3_king_grab(void* vod_p) } #else { - u3_term_io_loja(0); + u3_term_io_loja(0, fil_u); } #endif } diff --git a/pkg/urbit/vere/lord.c b/pkg/urbit/vere/lord.c index 25ffe6096..e07d9ceb4 100644 --- a/pkg/urbit/vere/lord.c +++ b/pkg/urbit/vere/lord.c @@ -267,13 +267,13 @@ _lord_plea_live(u3_lord* god_u, u3_noun dat) case u3_writ_meld: { // XX wire into cb // - u3l_log("pier: meld complete\n"); + u3l_log("pier: meld complete"); } break; case u3_writ_pack: { // XX wire into cb // - u3l_log("pier: pack complete\n"); + u3l_log("pier: pack complete"); } break; } @@ -1098,10 +1098,10 @@ _lord_on_serf_bail(void* ptr_v, u3_lord* god_u = ptr_v; if ( UV_EOF == err_i ) { - u3l_log("pier: serf unexpectedly shut down\r\n"); + u3l_log("pier: serf unexpectedly shut down"); } else { - u3l_log("pier: serf error: %s\r\n", err_c); + u3l_log("pier: serf error: %s", err_c); } _lord_bail(god_u); @@ -1112,7 +1112,7 @@ _lord_on_serf_bail(void* ptr_v, void u3_lord_info(u3_lord* god_u) { - u3l_log(" lord: live=%s, event=%" PRIu64 ", mug=%x, queue=%u\n", + u3l_log(" lord: live=%s, event=%" PRIu64 ", mug=%x, queue=%u", ( c3y == god_u->liv_o ) ? "&" : "|", god_u->eve_d, god_u->mug_l, @@ -1148,7 +1148,7 @@ u3_lord_init(c3_c* pax_c, c3_w wag_w, c3_d key_d[4], u3_lord_cb cb_u) c3_c cev_c[11]; c3_i err_i; - sprintf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64 "", + sprintf(key_c, "%" PRIx64 ":%" PRIx64 ":%" PRIx64 ":%" PRIx64, god_u->key_d[0], god_u->key_d[1], god_u->key_d[2], diff --git a/pkg/urbit/vere/newt.c b/pkg/urbit/vere/newt.c index 6325f0ef9..5c8a2a693 100644 --- a/pkg/urbit/vere/newt.c +++ b/pkg/urbit/vere/newt.c @@ -362,7 +362,7 @@ u3_newt_moat_info(u3_moat* mot_u) } if ( len_w ) { - u3l_log(" newt: %u inbound ipc messages pending\n", len_w); + u3l_log(" newt: %u inbound ipc messages pending", len_w); } } diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 2bd308534..c64df414d 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -251,7 +251,7 @@ _pier_work(u3_work* wok_u) // XX this is when "boot" is actually complete // XX even better would be after neighboring with our sponsor // - u3l_log("pier (%" PRIu64 "): live\r\n", pir_u->god_u->eve_d); + u3l_log("pier (%" PRIu64 "): live", pir_u->god_u->eve_d); // XX move callbacking to king // @@ -286,7 +286,7 @@ _pier_on_lord_work_spin(void* ptr_v, u3_atom pin, c3_o del_o) u3_term_start_spinner(pin, del_o); } -/* _pier_on_lord_work_spin(): stop spinner +/* _pier_on_lord_work_spun(): stop spinner */ static void _pier_on_lord_work_spun(void* ptr_v) @@ -472,13 +472,13 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) u3_weak res = u3r_at(7, nun); if (u3_none == res) { - u3l_log("pier: scry failed\n"); + u3l_log("pier: scry failed"); } else { u3_weak out, pad; c3_c *ext_c, *pac_c; - u3l_log("pier: scry succeeded\n"); + u3l_log("pier: scry succeeded"); if ( u3_Host.ops_u.puk_c ) { pac_c = u3_Host.ops_u.puk_c; @@ -531,11 +531,11 @@ _pier_on_scry_done(void* ptr_v, u3_noun nun) pir_u->pax_c, pac_c+1, ext_c); u3_walk_save(fil_c, 0, out, pir_u->pax_c, pad); - u3l_log("pier: scry result in %s\n", fil_c); + u3l_log("pier: scry result in %s", fil_c); } } - u3l_log("pier: exit\n"); + u3l_log("pier: exit"); u3_pier_exit(pir_u); u3z(nun); @@ -614,7 +614,7 @@ _pier_work_init(u3_pier* pir_u) } else { // run the requested scry, jam to disk, then exit // - u3l_log("pier: scry\n"); + u3l_log("pier: scry"); u3_pier_peek_last(pir_u, u3_nul, u3k(car), u3k(dek), u3k(pax), pir_u, _pier_on_scry_done); } @@ -663,7 +663,7 @@ _pier_wyrd_fail(u3_pier* pir_u, u3_ovum* egg_u, u3_noun lud) { // XX version negotiation failed, print upgrade message // - u3l_log("pier: version negotation failed\n\n"); + u3l_log("pier: version negotation failed"); // XX only print trace with -v ? // @@ -749,7 +749,7 @@ _pier_on_lord_wyrd_done(void* ptr_v, // XX messaging, cli argument to bypass // - u3l_log("pier: version negotiation failed; downgrade\n"); + u3l_log("pier: version negotiation failed; downgrade"); _pier_wyrd_fail(pir_u, egg_u, u3_nul); } else { @@ -842,7 +842,7 @@ _pier_wyrd_init(u3_pier* pir_u) pir_u->sat_e = u3_psat_wyrd; - u3l_log("vere: checking version compatibility\n"); + u3l_log("vere: checking version compatibility"); { u3_lord* god_u = pir_u->god_u; @@ -1031,11 +1031,11 @@ _pier_play(u3_play* pay_u) if ( god_u->eve_d == pay_u->eve_d ) { // XX should be play_cb // - u3l_log("---------------- playback complete ----------------\r\n"); + u3l_log("---------------- playback complete ----------------"); u3_term_stop_spinner(); if ( pay_u->eve_d < log_u->dun_d ) { - // u3l_log("pier: replay barrier reached, shutting down\r\n"); + // u3l_log("pier: replay barrier reached, shutting down"); // // XX graceful shutdown // // // u3_lord_save(pir_u->god_u); @@ -1044,7 +1044,7 @@ _pier_play(u3_play* pay_u) // XX temporary hack // - u3l_log("pier: replay barrier reached, cramming\r\n"); + u3l_log("pier: replay barrier reached, cramming"); u3_pier_cram(pir_u); } else if ( pay_u->eve_d == log_u->dun_d ) { @@ -1070,12 +1070,12 @@ _pier_on_lord_play_done(void* ptr_v, u3_info fon_u, c3_l mug_l) c3_assert( u3_psat_play == pir_u->sat_e ); - u3l_log("pier: (%" PRIu64 "): play: done\r\n", tac_u->eve_d); + u3l_log("pier: (%" PRIu64 "): play: done", tac_u->eve_d); // XX optional // if ( tac_u->mug_l && (tac_u->mug_l != mug_l) ) { - u3l_log("pier: (%" PRIu64 "): play: mug mismatch %x %x\r\n", + u3l_log("pier: (%" PRIu64 "): play: mug mismatch %x %x", tac_u->eve_d, tac_u->mug_l, mug_l); @@ -1124,7 +1124,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // XX optional // if ( las_l && (las_l != mug_l) ) { - u3l_log("pier: (%" PRIu64 "): play bail: mug mismatch %x %x\r\n", + u3l_log("pier: (%" PRIu64 "): play bail: mug mismatch %x %x", (c3_d)(eve_d - 1ULL), las_l, mug_l); @@ -1135,7 +1135,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, // #if 0 { - u3l_log("pier: (%" PRIu64 "): play: retry\r\n", eve_d); + u3l_log("pier: (%" PRIu64 "): play: retry", eve_d); fon_u.ext_u = tac_u; @@ -1156,7 +1156,7 @@ _pier_on_lord_play_bail(void* ptr_v, u3_info fon_u, } #else { - u3l_log("pier: (%" PRIu64 "): play: bail\r\n", eve_d); + u3l_log("pier: (%" PRIu64 "): play: bail", eve_d); u3_pier_punt_goof("play", dud); { u3_noun wir, tag; @@ -1192,12 +1192,12 @@ _pier_play_init(u3_pier* pir_u, c3_d eve_d) pay_u->eve_d = eve_d; pay_u->sen_d = god_u->eve_d; - u3l_log("---------------- playback starting ----------------\r\n"); + u3l_log("---------------- playback starting ----------------"); if ( (1ULL + god_u->eve_d) == eve_d ) { - u3l_log("pier: replaying event %" PRIu64 "\r\n", eve_d); + u3l_log("pier: replaying event %" PRIu64, eve_d); } else { - u3l_log("pier: replaying events %" PRIu64 "-%" PRIu64 "\r\n", + u3l_log("pier: replaying events %" PRIu64 "-%" PRIu64, (c3_d)(1ULL + god_u->eve_d), eve_d); } @@ -1326,7 +1326,7 @@ _pier_on_lord_cram(void* ptr_v) // XX temporary hack // if ( u3_psat_play == pir_u->sat_e ) { - u3l_log("pier: cram complete, shutting down\r\n"); + u3l_log("pier: cram complete, shutting down"); u3_pier_bail(pir_u); exit(0); } @@ -1355,7 +1355,7 @@ _pier_on_lord_exit(void* ptr_v) pir_u->god_u = 0; if ( u3_psat_done != pir_u->sat_e ) { - u3l_log("pier: serf shutdown unexpected\r\n"); + u3l_log("pier: serf shutdown unexpected"); u3_pier_bail(pir_u); } // if we made it all the way here, it's our jab to wrap up @@ -1416,10 +1416,10 @@ _pier_on_lord_live(void* ptr_v) // if ( u3_Host.ops_u.til_c ) { if ( 1 == sscanf(u3_Host.ops_u.til_c, "%" PRIu64 "", &eve_d) ) { - u3l_log("pier: replay till %" PRIu64 "\r\n", eve_d); + u3l_log("pier: replay till %" PRIu64, eve_d); } else { - u3l_log("pier: ignoring invalid replay barrier '%s'\r\n", + u3l_log("pier: ignoring invalid replay barrier '%s'", u3_Host.ops_u.til_c); eve_d = log_u->dun_d; } @@ -1443,51 +1443,51 @@ u3_pier_info(u3_pier* pir_u) { switch ( pir_u->sat_e ) { default: { - u3l_log("pier: unknown state: %u\r\n", pir_u->sat_e); + u3l_log("pier: unknown state: %u", pir_u->sat_e); } break; case u3_psat_init: { - u3l_log("pier: init\n"); + u3l_log("pier: init"); } break; case u3_psat_boot: { - u3l_log("pier: boot\n"); + u3l_log("pier: boot"); } break; case u3_psat_play: { - u3l_log("pier: play\n"); + u3l_log("pier: play"); { u3_play* pay_u = pir_u->pay_u; - u3l_log(" target: %" PRIu64 "\n", pay_u->eve_d); - u3l_log(" sent: %" PRIu64 "\n", pay_u->sen_d); - u3l_log(" read: %" PRIu64 "\n", pay_u->req_d); + u3l_log(" target: %" PRIu64, pay_u->eve_d); + u3l_log(" sent: %" PRIu64, pay_u->sen_d); + u3l_log(" read: %" PRIu64, pay_u->req_d); } } break; case u3_psat_work: { - u3l_log("pier: work\n"); + u3l_log("pier: work"); { u3_work* wok_u = pir_u->wok_u; - u3l_log(" effects: released=%" PRIu64 "\n", wok_u->fec_u.rel_d); + u3l_log(" effects: released=%" PRIu64, wok_u->fec_u.rel_d); if ( wok_u->fec_u.ext_u ) { if ( wok_u->fec_u.ext_u != wok_u->fec_u.ent_u ) { - u3l_log(" pending %" PRIu64 "-%" PRIu64 "\n", + u3l_log(" pending %" PRIu64 "-%" PRIu64, wok_u->fec_u.ext_u->eve_d, wok_u->fec_u.ent_u->eve_d); } else { - u3l_log(" pending %" PRIu64 "\n", wok_u->fec_u.ext_u->eve_d); + u3l_log(" pending %" PRIu64, wok_u->fec_u.ext_u->eve_d); } } if ( wok_u->wal_u ) { - u3l_log(" wall: %" PRIu64 "\n", wok_u->wal_u->eve_d); + u3l_log(" wall: %" PRIu64, wok_u->wal_u->eve_d); } if ( wok_u->car_u ) { @@ -1497,7 +1497,7 @@ u3_pier_info(u3_pier* pir_u) } break; case u3_psat_done: { - u3l_log("pier: done\n"); + u3l_log("pier: done"); } break; } @@ -1611,7 +1611,7 @@ u3_pier_stay(c3_w wag_w, u3_noun pax) if ( c3y == u3_Host.ops_u.veb ) { FILE* fil_u = u3_term_io_hija(); u3_lmdb_stat(pir_u->log_u->mdb_u, fil_u); - u3_term_io_loja(1); + u3_term_io_loja(1, fil_u); } u3z(pax); @@ -2221,10 +2221,12 @@ _pier_dump_wall(FILE* fil_u, u3_noun wol) while ( u3_nul != wal ) { _pier_dump_tape(fil_u, u3k(u3h(wal))); - putc(13, fil_u); - putc(10, fil_u); - wal = u3t(wal); + + if ( u3_nul != wal ) { + putc(13, fil_u); + putc(10, fil_u); + } } u3z(wol); @@ -2250,6 +2252,7 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) case 3: fprintf(fil_u, "\033[31m>>> "); break; case 2: fprintf(fil_u, "\033[33m>> "); break; case 1: fprintf(fil_u, "\033[32m> "); break; + case 0: fprintf(fil_u, "\033[90m" ); break; } } else { @@ -2266,8 +2269,6 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) if ( 0 == u3A->roc ) { if ( c3__leaf == u3h(tac) ) { _pier_dump_tape(fil_u, u3k(u3t(tac))); - putc(13, fil_u); - putc(10, fil_u); } } // We are calling nock here, but hopefully need no protection. @@ -2284,7 +2285,7 @@ u3_pier_tank(c3_l tab_l, c3_w pri_w, u3_noun tac) fflush(fil_u); - u3_term_io_loja(0); + u3_term_io_loja(0, fil_u); u3z(blu); u3z(tac); } @@ -2314,12 +2315,12 @@ u3_pier_punt_goof(const c3_c* cap_c, u3_noun dud) u3x_cell(dud, &mot, &tan); - u3l_log("\n"); + u3l_log(""); u3_pier_punt(0, u3qb_flop(tan)); { c3_c* mot_c = u3r_string(mot); - u3l_log("%s: bail: %%%s\r\n", cap_c, mot_c); + u3l_log("%s: bail: %%%s", cap_c, mot_c); c3_free(mot_c); } @@ -2335,7 +2336,7 @@ u3_pier_punt_ovum(const c3_c* cap_c, u3_noun wir, u3_noun tag) u3_noun riw = u3do("spat", wir); c3_c* wir_c = u3r_string(riw); - u3l_log("%s: %%%s event on %s failed\r\n\n", cap_c, tag_c, wir_c); + u3l_log("%s: %%%s event on %s failed", cap_c, tag_c, wir_c); c3_free(tag_c); c3_free(wir_c); diff --git a/pkg/urbit/vere/save.c b/pkg/urbit/vere/save.c index b2fc5b390..956d750cc 100644 --- a/pkg/urbit/vere/save.c +++ b/pkg/urbit/vere/save.c @@ -25,7 +25,7 @@ u3_save_ef_chld(u3_pier *pir_u) /* modified for cases with no pid_w */ - u3l_log("checkpoint: complete %d\n", sav_u->pid_w); + u3l_log("checkpoint: complete %d", sav_u->pid_w); pid_w = wait(&loc_i); if (0 != sav_u->pid_w) { c3_assert(pid_w == sav_u->pid_w); diff --git a/pkg/urbit/vere/walk.c b/pkg/urbit/vere/walk.c index 5c113cbac..3e0bb4a8c 100644 --- a/pkg/urbit/vere/walk.c +++ b/pkg/urbit/vere/walk.c @@ -37,7 +37,7 @@ u3_walk_safe(c3_c* pas_c) c3_y* pad_y; if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - // u3l_log("%s: %s\n", pas_c, strerror(errno)); + // u3l_log("%s: %s", pas_c, strerror(errno)); return 0; } fln_w = buf_b.st_size; @@ -69,7 +69,7 @@ u3_walk_load(c3_c* pas_c) c3_y* pad_y; if ( (fid_i < 0) || (fstat(fid_i, &buf_b) < 0) ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); + u3l_log("%s: %s", pas_c, strerror(errno)); return u3m_bail(c3__fail); } fln_w = buf_b.st_size; @@ -117,7 +117,7 @@ _walk_mkdirp(c3_c* bas_c, u3_noun pax) pax_c[len_w] = '\0'; if ( 0 != mkdir(pax_c, 0755) && EEXIST != errno ) { - u3l_log("error mkdiring %s: %s\n", pax_c, strerror(errno)); + u3l_log("error mkdiring %s: %s", pax_c, strerror(errno)); u3m_bail(c3__fail); } @@ -140,7 +140,7 @@ u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) return u3_walk_save(pas_c, tim, pad, 0, u3_nul); } - u3l_log("%s: %s\n", pas_c, strerror(errno)); + u3l_log("%s: %s", pas_c, strerror(errno)); u3m_bail(c3__fail); } @@ -155,7 +155,7 @@ u3_walk_save(c3_c* pas_c, u3_noun tim, u3_atom pad, c3_c* bas_c, u3_noun pax) c3_free(pad_y); if ( rit_w != fln_w ) { - u3l_log("%s: %s\n", pas_c, strerror(errno)); + u3l_log("%s: %s", pas_c, strerror(errno)); u3m_bail(c3__fail); } @@ -185,7 +185,7 @@ _walk_in(const c3_c* dir_c, c3_w len_w) struct dirent* out_n; if ( u3_readdir_r(dir_d, &ent_n, &out_n) != 0 ) { - u3l_log("%s: %s\n", dir_c, strerror(errno)); + u3l_log("%s: %s", dir_c, strerror(errno)); break; } else if ( !out_n ) { @@ -267,7 +267,7 @@ u3_walk(const c3_c* dir_c, u3_noun old) struct stat buf_b; if ( 0 != stat(dir_c, &buf_b) ) { - u3l_log("can't stat %s\n", dir_c); + u3l_log("can't stat %s", dir_c); // return u3m_bail(c3__fail); c3_assert(0); } diff --git a/pkg/urbit/worker/serf.c b/pkg/urbit/worker/serf.c index 79fab1fc6..c8e3e6e51 100644 --- a/pkg/urbit/worker/serf.c +++ b/pkg/urbit/worker/serf.c @@ -244,7 +244,7 @@ _serf_grab(u3_serf* sef_u) u3z(sef_u->sac); sef_u->sac = u3_nul; - u3l_log("\n"); + u3l_log(""); } } @@ -282,7 +282,7 @@ u3_serf_post(u3_serf* sef_u) if ( c3y == sef_u->pac_o ) { u3a_print_memory(stderr, "serf: pack: gained", u3m_pack()); - u3l_log("\n"); + u3l_log(""); sef_u->pac_o = c3n; } } @@ -464,7 +464,7 @@ _serf_poke(u3_serf* sef_u, c3_c* cap_c, c3_w mil_w, u3_noun job) if ( (c3__belt != tag) && (c3__crud != tag) ) { - u3l_log("serf: %s (%" PRIu64 ") %s\r\n", cap_c, sef_u->sen_d, txt_c); + u3l_log("serf: %s (%" PRIu64 ") %s", cap_c, sef_u->sen_d, txt_c); } } #endif @@ -484,7 +484,7 @@ _serf_poke(u3_serf* sef_u, c3_c* cap_c, c3_w mil_w, u3_noun job) clr_w = ms_w > 1000 ? 1 : ms_w < 100 ? 2 : 3; // red, green, yellow if ( clr_w != 2 ) { - u3l_log("\x1b[3%dm%%%s (%" PRIu64 ") %4d.%02dms\x1b[0m\n", + u3l_log("\x1b[3%dm%%%s (%" PRIu64 ") %4d.%02dms\x1b[0m", clr_w, txt_c, sef_u->sen_d, ms_w, (int) (d0.tv_usec % 1000) / 10); } @@ -523,7 +523,7 @@ _serf_work(u3_serf* sef_u, c3_w mil_w, u3_noun job) // if ( u3_blip == u3h(gon) ) { u3_noun vir = _serf_sure(sef_u, pre_w, u3k(u3t(gon))); - + u3z(gon); u3z(job); return u3nc(c3__done, u3nt(u3i_chubs(1, &sef_u->dun_d), sef_u->mug_l, @@ -901,7 +901,7 @@ u3_serf_live(u3_serf* sef_u, u3_noun com, u3_noun* ret) return c3n; } - u3l_log("serf (%" PRIu64 "): saving rock\r\n", sef_u->dun_d); + u3l_log("serf (%" PRIu64 "): saving rock", sef_u->dun_d); if ( c3n == u3u_cram(sef_u->dir_c, eve_d) ) { fprintf(stderr, "serf (%" PRIu64 "): unable to jam state\r\n", eve_d); @@ -1045,7 +1045,7 @@ u3_serf_writ(u3_serf* sef_u, u3_noun wit, u3_noun* pel) static u3_noun _serf_ripe(u3_serf* sef_u) { - // u3l_log("serf: ripe %" PRIu64 "\r\n", sef_u->dun_d); + // u3l_log("serf: ripe %" PRIu64, sef_u->dun_d); sef_u->mug_l = ( 0 == sef_u->dun_d ) ? 0 From bbb1a716bf0d0c0111ed0b02073e9e82063adcdc Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 16 Feb 2022 01:04:08 +0100 Subject: [PATCH 002/249] ph: link missing lib Must've gotten lost during merge or something. --- pkg/arvo/lib/ph/util.hoon | 1 + 1 file changed, 1 insertion(+) create mode 120000 pkg/arvo/lib/ph/util.hoon diff --git a/pkg/arvo/lib/ph/util.hoon b/pkg/arvo/lib/ph/util.hoon new file mode 120000 index 000000000..ec423efc0 --- /dev/null +++ b/pkg/arvo/lib/ph/util.hoon @@ -0,0 +1 @@ +../../../base-dev/lib/ph/util.hoon \ No newline at end of file From c4f38032cec2418f7792f6d15bdeec8a124a352b Mon Sep 17 00:00:00 2001 From: fang Date: Sun, 20 Feb 2022 15:35:55 -0600 Subject: [PATCH 003/249] pkg: move /lib/dill into base-dev, include it Landscape desk needed it, but didn't have it. --- pkg/arvo/lib/dill.hoon | 94 +------------------------------------ pkg/base-dev/lib/dill.hoon | 93 ++++++++++++++++++++++++++++++++++++ pkg/landscape/lib/dill.hoon | 1 + 3 files changed, 95 insertions(+), 93 deletions(-) mode change 100644 => 120000 pkg/arvo/lib/dill.hoon create mode 100644 pkg/base-dev/lib/dill.hoon create mode 120000 pkg/landscape/lib/dill.hoon diff --git a/pkg/arvo/lib/dill.hoon b/pkg/arvo/lib/dill.hoon deleted file mode 100644 index d4cecdf14..000000000 --- a/pkg/arvo/lib/dill.hoon +++ /dev/null @@ -1,93 +0,0 @@ -:: 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 'r'^(numb r.p.blit) 'c'^(numb c.p.blit) ~) - %put a+(turn p.blit |=(c=@c s+(tuft c))) - %nel b+& - %url s+p.blit - %wyp b+& - :: - %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 'r'^ni 'c'^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) - -- - -- --- \ No newline at end of file diff --git a/pkg/arvo/lib/dill.hoon b/pkg/arvo/lib/dill.hoon new file mode 120000 index 000000000..f9c2362f0 --- /dev/null +++ b/pkg/arvo/lib/dill.hoon @@ -0,0 +1 @@ +../../base-dev/lib/dill.hoon \ No newline at end of file diff --git a/pkg/base-dev/lib/dill.hoon b/pkg/base-dev/lib/dill.hoon new file mode 100644 index 000000000..d4cecdf14 --- /dev/null +++ b/pkg/base-dev/lib/dill.hoon @@ -0,0 +1,93 @@ +:: 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 'r'^(numb r.p.blit) 'c'^(numb c.p.blit) ~) + %put a+(turn p.blit |=(c=@c s+(tuft c))) + %nel b+& + %url s+p.blit + %wyp b+& + :: + %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 'r'^ni 'c'^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) + -- + -- +-- \ No newline at end of file diff --git a/pkg/landscape/lib/dill.hoon b/pkg/landscape/lib/dill.hoon new file mode 120000 index 000000000..f9c2362f0 --- /dev/null +++ b/pkg/landscape/lib/dill.hoon @@ -0,0 +1 @@ +../../base-dev/lib/dill.hoon \ No newline at end of file From 3120681b2bd5abc59645dbee6b4fac01cd55ce4d Mon Sep 17 00:00:00 2001 From: fang Date: Sun, 20 Feb 2022 15:53:53 -0600 Subject: [PATCH 004/249] sole: properly support multiple sessions We update the sole protocol to more cleanly support multiple sessions. Primarily, the "sole id" is updated to be a [@p @ta] instead of a @ta, and it is now generated based off the connected dill session, rather than statically. This change ripples out to applications that support the sole protocol: the subscription path becomes /sole/[ship]/[session] (as opposed to /sole/[per-ship-constant]), and %sole-action pokes include the new id as well. For shoe agents, this means (at the very least) updating the function signatures of the shoe arms. /lib/sole has been updated to include helper functions for parsing a sole-id from a subscription path, and turning a sole-id into its corresponding path. It also has a function to aid in migrating old sole-ids. Existing sole agents are made to kick any known open sessions, forcing a resubscribe by drum, so that they may use exclusively the new format going forward. Third-party agents are recommended to do the same. Note that some functionality, such as |link, still operates exclusively on the default session. Improvements in this area to follow soon. --- pkg/arvo/app/dojo.hoon | 61 ++++++++++++++++++------- pkg/arvo/app/shoe.hoon | 8 ++-- pkg/arvo/lib/hood/drum.hoon | 41 ++++++++++------- pkg/base-dev/lib/shoe.hoon | 81 +++++++++++++++++++++------------ pkg/base-dev/lib/sole.hoon | 24 ++++++++++ pkg/base-dev/sur/sole.hoon | 3 +- pkg/landscape/app/chat-cli.hoon | 55 ++++++++++++++++------ 7 files changed, 193 insertions(+), 80 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index 938d9f25a..c8fbd49d7 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -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 @@ -1019,13 +1019,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 ^+ . @@ -1533,21 +1534,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 @@ -1574,9 +1601,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)] -- :: @@ -1630,8 +1658,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) @@ -1643,7 +1670,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 @@ -1652,13 +1679,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) == diff --git a/pkg/arvo/app/shoe.hoon b/pkg/arvo/app/shoe.hoon index 4b0538ad3..0e827f57c 100644 --- a/pkg/arvo/app/shoe.hoon +++ b/pkg/arvo/app/shoe.hoon @@ -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) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index c50f5a818..67abf801a 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -105,14 +105,15 @@ :: :: :: |% ++ en-gill :: gill to wire - |= gyl=gill:gall + |= [ses=@tas gyl=gill:gall] ^- wire - ::TODO include session? - [%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) [(slav %p i.way) i.t.way]) + |= way=wire ^- [@tas gill:gall] + ?> ?=([@ @ ?(~ [@ ~])] way) + :- ?~(t.t.way %$ i.t.t.way) + [(slav %p i.way) i.t.way] -- :: |= [hid=bowl:gall state] @@ -135,10 +136,15 @@ =. 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) + =^ gyl this (open way) ?: (se-aint gyl) +>.$ (se-diff gyl fec) :: @@ -228,7 +234,7 @@ ++ reap-phat :: ack connect |= [way=wire saw=(unit tang)] =< se-abet =< se-view - =+ gyl=(de-gill way) + =^ gyl this (open way) ?~ saw (se-join gyl) :: Don't print stack trace because we probably just crashed to @@ -240,7 +246,7 @@ |= [way=wire saw=(unit tang)] =< se-abet =< se-view ?~ saw +> - =+ gyl=(de-gill way) + =^ gyl this (open way) ?: (se-aint gyl) +>.$ %- se-dump:(se-drop:(se-pull gyl) & gyl) :_ u.saw @@ -264,7 +270,7 @@ ++ quit-phat :: |= way=wire =< se-abet =< se-view - =+ gyl=(de-gill way) + =^ gyl this (open way) ~& [%drum-quit src.hid gyl] (se-drop %| gyl) :: :: :: @@ -279,7 +285,11 @@ :_ (flop moz) =/ =dill-blit:dill ?~(t.biz i.biz [%mor (flop biz)]) ::TODO remove /drum after dill cleans up - [%give %fact ~[/drum /dill/[ses]] %dill-blit !>(dill-blit)] + ::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 !>(dill-blit)] :: ++ se-adze :: update connections ^+ . @@ -518,19 +528,18 @@ :: ++ 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>}" - ::TODO include session - =/ =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 @@ -555,7 +564,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) diff --git a/pkg/base-dev/lib/shoe.hoon b/pkg/base-dev/lib/shoe.hoon index cd4ab18db..856a4d782 100644 --- a/pkg/base-dev/lib/shoe.hoon +++ b/pkg/base-dev/lib/shoe.hoon @@ -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 diff --git a/pkg/base-dev/lib/sole.hoon b/pkg/base-dev/lib/sole.hoon index 66684668a..ad6b74962 100644 --- a/pkg/base-dev/lib/sole.hoon +++ b/pkg/base-dev/lib/sole.hoon @@ -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) -- diff --git a/pkg/base-dev/sur/sole.hoon b/pkg/base-dev/sur/sole.hoon index e942bccb8..f8141f701 100644 --- a/pkg/base-dev/sur/sole.hoon +++ b/pkg/base-dev/sur/sole.hoon @@ -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 diff --git a/pkg/landscape/app/chat-cli.hoon b/pkg/landscape/app/chat-cli.hoon index 4398cc7e8..a5aa5dee2 100644 --- a/pkg/landscape/app/chat-cli.hoon +++ b/pkg/landscape/app/chat-cli.hoon @@ -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 From da47cfb08e8e9044790633a76892c6f0794af611 Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 21 Feb 2022 12:11:40 -0600 Subject: [PATCH 005/249] drum: correctly initialize session in +prep --- pkg/arvo/lib/hood/drum.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 67abf801a..1448d649e 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -132,7 +132,7 @@ :: ++ prep |= s=@tas - =. ses ses + =. ses s =. dev (~(gut by bin) ses *source) this :: From bb11c74278b6619652b34093a77d77d91ab2058e Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 28 Feb 2022 16:24:41 -0600 Subject: [PATCH 006/249] drum: don't drop state during se-subze Previously, it was putting new session state into the old map, preserving only the state of the last session in the map. --- pkg/arvo/lib/hood/drum.hoon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 1448d649e..0f1aa6ce4 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -315,7 +315,7 @@ =< .(con +>) |: $:,[[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) ses dev.xeno)) + xeno(ses ses.con, dev dev.con, bin (~(put by bin.xeno) ses dev.xeno)) :: ++ se-subze-local ^+ . From bf97b8da38a84e68534faae1c2be96f645dd93d2 Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 28 Feb 2022 16:27:29 -0600 Subject: [PATCH 007/249] drum: move +se-view call into +se-abet We practically always do se-abet:se-view anyway. --- pkg/arvo/lib/hood/drum.hoon | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 0f1aa6ce4..3019b8826 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -143,7 +143,7 @@ :: ++ diff-sole-effect-phat :: app event |= [way=wire fec=sole-effect] - =< se-abet =< se-view + =< se-abet =^ gyl this (open way) ?: (se-aint gyl) +>.$ (se-diff gyl fec) @@ -154,7 +154,7 @@ (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 "[{}, driving {}]") :: ++ poke-dill @@ -163,7 +163,7 @@ :: ++ poke-dill-belt :: terminal event |= bet=dill-belt:dill - =< se-abet =< se-view + =< se-abet (se-belt bet) :: ++ poke-dill-blit :: terminal output @@ -172,12 +172,12 @@ :: ++ poke-link :: connect app |= gyl=gill:gall - =< se-abet =< se-view + =< se-abet (se-link gyl) :: ++ poke-unlink :: disconnect app |= gyl=gill:gall - =< se-abet =< se-view + =< se-abet (se-drop:(se-pull gyl) & gyl) :: ++ poke-exit :: shutdown @@ -201,7 +201,7 @@ :: ++ 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) @@ -233,7 +233,7 @@ :: ++ reap-phat :: ack connect |= [way=wire saw=(unit tang)] - =< se-abet =< se-view + =< se-abet =^ gyl this (open way) ?~ saw (se-join gyl) @@ -244,7 +244,7 @@ :: ++ take-coup-phat :: ack poke |= [way=wire saw=(unit tang)] - =< se-abet =< se-view + =< se-abet ?~ saw +> =^ gyl this (open way) ?: (se-aint gyl) +>.$ @@ -269,7 +269,7 @@ :: ++ quit-phat :: |= way=wire - =< se-abet =< se-view + =< se-abet =^ gyl this (open way) ~& [%drum-quit src.hid gyl] (se-drop %| gyl) @@ -278,7 +278,7 @@ :: :: :: ++ se-abet :: resolve ^- (quip card:agent:gall state) - =. . se-subze:se-adze + =. . se-view:se-subze:se-adze :_ sat(bin (~(put by bin) ses dev)) ^- (list card:agent:gall) ?~ biz (flop moz) From 41a063867b52ebfc87d97b837afacf913c263e32 Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 28 Feb 2022 16:41:49 -0600 Subject: [PATCH 008/249] dojo: auto-fill generator's named drum-session arg If a generator has a named argument named "drum-session", and the caller doesn't specify a value for it, dojo auto-fills it with the current drum session identifier. --- pkg/arvo/app/dojo.hoon | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/arvo/app/dojo.hoon b/pkg/arvo/app/dojo.hoon index c8fbd49d7..bf0c24dd4 100644 --- a/pkg/arvo/app/dojo.hoon +++ b/pkg/arvo/app/dojo.hoon @@ -821,12 +821,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) ~) From f6f2fcfcac5ace02e7d451efad9d790aba1003e1 Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 28 Feb 2022 16:45:56 -0600 Subject: [PATCH 009/249] drum: make eel per-session This allows us to have different apps connected to different sessions. --- pkg/arvo/lib/hood/drum.hoon | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 3019b8826..27792b56d 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -15,8 +15,7 @@ +$ state-2 [%2 pith-2] :: +$ pith-5 - $: eel=(set gill:gall) :: connect to - bin=(map @ source) :: terminals + $: bin=(map @ source) :: terminals == :: +$ pith-4 @@ -75,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 == :: @@ -205,12 +205,12 @@ =? old ?=(%2 -.old) [%4 [eel bin]:old] =? old ?=(%3 -.old) [%4 [eel bin]:old] =? old ?=(%4 -.old) - :+ %5 eel.old - |^ (~(run by bin.old) source-4-to-5) + |^ 5+(~(run by bin.old) source-4-to-5) ++ source-4-to-5 - |= s=source-4 + |= source-4 ^- source - s(fug (~(run by fug.s) |=(t=(unit target-4) (bind t target-4-to-5)))) + =; 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 From e53cb4a205c212e121d1c815047711ee1c775c51 Mon Sep 17 00:00:00 2001 From: fang Date: Mon, 28 Feb 2022 16:47:49 -0600 Subject: [PATCH 010/249] drum: make |un/link work for non-default sessions --- pkg/arvo/gen/hood/link.hoon | 4 +++- pkg/arvo/gen/hood/unlink.hoon | 4 +++- pkg/arvo/lib/hood/drum.hoon | 2 +- pkg/arvo/mar/drum-put.hoon | 7 +++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/arvo/gen/hood/link.hoon b/pkg/arvo/gen/hood/link.hoon index 5fe183279..5e14126a1 100644 --- a/pkg/arvo/gen/hood/link.hoon +++ b/pkg/arvo/gen/hood/link.hoon @@ -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] diff --git a/pkg/arvo/gen/hood/unlink.hoon b/pkg/arvo/gen/hood/unlink.hoon index d7bc509b0..fc6e1fb01 100644 --- a/pkg/arvo/gen/hood/unlink.hoon +++ b/pkg/arvo/gen/hood/unlink.hoon @@ -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] diff --git a/pkg/arvo/lib/hood/drum.hoon b/pkg/arvo/lib/hood/drum.hoon index 27792b56d..f62143e21 100644 --- a/pkg/arvo/lib/hood/drum.hoon +++ b/pkg/arvo/lib/hood/drum.hoon @@ -128,7 +128,7 @@ ++ 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 diff --git a/pkg/arvo/mar/drum-put.hoon b/pkg/arvo/mar/drum-put.hoon index e6094158e..8fa3773c0 100644 --- a/pkg/arvo/mar/drum-put.hoon +++ b/pkg/arvo/mar/drum-put.hoon @@ -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 -- -- From 998f7d081a4a88b2fe61d6fbda029274c4e3b5b4 Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 2 Mar 2022 17:24:54 -0600 Subject: [PATCH 011/249] dill: fix %shut session deletion +abet would re-insert the session into state, so we just pull the deletion logic outside of the main core. --- pkg/arvo/sys/vane/dill.hoon | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/arvo/sys/vane/dill.hoon b/pkg/arvo/sys/vane/dill.hoon index b7c81afc7..e2c1e4d2e 100644 --- a/pkg/arvo/sys/vane/dill.hoon +++ b/pkg/arvo/sys/vane/dill.hoon @@ -219,10 +219,6 @@ |= [g=gill _..open] (send [%yow g]) :: - ++ shut - ::TODO send a %bye blit? - pull(eye.all (~(del by eye.all) ses)) - :: ++ send :: send action |= bet=dill-belt ^+ +> @@ -384,7 +380,12 @@ =/ nus ~| [%no-session ses] (need (ax hen ses)) - =^ moz all abet:shut:nus + ::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 :: From d98611a04bb3f5aeb87bc154cc9485a72aef3402 Mon Sep 17 00:00:00 2001 From: fang Date: Wed, 2 Mar 2022 17:34:19 -0600 Subject: [PATCH 012/249] webterm: support multiple sessions Fully implements webterm support for multiple dill terminal sessions. Remaining work includes styling, session creation safety (name-wise), and general cleanup. Co-authored-by: tomholford Co-authored-by: liam-fitzgerald --- pkg/interface/webterm/.eslintrc.js | 7 + pkg/interface/webterm/.nvmrc | 1 + pkg/interface/webterm/Buffer.tsx | 276 ++++++++++++++++++ pkg/interface/webterm/Tab.tsx | 44 +++ pkg/interface/webterm/Tabs.tsx | 36 +++ pkg/interface/webterm/app.tsx | 416 +++------------------------- pkg/interface/webterm/constants.ts | 1 + pkg/interface/webterm/index.html | 38 +++ pkg/interface/webterm/lib/blit.ts | 73 +++++ pkg/interface/webterm/lib/stye.ts | 60 ++++ pkg/interface/webterm/lib/theme.ts | 21 ++ pkg/interface/webterm/state.ts | 12 +- pkg/interface/webterm/tsconfig.json | 26 ++ pkg/npm/api/term/lib.ts | 4 +- pkg/npm/api/term/types.ts | 4 +- 15 files changed, 626 insertions(+), 393 deletions(-) create mode 100644 pkg/interface/webterm/.eslintrc.js create mode 100644 pkg/interface/webterm/.nvmrc create mode 100644 pkg/interface/webterm/Buffer.tsx create mode 100644 pkg/interface/webterm/Tab.tsx create mode 100644 pkg/interface/webterm/Tabs.tsx create mode 100644 pkg/interface/webterm/constants.ts create mode 100644 pkg/interface/webterm/lib/blit.ts create mode 100644 pkg/interface/webterm/lib/stye.ts create mode 100644 pkg/interface/webterm/lib/theme.ts create mode 100644 pkg/interface/webterm/tsconfig.json diff --git a/pkg/interface/webterm/.eslintrc.js b/pkg/interface/webterm/.eslintrc.js new file mode 100644 index 000000000..66d65c291 --- /dev/null +++ b/pkg/interface/webterm/.eslintrc.js @@ -0,0 +1,7 @@ +const config = { + "rules": { + "spaced-comment": false, + } +} + +export default config; diff --git a/pkg/interface/webterm/.nvmrc b/pkg/interface/webterm/.nvmrc new file mode 100644 index 000000000..0b77208ae --- /dev/null +++ b/pkg/interface/webterm/.nvmrc @@ -0,0 +1 @@ +16.14.0 \ No newline at end of file diff --git a/pkg/interface/webterm/Buffer.tsx b/pkg/interface/webterm/Buffer.tsx new file mode 100644 index 000000000..d33b2e9ec --- /dev/null +++ b/pkg/interface/webterm/Buffer.tsx @@ -0,0 +1,276 @@ +import { Terminal, ITerminalOptions } from 'xterm'; +import { FitAddon } from 'xterm-addon-fit'; +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 { useDark } from './join'; +import { showBlit, csi, showSlog } from './lib/blit'; + +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 +}; + +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({ 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: { 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; +}; + +const onResize = (session: Session) => () => { + //TODO debounce, if it ever becomes a problem + //TODO test that we only send this to the selected session, + // and that we *do* send it on-selected-change if necessary. + session?.fit.fit(); +}; + +const onInput = (name: string, session: Session, e: string) => { + if (!session) { + return; + } + const term = session.term; + const belts = readInput(term, e); + belts.map((b) => { + api.poke(pokeBelt(name, b)); + }); +}; + +interface BufferProps { + name: string, + selected: boolean, +} + +export default function Buffer({ name, selected }: BufferProps) { + const container = useRef(null); + const dark = useDark(); + + const session: Session = useTermState(s => s.sessions[name]); + + const initSession = useCallback(async (name: string, dark: boolean) => { + console.log('setting up', name); + + // set up xterm terminal + // + const term = new Terminal(termConfig); + term.setOption('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 }; + + // set up event handlers + // + term.onData(e => onInput(name, ses, e)); + term.onBinary(e => onInput(name, ses, e)); + term.onResize((e) => { + api.poke(pokeTask(name, { blew: { w: e.cols, h: e.rows } })); + }); + + // open subscription + // + await api.subscribe({ app: 'herm', path: '/session/'+name+'/view', + event: (e) => { + showBlit(ses.term, e); + if (e.bel && !selected) { + useTermState.getState().set(state => { + state.sessions[name].hasBell = true; + }); + } + //TODO should handle %bye on this higher level though, for deletion + }, + quit: () => { // quit + // TODO show user a message + console.error('oops quit, pls handle'); + } + }); + + useTermState.getState().set((state) => { + state.sessions[name] = ses; + }); + }, []); + + // init session + useEffect(() => { + if(session) { + return; + } + + initSession(name, dark); + }, [name]); + + // on selected change, maybe setup the term, or put it into the container + // + const setContainer = useCallback((containerRef: HTMLDivElement | null) => { + let newContainer = containerRef || container.current; + if(session && newContainer) { + container.current = newContainer; + console.log('newcont', newContainer); + // session.term.open(newContainer); + } else { + console.log('kaboom', session); + } + }, [session]); + + // on-init, open slogstream and fetch existing sessions + // + useEffect(() => { + + window.addEventListener('resize', onResize(session)); + + return () => { + // TODO clean up subs? + window.removeEventListener('resize', onResize(session)); + }; + }, []); + + // on dark mode change, change terminals' theme + // + useEffect(() => { + const theme = makeTheme(dark); + if (session) { + session.term.setOption('theme', theme); + } + if (container.current) { + container.current.style.backgroundColor = theme.background || ''; + } + }, [dark]); + + useEffect(() => { + if (session && selected && !session.term.isOpen) { + session!.term.open(container.current); + session!.fit.fit(); + session!.term.focus(); + session!.term.isOpen = true; + } + }, [selected, session]); + + return ( + !session && !selected ? +