├── tanote ├── sys.kelvin ├── desk.ship ├── mar │ ├── path.hoon │ ├── thread-done.hoon │ ├── thread-fail.hoon │ ├── tape.hoon │ ├── woff2.hoon │ ├── png.hoon │ ├── svg.hoon │ ├── urbit.hoon │ ├── language-server │ │ └── rpc │ │ │ ├── response.hoon │ │ │ ├── request.hoon │ │ │ └── notification.hoon │ ├── story-diff.hoon │ ├── txt-diff.hoon │ ├── atom.hoon │ ├── purl.hoon │ ├── noun.hoon │ ├── htm.hoon │ ├── ship.hoon │ ├── kelvin.hoon │ ├── docket-0.hoon │ ├── hymn.hoon │ ├── belt.hoon │ ├── js.hoon │ ├── urb.hoon │ ├── udon.hoon │ ├── httr.hoon │ ├── umd.hoon │ ├── mime.hoon │ ├── json.hoon │ ├── xml.hoon │ ├── tang.hoon │ ├── html.hoon │ ├── bill.hoon │ ├── json │ │ └── rpc │ │ │ └── response.hoon │ ├── sole │ │ ├── action.hoon │ │ └── effect.hoon │ ├── blit.hoon │ ├── hoon.hoon │ └── story.hoon ├── sur │ ├── verb.hoon │ ├── story.hoon │ ├── spider.hoon │ ├── keygen.hoon │ ├── json │ │ └── rpc.hoon │ ├── settings.hoon │ ├── ring.hoon │ ├── docket.hoon │ ├── bitcoin.hoon │ ├── aquarium.hoon │ ├── language-server.hoon │ ├── asn1.hoon │ ├── hark-store.hoon │ └── sole.hoon ├── desk.docket-0 ├── lib │ ├── skeleton.hoon │ ├── bip39.hoon │ ├── language-server │ │ ├── build.hoon │ │ └── parser.hoon │ ├── mip.hoon │ ├── test.hoon │ ├── default-agent.hoon │ ├── cram.hoon │ ├── primitive-rsa.hoon │ ├── ph │ │ └── util.hoon │ ├── agentio.hoon │ ├── keygen.hoon │ ├── story.hoon │ ├── verb.hoon │ ├── pill.hoon │ ├── bitcoin-utils.hoon │ ├── sole.hoon │ ├── bip │ │ ├── b174.hoon │ │ └── b173.hoon │ ├── dbug.hoon │ ├── server.hoon │ ├── azimuthio.hoon │ ├── tanote.hoon │ ├── strand.hoon │ ├── hark-store.hoon │ ├── docket.hoon │ └── jose.hoon └── gen │ ├── help.hoon │ └── testlib.hoon ├── urbit.aide ├── tanote.md ├── tanote-glob ├── img │ ├── tanote.png │ ├── crop_tanote.png │ ├── tanote_landscape.png │ └── tanote.svg └── index.html ├── screen layout.md ├── ~modnyd-salser 2022-04.md ├── urbsidian.md ├── README.md ├── session init.md ├── icon.md ├── proposal project.md ├── ~hanfel-dovned 2021.md ├── Aide ├── LICENSE ├── %pony.md ├── create desk files.md ├── Funes the memorious.md ├── proposal meta.md ├── tah-noh-tay members.md ├── ~pocwet journal.md ├── publish.md ├── session Gettysburg.md ├── tangents.md ├── create and upload glob.md ├── create desk.md ├── glossary.md ├── announce.md ├── Yarvin 2007.md ├── data structures.md ├── proposal tech.md ├── ~tonned-fampet 2022-06-23.md ├── brainstorm.md ├── session Nocturna.md └── interfaces.md /tanote/sys.kelvin: -------------------------------------------------------------------------------- 1 | [%zuse 418] 2 | -------------------------------------------------------------------------------- /tanote/desk.ship: -------------------------------------------------------------------------------- 1 | ~ponhec-picwen 2 | -------------------------------------------------------------------------------- /urbit.aide: -------------------------------------------------------------------------------- 1 | /n/local/home/jdc/urbit/bus 2 | /n/local/home/jdc/urbit/zod 3 | -------------------------------------------------------------------------------- /tanote.md: -------------------------------------------------------------------------------- 1 | https://github.com/catenate/tanote 2 | 3 | https://i.imgur.com/zTLTq0U.png 4 | 5 | -------------------------------------------------------------------------------- /tanote-glob/img/tanote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catenate/tanote/HEAD/tanote-glob/img/tanote.png -------------------------------------------------------------------------------- /tanote-glob/img/crop_tanote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catenate/tanote/HEAD/tanote-glob/img/crop_tanote.png -------------------------------------------------------------------------------- /tanote-glob/img/tanote_landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/catenate/tanote/HEAD/tanote-glob/img/tanote_landscape.png -------------------------------------------------------------------------------- /tanote/mar/path.hoon: -------------------------------------------------------------------------------- 1 | |_ pax=path 2 | ++ grad %noun 3 | ++ grow 4 | |% 5 | ++ noun pax 6 | -- 7 | ++ grab 8 | |% 9 | ++ noun path 10 | -- 11 | -- 12 | -------------------------------------------------------------------------------- /tanote/mar/thread-done.hoon: -------------------------------------------------------------------------------- 1 | |_ res=* 2 | ++ grab 3 | |% 4 | ++ noun * 5 | -- 6 | ++ grow 7 | |% 8 | ++ noun res 9 | -- 10 | ++ grad %noun 11 | -- 12 | -------------------------------------------------------------------------------- /tanote/mar/thread-fail.hoon: -------------------------------------------------------------------------------- 1 | |_ err=* 2 | ++ grab 3 | |% 4 | ++ noun (pair term tang) 5 | -- 6 | ++ grow 7 | |% 8 | ++ noun err 9 | -- 10 | ++ grad %noun 11 | -- 12 | -------------------------------------------------------------------------------- /tanote/mar/tape.hoon: -------------------------------------------------------------------------------- 1 | |_ tap=tape 2 | ++ grad %noun 3 | ++ grow 4 | |% 5 | ++ noun tap 6 | ++ json s+(crip tap) 7 | -- 8 | ++ grab 9 | |% 10 | ++ noun tape 11 | -- 12 | -- 13 | -------------------------------------------------------------------------------- /tanote/mar/woff2.hoon: -------------------------------------------------------------------------------- 1 | |_ dat=octs 2 | ++ grow 3 | |% 4 | ++ mime [/font/woff2 dat] 5 | -- 6 | ++ grab 7 | |% 8 | ++ mime |=([=mite =octs] octs) 9 | ++ noun octs 10 | -- 11 | ++ grad %mime 12 | -- 13 | -------------------------------------------------------------------------------- /tanote/mar/png.hoon: -------------------------------------------------------------------------------- 1 | |_ dat=@ 2 | ++ grow 3 | |% 4 | ++ mime [/image/png (as-octs:mimes:html dat)] 5 | -- 6 | ++ grab 7 | |% 8 | ++ mime |=([p=mite q=octs] q.q) 9 | ++ noun @ 10 | -- 11 | ++ grad %mime 12 | -- 13 | -------------------------------------------------------------------------------- /tanote/mar/svg.hoon: -------------------------------------------------------------------------------- 1 | |_ dat=@ 2 | ++ grow 3 | |% 4 | ++ mime [/image/'svg+xml' (as-octs:mimes:html dat)] 5 | -- 6 | ++ grab 7 | |% 8 | ++ mime |=([p=mite q=octs] q.q) 9 | ++ noun @ 10 | -- 11 | ++ grad %mime 12 | -- 13 | -------------------------------------------------------------------------------- /screen layout.md: -------------------------------------------------------------------------------- 1 | [[tanote/tanote]] 2 | 3 | General outline of the format of the screen. 4 | 5 | > tags and @ps 6 | > 7 | > names of notes. separated by periods. like sentence fragments. 8 | > 9 | > headers of the text 10 | > 11 | > body of the text 12 | 13 | -------------------------------------------------------------------------------- /tanote/mar/urbit.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/urbit/mar 3 | :: 4 | /? 310 5 | :::: A minimal urbit mark 6 | :: 7 | |_ her=@p 8 | ++ grab 9 | |% 10 | ++ noun @p 11 | -- 12 | ++ grow 13 | |% 14 | ++ noun her 15 | -- 16 | ++ grad %noun 17 | -- 18 | -------------------------------------------------------------------------------- /tanote/sur/verb.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ event 3 | $% [%on-init ~] 4 | [%on-load ~] 5 | [%on-poke =mark] 6 | [%on-watch =path] 7 | [%on-leave =path] 8 | [%on-agent =wire sign=term] 9 | [%on-arvo =wire vane=term sign=term] 10 | [%on-fail =term] 11 | == 12 | -- -------------------------------------------------------------------------------- /~modnyd-salser 2022-04.md: -------------------------------------------------------------------------------- 1 | [[edit text]] 2 | 3 | [[~modnyd-salser]]. [[2022-04]]. The estuary: Non-linear decentralized text editing environment. [[Hackmd]]. https://hackmd.io/@yaHLeQfXQMO1b9SlGU4KOw/rJLoBnVmq 4 | 5 | Also published in [[Urbit]], in the group [[Other life]]: Open group blog. 6 | 7 | -------------------------------------------------------------------------------- /tanote/desk.docket-0: -------------------------------------------------------------------------------- 1 | :~ title+'Tanote' 2 | info+'factious note store' 3 | color+0x4c.f9ff 4 | version+[0 0 2] 5 | website+'https://github.com/catenate/tanote' 6 | license+'MIT' 7 | base+'tanote' 8 | glob-ames+[~zod 0v0] 9 | image+'https://i.imgur.com/llOoZD3.png' 10 | == 11 | -------------------------------------------------------------------------------- /tanote/mar/language-server/rpc/response.hoon: -------------------------------------------------------------------------------- 1 | /- *language-server 2 | /+ lsp=language-server-json 3 | |_ res=all:response 4 | :: 5 | ++ grad %noun 6 | ++ grow 7 | |% 8 | ++ noun res 9 | ++ json (response:enjs:lsp res) 10 | -- 11 | :: 12 | ++ grab 13 | |% 14 | ++ noun all:response 15 | -- 16 | :: 17 | -- 18 | -------------------------------------------------------------------------------- /tanote/mar/language-server/rpc/request.hoon: -------------------------------------------------------------------------------- 1 | /- *language-server 2 | /+ lsp-json=language-server-json 3 | |_ req=all:request 4 | ++ grad %noun 5 | ++ grow 6 | |% 7 | ++ noun req 8 | -- 9 | ++ grab 10 | |% 11 | ++ noun all:request 12 | ++ json 13 | |= jon=^json 14 | (request:dejs:lsp-json jon) 15 | -- 16 | -- 17 | -------------------------------------------------------------------------------- /tanote/mar/story-diff.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: 3 | :: 4 | /- *story 5 | |_ =story-diff 6 | :: 7 | ++ grad %noun 8 | ++ grow 9 | |% 10 | ++ noun story-diff 11 | -- 12 | ++ grab :: convert from 13 | |% 14 | ++ noun ^story-diff :: make from %noun 15 | -- 16 | -- 17 | -------------------------------------------------------------------------------- /tanote/mar/txt-diff.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/txt-diff/mar 3 | :: 4 | /? 310 5 | |_ txt-diff=(urge:clay cord) 6 | :: 7 | ++ grad %noun 8 | ++ grow 9 | |% 10 | ++ noun txt-diff 11 | -- 12 | ++ grab :: convert from 13 | |% 14 | ++ noun (urge:clay cord) :: make from %noun 15 | -- 16 | -- 17 | -------------------------------------------------------------------------------- /tanote/mar/atom.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/atom/mar 3 | :: 4 | /? 310 5 | :: 6 | :::: A minimal atom mark 7 | :: 8 | =, mimes:html 9 | |_ ato=@ 10 | ++ grab |% 11 | ++ noun @ 12 | ++ mime |=([* p=octs] q.p) 13 | -- 14 | ++ grow |% 15 | ++ mime [/application/x-urb-unknown (as-octs ato)] 16 | -- 17 | ++ grad %mime 18 | -- 19 | -------------------------------------------------------------------------------- /tanote-glob/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | tanote 5 | 10 | 11 | 12 |

factious note store

13 | pot 14 | 15 | 16 | -------------------------------------------------------------------------------- /tanote/mar/purl.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/purl/mar 3 | :: 4 | /? 310 5 | =, eyre 6 | |_ url=purl 7 | ++ grad %noun 8 | :: 9 | ++ grow 10 | |% 11 | ++ noun url 12 | ++ hiss [url %get ~ ~] 13 | -- 14 | ++ grab :: convert from 15 | |% 16 | ++ noun purl :: clam from %noun 17 | -- 18 | -- 19 | -------------------------------------------------------------------------------- /tanote/mar/noun.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/noun/mar 3 | :: 4 | /? 310 5 | !: 6 | :::: A minimal noun mark 7 | |_ non=* 8 | ++ grab |% 9 | ++ noun * 10 | -- 11 | ++ grad 12 | |% 13 | ++ form %noun 14 | ++ diff |=(* +<) 15 | ++ pact |=(* +<) 16 | ++ join |=([* *] *(unit *)) 17 | ++ mash |=([[ship desk *] [ship desk *]] `*`~|(%noun-mash !!)) 18 | -- 19 | -- 20 | -------------------------------------------------------------------------------- /tanote/mar/language-server/rpc/notification.hoon: -------------------------------------------------------------------------------- 1 | /- *language-server 2 | /+ lsp-json=language-server-json 3 | |_ not=all:notification 4 | ++ grad %noun 5 | ++ grab 6 | |% 7 | ++ noun all:notification 8 | ++ json 9 | |= jon=^json 10 | (notification:dejs:lsp-json jon) 11 | -- 12 | ++ grow 13 | |% 14 | ++ noun not 15 | ++ json 16 | (notification:enjs:lsp-json not) 17 | -- 18 | -- 19 | -------------------------------------------------------------------------------- /tanote/mar/htm.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/htm/mar 3 | :: 4 | /? 310 5 | |_ own=manx 6 | :: 7 | ++ grad %noun 8 | ++ grow :: convert to 9 | |% 10 | ++ noun own 11 | ++ hymn own 12 | -- 13 | ++ grab |% :: convert from 14 | ++ noun manx :: clam from %noun 15 | -- -- 16 | -------------------------------------------------------------------------------- /tanote/mar/ship.hoon: -------------------------------------------------------------------------------- 1 | |_ s=ship 2 | ++ grad %noun 3 | ++ grow 4 | |% 5 | ++ noun s 6 | ++ json s+(scot %p s) 7 | ++ mime 8 | ^- ^mime 9 | [/text/x-ship (as-octt:mimes:html (scow %p s))] 10 | 11 | -- 12 | ++ grab 13 | |% 14 | ++ noun ship 15 | ++ json (su:dejs:format ;~(pfix sig fed:ag)) 16 | ++ mime 17 | |= [=mite len=@ tex=@] 18 | (slav %p (snag 0 (to-wain:format tex))) 19 | -- 20 | -- 21 | -------------------------------------------------------------------------------- /tanote/sur/story.hoon: -------------------------------------------------------------------------------- 1 | ^? 2 | |% 3 | +$ prose [title=@t body=@t] 4 | +$ proses (set prose) 5 | +$ story (jug tako:clay prose) :: set len > 1 means conflicting messages have been assigned 6 | +$ chapter [tako:clay proses] :: prose entry type 7 | +$ cash $%([%tako p=tako:clay] case) :: used in generators to accept a tako directly as well 8 | +$ story-diff [additions=story deletions=story] 9 | -- -------------------------------------------------------------------------------- /tanote/mar/kelvin.hoon: -------------------------------------------------------------------------------- 1 | =/ weft ,[lal=@tas num=@ud] :: TODO remove after merge 2 | |_ kel=weft 3 | ++ grow 4 | |% 5 | ++ mime `^mime`[/text/x-kelvin (as-octs:mimes:html hoon)] 6 | ++ noun kel 7 | ++ hoon (crip "{<[lal num]:kel>}\0a") 8 | ++ txt (to-wain:format hoon) 9 | -- 10 | ++ grab 11 | |% 12 | ++ noun weft 13 | ++ mime 14 | |= [=mite len=@ud tex=@] 15 | !<(weft (slap !>(~) (ream tex))) 16 | -- 17 | ++ grad %noun 18 | -- 19 | -------------------------------------------------------------------------------- /tanote/sur/spider.hoon: -------------------------------------------------------------------------------- 1 | /+ libstrand=strand 2 | =, strand=strand:libstrand 3 | |% 4 | +$ thread $-(vase _*form:(strand ,vase)) 5 | +$ input [=tid =cage] 6 | +$ tid tid:strand 7 | +$ bowl bowl:strand 8 | +$ http-error 9 | $? %bad-request :: 400 10 | %forbidden :: 403 11 | %nonexistent :: 404 12 | %offline :: 504 13 | == 14 | +$ start-args 15 | $: parent=(unit tid) 16 | use=(unit tid) 17 | =beak 18 | file=term 19 | =vase 20 | == 21 | -- 22 | -------------------------------------------------------------------------------- /urbsidian.md: -------------------------------------------------------------------------------- 1 | [[~sogrum-savluc]]: We could get a decent way towards a minimally-useful version with just some additional UI on linking [[Groups Notebook]] posts. Imagine when you typed a `[[` in a Notebook post you got a dropdown fuzzy-finder for other posts whereby clicking on one filled in the appropriate markdown link to that post. That seems small and easy, yet wildly powerful. I guess we'd need backlinks, too. Trying to shoehorn this all into Notebooks isn't the ideal long-term product, but with a few tweaks it could get really close in the near term. 2 | 3 | -------------------------------------------------------------------------------- /tanote/mar/docket-0.hoon: -------------------------------------------------------------------------------- 1 | /+ dock=docket 2 | |_ =docket:dock 3 | ++ grow 4 | |% 5 | ++ mime 6 | ^- ^mime 7 | [/text/x-docket (as-octt:mimes:html (spit-docket:mime:dock docket))] 8 | ++ noun docket 9 | ++ json (docket:enjs:dock docket) 10 | -- 11 | ++ grab 12 | |% 13 | :: 14 | ++ mime 15 | |= [=mite len=@ud tex=@] 16 | ^- docket:dock 17 | %- need 18 | %- from-clauses:mime:dock 19 | !<((list clause:dock) (slap !>(~) (ream tex))) 20 | 21 | :: 22 | ++ noun docket:dock 23 | -- 24 | ++ grad %noun 25 | -- 26 | -------------------------------------------------------------------------------- /tanote/sur/keygen.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ revision @ud 3 | +$ nodetype tape 4 | +$ mnemonic tape 5 | :: 6 | +$ vault 7 | $: ownership=node 8 | voting=node 9 | management=node 10 | transfer=node 11 | spawn=node 12 | network=uode 13 | == 14 | :: 15 | +$ node [type=nodetype seed=mnemonic keys=wallet] 16 | +$ uode [revi=revision seed=@ux keys=edkeys] 17 | :: 18 | +$ wallet [keys=[public=@ux private=@ux] addr=@ux chain=@ux] 19 | :: 20 | +$ edkeys [auth=keypair crypt=keypair] 21 | :: 22 | +$ keypair [public=@ux secret=@ux] 23 | -- 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tanote 2 | 3 | Tanote (tah-noh-tay) is a [factious](https://www.unqualified-reservations.org/2007/08/uberfact-ultimate-social-verifier/) note store for [Urbit](https://urbit.org/docs/development/develop), which uses tags to present subsets of notes, and sends versions of notes to others. 4 | 5 | I'm currently working through [Hoon School](https://urbit.org/docs/hoon/hoon-school), so this project will be in development for a while, as I figure out how to write it. 6 | 7 | The markdown files in this repository are best viewed in [Obsidian](https://obsidian.md/). 8 | 9 | -------------------------------------------------------------------------------- /tanote/mar/hymn.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/hymn/mar 3 | :: 4 | /? 310 5 | =, mimes:html 6 | =, html 7 | |_ own=manx 8 | :: 9 | ++ grad %noun 10 | ++ grow :: convert to 11 | |% 12 | ++ html (crip (en-xml own)) :: convert to %html 13 | ++ mime [/text/html (as-octs html)] :: convert to %mime 14 | -- 15 | ++ grab |% :: convert from 16 | ++ noun manx :: clam from %noun 17 | -- -- 18 | -------------------------------------------------------------------------------- /tanote/mar/belt.hoon: -------------------------------------------------------------------------------- 1 | :: belt: runtime belt structure 2 | :: 3 | |_ =belt:dill 4 | ++ grad %noun 5 | :: +grab: convert from 6 | :: 7 | ++ grab 8 | |% 9 | ++ noun belt:dill 10 | ++ json 11 | ^- $-(^json belt:dill) 12 | =, dejs:format 13 | %- of 14 | :~ aro+(su (perk %d %l %r %u ~)) 15 | bac+ul 16 | ctl+(cu taft so) 17 | del+ul 18 | met+(cu taft so) 19 | ret+ul 20 | txt+(ar (cu taft so)) 21 | == 22 | -- 23 | :: +grow: convert to 24 | :: 25 | ++ grow 26 | |% 27 | ++ noun belt 28 | -- 29 | -- 30 | -------------------------------------------------------------------------------- /tanote/mar/js.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/js/mar 3 | :: 4 | /? 310 5 | :: 6 | =, eyre 7 | |_ mud=@ 8 | ++ grow 9 | |% 10 | ++ mime [/application/javascript (as-octs:mimes:html (@t mud))] 11 | ++ elem ;script 12 | ;- (trip (@t mud)) 13 | == 14 | ++ hymn ;html:(head:"+{elem}" body) 15 | -- 16 | ++ grab 17 | |% :: convert from 18 | ++ mime |=([p=mite q=octs] (@t q.q)) 19 | ++ noun cord :: clam from %noun 20 | -- 21 | ++ grad %mime 22 | -- 23 | -------------------------------------------------------------------------------- /session init.md: -------------------------------------------------------------------------------- 1 | [[tanote/tanote]] 2 | [[screen layout]] 3 | 4 | The starting screen, before adding any version. The list of @ps comes from %pals. `|` represents the cursor at the start of a text entry field. Struck-out text is changeable. Highlighted text is clickable. Your own id is italic because it’s in the text of the note. The star should be bold, since it is selected by default, and highlighted, since it is clickable. 5 | 6 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==_~ponhec-picwen_== 7 | > 8 | > 9 | > 10 | > by ~ponhec-picwen 11 | > ==to== | 12 | > re | 13 | > ==no== ~~1~~ of 1 14 | > 15 | > | 16 | 17 | -------------------------------------------------------------------------------- /tanote/sur/json/rpc.hoon: -------------------------------------------------------------------------------- 1 | :: json-rpc: protocol types 2 | :: 3 | |% 4 | +$ batch-request 5 | $% [%a p=(list request)] 6 | [%o p=request] 7 | == 8 | :: 9 | +$ request 10 | $: id=@t 11 | jsonrpc=@t 12 | method=@t 13 | params=request-params 14 | == 15 | :: 16 | +$ request-params 17 | $% [%list (list json)] 18 | [%map (map @t json)] 19 | [%object (list (pair @t json))] 20 | == 21 | +$ response 22 | $~ [%fail *httr:eyre] 23 | $% [%result id=@t res=json] 24 | [%error id=@t code=@t message=@t] ::TODO data? 25 | [%fail hit=httr:eyre] 26 | [%batch bas=(list response)] 27 | == 28 | -- 29 | -------------------------------------------------------------------------------- /tanote/mar/urb.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/elem/urb/mar 3 | :: 4 | /? 310 5 | =, mimes:html 6 | =, html 7 | |_ own=manx 8 | :: 9 | ++ grad %noun 10 | ++ grow :: convert to 11 | |% 12 | ++ hymn ;html:(head body:"+{own}") :: convert to %hymn 13 | ++ html (crip (en-xml hymn)) :: convert to %html 14 | ++ mime [/text/html (as-octs html)] :: convert to %mime 15 | -- 16 | ++ grab |% :: convert from 17 | ++ noun manx :: clam from %noun 18 | -- -- 19 | -------------------------------------------------------------------------------- /tanote/mar/udon.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/udon/mar 3 | :: 4 | /+ cram 5 | :: 6 | |_ mud=@t 7 | ++ grow 8 | |% 9 | ++ mime [/text/x-unmark (as-octs:mimes:html mud)] 10 | ++ txt 11 | (to-wain:format mud) 12 | ++ elem 13 | ^- manx 14 | =, cram 15 | elm:(static (ream mud)) 16 | ++ front :: XX performance, types 17 | ^- (map term knot) 18 | %- ~(run by inf:(static:cram (ream mud))) 19 | |= a=dime ^- cord 20 | ?+ (end 3 p.a) (scot a) 21 | %t q.a 22 | == 23 | -- 24 | ++ grab 25 | |% 26 | ++ mime |=((pair mite octs) q.q) 27 | ++ noun @t 28 | ++ txt of-wain:format 29 | -- 30 | ++ grad %txt 31 | -- 32 | -------------------------------------------------------------------------------- /tanote/mar/httr.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/httr/mar 3 | :: 4 | /? 310 5 | :: 6 | =, eyre 7 | =, format 8 | =, html 9 | |_ hit=httr 10 | ++ grad %noun 11 | ++ grow |% ++ wall (turn wain trip) 12 | ++ wain (to-wain cord) 13 | ++ json (need (de-json cord)) 14 | ++ cord q:octs 15 | ++ noun hit 16 | ++ octs 17 | ~| hit 18 | ?> =(2 (div p.hit 100)) 19 | (need r.hit) 20 | -- 21 | ++ grab :: convert from 22 | |% 23 | ++ noun httr :: clam from %noun 24 | -- 25 | -- 26 | -------------------------------------------------------------------------------- /tanote/mar/umd.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/umd/mar 3 | :: 4 | /+ cram 5 | :: 6 | |_ mud=@t 7 | ++ grow 8 | |% 9 | ++ mime [/text/x-unmark (as-octs:mimes:html mud)] 10 | ++ txt 11 | (to-wain:format mud) 12 | ++ elem 13 | ^- manx 14 | =, cram 15 | elm:(static (ream mud)) 16 | ++ front :: XX performance, types 17 | ^- (map term knot) 18 | %- ~(run by inf:(static:cram (ream mud))) 19 | |= a=dime ^- cord 20 | ?+ (end 3 p.a) (scot a) 21 | %t q.a 22 | == 23 | -- 24 | ++ grab 25 | |% 26 | ++ mime |=((pair mite octs) q.q) 27 | ++ noun @t 28 | ++ txt of-wain:format 29 | -- 30 | ++ grad %txt 31 | ++ garb /down 32 | -- 33 | -------------------------------------------------------------------------------- /tanote/mar/mime.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/mime/mar 3 | :: 4 | /? 310 5 | :: 6 | |_ own=mime 7 | ++ grow 8 | ^? 9 | |% 10 | ++ jam `@`q.q.own 11 | -- 12 | :: 13 | ++ grab :: convert from 14 | ^? 15 | |% 16 | ++ noun mime :: clam from %noun 17 | ++ tape 18 | |=(a=_"" [/application/x-urb-unknown (as-octt:mimes:html a)]) 19 | -- 20 | ++ grad 21 | ^? 22 | |% 23 | ++ form %mime 24 | ++ diff |=(mime +<) 25 | ++ pact |=(mime +<) 26 | ++ join |=([mime mime] `(unit mime)`~) 27 | ++ mash 28 | |= [[ship desk mime] [ship desk mime]] 29 | ^- mime 30 | ~|(%mime-mash !!) 31 | -- 32 | -- 33 | -------------------------------------------------------------------------------- /icon.md: -------------------------------------------------------------------------------- 1 | ![[crop_tanote.png]] 2 | 3 | Small PNG from drawshield. Three stacked horizontal sections. Top: vert, hash sable. Middle: or, bar sable. Bottom: celestial azure, v sable. Alternately, arrow fletched facing downward sable. 4 | 5 | Crop to remove bottom section. 6 | 7 | Color picker says the code for the bottom section is 4cf9ff. This apparently doesn't quite match, or landscape does something to the bubble around the name to make it slightly lighter. 8 | 9 | ## blazon 10 | 11 | Tierced-in-fess vert and or and celestial azure, in chief a letter "#" sable shown slightly lower, in fess point a letter "|" sable shown very much smaller, in base point the letter "v" sable shown much lower, drawn in a square shape 12 | 13 | -------------------------------------------------------------------------------- /tanote/mar/json.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/json/mar 3 | :: 4 | /? 310 5 | :: 6 | :::: compute 7 | :: 8 | =, eyre 9 | =, format 10 | =, html 11 | |_ jon=json 12 | :: 13 | ++ grow :: convert to 14 | |% 15 | ++ mime [/application/json (as-octs:mimes -:txt)] :: convert to %mime 16 | ++ txt [(crip (en-json jon))]~ 17 | -- 18 | ++ grab 19 | |% :: convert from 20 | ++ mime |=([p=mite q=octs] (fall (rush (@t q.q) apex:de-json) *json)) 21 | ++ noun json :: clam from %noun 22 | ++ numb numb:enjs 23 | ++ time time:enjs 24 | -- 25 | ++ grad %mime 26 | -- 27 | -------------------------------------------------------------------------------- /tanote/mar/xml.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/xml/mar 3 | :: 4 | /? 310 5 | :: 6 | :::: compute 7 | :: 8 | =, mimes:html 9 | =, html 10 | |_ xml=@t 11 | :: 12 | ++ grad %mime 13 | ++ grow :: convert to 14 | |% :: 15 | ++ mime [/application/xml (as-octs xml)] :: to %mime 16 | ++ hymn (need (de-xml xml)) :: to %hymn 17 | -- :: 18 | ++ grab |% :: convert from 19 | ++ noun @t :: clam from %noun 20 | ++ mime |=([p=mite q=octs] q.q) :: retrieve form %mime 21 | -- -- 22 | -------------------------------------------------------------------------------- /tanote/mar/tang.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/tang/mar 3 | :: 4 | /? 310 5 | :: 6 | =, format 7 | |_ tan=(list tank) 8 | ++ grad %noun 9 | ++ grow 10 | |% 11 | ++ noun tan 12 | ++ json 13 | =/ result=(each (list ^json) tang) 14 | (mule |.((turn tan tank:enjs:format))) 15 | ?- -.result 16 | %& a+p.result 17 | %| a+[a+[%s '[[output rendering error]]']~]~ 18 | == 19 | :: 20 | ++ elem 21 | =- ;pre:code:"{(of-wall -)}" 22 | ^- wall %- zing ^- (list wall) 23 | (turn (flop tan) |=(a=tank (wash 0^160 a))) 24 | -- 25 | ++ grab :: convert from 26 | |% 27 | ++ noun (list ^tank) :: clam from %noun 28 | ++ tank |=(a=^tank [a]~) 29 | -- 30 | -- 31 | -------------------------------------------------------------------------------- /tanote/mar/html.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/html/mar 3 | :: 4 | /? 310 5 | :: 6 | :::: compute 7 | :: 8 | =, html 9 | |_ htm=@t 10 | ++ grow :: convert to 11 | ^? 12 | |% :: 13 | ++ mime [/text/html (met 3 htm) htm] :: to %mime 14 | ++ hymn (need (de-xml htm)) :: to %hymn 15 | -- :: 16 | ++ grab ^? 17 | |% :: convert from 18 | ++ noun @t :: clam from %noun 19 | ++ mime |=([p=mite q=octs] q.q) :: retrieve form %mime 20 | -- 21 | ++ grad %mime 22 | -- 23 | -------------------------------------------------------------------------------- /proposal project.md: -------------------------------------------------------------------------------- 1 | # Tanote proposal 2 | 3 | ## Project summary 4 | 5 | ### Qualifications 6 | 7 | I recently had a brainstorm that defined this project, and have been inspired to make something that strikes me as Martian. I'm doing this on my own, but I have a Computer Engineering degree and 40 years experience writing software (taught myself BASIC on a TI-99/4A and Logo on a Commodore 64), so I should be able to figure it out. Professionally, I’ve been a software build engineer since 1994, in telecoms, build-tool, financial, and electrical-distribution industries, and I use Inferno over top of whichever laptop OS they give me. 8 | 9 | ### Funding 10 | 11 | I’ll let the Foundation decide how much this project is worth. I hope at least one star, which I would use to get more people into Urbit. 12 | 13 | -------------------------------------------------------------------------------- /tanote/mar/bill.hoon: -------------------------------------------------------------------------------- 1 | |_ bil=(list dude:gall) 2 | ++ grow 3 | |% 4 | ++ mime `^mime`[/text/x-bill (as-octs:mimes:html hoon)] 5 | ++ noun bil 6 | ++ hoon 7 | ^- @t 8 | |^ (crip (of-wall:format (wrap-lines (spit-duz bil)))) 9 | :: 10 | ++ wrap-lines 11 | |= taz=wall 12 | ^- wall 13 | ?~ taz ["~"]~ 14 | :- (weld ":~ " i.taz) 15 | %- snoc :_ "==" 16 | (turn t.taz |=(t=tape (weld " " t))) 17 | :: 18 | ++ spit-duz 19 | |= duz=(list dude:gall) 20 | ^- wall 21 | (turn duz |=(=dude:gall ['%' (trip dude)])) 22 | -- 23 | ++ txt (to-wain:format hoon) 24 | -- 25 | ++ grab 26 | |% 27 | ++ noun (list dude:gall) 28 | ++ mime 29 | |= [=mite len=@ud tex=@] 30 | ~_ tex 31 | !<((list dude:gall) (slap !>(~) (ream tex))) 32 | -- 33 | ++ grad %noun 34 | -- 35 | -------------------------------------------------------------------------------- /tanote/sur/settings.hoon: -------------------------------------------------------------------------------- 1 | /+ *mip 2 | |% 3 | :: 4 | ++ settings-0 5 | =< settings 6 | |% 7 | +$ settings (map key bucket) 8 | +$ bucket (map key val) 9 | +$ val 10 | $% [%s p=@t] 11 | [%b p=?] 12 | [%n p=@] 13 | == 14 | -- 15 | :: 16 | ++ settings-1 17 | =< settings 18 | |% 19 | +$ settings (map key bucket) 20 | -- 21 | +$ bucket (map key val) 22 | +$ key term 23 | +$ val 24 | $~ [%n 0] 25 | $% [%s p=@t] 26 | [%b p=?] 27 | [%n p=@] 28 | [%a p=(list val)] 29 | == 30 | :: 31 | +$ settings (mip desk key bucket) 32 | +$ event 33 | $% [%put-bucket =desk =key =bucket] 34 | [%del-bucket =desk =key] 35 | [%put-entry =desk buc=key =key =val] 36 | [%del-entry =desk buc=key =key] 37 | == 38 | +$ data 39 | $% [%all =settings] 40 | [%bucket =bucket] 41 | [%desk desk=(map key bucket)] 42 | [%entry =val] 43 | == 44 | -- 45 | -------------------------------------------------------------------------------- /~hanfel-dovned 2021.md: -------------------------------------------------------------------------------- 1 | [[~hanfel-dovned]]. [[2021-05-26]]. Userspace apprenticeship: Collaborative text editor and annotator. Urbit: Grants. https://urbit.org/grants/ua-collaborative-text-editor 2 | 3 | [[apprenticeship]] [[urbit app]] [[arvo]] [[~timluc-miptev]] 4 | 5 | ## Summary 6 | 7 | A line-based editor for looking at text and code. Can be organized by projects. Allows multiple people to edit, but can use locking for now. 8 | 9 | Could store edits as diffs. Graph-store is probably fine for this, but a native storage format could work as well and would be good to think through tradeoffs. Interesting extensions would be things like line annotations. 10 | 11 | This project is a good introduction to social apps in Urbit, and could become the framework for a larger product if the apprenticeship prototype works. 12 | 13 | ## User stories 14 | 15 | As a user I can: 16 | 17 | - create projects 18 | - create text files within those projects 19 | - invite other users to my project, with varying permissions -------------------------------------------------------------------------------- /tanote/lib/skeleton.hoon: -------------------------------------------------------------------------------- 1 | :: Similar to default-agent except crashes everywhere 2 | ^- agent:gall 3 | |_ bowl:gall 4 | ++ on-init 5 | ^- (quip card:agent:gall agent:gall) 6 | !! 7 | :: 8 | ++ on-save 9 | ^- vase 10 | !! 11 | :: 12 | ++ on-load 13 | |~ old-state=vase 14 | ^- (quip card:agent:gall agent:gall) 15 | !! 16 | :: 17 | ++ on-poke 18 | |~ in-poke-data=cage 19 | ^- (quip card:agent:gall agent:gall) 20 | !! 21 | :: 22 | ++ on-watch 23 | |~ path 24 | ^- (quip card:agent:gall agent:gall) 25 | !! 26 | :: 27 | ++ on-leave 28 | |~ path 29 | ^- (quip card:agent:gall agent:gall) 30 | !! 31 | :: 32 | ++ on-peek 33 | |~ path 34 | ^- (unit (unit cage)) 35 | !! 36 | :: 37 | ++ on-agent 38 | |~ [wire sign:agent:gall] 39 | ^- (quip card:agent:gall agent:gall) 40 | !! 41 | :: 42 | ++ on-arvo 43 | |~ [wire =sign-arvo] 44 | ^- (quip card:agent:gall agent:gall) 45 | !! 46 | :: 47 | ++ on-fail 48 | |~ [term tang] 49 | ^- (quip card:agent:gall agent:gall) 50 | !! 51 | -- 52 | -------------------------------------------------------------------------------- /Aide: -------------------------------------------------------------------------------- 1 | . 2 | .git/info/exclude 3 | Edit ,|sort|uniq 4 | New urbit.aide 5 | cp -rx /n/local/home/jdc/urbit/zod/tanote tanote 6 | cp -rx tanote/* /n/local/home/jdc/urbit/zod/tanote 7 | cp /n/local/home/jdc/urbit/zod/tanote/desk.docket-0 . 8 | cp tanote/desk.docket-0 /n/local/home/jdc/urbit/zod/tanote 9 | cp tanote/desk.ship /n/local/home/jdc/urbit/zod/tanote 10 | cp tanote/sys.kelvin /n/local/home/jdc/urbit/zod/tanote 11 | git add --all . 12 | git checkout 'create tanote desk files.md' 13 | git commit -a -m 'Add icon designed in Drawshield. Split progress into back-end and front-end. Update members of tah-noh-tay. Add front struct, to store filters and a filtered store. List regards in a store. Filter store front by regards or user tags. Filter a store by tags.' 14 | git diff --staged >commit.diff 15 | git diff >commit.diff 16 | git grep -n '^++ ' 17 | git grep -n wut 18 | git push origin main 19 | git status --branch --short 20 | host which urbit 21 | mv ../tanote*.md . 22 | rm -rf /n/local/home/jdc/urbit/zod/tanote/* 23 | https://i.imgur.com/S7PHgtX.png 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jason Catena 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tanote/lib/bip39.hoon: -------------------------------------------------------------------------------- 1 | :: bip39 implementation in hoon 2 | :: 3 | /+ bip39-english 4 | :: 5 | |% 6 | ++ from-entropy 7 | |= byts 8 | ^- tape 9 | =. wid (mul wid 8) 10 | ~| [%unsupported-entropy-bit-length wid] 11 | ?> &((gte wid 128) (lte wid 256)) 12 | :: 13 | =+ cs=(div wid 32) 14 | =/ check=@ 15 | %+ rsh [0 (sub 256 cs)] 16 | (sha-256l:sha (div wid 8) dat) 17 | =/ bits=byts 18 | :- (add wid cs) 19 | %+ can 0 20 | :~ cs^check 21 | wid^dat 22 | == 23 | :: 24 | =/ pieces 25 | |- ^- (list @) 26 | :- (end [0 11] dat.bits) 27 | ?: (lte wid.bits 11) ~ 28 | $(bits [(sub wid.bits 11) (rsh [0 11] dat.bits)]) 29 | :: 30 | =/ words=(list tape) 31 | %+ turn pieces 32 | |= ind=@ud 33 | (snag ind `(list tape)`bip39-english) 34 | :: 35 | %+ roll (flop words) 36 | |= [nex=tape all=tape] 37 | ?~ all nex 38 | :(weld all " " nex) 39 | :: 40 | ::NOTE always produces a 512-bit result 41 | ++ to-seed 42 | |= [mnem=tape pass=tape] 43 | ^- @ 44 | %- hmac-sha512t:pbkdf:crypto 45 | [(crip mnem) (crip (weld "mnemonic" pass)) 2.048 64] 46 | -- 47 | -------------------------------------------------------------------------------- /tanote/mar/json/rpc/response.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | /- *json-rpc 3 | :: 4 | |_ res=response 5 | :: 6 | ++ grad %noun 7 | ++ grow 8 | |% 9 | ++ noun res 10 | -- 11 | ++ grab :: convert from 12 | |% 13 | ++ noun response :: from noun 14 | ++ httr :: from httr 15 | |= hit=httr:eyre 16 | ^- response 17 | ~| hit 18 | ?: ?=(%2 (div p.hit 100)) 19 | =, html 20 | %- json 21 | ?~ r.hit 22 | a+~ 23 | (need (de-json q:u.r.hit)) 24 | fail+hit 25 | ++ json :: from json 26 | =, dejs-soft:format 27 | |= a=json 28 | ^- response 29 | =; dere 30 | =+ res=((ar dere) a) 31 | ?~ res (need (dere a)) 32 | [%batch u.res] 33 | |= a=json 34 | ^- (unit response) 35 | =/ res=(unit [@t json]) 36 | ::TODO breaks when no id present 37 | ((ot id+so result+some ~) a) 38 | ?^ res `[%result u.res] 39 | ~| a 40 | :+ ~ %error %- need 41 | ((ot id+so error+(ot code+no message+so ~) ~) a) 42 | -- 43 | -- 44 | -------------------------------------------------------------------------------- /%pony.md: -------------------------------------------------------------------------------- 1 | [[~normul-postem]]: [[~sarlev-sarsen]], I'm still happy to work on [[%pony]]! But I still need a more experienced [[Hoon]] dev. 2 | 3 | [[~hatryx-lastud]]: [[%pony]] sounds possibly cool though my feedback would be that email is arguably the least broken and crappy thing in all of normie computing today, so I wonder about the utility of an [[urbit app]] that competes with [[email]]. 4 | 5 | [[~ponhec-picwen]]: [[~hatryx-lastud]], but email is centralised, and no-one routes email from host to host with [[sendmail]] anymore in a [[distributed network]], because it takes the resources of a [[Google]] to catch [[spam]], because [[identity]] is free on the [[internet]]. 6 | 7 | [[~sarlev-sarsen]]: I’d make the case (as the one pushing this as something we need on Urbit) that the unbroken nature of e-mail as being on of the things most needed to be cloned over to Urbit. Threaded conversations which can add and remove participants during any part of the conversation by any participant and the ability to manage multiple conversations with the same person or set of people is tremendously useful. 8 | 9 | [[~ponhec-picwen]]: I plan something like this in %tanote: every time each note changes it creates a new version, which may be sent to a different group of people. 10 | 11 | -------------------------------------------------------------------------------- /tanote/mar/sole/action.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/action/sole/mar 3 | :: 4 | /? 310 5 | /- sole 6 | :: 7 | :::: 8 | :: 9 | =, sole 10 | |_ sole-action 11 | :: 12 | ++ grad %noun 13 | ++ grow 14 | |% 15 | ++ noun +<.grad 16 | -- 17 | ++ grab :: convert from 18 | |% 19 | ++ json 20 | |= jon=^json ^- sole-action 21 | %- need %. jon 22 | => [dejs-soft:format ..sole-action] 23 | |^ (ot id+so dat+(fo %ret (of det+change tab+ni ~)) ~) 24 | ++ fo 25 | |* [a=term b=fist] 26 | |=(c=json ?.(=([%s a] c) (b c) (some [a ~]))) 27 | :: 28 | ++ ra 29 | |* [a=[term fist] b=fist] 30 | |= c=json %. c 31 | ?.(=(%a -.c) b (pe -.a (ar +.a))) 32 | :: 33 | ++ ke :: callbacks 34 | |* [gar=* sef=(trap fist)] 35 | |= jon=json ^- (unit _gar) 36 | =- ~! gar ~! (need -) - 37 | ((sef) jon) 38 | :: 39 | ++ change (ot ler+(at ni ni ~) ted+(pe 0v0 edit) ~) 40 | ++ char (cu taft so) 41 | ++ edit 42 | %+ ke *sole-edit |. ~+ 43 | %+ fo %nop 44 | %+ ra mor+edit 45 | (of del+ni set+(cu tuba sa) ins+(ot at+ni cha+char ~) ~) 46 | -- 47 | :: 48 | ++ noun sole-action :: clam from %noun 49 | -- 50 | -- 51 | -------------------------------------------------------------------------------- /tanote/lib/language-server/build.hoon: -------------------------------------------------------------------------------- 1 | /- *language-server 2 | :: 3 | |% 4 | ++ parse-error 5 | |= =tape 6 | ^- (unit [=path =range]) 7 | =/ parse-pair 8 | %+ cook 9 | |=([row=@ud col=@ud] [(dec row) col]) 10 | (ifix [sel ser] ;~((glue ace) dem dem)) 11 | =/ parse-path 12 | %+ cook 13 | |=(p=path (slag 3 p)) 14 | (ifix [fas (jest '::')] (more fas urs:ab)) 15 | =/ parse-full 16 | ;~(plug parse-path ;~(sfix ;~((glue dot) parse-pair parse-pair) gar)) 17 | (rust tape parse-full) 18 | :: 19 | ++ get-errors-from-tang 20 | |= [uri=@t =tang] 21 | ^- (list range) 22 | =/ =path 23 | (uri-to-path uri) 24 | %+ murn tang 25 | |= =tank 26 | ^- (unit range) 27 | ?. ?=([%leaf *] tank) 28 | ~ 29 | =/ error 30 | (parse-error p.tank) 31 | ?~ error 32 | ~ 33 | ?: =(path path.u.error) 34 | `range.u.error 35 | ~ 36 | :: 37 | ++ uri-to-path 38 | |= uri=@t 39 | ^- path 40 | =/ pier-root=(set cord) 41 | %- sy 42 | ['app' 'gen' 'lib' 'mar' 'ren' 'sur' 'sys' 'test' ~] 43 | =/ path=(list cord) 44 | (parse-uri uri) 45 | |- 46 | ?< ?=(~ path) 47 | ?: (~(has in pier-root) i.path) 48 | `^path`path 49 | $(path t.path) 50 | :: 51 | ++ parse-uri 52 | |= uri=@t 53 | =- (fall - /fail) 54 | %+ rush uri 55 | %+ more 56 | ;~(pose (plus fas) dot) 57 | %+ cook 58 | crip 59 | (star ;~(pose col hep alf)) 60 | :: 61 | -- 62 | -------------------------------------------------------------------------------- /tanote/lib/mip.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | ++ mip :: map of maps 3 | |$ [kex key value] 4 | (map kex (map key value)) 5 | :: 6 | ++ bi :: mip engine 7 | =| a=(map * (map)) 8 | |@ 9 | ++ del 10 | |* [b=* c=*] 11 | =+ d=(~(gut by a) b ~) 12 | =+ e=(~(del by d) c) 13 | ?~ e 14 | (~(del by a) b) 15 | (~(put by a) b e) 16 | :: 17 | ++ get 18 | |* [b=* c=*] 19 | => .(b `_?>(?=(^ a) p.n.a)`b, c `_?>(?=(^ a) ?>(?=(^ q.n.a) p.n.q.n.a))`c) 20 | ^- (unit _?>(?=(^ a) ?>(?=(^ q.n.a) q.n.q.n.a))) 21 | (~(get by (~(gut by a) b ~)) c) 22 | :: 23 | ++ got 24 | |* [b=* c=*] 25 | (need (get b c)) 26 | :: 27 | ++ gut 28 | |* [b=* c=* d=*] 29 | (~(gut by (~(gut by a) b ~)) c d) 30 | :: 31 | ++ has 32 | |* [b=* c=*] 33 | !=(~ (get b c)) 34 | :: 35 | ++ key 36 | |* b=* 37 | ~(key by (~(gut by a) b ~)) 38 | :: 39 | ++ put 40 | |* [b=* c=* d=*] 41 | %+ ~(put by a) b 42 | %. [c d] 43 | %~ put by 44 | (~(gut by a) b ~) 45 | :: 46 | ++ tap 47 | ::NOTE naive turn-based implementation find-errors ): 48 | =< $ 49 | =+ b=`_?>(?=(^ a) *(list [x=_p.n.a _?>(?=(^ q.n.a) [y=p v=q]:n.q.n.a)]))`~ 50 | |. ^+ b 51 | ?~ a 52 | b 53 | $(a r.a, b (welp (turn ~(tap by q.n.a) (lead p.n.a)) $(a l.a))) 54 | -- 55 | -- 56 | -------------------------------------------------------------------------------- /create desk files.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] [[tanote/tanote]] 2 | 3 | https://dev.tlon.io/ 4 | 5 | ## create desk files 6 | 7 | The optional `desk.ship` file specifies the original publisher of this desk. Since we merged this from `%garden` it's currently set to `~mister-dister-dozzod-dozzod`. Let's change this to our fake ship `~zod`. In practice you'll set this to the ID you want to be seen as the publisher (likely your own Urbit ID). Currently there is no verification that makes sure publishers are honest about this, but eventually there will be. 8 | 9 | ```bash 10 | echo "~ponhec-picwen" > tanote/desk.ship 11 | ``` 12 | 13 | The final file we need to edit is `desk.docket-0`. #now 14 | 15 | ```hoon 16 | :~ title+'Tanote' 17 | info+'factional note manager' 18 | color+0x81.88c9 19 | version+[0 0 1] 20 | website+'https://github.com/catenate/tanote' 21 | license+'MIT' 22 | base+'tanote' 23 | glob-ames+[~zod 0v0] 24 | image+'https://media.urbit.org/docs/userspace/dist/wut.svg' 25 | == 26 | ``` 27 | 28 | Commit and install our changes. 29 | 30 | ```bash 31 | |commit %tanote 32 | |install our %tanote 33 | ``` 34 | 35 | Open a browser and navigate to [localhost:80](http://localhost:80) . To get the login code ([[access key]]), enter `+code` into the [[dojo]] prompt for your ship. For [[fake ~zod]]s, the code is always `lidlut-tabwed-pillex-ridrup`. You'll see our tile, but it says installing with a spinner due to the missing glob. 36 | 37 | -------------------------------------------------------------------------------- /Funes the memorious.md: -------------------------------------------------------------------------------- 1 | _ut nihil non iisdem verbis redderetur auditurn_: that nothing should be rendered without the same words (Google translate) 2 | 3 | "I have more memories in myself alone than all men have had since the world was a world." 4 | 5 | "My dreams are like your vigils." 6 | 7 | "My memory, sir, is like a garbage disposal." 8 | 9 | The truth is that we all live by leaving behind; no doubt we all profoundly know that we are immortal and that sooner or later every man will do all things and know everything. 10 | 11 | He had not written it down, for what he once meditated would not be erased. 12 | 13 | The two projects I have indicated (an infinite vocabulary for the natural series of numbers, and a usable mental catalogue of all the images of memory) are lacking in sense, but they reveal a certain stammering greatness. They allow us to make out dimly, or to infer, the dizzying world of Funes. He was, let us not forget, almost incapable of general, platonic ideas. 14 | 15 | Funes could continuously make out the tranquil advances of corruption, of caries, of fatigue. He noted the progress of death, of moisture. He was the solitary and lucid spectator of a multiform world which was instantaneously and almost intolerably exact. 16 | 17 | I suspect, nevertheless, that he was not very capable of thought. To think is to forget a difference, to generalize, to abstract. In the overly replete world of Funes there were nothing but details, almost contiguous details. 18 | 19 | -------------------------------------------------------------------------------- /tanote/lib/test.hoon: -------------------------------------------------------------------------------- 1 | :: testing utilities meant to be directly used from files in %/tests 2 | :: 3 | |% 4 | :: +expect-eq: compares :expected and :actual and pretty-prints the result 5 | :: 6 | ++ expect-eq 7 | |= [expected=vase actual=vase] 8 | ^- tang 9 | :: 10 | =| result=tang 11 | :: 12 | =? result !=(q.expected q.actual) 13 | %+ weld result 14 | ^- tang 15 | :~ [%palm [": " ~ ~ ~] [leaf+"expected" (sell expected) ~]] 16 | [%palm [": " ~ ~ ~] [leaf+"actual " (sell actual) ~]] 17 | == 18 | :: 19 | =? result !(~(nest ut p.actual) | p.expected) 20 | %+ weld result 21 | ^- tang 22 | :~ :+ %palm [": " ~ ~ ~] 23 | :~ [%leaf "failed to nest"] 24 | (~(dunk ut p.actual) %actual) 25 | (~(dunk ut p.expected) %expected) 26 | == == 27 | result 28 | :: +expect: compares :actual to %.y and pretty-prints anything else 29 | :: 30 | ++ expect 31 | |= actual=vase 32 | (expect-eq !>(%.y) actual) 33 | :: +expect-fail: kicks a trap, expecting crash. pretty-prints if succeeds 34 | :: 35 | ++ expect-fail 36 | |= a=(trap) 37 | ^- tang 38 | =/ b (mule a) 39 | ?- -.b 40 | %| ~ 41 | %& [leaf+"expected failure - succeeded" ~] 42 | == 43 | :: +category: prepends a name to an error result; passes successes unchanged 44 | :: 45 | ++ category 46 | |= [a=tape b=tang] ^- tang 47 | ?: =(~ b) ~ :: test OK 48 | :- leaf+"in: '{a}'" 49 | (turn b |=(c=tank rose+[~ " " ~]^~[c])) 50 | -- 51 | -------------------------------------------------------------------------------- /proposal meta.md: -------------------------------------------------------------------------------- 1 | [[~sarlev-sarsen]]: Some reason I can’t join this group, but if you are interested in making this a serious project, submit it at [https://Urbit.org/grants/proposals](https://urbit.org/grants/proposals) and we can see about getting some address space into your hands if you succeed in building something useful. 2 | 3 | [[Jason Catena]] 4 | [[~ponhec-picwen]] 5 | [catenaten@gmail.com](mailto:catenaten@gmail.com) 6 | 7 | Tanote, a factious note store 8 | web+urbitgraph://group/~ponhec-picwen/tah-noh-tay 9 | just me :) 10 | 11 | --- 12 | 13 | Good proposals all include the following: 14 | 15 | - A **detailed and clear description of the proposal**. If you're proposing something technical, user stories are a good idea. 16 | - An overview of **why you are the right person for the job**. A description of your background, familiarity with the project, and professional/education experience are all good starts. 17 | - Your estimate for **date of completion**. 18 | - The **amount of funding** you'd like for the project, denominated in stars. 19 | - What **specific deliverables** will look like. 20 | 21 | It's recommended to break your project into _milestones_, each of which must have its own completion dates, funding amounts and deliverables. In general, proposals should target a first deliverable within two months of the start of the project. Proposals should have a maximum of five milestones as scoping a project beyond that is impractical, and each milestone should constitute significant enough work to warrant the reward of a full star. -------------------------------------------------------------------------------- /tanote/mar/blit.hoon: -------------------------------------------------------------------------------- 1 | :: blit: runtime blit structure 2 | :: 3 | |_ =blit:dill 4 | ++ grad %noun 5 | :: +grab: convert from 6 | :: 7 | ++ grab 8 | |% 9 | ++ noun blit:dill 10 | -- 11 | :: +grow: convert to 12 | :: 13 | ++ grow 14 | |% 15 | ++ noun blit 16 | ++ json 17 | ^- ^json 18 | =, enjs:format 19 | %+ frond -.blit 20 | ?- -.blit 21 | %bel b+& 22 | %clr b+& 23 | %hop (numb p.blit) 24 | %lin a+(turn p.blit |=(c=@c s+(tuft c))) 25 | %mor b+& 26 | %url s+p.blit 27 | :: 28 | %sag 29 | %- pairs 30 | :~ 'path'^(path p.blit) 31 | 'file'^s+(en:base64:mimes:html (as-octs:mimes:html (jam q.blit))) 32 | == 33 | :: 34 | %sav 35 | %- pairs 36 | :~ 'path'^(path p.blit) 37 | 'file'^s+(en:base64:mimes:html (as-octs:mimes:html q.blit)) 38 | == 39 | :: 40 | %klr 41 | :- %a 42 | %+ turn p.blit 43 | |= [=stye text=(list @c)] 44 | %- pairs 45 | :~ 'text'^a+(turn text |=(c=@c s+(tuft c))) 46 | :: 47 | :- 'stye' 48 | %- pairs 49 | |^ :~ 'back'^(color p.q.stye) 50 | 'fore'^(color q.q.stye) 51 | 'deco'^a+(turn ~(tap in p.stye) |=(d=deco ?~(d ~ s+d))) 52 | == 53 | ++ color 54 | |= =tint 55 | ?@ tint ?~(tint ~ s+tint) 56 | s+(crip ((x-co:co 6) (rep 3 ~[b g r]:tint))) 57 | -- 58 | == 59 | == 60 | -- 61 | -- 62 | -------------------------------------------------------------------------------- /tanote/lib/default-agent.hoon: -------------------------------------------------------------------------------- 1 | /+ skeleton 2 | |* [agent=* help=*] 3 | ?: ?=(%& help) 4 | ~| %default-agent-helpfully-crashing 5 | skeleton 6 | |_ =bowl:gall 7 | ++ on-init 8 | `agent 9 | :: 10 | ++ on-save 11 | !>(~) 12 | :: 13 | ++ on-load 14 | |= old-state=vase 15 | `agent 16 | :: 17 | ++ on-poke 18 | |= =cage 19 | ~| "unexpected poke to {} with mark {}" 20 | !! 21 | :: 22 | ++ on-watch 23 | |= =path 24 | ~| "unexpected subscription to {} on path {}" 25 | !! 26 | :: 27 | ++ on-leave 28 | |= path 29 | `agent 30 | :: 31 | ++ on-peek 32 | |= =path 33 | ~| "unexpected scry into {} on path {}" 34 | !! 35 | :: 36 | ++ on-agent 37 | |= [=wire =sign:agent:gall] 38 | ^- (quip card:agent:gall _agent) 39 | ?- -.sign 40 | %poke-ack 41 | ?~ p.sign 42 | `agent 43 | %- (slog leaf+"poke failed from {} on wire {}" u.p.sign) 44 | `agent 45 | :: 46 | %watch-ack 47 | ?~ p.sign 48 | `agent 49 | =/ =tank leaf+"subscribe failed from {} on wire {}" 50 | %- (slog tank u.p.sign) 51 | `agent 52 | :: 53 | %kick `agent 54 | %fact 55 | ~| "unexpected subscription update to {} on wire {}" 56 | ~| "with mark {}" 57 | !! 58 | == 59 | :: 60 | ++ on-arvo 61 | |= [=wire =sign-arvo] 62 | ~| "unexpected system response {<-.sign-arvo>} to {} on wire {}" 63 | !! 64 | :: 65 | ++ on-fail 66 | |= [=term =tang] 67 | %- (slog leaf+"error in {}" >term< tang) 68 | `agent 69 | -- 70 | -------------------------------------------------------------------------------- /tah-noh-tay members.md: -------------------------------------------------------------------------------- 1 | ~libbyl-lonsyd 2 | Role 3 | Member 4 | 5 | calibri 6 | ~normul-postem 7 | Role 8 | Member 9 | ~nocsyx-lassul ⚗️ 10 | ~nocsyx-lassul 11 | Role 12 | Member 13 | ~silnem 14 | Role 15 | Member 16 | 17 | a tonned fampet 18 | ~tonned-fampet 19 | Role 20 | Member 21 | 22 | ~niblyx-the-zaptist 23 | ~niblyx-malnus 24 | Role 25 | Member 26 | ~ponhec-picwen 27 | Role 28 | Admin 29 | Kate Bush Experimenting with Orgone Rabsef 30 | ~rabsef-bicrym 31 | Role 32 | Member 33 | 34 | ~am 35 | ~haddef-sigwen 36 | Role 37 | Member 38 | ~bilnut-holdem 39 | ~bilnut-holdem 40 | Role 41 | Member 42 | ~hodreb-racdem 43 | Role 44 | Member 45 | ~sogrum-savluc, webmaster 46 | ~sogrum-savluc 47 | Role 48 | Member 49 | ~lorfeb-taglut 50 | Role 51 | Member 52 | ~hosted-fornet 53 | Role 54 | Member 55 | 56 | ~sarlev-sarsen 57 | Role 58 | Member 59 | ~lomseg-laclut 🍝 60 | ~lomseg-laclut 61 | Role 62 | Member 63 | Vitalii Bulychov 64 | ~hardem 65 | Role 66 | Member 67 | 68 | ~norsyr-torryn 69 | Role 70 | Member 71 | ~midden-fabler 72 | Role 73 | Member 74 | ~siplyn-difmev 75 | Role 76 | Member 77 | 78 | ~wicrum-wicrun 79 | Role 80 | Member 81 | ixv 82 | ~novlud-padtyv 83 | Role 84 | Member 85 | ~taller-ravnut� 86 | ~lomseg-laclut 87 | Role 88 | Member 89 | Vitalii Bulychov 90 | ~hardem 91 | Role 92 | Member 93 | 94 | ~norsyr-torryn 95 | Role 96 | Member 97 | ~midden-fabler 98 | Role 99 | Member 100 | ~siplyn-difmev 101 | Role 102 | Member 103 | 104 | ~wicrum-wicrun 105 | Role 106 | Member 107 | ixv 108 | ~novlud-padtyv 109 | Role 110 | Member 111 | ~taller-ravnut 112 | -------------------------------------------------------------------------------- /~pocwet journal.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] [[~pocwet]] [[journal]] 2 | 3 | --- 4 | 5 | https://urbit.org/docs/hoon/hoon-school/intro 6 | 7 | This series is designed to teach you Hoon without assuming you have an extensive programming background. In fact, you should be able to follow much of it even if you have no programming experience at all, though of course experience helps. We strongly encourage you to try out all the examples of each lesson. These lessons are meant for the beginner, but they aren't meant to be skimmed. Each lesson falls into one of two categories: **readings**, which are prose-heavy explanations of Hoon fundamentals, and **walkthroughs**, which are line-by-line explanations of example programs. Walkthroughs are found between readings, offering a practical implementation of the concepts taught in the reading before. 8 | 9 | --- 10 | 11 | https://urbit.org/docs/userspace/gall-guide/intro 12 | 13 | This guide will walk through everything you need to know to write your own Gall agents. The Gall Guide is suitable for anyone with an intermediate knowledge of Hoon. If you've worked through [Hoon School](https://urbit.org/docs/hoon/hoon-school/intro) or something equivalent, you should be fine. 14 | 15 | --- 16 | 17 | https://urbit.org/docs/userspace/full-stack/1-intro 18 | 19 | This series walks through the writing of a full Gall agent, and then the process of integrating it with a React front-end. This series follows on from the previous [Gall Guide](https://urbit.org/docs/userspace/gall-guide/intro). If you haven't completed that, or otherwise aren't familiar with the basics of writing Gall agents, it's strongly recommended to work through that guide first. 20 | 21 | -------------------------------------------------------------------------------- /publish.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] [[tanote/tanote]] 2 | 3 | https://dev.tlon.io/ 4 | 5 | ## Publish 6 | 7 | The final step is publishing our desk with the `%treaty` agent so others can install it. To do this, there's a simple command in the dojo. 8 | 9 | ```bash 10 | :treaty|publish %tanote 11 | ``` 12 | 13 | > **Note**: For desks without a docket file (and therefore without a tile and glob), treaty can't be used. Instead you can make the desk public with `|public %desk-name`. 14 | 15 | > **Note**: Desks aren't publicly readable by default, `:treaty|publish` publishes the metadata and also makes the desk publicly readable, like `|public`. 16 | 17 | ## Remote install 18 | 19 | Let's spin up another fake ship so we can try to install our newly published app. 20 | 21 | ```bash 22 | cd ~/urbit 23 | ./urbit bus 24 | ``` 25 | 26 | > **Note**: For desks without a docket file (and therefore without a tile and glob), users cannot install them through the web interface. Instead remote users can install it from the dojo with `|install ~our-ship %desk-name`. 27 | 28 | In the browser, navigate to [http://localhost:8081](http://localhost:8081/) and login with [[fake ~bus]]'s code which can be found by running `+code` in the dojo for `bus`. In this case, the default is `riddec-bicrym-ridlev-pocsef`. Next, type `~zod/` in the search bar, and it should pop up a list of `~zod`'s published apps, which in this case is our `Tanote` app. 29 | 30 | When we click on the app, it'll show some of the information from the clauses in the docket file. Click `Get App`. It'll ask as if we want to install it. Finally, click `Get "Tanote"`. It'll be installed as a tile on `~bus` which can then be opened. 31 | 32 | -------------------------------------------------------------------------------- /tanote/lib/language-server/parser.hoon: -------------------------------------------------------------------------------- 1 | :: lifted directly from ford, should probably be in zuse 2 | =, clay 3 | =< pile-rule 4 | |% 5 | ++ pile-rule 6 | |= pax=path 7 | %- full 8 | %+ ifix 9 | :_ gay 10 | :: parse optional /? and ignore 11 | :: 12 | ;~(plug gay (punt ;~(plug fas wut gap dem gap))) 13 | |^ 14 | ;~ plug 15 | %+ cook (bake zing (list (list taut))) 16 | %+ rune hep 17 | (most ;~(plug com gaw) taut-rule) 18 | :: 19 | %+ cook (bake zing (list (list taut))) 20 | %+ rune lus 21 | (most ;~(plug com gaw) taut-rule) 22 | :: 23 | %+ rune tis 24 | ;~(plug sym ;~(pfix gap stap)) 25 | :: 26 | %+ rune sig 27 | ;~((glue gap) sym wyde:vast stap) 28 | :: 29 | %+ rune cen 30 | ;~(plug sym ;~(pfix gap ;~(pfix cen sym))) 31 | :: 32 | %+ rune buc 33 | ;~ (glue gap) 34 | sym 35 | ;~(pfix cen sym) 36 | ;~(pfix cen sym) 37 | == 38 | :: 39 | %+ rune tar 40 | ;~ (glue gap) 41 | sym 42 | ;~(pfix cen sym) 43 | stap 44 | == 45 | :: 46 | %+ stag %tssg 47 | (most gap tall:(vang & pax)) 48 | == 49 | :: 50 | ++ pant 51 | |* fel=^rule 52 | ;~(pose fel (easy ~)) 53 | :: 54 | ++ mast 55 | |* [bus=^rule fel=^rule] 56 | ;~(sfix (more bus fel) bus) 57 | :: 58 | ++ rune 59 | |* [bus=^rule fel=^rule] 60 | %- pant 61 | %+ mast gap 62 | ;~(pfix fas bus gap fel) 63 | -- 64 | :: 65 | ++ taut-rule 66 | %+ cook |=(taut +<) 67 | ;~ pose 68 | (stag ~ ;~(pfix tar sym)) 69 | ;~(plug (stag ~ sym) ;~(pfix tis sym)) 70 | (cook |=(a=term [`a a]) sym) 71 | == 72 | -- 73 | -------------------------------------------------------------------------------- /tanote/sur/ring.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | :: +raw-ring-signature: low level ring signature type 3 | :: 4 | :: The :s field of a ring signature grows O(n) with the number of 5 | :: participants in the ring. 6 | :: 7 | ++ raw-ring-signature 8 | $: ch0=@ 9 | :: 10 | s=(list @) 11 | :: linked ring signature tag 12 | :: 13 | :: Two linked ring signatures with the same link scope can be shown to 14 | :: have been made by the same private key, leading to Sybil 15 | :: resistance...but if your private keys are compromised, your 16 | :: adversary can determine which signatures you made. 17 | :: 18 | y=(unit @udpoint) 19 | == 20 | :: +ring-signature: higher level ring signature type 21 | :: 22 | :: This contains all the identifying information to verify a ring signature 23 | :: in an urbit context. 24 | :: 25 | ++ ring-signature 26 | $: :: a ring signature is computed over a set of public keys. the 27 | :: participants set is not those keys, but static references to them. 28 | :: 29 | participants=(set [ship=@p =life]) 30 | :: the linkage scope this signature was made on 31 | :: 32 | link-scope=(unit *) 33 | :: the rest of the low level ring signature is appended 34 | :: 35 | raw=raw-ring-signature 36 | == 37 | :: 38 | +$ ring-group 39 | $: :: a ring signature is computed over a set of public keys. the 40 | :: participants set is not those keys, but static references to them. 41 | :: 42 | participants=(set [ship=@p =life]) 43 | :: the linkage scope this signature was made on 44 | :: 45 | link-scope=(unit *) 46 | == 47 | -- 48 | -------------------------------------------------------------------------------- /session Gettysburg.md: -------------------------------------------------------------------------------- 1 | [[tanote/tanote]] 2 | [[session init]] 3 | 4 | --- 5 | 6 | Receive a version of this text, with regards to a new note name. 7 | 8 | > by ~abeham-lincon as president 9 | > to ~ponhec-picwen 10 | > re draft from train 11 | > 12 | > #Gettysburg address 13 | > 14 | > Four score and seven years ago… 15 | 16 | Automatically update tags, @ps, and regards. 17 | 18 | > ==`*`== ==~abeham-lincon== ==~hatryx-lastud== ==~paldev== ==_~ponhec-picwen_== ==Gettysburg== 19 | > 20 | > ==draft from train==. 21 | > 22 | > by ~ponhec-picwen as | 23 | > ==to== | 24 | > re | 25 | > ==no== ~~1~~ of 1 26 | > 27 | > | 28 | 29 | Select it via its tag. This filters out other notes without the tag, and displays the set of matching notes. This blanks the text because we haven't yet selected a specific node 30 | 31 | > ==`*`== ==~abeham-lincon== ==~hatryx-lastud== ==~paldev== ==~ponhec-picwen== ==**Gettysburg**== 32 | > 33 | > ==draft from train==. 34 | > 35 | > 36 | 37 | Selecting a notes' regards displays it. 38 | 39 | > ==`*`== ==_~abeham-lincon_== ==~hatryx-lastud== ==~paldev== ==_~ponhec-picwen_== ==**Gettysburg**== 40 | > 41 | > ==**draft from train**==. 42 | > 43 | > by ~abeham-lincon as ~~president~~ 44 | > ==to== ~~~ponhec-picwen~~ 45 | > re ~~draft from train~~ 46 | > ==no== ~~1~~ of 1 47 | > 48 | > ~~#Gettysburg address 49 | > 50 | > Four score and seven years ago…~~ 51 | 52 | The list of recipients, the regards, the version, and the text are editable, but this changed version is only buffered and may be lost, until the user clicks ==to== (add version, and send to recipients) or ==no== (add version), at which point a new version (of possibly a different note, if the regards changed) is added. 53 | 54 | -------------------------------------------------------------------------------- /tangents.md: -------------------------------------------------------------------------------- 1 | [[~fabled-faster]]. month _circa_ [[2021-10]]. Mass proliferation of writing/[[Roam]]-like apps. [[urbit group]]s: [[Foundation grant]] ideas. web+urbitgraph://group/~wolref-podlex/foundation/graph/~wolref-podlex/grant-ideas/170141184505228879328373638614380183552 2 | 3 | [[Roam]] and [[Notion]] are onto something. It’s important to be able to go beyond writing and into the realm of creating interconnected graphs of nodes that you can share with others across the network. There could be great overlap between writing, ‘groups’ (new landscape) and a knowledge graph or roamlike. 4 | 5 | ... 6 | 7 | ~wicrum-wicrun: Could I later edit the node in the knowledge graph (_eg_ add links to other nodes, or just rephrase it)? Without affecting the original chat message? While still keeping the "forked from"-link to the original chat message (and vice versa)? 8 | 9 | --- 10 | 11 | [[~datryn-ribdun]]: Would be cool to make an easily deployable [[gora]] for new app users. Like "I just made %dongers, and some people have installed it. I want to send all of them gorae to thank them". Easy to do if you have a list, but not sure how you'd get the list automatically. somewhere software distribution must store the [[@p]]s that have installed from the developer's desk, you just have to extract it. 12 | 13 | --- 14 | 15 | [[~noddep-hanwep]]: Is there some nice way of having long discussions on very specific topics on Urbit? 16 | 17 | [[~ravmel-ropdyl]]: We use notebooks for this from time to time, but it's not ideal. 18 | 19 | [[~noddep-hanwep]]: I mean the kind of stuff that belongs in a forum thread rather than a chat 20 | 21 | [[~ravmel-ropdyl]]: Yeah, notebooks are the stand in for this. 22 | 23 | --- 24 | 25 | -------------------------------------------------------------------------------- /tanote/mar/hoon.hoon: -------------------------------------------------------------------------------- 1 | :::: /hoon/hoon/mar 2 | :: 3 | /? 310 4 | :: 5 | =, eyre 6 | |_ own=@t 7 | :: 8 | ++ grow :: convert to 9 | |% 10 | ++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime 11 | ++ elem :: convert to %html 12 | ;div:pre(urb_codemirror "", mode "hoon"):"{(trip own)}" 13 | :: =+ gen-id="src-{<`@ui`(mug own)>}" 14 | :: ;div 15 | :: ;textarea(id "{gen-id}"):"{(trip own)}" 16 | :: ;script:""" 17 | :: CodeMirror.fromTextArea( 18 | :: window[{}], 19 | :: \{lineNumbers:true, readOnly:true} 20 | :: ) 21 | :: """ 22 | :: == 23 | ++ hymn 24 | :: ;html:(head:title:"Source" "+{elem}") 25 | ;html 26 | ;head 27 | ;title:"Source" 28 | ;script@"//cdnjs.cloudflare.com/ajax/libs/codemirror/4.3.0/codemirror.js"; 29 | ;script@"/lib/syntax/hoon.js"; 30 | ;link(rel "stylesheet", href "//cdnjs.cloudflare.com/ajax/libs/". 31 | "codemirror/4.3.0/codemirror.min.css"); 32 | ;link/"/lib/syntax/codemirror.css"(rel "stylesheet"); 33 | == 34 | ;body 35 | ;textarea#src:"{(trip own)}" 36 | ;script:'CodeMirror.fromTextArea(src, {lineNumbers:true, readOnly:true})' 37 | == 38 | == 39 | ++ txt 40 | (to-wain:format own) 41 | -- 42 | ++ grab 43 | |% :: convert from 44 | ++ mime |=([p=mite q=octs] q.q) 45 | ++ noun @t :: clam from %noun 46 | ++ txt of-wain:format 47 | -- 48 | ++ grad %txt 49 | -- 50 | -------------------------------------------------------------------------------- /tanote/sur/docket.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | :: 3 | +$ version 4 | [major=@ud minor=@ud patch=@ud] 5 | :: 6 | +$ glob (map path mime) 7 | :: 8 | +$ url cord 9 | :: $glob-location: How to retrieve a glob 10 | :: 11 | +$ glob-reference 12 | [hash=@uvH location=glob-location] 13 | :: 14 | +$ glob-location 15 | $% [%http =url] 16 | [%ames =ship] 17 | == 18 | :: $href: Where a tile links to 19 | :: 20 | +$ href 21 | $% [%glob base=term =glob-reference] 22 | [%site =path] 23 | == 24 | :: $chad: State of a docket 25 | :: 26 | +$ chad 27 | $~ [%install ~] 28 | $% :: Done 29 | [%glob =glob] 30 | [%site ~] 31 | :: Waiting 32 | [%install ~] 33 | [%suspend glob=(unit glob)] 34 | :: Error 35 | [%hung err=cord] 36 | == 37 | :: 38 | :: $charge: A realized $docket 39 | :: 40 | +$ charge 41 | $: =docket 42 | =chad 43 | == 44 | :: 45 | :: $clause: A key and value, as part of a docket 46 | :: 47 | :: Only used to parse $docket 48 | :: 49 | +$ clause 50 | $% [%title title=@t] 51 | [%info info=@t] 52 | [%color color=@ux] 53 | [%glob-http url=cord hash=@uvH] 54 | [%glob-ames =ship hash=@uvH] 55 | [%image =url] 56 | [%site =path] 57 | [%base base=term] 58 | [%version =version] 59 | [%website website=url] 60 | [%license license=cord] 61 | == 62 | :: 63 | :: $docket: A description of JS bundles for a desk 64 | :: 65 | +$ docket 66 | $: %1 67 | title=@t 68 | info=@t 69 | color=@ux 70 | =href 71 | image=(unit url) 72 | =version 73 | website=url 74 | license=cord 75 | == 76 | :: 77 | +$ charge-update 78 | $% [%initial initial=(map desk charge)] 79 | [%add-charge =desk =charge] 80 | [%del-charge =desk] 81 | == 82 | -- 83 | -------------------------------------------------------------------------------- /create and upload glob.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] [[tanote/tanote]] 2 | 3 | ## create files for glob 4 | 5 | We'll now create the files for the glob. We'll use a very simple static HTML page that just displays "Hello World!" and an image. Typically we'd have a more complex JS web app that talked to apps on our ship through the server API, but for the sake of simplicity we'll forgo that. Let's hop back in the Unix terminal. 6 | 7 | ```bash 8 | cd git/tanote 9 | mkdir tanote-glob 10 | cd tanote-glob 11 | mkdir img 12 | curl https://media.urbit.org/docs/userspace/dist/pot.svg --output img/pot.svg 13 | ``` 14 | 15 | We've grabbed an image to use in our "Hello world!" page. The next thing we need to add is an `index.html` file in the root of the folder. The `index.html` file is mandatory; it's what will be loaded when the app's tile is clicked. 16 | 17 | ```html 18 | 19 | 20 | 21 | tanote 22 | 27 | 28 | 29 |

a community knowledge manager

30 | pot 31 | 32 | 33 | ``` 34 | 35 | ## upload to glob 36 | 37 | We can now create a glob from the directory. To do so, navigate to [docket/upload](http://localhost:80/docket/upload) in the browser. This will bring up the `%docket` app's Globulator tool. 38 | 39 | 1. Simply select the `tanote` desk from the drop-down, click `Choose file` and select the `tanote-glob` folder in the file browser, then hit `glob!`. 40 | 2. Now if we return to our ship's homescreen, we should see the tile looks as we specified in the docket file: `http://localhost:80` 41 | 3. And if we click on the tile, it'll load the `index.html` in our glob. 42 | 4. Our app is working! 43 | 44 | -------------------------------------------------------------------------------- /tanote/sur/bitcoin.hoon: -------------------------------------------------------------------------------- 1 | :: sur/btc.hoon 2 | :: Utilities for working with BTC data types and transactions 3 | :: 4 | :: chyg: whether account is (non-)change. 0 or 1 5 | :: bytc: "btc-byts" with dat cast to @ux 6 | |% 7 | +$ network ?(%main %testnet) 8 | +$ hexb [wid=@ dat=@ux] :: hex byts 9 | +$ bits [wid=@ dat=@ub] 10 | +$ xpub @ta 11 | +$ address 12 | $% [%base58 @uc] 13 | [%bech32 cord] 14 | == 15 | +$ fprint hexb 16 | +$ bipt $?(%44 %49 %84) 17 | +$ chyg $?(%0 %1) 18 | +$ idx @ud 19 | +$ hdkey [=fprint pubkey=hexb =network =bipt =chyg =idx] 20 | +$ sats @ud 21 | +$ vbytes @ud 22 | +$ txid hexb 23 | +$ utxo [pos=@ =txid height=@ value=sats recvd=(unit @da)] 24 | ++ address-info 25 | $: =address 26 | confirmed-value=sats 27 | unconfirmed-value=sats 28 | utxos=(set utxo) 29 | == 30 | ++ tx 31 | |% 32 | +$ data 33 | $: is=(list input) 34 | os=(list output) 35 | locktime=@ud 36 | nversion=@ud 37 | segwit=(unit @ud) 38 | == 39 | +$ val 40 | $: =txid 41 | pos=@ud 42 | =address 43 | value=sats 44 | == 45 | :: included: whether tx is in the mempool or blockchain 46 | :: 47 | +$ info 48 | $: included=? 49 | =txid 50 | confs=@ud 51 | recvd=(unit @da) 52 | inputs=(list val) 53 | outputs=(list val) 54 | == 55 | +$ input 56 | $: =txid 57 | pos=@ud 58 | sequence=hexb 59 | script-sig=(unit hexb) 60 | pubkey=(unit hexb) 61 | value=sats 62 | == 63 | +$ output 64 | $: script-pubkey=hexb 65 | value=sats 66 | == 67 | -- 68 | ++ psbt 69 | |% 70 | +$ base64 cord 71 | +$ in [=utxo rawtx=hexb =hdkey] 72 | +$ out [=address hk=(unit hdkey)] 73 | +$ target $?(%input %output) 74 | +$ keyval [key=hexb val=hexb] 75 | +$ map (list keyval) 76 | -- 77 | ++ ops 78 | |% 79 | ++ op-dup 118 80 | ++ op-equalverify 136 81 | ++ op-hash160 169 82 | ++ op-checksig 172 83 | -- 84 | -- 85 | -------------------------------------------------------------------------------- /create desk.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] [[tanote/tanote]] 2 | 3 | https://urbit.org/docs/development/environment 4 | 5 | ### Create a new desk 6 | 7 | To create a new desk, you'll need to merge from an existing one, typically `%base`. In the dojo, run the following (you can change `%mydesk` to your preferred name): 8 | 9 | ```hoon 10 | |merge %tanote our %base 11 | |mount %tanote 12 | ``` 13 | 14 | If you now mount it, you'll have `/mydesk` directory in your pier with all the files of the `%base` desk inside. You can then delete the contents, copy in your own files and `|commit` it. 15 | 16 | Desks must contain all the `mark` files, libraries, etc, that they need. A `sys.kelvin` file is mandatory, and there are a few `mark` files necessary as well. In the next couple of sections we'll look at different ways to populate a new desk with the necessary files. 17 | 18 | The desks in [[urbit/pkg]] ending in `-dev`, like `base-dev` and `garden-dev`, contain files for interfacing with those respective desks. If you're creating a new desk that has a tile and front-end, for example, you might like to use `base-dev` and `garden-dev` as a base. To create such a base, there's a `symbolic-merge.sh` script included in the directory. You can use it like so: 19 | 20 | ```shell 21 | ./symbolic-merge.sh base-dev tanote 22 | ./symbolic-merge.sh garden-dev tanote 23 | ``` 24 | 25 | Then, you can go into your pier: 26 | 27 | ```shell 28 | cd /home/jdc/urbit/zod 29 | ``` 30 | 31 | Delete the contents of `tanote`: 32 | 33 | ```shell 34 | rm -r tanote/* 35 | ``` 36 | 37 | And then copy in the contents of the desk you created: 38 | 39 | ```shell 40 | cp -rL ~/obsidian/flake/urbit/pkg/tanote/* tanote 41 | ``` 42 | 43 | Note you have to use `cp -rL` rather than just `cp -r` because the `symbolic-merge.sh` script creates symlinks, so the `L` flag is to resolve them and copy the actual files. 44 | 45 | Now you can just add a `sys.kelvin` file: 46 | 47 | ```shell 48 | echo '[%zuse 418]' > tanote/sys.kelvin 49 | ``` 50 | 51 | And you'll be able to mount the desk with  52 | 53 | ```hoon 54 | |commit %tanote 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /tanote/lib/cram.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | ++ static :: freeze .mdh hoon subset 3 | |= gen=hoon ^- [inf=(map term dime) elm=manx] 4 | ?+ -.gen 5 | =/ gen ~(open ap gen) 6 | ?: =(gen ^gen) ~|([%cram-dynamic -.gen] !!) 7 | $(gen gen) 8 | :: 9 | %xray [~ (single (shut gen))] 10 | ^ [(malt (frontmatter p.gen)) (single (shut q.gen))] 11 | == 12 | :: 13 | ++ single :: unwrap one-elem marl 14 | |= xml=marl ^- manx 15 | ?: ?=([* ~] xml) i.xml 16 | ~|(%many-elems !!) 17 | :: 18 | ++ shut-mart :: xml attrs 19 | |=([n=mane v=(list beer:hoot)] [n (turn v |=(a=beer:hoot ?^(a !! a)))]) 20 | :: 21 | ++ shut :: as xml constant 22 | |= gen=hoon ^- marl 23 | ?+ -.gen ~|([%bad-xml -.gen] !!) 24 | %dbug $(gen q.gen) 25 | :: 26 | %xray 27 | [[n.g.p.gen (turn a.g.p.gen shut-mart)] $(gen [%mcts c.p.gen])]~ 28 | :: 29 | %mcts 30 | ?~ p.gen ~ 31 | =- (weld - $(p.gen t.p.gen)) 32 | ?^ -.i.p.gen $(gen [%xray i.p.gen]) 33 | ~| [%shut-tuna -.i.p.gen] 34 | ?+ -.i.p.gen !! 35 | %manx ?>(?=(%xray -.p.i.p.gen) $(gen p.i.p.gen)) 36 | %marl ?>(?=(%mcts -.p.i.p.gen) $(gen p.i.p.gen)) 37 | == 38 | == 39 | :: 40 | :: 41 | ++ frontmatter :: parse ~[[%foo 1] [%bar ~s2]] 42 | |= gen=hoon ^- (list [term dime]) 43 | ?: ?=([%bust %null] gen) ~ 44 | ?: ?=(%dbug -.gen) $(gen q.gen) 45 | ?. ?=(%clsg -.gen) ~|([%bad-frontmatter -.gen] !!) 46 | %+ turn p.gen 47 | |= gen=hoon 48 | ?. ?=(^ -.gen) 49 | =/ gen ~(open ap gen) 50 | ?: =(gen ^gen) ~|([%bad-frontmatter-elem -.gen] !!) 51 | $(gen gen) 52 | =/ hed (as-dime p.gen) 53 | ?. =(%tas p.hed) ~|([%bad-frontmatter-key-type p.hed] !!) 54 | [q.hed (as-dime q.gen)] 55 | :: 56 | ++ as-dime :: %foo ~.foo 0vbar etc 57 | |= gen=hoon ^- dime 58 | ?: ?=(%dbug -.gen) $(gen q.gen) 59 | ?. ?=([?(%rock %sand) @ @] gen) ~|([%bad-literal gen] !!) 60 | +.gen 61 | -- 62 | -------------------------------------------------------------------------------- /tanote/mar/sole/effect.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/effect/sole/mar 3 | :: 4 | /? 310 5 | /- sole 6 | !: 7 | :: 8 | :::: 9 | :: 10 | =, sole 11 | =, format 12 | |% 13 | ++ mar-sole-change :: XX dependency 14 | |_ cha=sole-change 15 | ++ grow 16 | |% ++ json 17 | ^- ^json 18 | =, enjs 19 | =; edi 20 | =,(cha (pairs ted+(edi ted) ler+a+~[(numb own.ler) (numb his.ler)] ~)) 21 | |= det=sole-edit 22 | ?- -.det 23 | %nop [%s 'nop'] 24 | %mor [%a (turn p.det ..$)] 25 | %del (frond %del (numb p.det)) 26 | %set (frond %set (tape (tufa p.det))) 27 | %ins (frond %ins (pairs at+(numb p.det) cha+s+(tuft q.det) ~)) 28 | == 29 | -- 30 | -- 31 | ++ wush 32 | |= [wid=@u tan=tang] 33 | ^- tape 34 | (of-wall (turn (flop tan) |=(a=tank (of-wall (wash 0^wid a))))) 35 | :: 36 | ++ purge :: discard ++styx style 37 | |= a=styx ^- tape 38 | %- zing %+ turn a 39 | |= a=_?>(?=(^ a) i.a) 40 | ?@(a (trip a) ^$(a q.a)) 41 | -- 42 | :: 43 | |_ sef=sole-effect 44 | :: 45 | ++ grad %noun 46 | ++ grab :: convert from 47 | |% 48 | ++ noun sole-effect :: clam from %noun 49 | -- 50 | ++ grow 51 | =, enjs 52 | |% 53 | ++ noun sef 54 | ++ json 55 | ^- ^json 56 | ?+ -.sef 57 | ~|(unsupported-effect+-.sef !!) 58 | %mor [%a (turn p.sef |=(a=sole-effect json(sef a)))] 59 | %err (frond %hop (numb p.sef)) 60 | %txt (frond %txt (tape p.sef)) 61 | %tan (frond %tan (tape (wush 160 p.sef))) 62 | %det (frond %det json:~(grow mar-sole-change +.sef)) 63 | :: 64 | %pro 65 | %+ frond %pro 66 | (pairs vis+b+vis.sef tag+s+tag.sef cad+(tape (purge cad.sef)) ~) 67 | :: 68 | %tab 69 | :- %a 70 | %+ turn p.sef 71 | |= [=cord =^tank] 72 | %+ frond %tab 73 | %- pairs 74 | :~ match+s+cord 75 | info+(tape ~(ram re tank)) 76 | == 77 | :: 78 | ?(%bel %clr %nex %bye) 79 | (frond %act %s -.sef) 80 | == 81 | -- 82 | -- 83 | -------------------------------------------------------------------------------- /tanote/lib/primitive-rsa.hoon: -------------------------------------------------------------------------------- 1 | :: |rsa: primitive, textbook RSA 2 | :: 3 | :: Unpadded, unsafe, unsuitable for encryption! 4 | :: 5 | |% 6 | :: +key:rsa: rsa public or private key 7 | :: 8 | +$ key 9 | $: :: pub: public parameters (n=modulus, e=pub-exponent) 10 | :: 11 | pub=[n=@ux e=@ux] 12 | :: sek: secret parameters (d=private-exponent, p/q=primes) 13 | :: 14 | sek=(unit [d=@ux p=@ux q=@ux]) 15 | == 16 | :: +ramp: make rabin-miller probabilistic prime 17 | :: 18 | :: XX replace +ramp:number? 19 | :: a: bitwidth 20 | :: b: snags (XX small primes to check divisibility?) 21 | :: c: entropy 22 | :: 23 | ++ ramp 24 | |= [a=@ b=(list @) c=@] 25 | =. c (shas %ramp c) 26 | :: XX what is this value? 27 | :: 28 | =| d=@ 29 | |- ^- @ux 30 | :: XX what is this condition? 31 | :: 32 | ?: =((mul 100 a) d) 33 | ~|(%ar-ramp !!) 34 | :: e: prime candidate 35 | :: 36 | :: Sets low bit, as prime must be odd. 37 | :: Sets high bit, as +raw:og only gives up to :a bits. 38 | :: 39 | =/ e :(con 1 (lsh [0 (dec a)] 1) (~(raw og c) a)) 40 | :: XX what algorithm is this modular remainder check? 41 | :: 42 | ?: ?& (levy b |=(f=@ !=(1 (mod e f)))) 43 | (pram:number e) 44 | == 45 | e 46 | $(c +(c), d (shax d)) 47 | :: +elcm:rsa: carmichael totient 48 | :: 49 | ++ elcm 50 | |= [a=@ b=@] 51 | (div (mul a b) d:(egcd a b)) 52 | :: +new-key:rsa: write somethingXXX 53 | :: 54 | ++ new-key 55 | =/ e `@ux`65.537 56 | |= [wid=@ eny=@] 57 | ^- key 58 | =/ diw (rsh 0 wid) 59 | =/ p=@ux (ramp diw [3 5 ~] eny) 60 | =/ q=@ux (ramp diw [3 5 ~] +(eny)) 61 | =/ n=@ux (mul p q) 62 | =/ d=@ux (~(inv fo (elcm (dec p) (dec q))) e) 63 | [[n e] `[d p q]] 64 | :: +en:rsa: primitive RSA encryption 65 | :: 66 | :: ciphertext = message^e (mod n) 67 | :: 68 | ++ en 69 | |= [m=@ k=key] 70 | ~| %rsa-len 71 | ?> (lte (met 0 m) (met 0 n.pub.k)) 72 | (~(exp fo n.pub.k) e.pub.k m) 73 | :: +de:rsa: primitive RSA decryption 74 | :: 75 | :: message = ciphertext^d (mod e) 76 | :: 77 | ++ de 78 | |= [m=@ k=key] 79 | :: XX assert rsa-len here too? 80 | ~| %rsa-need-ring 81 | ?> ?=(^ sek.k) 82 | =/ fu (fu:number p.u.sek.k q.u.sek.k) 83 | (out.fu (exp.fu d.u.sek.k (sit.fu m))) 84 | -- 85 | -------------------------------------------------------------------------------- /tanote/mar/story.hoon: -------------------------------------------------------------------------------- 1 | /- *story 2 | /+ *story 3 | |_ tale=story 4 | ++ grad 5 | |% 6 | ++ form %story-diff 7 | ++ diff 8 | |= tory=story 9 | ^- story-diff 10 | :: Given new story (tory), old story (tale), compute the diff 11 | :: additions = new - old 12 | :: deletions = old - new 13 | [(dif-ju tory tale) (dif-ju tale tory)] 14 | ++ pact 15 | |= dif=story-diff 16 | :: Compute the new story after applying dif to tale. 17 | :: 18 | ^- story 19 | =. tale (uni-ju tale additions.dif) 20 | =. tale (dif-ju tale deletions.dif) 21 | tale 22 | ++ join 23 | |= [ali=story-diff bob=story-diff] 24 | ^- (unit story-diff) 25 | =/ joined-additions (uni-ju additions.ali additions.bob) 26 | =/ joined-deletions (uni-ju deletions.ali deletions.bob) 27 | :: 28 | :: In a true join, we'd do a set intersection on the keys. 29 | :: If they're not equal, we have a conflict. 30 | :: In this case, we'd produce null and kick the flow to +mash 31 | :: 32 | %- some 33 | [joined-additions joined-deletions] 34 | ++ mash 35 | :: called by meld, force merge, annotating conflicts 36 | |= $: [als=ship ald=desk ali=story-diff] 37 | [bos=ship bod=desk bob=story-diff] 38 | == 39 | ^- story-diff 40 | (need (join ali bob)) :: XX temporary, only because join doesn't fail 41 | -- 42 | :: 43 | ++ grow :: convert to 44 | |% :: 45 | ++ mime :: to %mime 46 | [/text/x-urb-story (as-octs:mimes:html (of-wain:format txt))] 47 | ++ txt 48 | ^- wain 49 | %- snoc :_ '' :: ensures terminating newline is present 50 | %+ murn ~(tap by tale) 51 | |= [[=tako:clay =proses]] 52 | ^- (unit cord) 53 | ?~ proses ~ 54 | %- some 55 | %- crip 56 | ;: welp 57 | (tako-to-text tako) 58 | (proses-to-text proses) 59 | "---" 60 | == 61 | -- 62 | ++ grab 63 | |% :: convert from 64 | ++ noun story :: clam from %noun 65 | ++ mime :: retrieve from %mime 66 | |= [p=mite q=octs] 67 | =/ story-text `@t`q.q 68 | `story`(rash story-text parse-story) 69 | -- 70 | -- 71 | -------------------------------------------------------------------------------- /tanote/sur/aquarium.hoon: -------------------------------------------------------------------------------- 1 | :: Traditionally, ovo refers to an ovum -- (pair wire card) -- and ova 2 | :: refers to a list of them. We have several versions of each of these 3 | :: depending on context, so we do away with that naming scheme and use 4 | :: the following naming scheme. 5 | :: 6 | :: Every card is either an `event` or an `effect`. Prepended to this 7 | :: is `unix` if it has no ship associated with it, or `aqua` if it 8 | :: does. `timed` is added if it includes the time of the event. 9 | :: 10 | :: Short names are simply the first letter of each word plus `s` if 11 | :: it's a list. 12 | :: 13 | /+ pill 14 | =, pill-lib=pill 15 | |% 16 | +$ az-log [topics=(lest @) data=@t] 17 | +$ az-state 18 | $: logs=(list az-log) 19 | lives=(map ship [lyfe=life rut=rift]) 20 | tym=@da 21 | == 22 | ++ ph-event 23 | $% [%test-done p=?] 24 | aqua-event 25 | == 26 | :: 27 | +$ unix-event ::NOTE like unix-event:pill-lib but for all tasks 28 | %+ pair wire 29 | $% [%wack p=@] 30 | [%what p=(list (pair path (cask)))] 31 | [%whom p=ship] 32 | [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))] 33 | [%wyrd p=vere] 34 | [%verb p=(unit ?)] 35 | task-arvo 36 | == 37 | +$ pill pill:pill-lib 38 | :: 39 | +$ aqua-event 40 | $% [%init-ship who=ship fake=?] 41 | [%pause-events who=ship] 42 | [%snap-ships lab=term hers=(list ship)] 43 | [%restore-snap lab=term] 44 | [%event who=ship ue=unix-event] 45 | == 46 | :: 47 | +$ azimuth-action 48 | $% [%init-azimuth ~] 49 | [%spawn who=ship] 50 | [%breach who=ship] 51 | == 52 | :: 53 | +$ aqua-effects 54 | [who=ship ufs=(list unix-effect)] 55 | :: 56 | +$ aqua-effect 57 | [who=ship ufs=unix-effect] 58 | :: 59 | +$ aqua-events 60 | [who=ship utes=(list unix-timed-event)] 61 | :: 62 | +$ aqua-boths 63 | [who=ship ub=(list unix-both)] 64 | :: 65 | +$ unix-both 66 | $% [%event unix-timed-event] 67 | [%effect unix-effect] 68 | == 69 | :: 70 | +$ unix-timed-event [tym=@da ue=unix-event] 71 | :: 72 | +$ unix-effect 73 | %+ pair wire 74 | $% [%blit p=(list blit:dill)] 75 | [%send p=lane:ames q=@] 76 | [%doze p=(unit @da)] 77 | [%thus p=@ud q=(unit hiss:eyre)] 78 | [%ergo p=@tas q=mode:clay] 79 | [%sleep ~] 80 | [%restore ~] 81 | [%kill ~] 82 | [%init ~] 83 | [%request id=@ud request=request:http] 84 | == 85 | -- 86 | -------------------------------------------------------------------------------- /tanote/sur/language-server.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | :: 3 | +$ versioned-doc-id 4 | [uri=@t version=(unit @)] 5 | :: 6 | ++ request 7 | |% 8 | +$ all 9 | $% 10 | text-document--hover 11 | text-document--completion 12 | unknown 13 | == 14 | +$ text-document--hover 15 | [%text-document--hover id=cord position versioned-doc-id] 16 | +$ text-document--completion 17 | [%text-document--completion id=cord position versioned-doc-id] 18 | +$ unknown 19 | [%unknown json] 20 | -- 21 | ++ response 22 | |% 23 | +$ all 24 | $% 25 | text-document--hover 26 | text-document--completion 27 | == 28 | +$ text-document--hover 29 | [%text-document--hover id=cord contents=(unit @t)] 30 | +$ text-document--completion 31 | [%text-document--completion id=cord completion=(list completion-item)] 32 | -- 33 | :: 34 | +$ completion-item 35 | $: 36 | label=cord 37 | kind=@ud 38 | detail=cord 39 | doc=cord 40 | insert-text=cord 41 | insert-text-format=@ud 42 | == 43 | 44 | 45 | 46 | :: 47 | +$ diagnostic 48 | [=range severity=@ud message=@t] 49 | :: 50 | +$ position 51 | [row=@ud col=@ud] 52 | :: 53 | +$ text-document-item 54 | [uri=@t version=(unit @) text=@t] 55 | :: 56 | ++ notification 57 | |% 58 | :: 59 | +$ in 60 | $% 61 | text-document--did-change 62 | text-document--did-open 63 | text-document--did-save 64 | text-document--did-close 65 | exit 66 | unknown 67 | == 68 | :: 69 | +$ out 70 | $% 71 | text-document--publish-diagnostics 72 | == 73 | :: 74 | +$ all 75 | $% 76 | out 77 | in 78 | == 79 | :: 80 | +$ text-document--did-change 81 | [%text-document--did-change versioned-doc-id changes=(list change)] 82 | :: 83 | +$ text-document--did-open 84 | [%text-document--did-open text-document-item] 85 | :: 86 | +$ text-document--did-save 87 | [%text-document--did-save versioned-doc-id] 88 | :: 89 | +$ text-document--did-close 90 | [%text-document--did-close versioned-doc-id] 91 | :: 92 | +$ exit 93 | [%exit ~] 94 | :: 95 | +$ unknown 96 | [%unknown =json] 97 | :: 98 | +$ text-document--publish-diagnostics 99 | [%text-document--publish-diagnostics uri=@t diagnostics=(list diagnostic)] 100 | :: 101 | -- 102 | :: 103 | +$ change 104 | $: range=(unit range) 105 | range-length=(unit @ud) 106 | text=@t 107 | == 108 | :: 109 | +$ range 110 | $: start=position 111 | end=position 112 | == 113 | :: 114 | -- 115 | -------------------------------------------------------------------------------- /glossary.md: -------------------------------------------------------------------------------- 1 | # Tanote glossary 2 | 3 | ## as 4 | 5 | > You’re going to find that many of the truths we cling to depend greatly on our own point of view.—George Lucas as Obi-Wan Kenobi 6 | 7 | A tag which identifies the faction (_confer_ [[Yarvin 2007]]) of the author with respect to a version of a note. 8 | 9 | Metadata carried with a note. Considered a tag of the note. 10 | 11 | ## backlink 12 | 13 | > Practically, the link context is an explanation on why you should follow a link. A good link context explains what you can expect if you follow the link. But it can also explain the nature of the relationship between both notes.—Sascha Fast 14 | 15 | References to other notes. A tape between `[[` and `]]`. Backlinks are carried in the text of the note. 16 | 17 | ## by 18 | 19 | > A reader should be able to identify a column without its byline or funny little picture on top purely by look or feel, or its turgidity ratio.—William Safire 20 | 21 | The single @p of the author of a version of a note. This field is read-only for the user, and is maintained by the code. For a new note, this is automatically set to our @p. When a note is changed, the author is automatically updated to our @p. 22 | 23 | Metadata carried with a note. Considered a tag of the note. 24 | 25 | ## if 26 | 27 | > Trifles they may be; but it is by such that character and disposition are oftenest revealed.—Washington Irving 28 | 29 | The gora which must be present on a ship for a version of a note to be received. 30 | 31 | ## regards 32 | 33 | > No one regards what is before his feet; we all gaze at the stars.—Quintus Ennius 34 | 35 | With regards: the subject and title of the note. Every note with the same title is considered to be a version of the same note. 36 | 37 | Metadata carried with a note, or the first tape of the data structure of a note, where the remaining cells in the list are versions of the same note. 38 | 39 | ## tag 40 | 41 | > Seeing, hearing, feeling, are miracles, and each part and tag of me is a miracle.—Walt Whitman 42 | 43 | An alphanumeric keyword by which the note is classified, following an octothorpe (`#`); or, a `@p` in the text (_eg_ `~ponhec-picwen`). Tags are carried in the text of the note. 44 | 45 | ## text 46 | 47 | > The absence of a message sometimes is a presence of one.—Hasse Jerner 48 | 49 | The text, the body of a note, excluding metadata. The tape which is the text contains tags and backlinks. 50 | 51 | ## to 52 | 53 | > Whatever is received is received according to the nature of the recipient.—Thomas Aquinas 54 | 55 | The set of @p of recipients of the note. 56 | 57 | Metadata carried with a note, and used to route the note to other users. Considered tags of the note? 58 | 59 | -------------------------------------------------------------------------------- /tanote-glob/img/tanote.svg: -------------------------------------------------------------------------------- 1 | 2 | tierced-in-fessDivision used to fill field 10 | 11 | 12 | a letter # 13 | 14 | 15 | 16 | 17 | 18 | a letter | 19 | 20 | 21 | 22 | 23 | 24 | the letter v 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /announce.md: -------------------------------------------------------------------------------- 1 | [[~ponhec-picwen]]. [[2022-06-04]]. Urbit community: General. Urbit groups. web+urbitgraph://group/~bitbet-bolbel/urbit-community/graph/~darrux-landes/general/170141184505669025390660775828512957267 2 | 3 | [[~nocsyx-lassul]]: we keep hoping someone will build one 4 | 5 | [[~ponhec-picwen]]: [[~nocsyx-lassul]], I recently had a brainstorm, and have been inspired to make something that strikes me as Martian. I just started Hoon school (I'm up to recursion), and then comes Gall school and working through the journal example. I'm doing this on my own, but I have a Computer Engineering degree and 40 years experience writing software (taught myself BASIC on a TI-99/4A and Logo on a Commodore 64), so I should be able to figure it out. Here's my work on it so far, which is mostly just notes and a static page. 6 | 7 | https://github.com/catenate/tanote 8 | 9 | Speaking of early days of home computers, Urbit most reminds me of the shareware and freeware produced by communities of hobbyists and spread by word-of-mouth, swap meets, BBSes, small-group zines, and ads in the back pages of magazines from which you typed in program listings. It's nice to get back to that spirit and enthusiasm, in which random people use what they know to make software they love. 10 | 11 | [[~pinsyt-nossub]]: [[~ponhec-picwen]], I assume you know about this grant, but I'd rather be redundant for you not to miss it: 12 | https://urbit.org/grants/app-engram 13 | 14 | [[~ponhec-picwen]]: [[~pinsyt-nossub]], I read that, but what I'd like to build is not that. It's not a mediated common view that tries to reconcile multiple simultaneous edits. It's more like email, in that you send asynchronously a particular version of a titled document, but the new (ur-)bit is that it stores and presents together, as versions in a series, all the notes with the same title, since it considers these drafts of the same document, working towards a definition of that title. Which document titles you may select from, to view, is determined by the active selected hash tags, and the list of hash tags to select from is composed from the list of hash tags in the latest versions of all the documents (plus a * to see every note, plus the note's faction, plus the @p of the note's author, plus the @p of each recipient). Each version of each note has a list of people (by @p) to whom it is sent, and once sent it appears in that person's set of notes (I'm not really yet planning on delete, but you can always make a new blank version of a note with any title to remove it from the hashtag index). I'm also planning on signalling which other visible notes have back links to the current note (though Urbsidian is also not quite what I want to write), and allowing the writer of the note to provide with each note a tag stating the note's single factional point of view (cf Uberfact), to keep the notes small and focused and coherent and findable. 15 | 16 | -------------------------------------------------------------------------------- /tanote/lib/ph/util.hoon: -------------------------------------------------------------------------------- 1 | :: Utility functions for constructing tests 2 | :: 3 | /- aquarium 4 | =, aquarium 5 | |% 6 | :: 7 | :: Turn [ship (list unix-event)] into (list ph-event) 8 | :: 9 | ++ send-events-to 10 | |= [who=ship what=(list unix-event)] 11 | ^- (list aqua-event) 12 | %+ turn what 13 | |= ue=unix-event 14 | [%event who ue] 15 | :: 16 | :: Start a ship (low-level; prefer +raw-ship) 17 | :: 18 | ++ init 19 | |= [who=ship fake=?] 20 | ^- (list aqua-event) 21 | [%init-ship who fake]~ 22 | :: 23 | :: Send dojo command 24 | :: 25 | ++ dojo 26 | |= [who=ship what=tape] 27 | ^- (list aqua-event) 28 | %+ send-events-to who 29 | ^- (list unix-event) 30 | :~ 31 | [/d/term/1 %belt %ctl `@c`%e] 32 | [/d/term/1 %belt %ctl `@c`%u] 33 | [/d/term/1 %belt %txt ((list @c) what)] 34 | [/d/term/1 %belt %ret ~] 35 | == 36 | :: 37 | :: Control character 38 | :: 39 | ++ ctrl 40 | |= [who=ship what=term] 41 | ^- (list ph-event) 42 | %+ send-events-to who 43 | :~ [/d/term/1 %belt %ctl (,@c what)] 44 | == 45 | :: 46 | :: Inject a file into a ship 47 | :: 48 | ++ insert-files 49 | |= [who=ship des=desk files=(list [=path txt=@t])] 50 | ^- (list aqua-event) 51 | =/ input 52 | %+ turn files 53 | |= [=path txt=@t] 54 | [path ~ /text/plain (as-octs:mimes:html txt)] 55 | %+ send-events-to who 56 | :~ 57 | [/c/sync/0v1n.2m9vh %into des | input] 58 | == 59 | :: 60 | :: Checks whether the given event is a dojo output blit containing the 61 | :: given tape 62 | ::TODO should be rename -dill-output 63 | ++ is-dojo-output 64 | |= [who=ship her=ship uf=unix-effect what=tape] 65 | ?& =(who her) 66 | ?=(%blit -.q.uf) 67 | :: 68 | %+ lien p.q.uf 69 | |= =blit:dill 70 | ?. ?=(%lin -.blit) 71 | | 72 | !=(~ (find what p.blit)) 73 | == 74 | :: 75 | :: Test is successful if +is-dojo-output 76 | :: 77 | ++ expect-dojo-output 78 | |= [who=ship her=ship uf=unix-effect what=tape] 79 | ^- (list ph-event) 80 | ?. (is-dojo-output who her uf what) 81 | ~ 82 | [%test-done &]~ 83 | :: 84 | :: Check whether the given event is an ergo 85 | :: 86 | ++ is-ergo 87 | |= [who=ship her=ship uf=unix-effect] 88 | ?& =(who her) 89 | ?=(%ergo -.q.uf) 90 | == 91 | :: 92 | :: Check if given effect is an http request; extract 93 | :: 94 | ++ extract-request 95 | |= [uf=unix-effect dest=@t] 96 | ^- (unit [num=@ud =request:http]) 97 | ?. ?=(%request -.q.uf) ~ 98 | ?. =(dest url.request.q.uf) ~ 99 | `[id.q.uf request.q.uf] 100 | :: 101 | :: Scry into a running aqua ship 102 | :: 103 | ++ scry-aqua 104 | |* [a=mold our=@p now=@da pax=path] 105 | .^ a 106 | %gx 107 | (scot %p our) 108 | %aqua 109 | (scot %da now) 110 | pax 111 | == 112 | -- 113 | -------------------------------------------------------------------------------- /tanote/sur/asn1.hoon: -------------------------------------------------------------------------------- 1 | :: |asn1: small selection of types and constants for ASN.1 2 | :: 3 | :: A minimal representation of some basic ASN.1 types, 4 | :: created to support PKCS keys, digests, and cert requests. 5 | :: 6 | ^? 7 | |% 8 | :: +bespoke:asn1: context-specific, generic ASN.1 tag type 9 | :: 10 | :: Note that *explicit* implies *constructed* (ie, bit 5 is set in DER). 11 | :: 12 | +$ bespoke 13 | :: imp: & is implicit, | is explicit 14 | :: tag: 5 bits for the custom tag number 15 | :: 16 | [imp=? tag=@ud] 17 | :: +spec:asn1: minimal representations of basic ASN.1 types 18 | :: 19 | +$ spec 20 | $% :: %int: arbitrary-sized, unsigned integers 21 | :: 22 | :: Unsigned integers, represented as having a positive sign. 23 | :: Negative integers would be two's complement in DER, 24 | :: but we don't need them. 25 | :: 26 | [%int int=@u] 27 | :: %bit: very minimal support for bit strings 28 | :: 29 | :: Specifically, values must already be padded and byte-aligned. 30 | :: len: bitwidth 31 | :: bit: data 32 | :: 33 | [%bit len=@ud bit=@ux] 34 | :: %oct: octets in little-endian byte order 35 | :: 36 | :: len: bytewidth 37 | :: bit: data 38 | :: 39 | [%oct len=@ud oct=@ux] 40 | :: %nul: fully supported! 41 | :: 42 | [%nul ~] 43 | :: %obj: object identifiers, pre-packed 44 | :: 45 | :: Object identifiers are technically a sequence of integers, 46 | :: represented here in their already-encoded form. 47 | :: 48 | [%obj obj=@ux] 49 | :: %seq: a list of specs 50 | :: 51 | [%seq seq=(list spec)] 52 | :: %set: a logical set of specs 53 | :: 54 | :: Implemented here as a list for the sake of simplicity. 55 | :: must be already deduplicated and sorted! 56 | :: 57 | [%set set=(list spec)] 58 | :: %con: context-specific 59 | :: 60 | :: General support for context-specific tags. 61 | :: bes: custom tag number, implicit or explicit 62 | :: con: already-encoded bytes 63 | :: 64 | [%con bes=bespoke con=(list @D)] 65 | == 66 | :: |obj:asn1: constant object ids, pre-encoded 67 | :: 68 | ++ obj 69 | ^? 70 | |% :: rfc4055 71 | ++ sha-256 0x1.0204.0365.0148.8660 :: 2.16.840.1.101.3.4.2.1 72 | ++ rsa 0x1.0101.0df7.8648.862a :: 1.2.840.113549.1.1.1 73 | ++ rsa-sha-256 0xb.0101.0df7.8648.862a :: 1.2.840.113549.1.1.11 74 | :: rfc2985 75 | ++ csr-ext 0xe.0901.0df7.8648.862a :: 1.2.840.113549.1.9.14 76 | :: rfc3280 77 | ++ sub-alt 0x11.1d55 :: 2.5.29.17 78 | -- 79 | -- 80 | 81 | -------------------------------------------------------------------------------- /Yarvin 2007.md: -------------------------------------------------------------------------------- 1 | [[Curtis Yarvin]] as [[Mencius Moldbug]]. [[2007-08-22]]. [[Uberfact]]: The ultimate social verifier. [[Unqualified reservations]]. https://www.unqualified-reservations.org/2007/08/uberfact-ultimate-social-verifier/ 2 | 3 | … 4 | 5 | Notice these group labels.  In Uberfact, these are called _factions_.  Factions are groups of people who see the world in the same way.  Factions may form on any issue and for any reason—progressive _versus_ conservative, Ford _versus_ Chevy, [emacs _versus_ vi](https://en.wikipedia.org/wiki/Editor_war). 6 | 7 | Any user can have a reputation in as many factions as he likes.  But reputation in one faction has no meaning to another faction.  To a Ford-lover, it means nothing that you’re a highly rated libertarian.  What do you know about limited-slip differentials?  Jack.  Until you prove otherwise. 8 | 9 | Every contribution to Uberfact must be associated with a faction, and it is judged by that faction and that faction only.  If the contribution is good, it improves your local reputation within that faction.  If I have something to share about Ezra Pound, I have to decide whether I’m saying it as a modernist, a postmodernist, a New Critic, _et cetera_, _et cetera_. 10 | 11 | Factions are self-constituting—they are responsible for their own reputation algorithms.  Anyone can start a new faction for any reason, but generally they form by the usual process of human group formation—one group gets too large and quarrelsome, and splits into parts.  The faction’s founders constitute and manage its reputation system. 12 | 13 | For example, early in Uberfact’s development, there would probably be a libertarian faction.  This would then fragment into Rothbardian, Randian, and Kochian libertarians—at least.  Various strongly-flavored personalities might spin off their own little factions, and so on. 14 | 15 | As a user of Uberfact, you have access to all content produced by all factions.  Your process for answering a question, such as “is George W Bush a tyrant,” is in two steps.  One, figure out what faction is both (a) interested in this question, and (b) reasonably aligned with your own perspective in the area.  Two, find out what that faction says about George W Bush. 16 | 17 | For example, it’s easy to imagine upgrading Wikipedia to be uberfactious.  Instead of one page for George W Bush, you could read the story of George W Bush according to libertarians, according to progressives, according to jihadis, racists, Ford lovers, emacs bigots, and so on—anyone who cares enough to have an opinion about George W Bush. 18 | 19 | One might quickly notice that these pages matched in certain details.  For example, jihadis, racists, and progressives probably all agree that George W Bush was born on July 6, 1946.  So all of these groups might contribute to a consensus page, signed by a large number of factions, which might even be similar to today’s “objective” page.  And since this would probably be the most commonly requested George W. Bush page, it would come up first.  An uberfactious Wikipedia doesn’t need to be any harder to use than today’s neutralist Wikipedia. 20 | 21 | -------------------------------------------------------------------------------- /data structures.md: -------------------------------------------------------------------------------- 1 | # alternative arrangements to store notes 2 | 3 | ## metadata and text 4 | 5 | Store each note independently in a larger list. 6 | 7 | ```hoon 8 | [[by=@p as=@t] to=(list @p) re=@t te=@t] 9 | ``` 10 | 11 | slot | accessor | noun 12 | --- | --- | --- 13 | +1:c | c | `[by=@p to=(list @p) re=@t te=@t]` 14 | +2:c | | `[by=@p as=@t]` 15 | +3:c | | `[to=(list @p) re=@t te=@t]` 16 | +4:c | (by c) | `by=@p` 17 | +5:c | (as c) | `as=@t` 18 | +6:c | (to c) | `to=(list @p)` 19 | +7:c | | `[re=@t te=@t]` 20 | | | 21 | +14:c | (re c) | `re=@t` 22 | +15:c | (te c) | `te=@t` 23 | 24 | `(ta c)` returns a `(list @t)` of tags (`#[^ ]+`) in `(te c)`. 25 | 26 | ## grouped by regards 27 | 28 | Store all versions by their common regards, within a larger list of all regards. 29 | 30 | ```hoon 31 | [re [[by as] to te] [[by as] to te]] 32 | ``` 33 | 34 | slot | subexpression | content 35 | --- | --- | --- 36 | +1:c | `[re [[by as] to te] [[by as] to te]]` | list of all notes with the same regards 37 | +2:c | `re` | @t of regards (title) common to all following notes 38 | +3:c | `[[by as] to te] [[by as] to te]` | all the versions of the notes, decreasing to 1 39 | | | 40 | +6:c | `[[by as] to te]` | version 2 of the note 41 | +7:c | `[[by as] to te]` | version 1 of the note 42 | | | 43 | +12:c | `[by as]` | author and faction of version 2 of the note 44 | +13:c | `[to te]` | recipients and text of version 2 of the note 45 | +14:c | `[by as]` | author and faction of version 1 of the note 46 | +15:c | `[to te]` | recipients and text of version 1 of the note 47 | | | 48 | +24:c | `(by +6:c)` (by gets +4) | @p of author of version 2 of the note 49 | +25:c | `(as +6:c)` (as gets +5) | @t of faction of version 2 of the note 50 | +26:c | `(to +6:c)` (to gets +6) | `(list @p)` of recipients of version 2 of the note 51 | +27:c | `(te +6:c)` (te gets +7) | @t of text of version 2 of the note 52 | +28:c | `(by +7:c)` | @p of author of version 1 of the note 53 | +29:c | `(as +7:c)` | @t of faction of version 1 of the note 54 | +30:c | `(to +7:c)` | `(list @p)` of recipients of version 1 of the note 55 | +31:c | `(te +7:c)` | @t of text of version 1 of the note 56 | 57 | Construct the list of all regards simply by grabbing +2 from all of the regards in the overall structure. We don’t have to keep a separate list of regards. How do we identify backlinks? We want to know, for the latest version of each note, whether the text of the note contains the regards of the uniquely **selected note** within `[[ ]]`. If so, present the regards of the _referring note_ in italics, if the note is filtered in by the multiple **selected tags**. 58 | 59 | Construct the list of all tags by extracting the list of tags in the text (always `(te +7:c)`) in the latest version (+6) of each regards. This means that the tags are always up-to-date, but that the history of tags is not presented. On the plus side, we don’t have to keep a separate list of tags. 60 | 61 | Tags include `by` (the `@p` of the author), `as` (the faction of the author with respect to this note), each `to` (`(list @p)` of recipients), and all tags (`#[^ ]+`) in the text. 62 | 63 | -------------------------------------------------------------------------------- /tanote/lib/agentio.hoon: -------------------------------------------------------------------------------- 1 | => 2 | |% 3 | ++ card card:agent:gall 4 | -- 5 | :: 6 | |_ =bowl:gall 7 | ++ scry 8 | |= [desk=@tas =path] 9 | %+ weld 10 | /(scot %p our.bowl)/[desk]/(scot %da now.bowl) 11 | path 12 | :: 13 | ++ pass 14 | |_ =wire 15 | ++ poke 16 | |= [=dock =cage] 17 | [%pass wire %agent dock %poke cage] 18 | :: 19 | ++ poke-our 20 | |= [app=term =cage] 21 | ^- card 22 | (poke [our.bowl app] cage) 23 | :: 24 | ++ poke-self 25 | |= =cage 26 | ^- card 27 | (poke-our dap.bowl cage) 28 | :: 29 | ++ arvo 30 | |= =note-arvo 31 | ^- card 32 | [%pass wire %arvo note-arvo] 33 | :: 34 | ++ watch 35 | |= [=dock =path] 36 | [%pass (watch-wire path) %agent dock %watch path] 37 | :: 38 | ++ watch-our 39 | |= [app=term =path] 40 | (watch [our.bowl app] path) 41 | :: 42 | ++ watch-wire 43 | |= =path 44 | ^+ wire 45 | ?. ?=(~ wire) 46 | wire 47 | agentio-watch+path 48 | :: 49 | ++ leave 50 | |= =dock 51 | [%pass wire %agent dock %leave ~] 52 | :: 53 | ++ leave-our 54 | |= app=term 55 | (leave our.bowl app) 56 | :: 57 | ++ leave-path 58 | |= [=dock =path] 59 | =. wire 60 | (watch-wire path) 61 | (leave dock) 62 | :: 63 | ++ wait 64 | |= p=@da 65 | (arvo %b %wait p) 66 | :: 67 | ++ rest 68 | |= p=@da 69 | (arvo %b %wait p) 70 | :: 71 | ++ warp 72 | |= [wer=ship =riff:clay] 73 | (arvo %c %warp wer riff) 74 | :: 75 | ++ warp-our 76 | |= =riff:clay 77 | (warp our.bowl riff) 78 | :: 79 | :: right here, right now 80 | ++ warp-slim 81 | |= [genre=?(%sing %next) =care:clay =path] 82 | =/ =mood:clay 83 | [care r.byk.bowl path] 84 | =/ =rave:clay 85 | ?:(?=(%sing genre) [genre mood] [genre mood]) 86 | (warp-our q.byk.bowl `rave) 87 | :: 88 | ++ connect 89 | |= [=binding:eyre app=term] 90 | (arvo %e %connect binding app) 91 | -- 92 | :: 93 | ++ fact-curry 94 | |* [=mark =mold] 95 | |= [paths=(list path) fac=mold] 96 | (fact mark^!>(fac) paths) 97 | :: 98 | ++ fact-kick 99 | |= [=path =cage] 100 | ^- (list card) 101 | :~ (fact cage ~[path]) 102 | (kick ~[path]) 103 | == 104 | :: 105 | ++ fact-init 106 | |= =cage 107 | ^- card 108 | [%give %fact ~ cage] 109 | :: 110 | ++ fact-init-kick 111 | |= =cage 112 | ^- (list card) 113 | :~ (fact cage ~) 114 | (kick ~) 115 | == 116 | :: 117 | ++ fact 118 | |= [=cage paths=(list path)] 119 | ^- card 120 | [%give %fact paths cage] 121 | :: 122 | ++ fact-all 123 | |= =cage 124 | ^- (unit card) 125 | =/ paths=(set path) 126 | %- ~(gas in *(set path)) 127 | %+ turn ~(tap by sup.bowl) 128 | |=([duct ship =path] path) 129 | ?: =(~ paths) ~ 130 | `(fact cage ~(tap in paths)) 131 | :: 132 | ++ kick 133 | |= paths=(list path) 134 | [%give %kick paths ~] 135 | :: 136 | ++ kick-only 137 | |= [=ship paths=(list path)] 138 | [%give %kick paths `ship] 139 | -- 140 | -------------------------------------------------------------------------------- /tanote/lib/keygen.hoon: -------------------------------------------------------------------------------- 1 | :: urbit-style key generation and derivation functions 2 | :: 3 | /- keygen 4 | :: 5 | /+ ethereum, bip32, bip39 6 | :: 7 | =, keygen 8 | :: 9 | |% 10 | ++ argon2u 11 | |= [who=ship tic=byts] 12 | ^- @ 13 | ~| [%who who (met 3 who)] 14 | :: ?> (lte (met 3 who) 4) 15 | %- (argon2-urbit:argon2:crypto 32) 16 | :- tic 17 | =- [(met 3 -) (swp 3 -)] 18 | %- crip 19 | (weld "urbitkeygen" (a-co:co who)) 20 | :: 21 | ++ child-node-from-seed 22 | |= [seed=@ typ=tape pass=(unit @t)] 23 | ^- node 24 | =+ sed=(seed:ds 32^seed typ) 25 | =+ nom=(from-entropy:bip39 32^sed) 26 | :+ typ nom 27 | %- wallet:ds 28 | %+ to-seed:bip39 nom 29 | (trip (fall pass '')) 30 | :: 31 | ++ derive-network-seed 32 | |= [mngs=@ rev=@ud] 33 | ^- @ux 34 | =+ (seed:ds 64^mngs (weld "network" (a-co:co rev))) 35 | ?: =(0 rev) - 36 | :: hash again to prevent length extension attacks 37 | (sha-256l:sha 32 -) 38 | :: 39 | ++ ownership-wallet-from-ticket 40 | |= [who=ship ticket=byts pass=(unit @t)] 41 | ^- node 42 | =+ master-seed=(argon2u who ticket) 43 | (child-node-from-seed master-seed "ownership" pass) 44 | :: 45 | ++ full-wallet-from-ticket 46 | :: who: username 47 | :: ticket: password 48 | :: rev: network key revision 49 | :: pass: optional passphrase 50 | :: 51 | |= [who=ship ticket=byts rev=@ud pass=(unit @t)] 52 | ^- vault 53 | =+ master-seed=(argon2u who ticket) 54 | =/ cn :: child node 55 | |= typ=nodetype 56 | (child-node-from-seed master-seed typ pass) 57 | :: 58 | :- ^= ownership ^- node 59 | (cn "ownership") 60 | :: 61 | :- ^= voting ^- node 62 | (cn "voting") 63 | :: 64 | =/ management=node 65 | (cn "management") 66 | :- management=management 67 | :: 68 | :- ^= transfer ^- node 69 | (cn "transfer") 70 | :: 71 | :- ^= spawn ^- node 72 | (cn "spawn") 73 | :: 74 | ^= network ^- uode 75 | =/ mad :: management seed 76 | %+ to-seed:bip39 77 | seed:management 78 | (trip (fall pass '')) 79 | =+ sed=(derive-network-seed mad rev) 80 | [rev sed (urbit:ds sed)] 81 | :: 82 | ++ ds :: derive from raw seed 83 | |% 84 | ++ wallet 85 | |= seed=@ 86 | ^- ^wallet 87 | =+ => (from-seed:bip32 64^seed) 88 | (derive-path "m/44'/60'/0'/0/0") 89 | :+ [public-key private-key] 90 | (address-from-prv:key:ethereum private-key) 91 | chain-code 92 | :: 93 | ++ urbit 94 | |= seed=@ 95 | ^- edkeys 96 | =+ =< [pub=pub:ex sec=sec:ex] 97 | (pit:nu:crub:crypto 256 seed) 98 | :- ^= auth 99 | :- (rsh 3 (end [3 33] pub)) 100 | (rsh 3 (end [3 33] sec)) 101 | ^= crypt 102 | :- (rsh [3 33] pub) 103 | (rsh [3 33] sec) 104 | :: 105 | ++ seed 106 | |= [seed=byts salt=tape] 107 | ^- @ux 108 | %- sha-256l:sha 109 | :- (add wid.seed (lent salt)) 110 | (cat 3 (crip (flop salt)) dat.seed) 111 | -- 112 | -- 113 | -------------------------------------------------------------------------------- /proposal tech.md: -------------------------------------------------------------------------------- 1 | # Tanote proposal 2 | 3 | ## Technical summary 4 | 5 | ### Screen layout 6 | 7 | In a graphical interface of mostly text (eg, Groups, Escape, Journal), Tanote captures titled, textual notes (a UTF-8 string) with a set of metadata (author, faction, recipients, tags in the text, and backlinks in the text). It presents three areas of text on the screen: (1) set of all tags in the most recent versions of notes stored locally (authored by the ship owner, or received from others), where each tag is clickable to select it; (2) set of titles of notes, for either all notes, or only notes which contain all the selected tags; one note title may be clicked on at a time, to select it; (3) and the text and metadata of the selected note, or the list of versions of the selected note. 8 | 9 | ### Additional user interface 10 | 11 | Notes which are selected by tags, but which are not the selected note, which contain a backlink to the selected note, are indicated by presenting the note title in italics. The user can edit the recipients (and text and other metadata; except author, which is set to the ship’s @p) of a note, to send (ie, forward) it to a new set of recipients, which stores it as a new version of the note. 12 | 13 | ### Storage 14 | 15 | All notes with the same title are considered versions of the same note. A note is stored as a title, and then a list of its versions. Each note becomes a new immutable version once it has been stored locally (via an add UI element), or once it has been sent to its recipients (which also stores it locally as a new version). A received note is automatically added to the store, its tags (including metadata), are added to set of tags shown in the tags section (always all known tags in the latest versions of notes), and the title (if new) is added to the set of notes shown in the titles section (if it should be shown by the selected tags). To make a note disappear again from the index of tags (and also from the set of shown notes, unless we are displaying all notes), the recipient may add a new version with no text. 16 | 17 | ### Interoperability 18 | 19 | I’d like to store these notes in a way that other applications can get to them, which might be %graph-store (I don’t know enough about this yet). This may mean that the application is architected as a layer that is called by the (minimal) GUI to talk to primitives that actually work with the data, so other programs may use these primitives. (It’s early days in my understanding of Urbit app architecture.) 20 | 21 | ### Economy 22 | 23 | We could possibly monetize notes, either automatically by gating the sending of the note on a blockchain transaction or the presence of a subscriber gora, or manually by the author not sending the note until the transaction is performed elsewhere. This was not one of my primary goals in writing this, but it could help people create an economy within Urbit around the text of notes. (It’s up to the authors to make them worth paying for.;) There’s a tension between allowing other apps access to notes, and monetizing them, in that the other apps accessing paid notes should not themselves send the note elsewhere, to get around the payment mechanism. 24 | 25 | -------------------------------------------------------------------------------- /tanote/lib/story.hoon: -------------------------------------------------------------------------------- 1 | /- *story 2 | !: 3 | ^? 4 | |% 5 | :: XX generalize move to hoon.hoon 6 | ++ dif-ju 7 | |= [a=story b=story] 8 | ^- story 9 | :: if 0 is the empty set, 10 | :: a \ 0 = a 11 | :: 0 \ b = 0 :: anything in 0 but not in b is by definition 0 12 | :: 13 | ?: =(~ a) ~ 14 | :: uno := (a-b) + (merged items in both a and b) + (b-a) 15 | :: ret := (a-b) + (merged items in both a and b) 16 | :: ret = (~(int by a) uno) :: preserve only the entries whose keys are in a 17 | =/ uno=story 18 | %- (~(uno by a) b) 19 | |= [k=tako:clay proses-a=proses proses-b=proses] 20 | ^- proses 21 | (~(dif in proses-a) proses-b) 22 | :: 23 | =/ ret=story (~(int by a) uno) 24 | :: normalizing step, remove any keys with null sets, 25 | :: which can occur if proses-a == proses-b above 26 | %- ~(gas by *story) 27 | (skip ~(tap by ret) |=([k=* v=proses] ?=(~ v))) 28 | :: 29 | ++ uni-ju 30 | |= [a=story b=story] 31 | ^- story 32 | :: 0 + b = b 33 | ?: =(~ a) b 34 | %- (~(uno by a) b) 35 | |= [k=tako:clay proses-a=proses proses-b=proses] 36 | ^- proses 37 | (~(uni in proses-a) proses-b) 38 | :: 39 | :: Canonical textual representation 40 | :: 41 | ++ tako-to-text 42 | |= [=tako:clay] 43 | ^- tape 44 | "commit: {<`@uv`tako>}\0a" 45 | :: 46 | ++ proses-to-text 47 | |= [=proses] 48 | ^- tape 49 | =/ proses-list=(list prose) ~(tap in proses) 50 | ?: ?=(~ proses-list) "" 51 | ?: ?=([prose ~] proses-list) 52 | (prose-to-text i.proses-list) 53 | %- tail 54 | %^ spin `(list prose)`t.proses-list 55 | (prose-to-text i.proses-list) 56 | |= [prz=prose state=tape] 57 | ^- [prose tape] 58 | :- prz 59 | ;: welp 60 | state 61 | "|||" 62 | "\0a" 63 | (prose-to-text prz) 64 | == 65 | :: 66 | ++ prose-to-text 67 | |= prz=prose 68 | =/ [title=@t body=@t] prz 69 | ^- tape 70 | ;: welp 71 | "{(trip title)}" 72 | "\0a\0a" 73 | "{(trip body)}" 74 | "\0a" 75 | == 76 | :: 77 | :: Parsers 78 | :: 79 | ++ parse-commit-hash 80 | ;~ sfix 81 | ;~ pfix (jest 'commit: ') 82 | (cook @uv ;~(pfix (jest '0v') viz:ag)) 83 | == 84 | :: 85 | (just '\0a') 86 | == 87 | :: 88 | ++ parse-title 89 | ;~ sfix 90 | (cook crip (star prn)) 91 | (jest '\0a\0a') 92 | == 93 | :: 94 | ++ parse-body 95 | %+ cook of-wain:format 96 | %- star 97 | ;~ less 98 | ;~(pose (jest '|||\0a') (jest '---\0a')) 99 | (cook crip ;~(sfix (star prn) (just '\0a'))) 100 | == 101 | :: 102 | ++ parse-prose ;~(plug parse-title parse-body) 103 | ++ parse-rest-proses (star ;~(pfix (jest '|||\0a') parse-prose)) 104 | ++ parse-proses (cook silt ;~(plug parse-prose parse-rest-proses)) 105 | ++ parse-chapter ;~(plug parse-commit-hash parse-proses) 106 | ++ parse-story 107 | (cook ~(gas by *story) (star ;~(sfix parse-chapter (jest '---\0a')))) 108 | :: 109 | :: N.B: If conflicting messages are written individually, 110 | :: instead of under the same commit, we will overwrite previous entries 111 | :: with later ones due to the nature of gas:by. 112 | -- 113 | -------------------------------------------------------------------------------- /~tonned-fampet 2022-06-23.md: -------------------------------------------------------------------------------- 1 | [[~monsut-bidnym]]: [[~tonned-fampet]], I think [[knowledge management]] on [[Urbit]] is a big project, but could encompass all of these things. [[Holium]] is making a bid at this with [[Engram]]. 2 | 3 | [[~tonned-fampet]]: [[~monsut-bidnym]], this has probably been said before, but a feature that would be really nice for [[Engram]] is [[bi-directional linking]], similar to [[Roam Research]] and [[Obsidian]]. My wife is a heavy user of Roam; although she has an [[Urbit planet]] that I gave her but rarely uses it. She has said that if there were a Roam competitor on Urbit she would actually use the platform. 4 | 5 | If her view is any indication, a Roam competitor on Urbit could be a killer app that could drive more mainstream adoption of Urbit, much more so than a reproduction of [[Google Docs]] or whatever. Google Docs is free, and so it will only be true Urbit believers already on the platform that would be interested in using an Urbit-based competitor to a Google product. But Roam Research costs about $15 a month, and so Roam users would have a strong financial incentive to take the time to set up a personal server to run an Urbit-based Roam competitor if it means eliminating lock-in to an expensive [[SaaS]] offering. An Urbit-based Roam competitor would also hit the right sweet spot of decentralization. If you don't want to pay for Roam Research, your best option is to use Obsidian, in which case you are stuck using a knowledge graph tied to your PC. 6 | 7 | [[~ponhec-picwen]]: I use Obsidian synced between my laptop and phone, so if one crashes the other can resync the replacement. I plan to have [[bi-directional linking]] in %[[tanote/tanote]], but I'm still working on internals, like structuring notes into histories and histories into stores, and extracting tags and back links from stores, to have the right displays on the front end. Also, I have no real plans to make an "[[Urbsidian]]": if we liken [[Emacs]] to [[Obsidian]], then what I want to create with %[[tanote]] is more like [[vi]] (or [[vim]]). 8 | 9 | I should also mention that I feel %[[tanote]] will be better at sharing than any of the mentioned tools, since it will be able to share (and record the fact of that sharing) specific versions of specific notes individually. Also, if it works out, my plan is to let you optionally gate the sharing on whether the recipient(s) have a specific [[gora]] that you can set per version of a note. 10 | 11 | [[~sarlev-sarsen]]: Build It. <<< My general statement for all things urbit notetaking/pkm related. There is lots of pontificating on this topic and the best way to figure out what works best is most certainly to start doing it. [[~ponhec-picwen]] is working on a proposal for this which is rad, and [[Engram]] is still an open bounty as of now, but would be good to see a few more options out there as well. [[~ribben-donnyl]] is working on an [[iOS]] mobile notes app that stores in your urbit, as well. 12 | 13 | [[~tonned-fampet]]: [[~ponhec-picwen]], sounds great—is there a group where I can follow the development progress? 14 | 15 | [[~ponhec-picwen]]: [[~tonned-fampet]]: I update (at least weekly) the proposal notebook in my tah-noh-tay group with the latest progress, and you can watch my [[GitHub]] repo catenate/[[tanote/tanote]] for commits. 16 | -------------------------------------------------------------------------------- /tanote/lib/verb.hoon: -------------------------------------------------------------------------------- 1 | :: Print what your agent is doing. 2 | :: 3 | /- verb 4 | :: 5 | |= [loud=? =agent:gall] 6 | =| bowl-print=_| 7 | ^- agent:gall 8 | |^ !. 9 | |_ =bowl:gall 10 | +* this . 11 | ag ~(. agent bowl) 12 | :: 13 | ++ on-init 14 | ^- (quip card:agent:gall agent:gall) 15 | %- (print bowl |.("{}: on-init")) 16 | =^ cards agent on-init:ag 17 | [[(emit-event %on-init ~) cards] this] 18 | :: 19 | ++ on-save 20 | ^- vase 21 | %- (print bowl |.("{}: on-save")) 22 | on-save:ag 23 | :: 24 | ++ on-load 25 | |= old-state=vase 26 | ^- (quip card:agent:gall agent:gall) 27 | %- (print bowl |.("{}: on-load")) 28 | =^ cards agent (on-load:ag old-state) 29 | [[(emit-event %on-load ~) cards] this] 30 | :: 31 | ++ on-poke 32 | |= [=mark =vase] 33 | ^- (quip card:agent:gall agent:gall) 34 | %- (print bowl |.("{}: on-poke with mark {}")) 35 | ?: ?=(%verb mark) 36 | ?- !<(?(%loud %bowl) vase) 37 | %loud `this(loud !loud) 38 | %bowl `this(bowl-print !bowl-print) 39 | == 40 | =^ cards agent (on-poke:ag mark vase) 41 | [[(emit-event %on-poke mark) cards] this] 42 | :: 43 | ++ on-watch 44 | |= =path 45 | ^- (quip card:agent:gall agent:gall) 46 | %- (print bowl |.("{}: on-watch on path {}")) 47 | =^ cards agent 48 | ?: ?=([%verb %events ~] path) 49 | [~ agent] 50 | (on-watch:ag path) 51 | [[(emit-event %on-watch path) cards] this] 52 | :: 53 | ++ on-leave 54 | |= =path 55 | ^- (quip card:agent:gall agent:gall) 56 | %- (print bowl |.("{}: on-leave on path {}")) 57 | ?: ?=([%verb %event ~] path) 58 | [~ this] 59 | =^ cards agent (on-leave:ag path) 60 | [[(emit-event %on-leave path) cards] this] 61 | :: 62 | ++ on-peek 63 | |= =path 64 | ^- (unit (unit cage)) 65 | %- (print bowl |.("{}: on-peek on path {}")) 66 | (on-peek:ag path) 67 | :: 68 | ++ on-agent 69 | |= [=wire =sign:agent:gall] 70 | ^- (quip card:agent:gall agent:gall) 71 | %- (print bowl |.("{}: on-agent on wire {}, {<-.sign>}")) 72 | =^ cards agent (on-agent:ag wire sign) 73 | [[(emit-event %on-agent wire -.sign) cards] this] 74 | :: 75 | ++ on-arvo 76 | |= [=wire =sign-arvo] 77 | ^- (quip card:agent:gall agent:gall) 78 | %- %+ print bowl |. 79 | "{}: on-arvo on wire {}, {<[- +<]:sign-arvo>}" 80 | =^ cards agent (on-arvo:ag wire sign-arvo) 81 | [[(emit-event %on-arvo wire [- +<]:sign-arvo) cards] this] 82 | :: 83 | ++ on-fail 84 | |= [=term =tang] 85 | ^- (quip card:agent:gall agent:gall) 86 | %- (print bowl |.("{}: on-fail with term {}")) 87 | =^ cards agent (on-fail:ag term tang) 88 | [[(emit-event %on-fail term) cards] this] 89 | -- 90 | :: 91 | ++ print 92 | |= [=bowl:gall render=(trap tape)] 93 | ^+ same 94 | =? . bowl-print 95 | %- (slog >bowl< ~) 96 | . 97 | ?. loud same 98 | %- (slog [%leaf $:render] ~) 99 | same 100 | :: 101 | ++ emit-event 102 | |= =event:verb 103 | ^- card:agent:gall 104 | [%give %fact ~[/verb/events] %verb-event !>(event)] 105 | -- 106 | -------------------------------------------------------------------------------- /brainstorm.md: -------------------------------------------------------------------------------- 1 | [[urbit app]] idea: tags-notes-text 2 | pronounced tah-noh-teh 3 | [[tanote/tanote]] 4 | 5 | community knowledge manager 6 | Teaching Assistant 7 | note-taker 8 | 9 | Tags at top: set of tags. bold if selected for display filter (clicked). italic if tagged by currently selected note (in text of note after `#`). list of @p are pulled from %pals, or ride with notes shared by others to you (*id est*, you are named as a reader). bold @p for author of current version of note. italic @p for readers of current version of note. `*` displays all notes. `/` displays all notes with backlinks to the currently selected note. update when a version is added: when a local version is saved, when a note is shared (which also saves it), or when a version of a note is received. ~~each tag needs to store a list of notes which referred to it in any version.~~ 10 | 11 | > * / *later* other **~ponhec-picwen** __*tanote*__ that 12 | 13 | --- 14 | 15 | Notes in middle: set of notes which match the tags selected for display filter. selected note (clicked) is bold. click on a note to switch to it. italic notes are those which still refer to the current note with a `[[]]` reference (backlink). updated when a version is added. ~~each note needs to maintain a list of other notes which referred to it in any version, and check whether the latest version still does.~~ 16 | 17 | > **tanote idea**. *tanote literate program*. tanote overview. tanote use cases. 18 | 19 | --- 20 | 21 | Text versions at bottom: current note text, sharing tools. title is first line. list of authors that changed the text in second line. text in `[[]]` is taken to be other notes. text from `#` to space is taken to be a tag. 22 | 23 | *by* (read-only) is the writer of this version of the note. Change to self when the note is edited. 24 | 25 | _as_ is the name of the faction (_confer_ [[Yarvin 2007]]) of the point of view of the note. 26 | 27 | *to* is the set of readers (exclude writers) to which this is shared. Share the current note when someone is named as a reader, and the author clicks *to* (or moves to a different line). 28 | 29 | *re* is the title of the note. update title in list of notes when this is clicked (or when the author moves to a different line), which locally saves a version. 30 | 31 | *no* is a serial count of the version saved when this is clicked, and *of* is the highest version known. when a new version is received, increment *of* (read-only). if an existing version is entered and this is clicked, present that version. if a version that does not yet exist is entered and this is clicked, save the text as that version. when a note is selected, display the highest version known. not everyone's correspondences between version number and text will be the same, since they may edit without sharing, may be added later, and may receive versions in different orders. 32 | 33 | > by ~ponhec-picwen as creator 34 | > to 35 | > re tanote idea 36 | > no 1 of 1 37 | > 38 | > Would be really nice to #later write a [[tanote literate program]] (which refers back to this note) to implement the #tanote idea. 39 | 40 | --- 41 | 42 | tanote (group) 43 | - code 44 | - user 45 | - risk 46 | - test 47 | 48 | start with just chat, notebook, and links 49 | 50 | for each of curt: chat, notebook, and links 51 | 52 | -------------------------------------------------------------------------------- /session Nocturna.md: -------------------------------------------------------------------------------- 1 | [[tanote/tanote]] [[session init]] 2 | 3 | General outline of the format of the screen. 4 | 5 | > tags and @ps 6 | > 7 | > names of notes. separated by periods. like sentences. 8 | > 9 | > headers of the text 10 | > body of the text 11 | 12 | The starting screen, before adding any version. The list of @ps comes from %pals. `|` represents the cursor at the start of a text entry field. Struck-out text is changeable. Highlighted text is clickable. Your own id is italic because it’s in the text of the note. The star should be bold, since it is selected by default, and highlighted, since it is clickable. 13 | 14 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==_~ponhec-picwen_== 15 | > 16 | > 17 | > 18 | > by ~ponhec-picwen as | 19 | > ==to== | 20 | > re | 21 | > ==no== ~~1~~ of 1 22 | > 23 | > | 24 | 25 | Name the note, add some text, set a recipient. 26 | 27 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==_~ponhec-picwen_== 28 | > 29 | > 30 | > 31 | > by ~ponhec-picwen as ~~muse~~ 32 | > ==to== ~~`~`petlod-byrons~~ 33 | > re ~~Nocturna~~ 34 | > ==no== ~~1~~ of 1 35 | > 36 | > ~~She walks in beauty, like the night…~~ 37 | 38 | ==no== saves the note, adding a version, if the version number is not already stored. 39 | 40 | Add tags and @ps automatically when a version is added, if not already known. 41 | 42 | Add note regards automatically when a version is added, if not already known. Bold the name of the current note. 43 | 44 | The text of the note is no longer editable. 45 | 46 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==~petlod-byrons== ==_~ponhec-picwen_== ==beauty== ==night== 47 | > 48 | > ==**Nocturna**==. 49 | > 50 | > by ~ponhec-picwen as muse 51 | > ==to== ~petlod-byrons 52 | > re Nocturna 53 | > ==no== 1 of 1 54 | > 55 | > She walks in #beauty, like the #night… 56 | 57 | Edit and resave to add another version and its tags and @ps. 58 | 59 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==_~petlod-byrons_== ==_~ponhec-picwen_== ==_beauty_== ==_bright_== ==_dark_== ==_day_== ==_Heaven_== ==_light_== ==_night_== 60 | > 61 | > ==**Nocturna**==. 62 | > 63 | > by ~ponhec-picwen as ~~poet~~ 64 | > ==to== ~~`~`petlod-byrons~~ 65 | > re ~~Nocturna~~ 66 | > ==no== ~~2~~ of 2 67 | > 68 | > ~~She walks in #beauty, like the #night 69 | > of cloudless climes and starry skies 70 | > and all that’s best of #dark and #bright 71 | > meet in her aspect and her eyes 72 | > this mellow’d to that tender #light 73 | > which #Heaven to gaudy #day denies.~~ 74 | 75 | Set the version field and click ==no== to switch back to the previous version. 76 | 77 | > ==`*`== ==~hatryx-lastud== ==~paldev== ==_~petlod-byrons_== ==_~ponhec-picwen_== ==_beauty_== ==bright== ==dark== ==day== ==Heaven== ==light== ==_night_== 78 | > 79 | > ==**Nocturna**==. 80 | > 81 | > by ~ponhec-picwen as muse 82 | > ==to== ~petlod-byrons 83 | > re Nocturna 84 | > ==no== 1 ==of== 2 85 | > 86 | > She walks in #beauty, like the #night… 87 | 88 | ==To== adds a version (if not already added), and sends the text to any named recipients. Re-sending an existing version adds a new version for the recipient. 89 | 90 | ==Of== lists, in the text section, the versions of the node available, each with the first line, or the (beginning of the) diff from the previous version. 91 | 92 | > 1 muse: She walks in #beauty, like the #night… 93 | > 2 poet: She walks in #beauty, like the #night~~...~~**of cloudless climes and starry skies** 94 | 95 | -------------------------------------------------------------------------------- /tanote/lib/pill.hoon: -------------------------------------------------------------------------------- 1 | :: |pill: helper functions for making pills 2 | :: 3 | /- dice 4 | ^? 5 | |% 6 | :: 7 | +$ pill 8 | $% [%ivory p=(list)] 9 | $: %pill 10 | nam=term 11 | boot-ova=(list) 12 | kernel-ova=(list unix-event) 13 | userspace-ova=(list unix-event) 14 | == == 15 | :: 16 | +$ unix-event 17 | %+ pair wire 18 | $% [%wack p=@] 19 | [%what p=(list (pair path (cask)))] 20 | [%whom p=ship] 21 | [%boot ? $%($>(%fake task:jael) $>(%dawn task:jael))] 22 | [%wyrd p=vere] 23 | [%verb p=(unit ?)] 24 | unix-task 25 | == 26 | :: +boot-ovum: boostrap kernel filesystem load 27 | :: 28 | ++ boot-ovum 29 | |= [hoon=cord arvo=cord] 30 | :~ //arvo 31 | %what 32 | [/sys/hoon hoon/hoon] 33 | [/sys/arvo hoon/arvo] 34 | == 35 | :: +file-ovum: userspace filesystem load 36 | :: 37 | :: bas: full path to / directory 38 | :: 39 | ++ file-ovum 40 | =/ directories=(list path) 41 | :~ /app :: %gall applications 42 | /gen :: :dojo generators 43 | /lib :: libraries 44 | /mar :: mark definitions 45 | /sur :: structures 46 | /sys :: system files 47 | /ted :: :spider strands 48 | /web :: %eyre web content 49 | /desk :: desk manifest 50 | == 51 | |= [des=desk bas=path] 52 | ^- unix-event 53 | %. directories 54 | |= :: sal: all spurs to load from 55 | :: 56 | sal=(list spur) 57 | ^- unix-event 58 | :: 59 | :: hav: all user files 60 | :: 61 | =; hav ~& user-files+(lent hav) 62 | =/ =yuki:clay 63 | :- *(list tako:clay) 64 | %- ~(gas by *(map path (each page lobe:clay))) 65 | (turn hav |=([=path =page] [path &+page])) 66 | [/c/sync [%park des &+yuki *rang:clay]] 67 | =| hav=(list [path page]) 68 | |- ^+ hav 69 | ?~ sal ~ 70 | =. hav $(sal t.sal) 71 | :: 72 | :: tyl: spur 73 | :: 74 | =/ tyl i.sal 75 | |- ^+ hav 76 | :: 77 | :: pax: full path at `tyl` 78 | :: lon: directory at `tyl` 79 | :: 80 | =/ lyt (flop tyl) 81 | =/ pax (weld bas lyt) 82 | =/ lon .^(arch %cy pax) 83 | =? hav ?=(^ fil.lon) 84 | :_ hav 85 | :- lyt 86 | ?. ?=([%azimuth-snapshot *] tyl) 87 | [mark=;;(@tas (head tyl)) noun=.^(* %cx pax)] 88 | =; convert 89 | mime/(convert .^(snap-state:dice %cx pax)) 90 | .^($-(snap-state:dice mime) %cf (weld bas /azimuth-snapshot/mime)) 91 | =/ all ~(tap by dir.lon) 92 | |- ^+ hav 93 | ?~ all hav 94 | $(all t.all, hav ^$(tyl [p.i.all tyl])) 95 | :: 96 | :: +file-ovum2: electric boogaloo 97 | :: 98 | ++ file-ovum2 |=(p=path `unix-event`[//arvo what/(user-files p)]) 99 | :: 100 | :: +user-files: all userspace hoon files 101 | :: 102 | ++ user-files 103 | |= bas=path 104 | %. directories:file-ovum 105 | |= sal=(list spur) 106 | ^- (list (pair path (cask))) 107 | :: 108 | :: hav: all user files 109 | :: 110 | =| hav=(list (pair path (cask))) 111 | |- ^+ hav 112 | ?~ sal ~ 113 | =. hav $(sal t.sal) 114 | :: 115 | :: tyl: spur 116 | :: 117 | =/ tyl i.sal 118 | |- ^+ hav 119 | :: 120 | :: pax: full path at `tyl` 121 | :: lon: directory at `tyl` 122 | :: 123 | =/ pax (weld bas (flop tyl)) 124 | =/ lon .^(arch %cy pax) 125 | =? hav ?=(^ fil.lon) 126 | :: 127 | :: install only hoon files for now 128 | :: 129 | ?. ?=([%hoon *] tyl) 130 | hav 131 | :_ hav 132 | [(flop `path`t.tyl) hoon/.^(@t %cx pax)] 133 | :: 134 | =/ all ~(tap by dir.lon) 135 | |- ^+ hav 136 | ?~ all hav 137 | $(all t.all, hav ^$(tyl [p.i.all tyl])) 138 | -- 139 | -------------------------------------------------------------------------------- /tanote/gen/help.hoon: -------------------------------------------------------------------------------- 1 | /+ tanote 2 | :- %say 3 | |= * 4 | :- %noun 5 | =/ note0=note:tanote [~ponhec-picwen "reviewer" [0x0 ~ponhec-picwen] ~ "note" "A note is composed of several #field: by, as, if, to, re, and text."] 6 | =/ note-history=history:tanote (add-note-history:tanote note0 ["note" ~]) 7 | =/ history0=note:tanote [~ponhec-picwen "reviewer" [0x0 ~ponhec-picwen] ~ "history" "A history is a list of notes, with the latest note first; and a regards, which is the same as the re #field of each note."] 8 | =/ history-history=history:tanote (add-note-history:tanote history0 ["history" ~]) 9 | =/ history1=note:tanote [~ponhec-picwen "reviewer" [0x0 ~ponhec-picwen] ~ "history" "A [[history]] is a #list of notes, with the latest [[note]] first; and a [[regards]], which a #tape (text string) that is the same as the [[re]] field of each [[note]]."] 10 | =/ updated-history-history=history:tanote (add-note-history:tanote history1 history-history) 11 | =/ store0=note:tanote [~ponhec-picwen "reviewer" [0x0 ~ponhec-picwen] ~ "store" "A store is a list of histories."] 12 | =/ store-history=history:tanote (add-note-history:tanote store0 ["store" ~]) 13 | =/ help0=store:tanote (add-note-store:tanote note0 (add-note-store:tanote history0 (add-note-store:tanote store0 ~))) 14 | =/ help1=store:tanote (add-note-store:tanote history1 help0) 15 | =/ all0=front:tanote [tab="default" tags=~ tugs=~ regards=~ histories=help0] 16 | =/ all1=front:tanote [tab="default" tags=~ tugs=~ regards=~ histories=help1] 17 | =/ filter-regards0=front:tanote (filter-front-regards:tanote [tab="histories" tags=~ tugs=~ regards="history" histories=help0]) 18 | =/ filter-field1=front:tanote (filter-front-tugs:tanote [tab="field" tags=~ tugs=(sy ~["#field"]) regards=~ histories=help1]) 19 | :- =(note-history ["note" ~[note0]]) 20 | :- =(history-history ["history" ~[history0]]) 21 | :- =(store-history ["store" ~[store0]]) 22 | :- help0 23 | :- .= help0 24 | ~[note-history history-history store-history] 25 | :- .= (extract-tags-store:tanote help0) 26 | (sy ~["#field"]) 27 | :- .= (extract-backlinks-store:tanote help0) 28 | (sy ~["reviewer"]) 29 | :- (filter-store-tag:tanote help0 "#field") 30 | :- .= (filter-store-tag:tanote help0 "#field") 31 | ~[history-history note-history] 32 | :- (find-store-regards:tanote help0 "history") 33 | :- .= (find-store-regards:tanote help0 "history") 34 | history-history 35 | :- =(updated-history-history ["history" ~[history1 history0]]) 36 | :- help1 37 | :- .= help1 38 | ~[store-history updated-history-history note-history] 39 | :- .= (extract-tags-store:tanote help1) 40 | (sy ~["#field" "#list" "#tape"]) 41 | :- .= (extract-backlinks-store:tanote help1) 42 | (sy ~["reviewer" "history" "note" "regards" "re" "note"]) 43 | :- (filter-store-tag:tanote help1 "#field") 44 | :- .= (filter-store-tag:tanote help1 "#field") 45 | ~[note-history] 46 | :- (find-store-regards:tanote help1 "history") 47 | :- .= (find-store-regards:tanote help1 "history") 48 | updated-history-history 49 | :- (display-tags:tanote help0) 50 | :- .= (display-tags:tanote help0) 51 | (sy ~["*" "/" "#field"]) 52 | :- (display-tags:tanote help1) 53 | :- .= (display-tags:tanote help1) 54 | (sy ~["*" "/" "#field" "#list" "#tape"]) 55 | :- (display-backlinks:tanote help0) 56 | :- .= (display-backlinks:tanote help0) 57 | (sy ~["reviewer"]) 58 | :- (display-backlinks:tanote help1) 59 | :- .= (display-backlinks:tanote help1) 60 | (sy ~["reviewer" "history" "note" "regards" "re" "note"]) 61 | :- (list-regards-store:tanote help0) 62 | :- .= (list-regards-store:tanote help0) 63 | ~["store" "history" "note"] 64 | :- all0 65 | :- .= histories.all0 66 | help0 67 | :- .= (list-regards-store:tanote histories.all0) 68 | ~["store" "history" "note"] 69 | :- all1 70 | :- .= histories.all1 71 | help1 72 | :- .= (list-regards-store:tanote histories.all1) 73 | ~["note" "history" "store"] 74 | :- filter-regards0 75 | :- .= filter-regards0 76 | [tab="histories" tags=~ tugs=~ regards="history" histories=~[history-history]] 77 | :- filter-field1 78 | ~ 79 | :: DO NOT EDIT THIS FILE. Auto-generated from verbose help.md by lit. 80 | -------------------------------------------------------------------------------- /interfaces.md: -------------------------------------------------------------------------------- 1 | # Tanote interfaces 2 | 3 | ## graph store 4 | 5 | ### note version structure 6 | 7 | An @p called `by`, which is the identity of the author of this version of the note. This field is considered a tag of this version of the note. 8 | 9 | A tape called `as`, which is the faction (_confer_ [[Yarvin 2007]]), or the point of view, of this version of the note. This field is considered a tag of this version of the note. 10 | 11 | A cell called `if`, with a @ux and an @p, which store the number and ship of the source of a gora. If the @ux is not 0, then this gora is checked before a note version is received (naïve approach) or sent (jaded approach). Both the @ux and @p are considered tags of this version of the note. 12 | 13 | A list of @p called `to`, which is the list of recipients of this version of the note. 14 | 15 | A tape called `re`, which is the regards, or subject, or title of the note. 16 | 17 | A tape called `text`, which is the body of this version of the note. Tags (`#tag`) in the text are considered tags of this version of the note. Backlinks ([[back link]]) in the text are references to the `regards` of other histories. 18 | 19 | See also the [[tanote/glossary]]. 20 | 21 | ### history structure 22 | 23 | A tape called `regards`, which is the `re` field of each note. All the note versions wich the same `re` are stored together in one history, with a single `regards`. 24 | 25 | A list of notes, called `versions`. The most recent note is first, and the remainder of the notes are in reverse-chronological order, as seen on this ship. 26 | 27 | ### store structure 28 | 29 | A list of histories, each with a different `regards`. 30 | 31 | ## libraries 32 | 33 | ### tanote 34 | 35 | [[tanote/tanote/lib/tanote]] contains the data structure of a note version, history, and store, and the arms which work with them. 36 | 37 | ### tanote-ames 38 | 39 | Send a note version to another ship. 40 | 41 | Receive a note version from another ship. 42 | 43 | ### tanote-gall 44 | 45 | Tanote as an application or agent. 46 | 47 | ### tanote-gora 48 | 49 | Check for the existence of a gora. 50 | 51 | ### tanote-graphstore 52 | 53 | Preserve the contents of a store. 54 | 55 | Load a preserved store to a running store. 56 | 57 | ## generators 58 | 59 | ### help 60 | 61 | [[help]] generates notes which describe usage and internals of the %tanote desk. 62 | 63 | ### testlib 64 | 65 | [[testlib]] generates the results of tests of arms of the [[tanote/tanote/lib/tanote]] library. 66 | 67 | ## front end 68 | 69 | Front end in three parts, split into three horizontal sections, one atop another. 70 | 71 | ### top section: tags 72 | 73 | First, all the tags, listed one after another as a paragraph. 74 | 75 | Each tag may separately be selected, which determines which notes are displayed in the second section. Selected tags are set in bold. 76 | 77 | Default tags are `*` (display all notes), `/` (display all notes with backlinks to the selected note), and the @p of our ship. 78 | 79 | ### middle section: note regards 80 | 81 | Second, a paragraph which displays a list of regards, of notes which have the selected tags in the text of the latest version. 82 | 83 | One note may be selected, which determines which note or history is displayed in the third section. 84 | 85 | Displayed notes which have backlinks to the selected note are set in italics. 86 | 87 | ### bottom section: note version(s) 88 | 89 | Third, a version of the selected note (a paragraph of metadata, and the text as it is formatted by the user), or a list of all the versions of the selected note. 90 | 91 | The metadata contains the generated phrase “==no== # ==of== #“. The first number is the count (the earliest version is 1) of this version in the `versions` list of the note’s history. The second version is the number of versions in the note’s history. 92 | 93 | Some fields in this section are editable, which buffers another version of the note and increments the note version. The buffered changes are saved as a new version when the button ==no== is clicked. Clicking on the button-word ==no== adds the buffered version to the beginning of the note’s history, which becomes the most recent version of the note. 94 | 95 | Clicking on the button-word ==of== displays the list of versions of this note. One of these may be selected to display that version of the note. 96 | 97 | -------------------------------------------------------------------------------- /tanote/lib/bitcoin-utils.hoon: -------------------------------------------------------------------------------- 1 | :: lib/bitcoin-utils.hoon 2 | :: Utilities for working with BTC data types and transactions 3 | :: 4 | /- *bitcoin 5 | ~% %bitcoin-utils-lib ..part ~ 6 | |% 7 | :: 8 | :: TODO: move this bit/byt stuff to zuse 9 | :: bit/byte utilities 10 | :: 11 | :: 12 | :: +blop: munge bit and byt sequences (cat, flip, take, drop) 13 | :: 14 | ++ blop 15 | ~/ %blop 16 | |_ =bloq 17 | +$ biyts [wid=@ud dat=@] 18 | ++ cat 19 | |= bs=(list biyts) 20 | ^- biyts 21 | :- (roll (turn bs |=(b=biyts -.b)) add) 22 | (can bloq (flop bs)) 23 | :: +flip: flip endianness while preserving lead/trail zeroes 24 | :: 25 | ++ flip 26 | |= b=biyts 27 | ^- biyts 28 | [wid.b (rev bloq b)] 29 | :: +take: take n bloqs from front 30 | :: pads front with extra zeroes if n is longer than input 31 | :: 32 | ++ take 33 | |= [n=@ b=biyts] 34 | ^- biyts 35 | ?: (gth n wid.b) 36 | [n dat.b] 37 | [n (rsh [bloq (sub wid.b n)] dat.b)] 38 | :: +drop: drop n bloqs from front 39 | :: returns 0^0 if n >= width 40 | :: 41 | ++ drop 42 | |= [n=@ b=biyts] 43 | ^- biyts 44 | ?: (gte n wid.b) 45 | 0^0x0 46 | =+ n-take=(sub wid.b n) 47 | [n-take (end [bloq n-take] dat.b)] 48 | -- 49 | ++ byt ~(. blop 3) 50 | :: 51 | ++ bit 52 | ~/ %bit 53 | =/ bl ~(. blop 0) 54 | |% 55 | ++ cat cat:bl:bit 56 | ++ flip flip:bl:bit 57 | ++ take take:bl:bit 58 | ++ drop drop:bl:bit 59 | ++ from-atoms 60 | |= [bitwidth=@ digits=(list @)] 61 | ^- bits 62 | %- cat:bit 63 | %+ turn digits 64 | |= a=@ 65 | ?> (lte (met 0 a) bitwidth) 66 | [bitwidth `@ub`a] 67 | :: +to-atoms: convert bits to atoms of bitwidth 68 | :: 69 | ++ to-atoms 70 | |= [bitwidth=@ bs=bits] 71 | ^- (list @) 72 | =| res=(list @) 73 | ?> =(0 (mod wid.bs bitwidth)) 74 | |- 75 | ?: =(0 wid.bs) res 76 | %= $ 77 | res (snoc res dat:(take:bit bitwidth bs)) 78 | bs (drop:bit bitwidth bs) 79 | == 80 | -- 81 | :: big endian sha256: input and output are both MSB first (big endian) 82 | :: 83 | ++ sha256 84 | ~/ %sha256 85 | |= =byts 86 | ^- hexb 87 | %- flip:byt 88 | [32 (shay (flip:byt byts))] 89 | :: 90 | ++ dsha256 91 | ~/ %dsha256 92 | |= =byts 93 | (sha256 (sha256 byts)) 94 | :: 95 | ++ hash-160 96 | ~/ %hash-160 97 | |= val=byts 98 | ^- hexb 99 | =, ripemd:crypto 100 | :- 20 101 | %- ripemd-160 102 | (sha256 val) 103 | 104 | :: 105 | :: hxb: hex parsing utilities 106 | :: 107 | ++ hxb 108 | ~% %hxb ..blop ~ 109 | |% 110 | ++ from-cord 111 | ~/ %from-cord 112 | |= h=@t 113 | ^- hexb 114 | ?: =('' h) 1^0x0 115 | :: Add leading 00 116 | :: 117 | =+ (lsh [3 2] h) 118 | :: Group by 4-size block 119 | :: 120 | =+ (rsh [3 2] -) 121 | :: Parse hex to atom 122 | :: 123 | =/ a (need (de:base16:mimes:html -)) 124 | [-.a `@ux`+.a] 125 | :: 126 | ++ to-cord 127 | ~/ %to-cord 128 | |= =hexb 129 | ^- cord 130 | (en:base16:mimes:html hexb) 131 | -- 132 | :: 133 | :: +csiz: CompactSize integers (a Bitcoin-specific datatype) 134 | :: https://btcinformation.org/en/developer-reference#compactsize-unsigned-integers 135 | :: - encode: big endian to little endian 136 | :: - decode: little endian to big endian 137 | :: 138 | ++ csiz 139 | ~% %csiz ..blop ~ 140 | |% 141 | ++ en 142 | ~/ %en 143 | |= a=@ 144 | ^- hexb 145 | =/ l=@ (met 3 a) 146 | ?: =(l 1) 1^a 147 | ?: =(l 2) (cat:byt ~[1^0xfd (flip:byt 2^a)]) 148 | ?: (lte l 4) (cat:byt ~[1^0xfe (flip:byt 4^a)]) 149 | ?: (lte l 8) (cat:byt ~[1^0xff (flip:byt 8^a)]) 150 | ~|("Cannot encode CompactSize longer than 8 bytes" !!) 151 | :: 152 | ++ de 153 | ~/ %de 154 | |= h=hexb 155 | ^- [n=hexb rest=hexb] 156 | =/ s=@ux dat:(take:byt 1 h) 157 | ?: (lth s 0xfd) [1^s (drop:byt 1 h)] 158 | ~| "Invalid compact-size at start of {}" 159 | =/ len=bloq 160 | ?+ s !! 161 | %0xfd 1 162 | %0xfe 2 163 | %0xff 3 164 | == 165 | :_ (drop:byt (add 1 len) h) 166 | %- flip:byt 167 | (take:byt (bex len) (drop:byt 1 h)) 168 | :: +dea: atom instead of hexb for parsed CompactSize 169 | :: 170 | ++ dea 171 | |= h=hexb 172 | ^- [a=@ rest=hexb] 173 | => (de h) 174 | [dat.n rest] 175 | -- 176 | -- 177 | -------------------------------------------------------------------------------- /tanote/lib/sole.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/sole/lib 3 | :: 4 | /? 310 5 | /- *sole 6 | :::: 7 | :: 8 | |_ sole-share :: shared-state engine 9 | ++ abet +< 10 | ++ apply 11 | |= ted=sole-edit 12 | ^+ +> 13 | ?- -.ted 14 | %del +>.$(buf (weld (scag p.ted buf) (slag +(p.ted) buf))) 15 | %ins +>.$(buf (weld (scag p.ted buf) `_buf`[q.ted (slag p.ted buf)])) 16 | %mor |- ^+ +>.^$ 17 | ?~ p.ted 18 | +>.^$ 19 | $(p.ted t.p.ted, +>.^$ ^$(ted i.p.ted)) 20 | %nop +>.$ 21 | %set +>.$(buf p.ted) 22 | == 23 | :: 24 | :::: 25 | :: ++transmute: symmetric operational transformation. 26 | :: 27 | :: for any sole state +>, obeys 28 | :: 29 | :: =+ [x=(transmute a b) y=(transmute b a)] 30 | :: .= (apply:(apply a) x) 31 | :: (apply:(apply b) y) 32 | :: 33 | ++ transmute :: dex as after sin 34 | |= [sin=sole-edit dex=sole-edit] 35 | ~| [%transmute sin dex] 36 | ^- sole-edit 37 | ?: ?=(%mor -.sin) 38 | |- ^- sole-edit 39 | ?~ p.sin dex 40 | $(p.sin t.p.sin, dex ^$(sin i.p.sin)) 41 | :: 42 | ?: ?=(%mor -.dex) 43 | :- %mor 44 | |- ^- (list sole-edit) 45 | ?~ p.dex ~ 46 | [^$(dex i.p.dex) $(p.dex t.p.dex)] 47 | :: 48 | ?: |(?=(%nop -.sin) ?=(%nop -.dex)) dex 49 | ?: ?=(%set -.sin) [%nop ~] 50 | ?: ?=(%set -.dex) dex 51 | :: 52 | ?- -.sin 53 | %del 54 | ?- -.dex 55 | %del ?: =(p.sin p.dex) [%nop ~] 56 | ?:((lth p.sin p.dex) dex(p (dec p.dex)) dex) 57 | %ins ?:((lth p.sin p.dex) dex(p (dec p.dex)) dex) 58 | == 59 | :: 60 | %ins 61 | ?- -.dex 62 | %del ?:((lte p.sin p.dex) dex(p +(p.dex)) dex) 63 | %ins ?: =(p.sin p.dex) 64 | ?:((lth q.sin q.dex) dex dex(p +(p.dex))) 65 | ?:((lte p.sin p.dex) dex(p +(p.dex)) dex) 66 | == 67 | == 68 | :: 69 | ++ commit :: local change 70 | |= ted=sole-edit 71 | ^- sole-share 72 | abet:(apply(own.ven +(own.ven), leg [ted leg]) ted) 73 | :: 74 | :::: 75 | :: ++inverse: inverse of change in context. 76 | :: 77 | :: for any sole state +>, obeys 78 | :: 79 | :: =(+> (apply:(apply a) (inverse a))) 80 | :: 81 | ++ inverse :: relative inverse 82 | |= ted=sole-edit 83 | ^- sole-edit 84 | =. ted ?.(?=([%mor * ~] ted) ted i.p.ted) 85 | ?- -.ted 86 | %del [%ins p.ted (snag p.ted buf)] 87 | %ins [%del p.ted] 88 | %mor :- %mor 89 | %- flop 90 | |- ^- (list sole-edit) 91 | ?~ p.ted ~ 92 | :- ^$(ted i.p.ted) 93 | $(p.ted t.p.ted, +>.^$ (apply i.p.ted)) 94 | %nop [%nop ~] 95 | %set [%set buf] 96 | == 97 | :: 98 | ++ receive :: naturalize event 99 | |= sole-change 100 | ^- [sole-edit sole-share] 101 | ?. &(=(his.ler his.ven) (lte own.ler own.ven)) 102 | ~| [%receive-sync his+[his.ler his.ven] own+[own.ler own.ven]] 103 | !! 104 | ?> &(=(his.ler his.ven) (lte own.ler own.ven)) 105 | ?> |(!=(own.ler own.ven) =(`@`0 haw) =(haw (sham buf))) 106 | =. leg (scag (sub own.ven own.ler) leg) 107 | :: ~? !=(own.ler own.ven) [%miss-leg leg] 108 | =+ dat=(transmute [%mor leg] ted) 109 | :: ~? !=(~ leg) [%transmute from+ted to+dat ~] 110 | [dat abet:(apply(his.ven +(his.ven)) dat)] 111 | :: 112 | ++ remit :: conditional accept 113 | |= [cal=sole-change ask=$-((list @c) ?)] 114 | ^- [(unit sole-change) sole-share] 115 | =+ old=buf 116 | =^ dat +>+<.$ (receive cal) 117 | ?: (ask buf) 118 | [~ +>+<.$] 119 | =^ lic +>+<.$ (transmit (inverse(buf old) dat)) 120 | [`lic +>+<.$] 121 | :: 122 | ++ transmit :: outgoing change 123 | |= ted=sole-edit 124 | ^- [sole-change sole-share] 125 | [[[his.ven own.ven] (sham buf) ted] (commit ted)] 126 | :: 127 | ++ transceive :: receive and invert 128 | |= sole-change 129 | ^- [sole-edit sole-share] 130 | =+ old=buf 131 | =^ dat +>+<.$ (receive +<.$) 132 | [(inverse(buf old) dat) +>+<.$] 133 | :: 134 | ++ transpose :: adjust position 135 | |= pos=@ud 136 | =+ dat=(transmute [%mor leg] [%ins pos `@c`0]) 137 | ?> ?=(%ins -.dat) 138 | p.dat 139 | -- 140 | -------------------------------------------------------------------------------- /tanote/lib/bip/b174.hoon: -------------------------------------------------------------------------------- 1 | :: BIP174: PSBTs 2 | :: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki 3 | :: 4 | /- sur=bitcoin 5 | /+ bcu=bitcoin-utils 6 | =, sur 7 | =, bcu 8 | |% 9 | ++ en 10 | |% 11 | ++ globals 12 | |= rawtx=hexb 13 | ^- map:psbt 14 | :~ [[1 0x0] rawtx] 15 | == 16 | :: 17 | ++ input 18 | |= [only-witness=? i=in:psbt] 19 | ^- map:psbt 20 | %+ weld 21 | ?: only-witness ~ 22 | ~[[1^0x0 rawtx.i]] 23 | :~ (witness-tx i) 24 | (hdkey %input hdkey.i) 25 | == 26 | :: 27 | ++ output 28 | |= =out:psbt 29 | ^- map:psbt 30 | ?~ hk.out ~ 31 | :~ (hdkey %output u.hk.out) 32 | == 33 | :: 34 | ++ witness-tx 35 | |= i=in:psbt 36 | ^- keyval:psbt 37 | :- [1 0x1] 38 | %- cat:byt 39 | :~ (flip:byt 8^value.utxo.i) 40 | 1^0x16 41 | 2^0x14 42 | (hash-160 pubkey.hdkey.i) 43 | == 44 | :: 45 | ++ hdkey 46 | |= [=target:psbt h=^hdkey] 47 | ^- keyval:psbt 48 | =/ typ=@ux 49 | ?- target 50 | %input 0x6 51 | %output 0x2 52 | == 53 | =/ coin-type=hexb 54 | ?- network.h 55 | %main 56 | 1^0x0 57 | %testnet 58 | 1^0x1 59 | == 60 | :- (cat:byt ~[1^typ pubkey.h]) 61 | %- cat:byt 62 | :~ fprint.h 63 | 1^`@ux`bipt.h 3^0x80 64 | coin-type 3^0x80 65 | 4^0x80 66 | 1^`@ux`chyg.h 3^0x0 67 | (flip:byt 4^idx.h) 68 | == 69 | :: 70 | ++ keyval-byts 71 | |= kv=keyval:psbt 72 | ^- hexb 73 | %- cat:byt 74 | :~ 1^wid.key.kv 75 | key.kv 76 | 1^wid.val.kv 77 | val.kv 78 | == 79 | :: 80 | ++ map-byts 81 | |= m=map:psbt 82 | ^- (unit hexb) 83 | ?~ m ~ 84 | :- ~ 85 | %- cat:byt 86 | (turn m keyval-byts) 87 | -- 88 | ++ base64 89 | |= b=hexb 90 | ^- base64:psbt 91 | %- en:base64:mimes:html 92 | (flip:byt b) 93 | :: +encode: make base64 cord of PSBT 94 | :: - only-witness: don't include non-witness UTXO 95 | :: 96 | ++ encode 97 | |= $: only-witness=? 98 | rawtx=hexb 99 | txid=hexb 100 | inputs=(list in:psbt) 101 | outputs=(list out:psbt) 102 | == 103 | ^- base64:psbt 104 | =/ sep=(unit hexb) `1^0x0 105 | =/ final=(list (unit hexb)) 106 | %+ join sep 107 | %+ turn 108 | %- zing 109 | :~ ~[(globals:en rawtx)] 110 | (turn inputs (cury input:en only-witness)) 111 | (turn outputs output:en) 112 | == 113 | map-byts:en 114 | %- base64:en 115 | ^- byts 116 | %- cat:byt 117 | %+ weld ~[[5 0x70.7362.74ff]] 118 | (murn (snoc final sep) same) 119 | :: 120 | ++ parse 121 | |= psbt-base64=cord 122 | ^- (list map:psbt) 123 | =/ todo=hexb 124 | (drop:byt 5 (to-byts psbt-base64)) 125 | =| acc=(list map:psbt) 126 | =| m=map:psbt 127 | |- 128 | ?: =(wid.todo 0) 129 | (snoc acc m) 130 | :: 0x0: map separator 131 | :: 132 | ?: =(1^0x0 (take:byt 1 todo)) 133 | $(acc (snoc acc m), m *map:psbt, todo (drop:byt 1 todo)) 134 | =^ kv todo (next-keyval todo) 135 | $(m (snoc m kv)) 136 | :: +get-txid: extract txid from a valid PSBT 137 | :: 138 | ++ get-txid 139 | |= psbt-base64=cord 140 | ^- hexb 141 | =/ tx=hexb 142 | %- raw-tx 143 | %+ drop:byt 5 144 | (to-byts psbt-base64) 145 | %- flip:byt 146 | (dsha256 tx) 147 | :: +raw-tx: extract hex transaction 148 | :: looks for key 0x0 in global map 149 | :: crashes if tx not in hex 150 | :: 151 | ++ raw-tx 152 | |= b=hexb 153 | ^- hexb 154 | |- 155 | ?: =(wid.b 0) !! 156 | ?: =(1^0x0 (take:byt 1 b)) !! 157 | =/ nk (next-keyval b) 158 | ?: =(0x0 dat.key.kv.nk) 159 | val.kv.nk 160 | $(b rest.nk) 161 | :: +next-keyval: returns next key-val in a PSBT map 162 | :: input first byte must be a map key length 163 | :: 164 | ++ next-keyval 165 | |= b=hexb 166 | ^- [kv=keyval:psbt rest=hexb] 167 | =/ klen dat:(take:byt 1 b) 168 | =/ k (take:byt klen (drop:byt 1 b)) 169 | =/ vlen dat:(take:byt 1 (drop:byt (add 1 klen) b)) 170 | =/ v (take:byt vlen (drop:byt (add 2 klen) b)) 171 | ?> ?&((gth wid.k 0) (gth wid.v 0)) 172 | :- [k v] 173 | (drop:byt ;:(add 2 klen vlen) b) 174 | :: 175 | ++ to-byts 176 | |= psbt-base64=cord 177 | ^- hexb 178 | ~| "Invalid PSBT" 179 | =+ p=(de:base64:mimes:html psbt-base64) 180 | ?~ p !! 181 | (flip:byt u.p) 182 | -- 183 | -------------------------------------------------------------------------------- /tanote/lib/dbug.hoon: -------------------------------------------------------------------------------- 1 | :: dbug: agent wrapper for generic debugging tools 2 | :: 3 | :: usage: %-(agent:dbug your-agent) 4 | :: 5 | |% 6 | +$ poke 7 | $% [%bowl ~] 8 | [%state grab=cord] 9 | [%incoming =about] 10 | [%outgoing =about] 11 | == 12 | :: 13 | +$ about 14 | $@ ~ 15 | $% [%ship =ship] 16 | [%path =path] 17 | [%wire =wire] 18 | [%term =term] 19 | == 20 | :: 21 | ++ agent 22 | |= =agent:gall 23 | ^- agent:gall 24 | !. 25 | |_ =bowl:gall 26 | +* this . 27 | ag ~(. agent bowl) 28 | :: 29 | ++ on-poke 30 | |= [=mark =vase] 31 | ^- (quip card:agent:gall agent:gall) 32 | ?. ?=(%dbug mark) 33 | =^ cards agent (on-poke:ag mark vase) 34 | [cards this] 35 | =/ dbug 36 | !<(poke vase) 37 | =; =tang 38 | ((%*(. slog pri 1) tang) [~ this]) 39 | ?- -.dbug 40 | %bowl [(sell !>(bowl))]~ 41 | :: 42 | %state 43 | =? grab.dbug =('' grab.dbug) '-' 44 | =; product=^vase 45 | [(sell product)]~ 46 | =/ state=^vase 47 | :: if the underlying app has implemented a /dbug/state scry endpoint, 48 | :: use that vase in place of +on-save's. 49 | :: 50 | =/ result=(each ^vase tang) 51 | (mule |.(q:(need (need (on-peek:ag /x/dbug/state))))) 52 | ?:(?=(%& -.result) p.result on-save:ag) 53 | %+ slap 54 | (slop state !>([bowl=bowl ..zuse])) 55 | (ream grab.dbug) 56 | :: 57 | %incoming 58 | =; =tang 59 | ?^ tang tang 60 | [%leaf "no matching subscriptions"]~ 61 | %+ murn 62 | %+ sort ~(tap by sup.bowl) 63 | |= [[* a=[=ship =path]] [* b=[=ship =path]]] 64 | (aor [path ship]:a [path ship]:b) 65 | |= [=duct [=ship =path]] 66 | ^- (unit tank) 67 | =; relevant=? 68 | ?. relevant ~ 69 | `>[path=path from=ship duct=duct]< 70 | ?: ?=(~ about.dbug) & 71 | ?- -.about.dbug 72 | %ship =(ship ship.about.dbug) 73 | %path ?=(^ (find path.about.dbug path)) 74 | %wire %+ lien duct 75 | |=(=wire ?=(^ (find wire.about.dbug wire))) 76 | %term !! 77 | == 78 | :: 79 | %outgoing 80 | =; =tang 81 | ?^ tang tang 82 | [%leaf "no matching subscriptions"]~ 83 | %+ murn 84 | %+ sort ~(tap by wex.bowl) 85 | |= [[[a=wire *] *] [[b=wire *] *]] 86 | (aor a b) 87 | |= [[=wire =ship =term] [acked=? =path]] 88 | ^- (unit tank) 89 | =; relevant=? 90 | ?. relevant ~ 91 | `>[wire=wire agnt=[ship term] path=path ackd=acked]< 92 | ?: ?=(~ about.dbug) & 93 | ?- -.about.dbug 94 | %ship =(ship ship.about.dbug) 95 | %path ?=(^ (find path.about.dbug path)) 96 | %wire ?=(^ (find wire.about.dbug wire)) 97 | %term =(term term.about.dbug) 98 | == 99 | == 100 | :: 101 | ++ on-peek 102 | |= =path 103 | ^- (unit (unit cage)) 104 | ?. ?=([@ %dbug *] path) 105 | (on-peek:ag path) 106 | ?+ path [~ ~] 107 | [%u %dbug ~] ``noun+!>(&) 108 | [%x %dbug %state ~] ``noun+!>(on-save:ag) 109 | [%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl) 110 | == 111 | :: 112 | ++ on-init 113 | ^- (quip card:agent:gall agent:gall) 114 | =^ cards agent on-init:ag 115 | [cards this] 116 | :: 117 | ++ on-save on-save:ag 118 | :: 119 | ++ on-load 120 | |= old-state=vase 121 | ^- (quip card:agent:gall agent:gall) 122 | =^ cards agent (on-load:ag old-state) 123 | [cards this] 124 | :: 125 | ++ on-watch 126 | |= =path 127 | ^- (quip card:agent:gall agent:gall) 128 | =^ cards agent (on-watch:ag path) 129 | [cards this] 130 | :: 131 | ++ on-leave 132 | |= =path 133 | ^- (quip card:agent:gall agent:gall) 134 | =^ cards agent (on-leave:ag path) 135 | [cards this] 136 | :: 137 | ++ on-agent 138 | |= [=wire =sign:agent:gall] 139 | ^- (quip card:agent:gall agent:gall) 140 | =^ cards agent (on-agent:ag wire sign) 141 | [cards this] 142 | :: 143 | ++ on-arvo 144 | |= [=wire =sign-arvo] 145 | ^- (quip card:agent:gall agent:gall) 146 | =^ cards agent (on-arvo:ag wire sign-arvo) 147 | [cards this] 148 | :: 149 | ++ on-fail 150 | |= [=term =tang] 151 | ^- (quip card:agent:gall agent:gall) 152 | =^ cards agent (on-fail:ag term tang) 153 | [cards this] 154 | -- 155 | -- 156 | -------------------------------------------------------------------------------- /tanote/lib/server.hoon: -------------------------------------------------------------------------------- 1 | =, eyre 2 | |% 3 | +$ request-line 4 | $: [ext=(unit @ta) site=(list @t)] 5 | args=(list [key=@t value=@t]) 6 | == 7 | :: +parse-request-line: take a cord and parse out a url 8 | :: 9 | ++ parse-request-line 10 | |= url=@t 11 | ^- request-line 12 | (fall (rush url ;~(plug apat:de-purl:html yque:de-purl:html)) [[~ ~] ~]) 13 | :: 14 | ++ manx-to-octs 15 | |= man=manx 16 | ^- octs 17 | (as-octt:mimes:html (en-xml:html man)) 18 | :: 19 | ++ json-to-octs 20 | |= jon=json 21 | ^- octs 22 | (as-octt:mimes:html (en-json:html jon)) 23 | :: 24 | ++ app 25 | |% 26 | :: 27 | :: +require-authorization: 28 | :: redirect to the login page when unauthenticated 29 | :: otherwise call handler on inbound request 30 | :: 31 | ++ require-authorization 32 | |= $: =inbound-request:eyre 33 | handler=$-(inbound-request:eyre simple-payload:http) 34 | == 35 | ^- simple-payload:http 36 | :: 37 | ?: authenticated.inbound-request 38 | ~! this 39 | ~! +:*handler 40 | (handler inbound-request) 41 | :: 42 | =- [[307 ['location' -]~] ~] 43 | %^ cat 3 44 | '/~/login?redirect=' 45 | url.request.inbound-request 46 | :: 47 | :: +require-authorization-simple: 48 | :: redirect to the login page when unauthenticated 49 | :: otherwise pass through simple-paylod 50 | :: 51 | ++ require-authorization-simple 52 | |= [=inbound-request:eyre =simple-payload:http] 53 | ^- simple-payload:http 54 | :: 55 | ?: authenticated.inbound-request 56 | ~! this 57 | simple-payload 58 | :: 59 | =- [[307 ['location' -]~] ~] 60 | %^ cat 3 61 | '/~/login?redirect=' 62 | url.request.inbound-request 63 | :: 64 | ++ give-simple-payload 65 | |= [eyre-id=@ta =simple-payload:http] 66 | ^- (list card:agent:gall) 67 | =/ header-cage 68 | [%http-response-header !>(response-header.simple-payload)] 69 | =/ data-cage 70 | [%http-response-data !>(data.simple-payload)] 71 | :~ [%give %fact ~[/http-response/[eyre-id]] header-cage] 72 | [%give %fact ~[/http-response/[eyre-id]] data-cage] 73 | [%give %kick ~[/http-response/[eyre-id]] ~] 74 | == 75 | -- 76 | ++ gen 77 | |% 78 | :: 79 | ++ max-1-da ['cache-control' 'max-age=86400'] 80 | ++ max-1-wk ['cache-control' 'max-age=604800'] 81 | :: 82 | ++ html-response 83 | =| cache=? 84 | |= =octs 85 | ^- simple-payload:http 86 | :_ `octs 87 | [200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]] 88 | :: 89 | ++ css-response 90 | =| cache=? 91 | |= =octs 92 | ^- simple-payload:http 93 | :_ `octs 94 | [200 [['content-type' 'text/css'] ?:(cache [max-1-wk ~] ~)]] 95 | :: 96 | ++ js-response 97 | =| cache=? 98 | |= =octs 99 | ^- simple-payload:http 100 | :_ `octs 101 | [200 [['content-type' 'text/javascript'] ?:(cache [max-1-wk ~] ~)]] 102 | :: 103 | ++ png-response 104 | =| cache=? 105 | |= =octs 106 | ^- simple-payload:http 107 | :_ `octs 108 | [200 [['content-type' 'image/png'] ?:(cache [max-1-wk ~] ~)]] 109 | :: 110 | ++ svg-response 111 | =| cache=? 112 | |= =octs 113 | ^- simple-payload:http 114 | :_ `octs 115 | [200 [['content-type' 'image/svg+xml'] ?:(cache [max-1-wk ~] ~)]] 116 | :: 117 | ++ ico-response 118 | |= =octs 119 | ^- simple-payload:http 120 | [[200 [['content-type' 'image/x-icon'] max-1-wk ~]] `octs] 121 | :: 122 | ++ woff2-response 123 | =| cache=? 124 | |= =octs 125 | ^- simple-payload:http 126 | [[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs] 127 | :: 128 | ++ json-response 129 | =| cache=_| 130 | |= =json 131 | ^- simple-payload:http 132 | :_ `(json-to-octs json) 133 | [200 [['content-type' 'application/json'] ?:(cache [max-1-da ~] ~)]] 134 | :: 135 | ++ manx-response 136 | =| cache=_| 137 | |= man=manx 138 | ^- simple-payload:http 139 | :_ `(manx-to-octs man) 140 | [200 [['content-type' 'text/html'] ?:(cache [max-1-da ~] ~)]] 141 | :: 142 | ++ not-found 143 | ^- simple-payload:http 144 | [[404 ~] ~] 145 | :: 146 | ++ login-redirect 147 | |= =request:http 148 | ^- simple-payload:http 149 | =- [[307 ['location' -]~] ~] 150 | %^ cat 3 151 | '/~/login?redirect=' 152 | url.request 153 | :: 154 | ++ redirect 155 | |= redirect=cord 156 | ^- simple-payload:http 157 | [[307 ['location' redirect]~] ~] 158 | -- 159 | -- 160 | -------------------------------------------------------------------------------- /tanote/lib/bip/b173.hoon: -------------------------------------------------------------------------------- 1 | :: BIP173: Bech32 Addresses 2 | :: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 3 | :: 4 | :: Heavily copies: 5 | :: https://github.com/bitcoinjs/bech32/blob/master/index.js 6 | :: 7 | /- sur=bitcoin 8 | /+ bcu=bitcoin-utils 9 | =, sur 10 | =, bcu 11 | |% 12 | ++ prefixes 13 | ^- (map network tape) 14 | (my [[%main "bc"] [%testnet "tb"] ~]) 15 | ++ charset "qpzry9x8gf2tvdw0s3jn54khce6mua7l" 16 | +$ raw-decoded [hrp=tape data=(list @) checksum=(list @)] 17 | :: below is a port of: https://github.com/bitcoinjs/bech32/blob/master/index.js 18 | :: 19 | ++ polymod 20 | |= values=(list @) 21 | |^ ^- @ 22 | =/ gen=(list @ux) 23 | ~[0x3b6a.57b2 0x2650.8e6d 0x1ea1.19fa 0x3d42.33dd 0x2a14.62b3] 24 | =/ chk=@ 1 25 | |- ?~ values chk 26 | =/ top (rsh [0 25] chk) 27 | =. chk 28 | (mix i.values (lsh [0 5] (dis chk 0x1ff.ffff))) 29 | $(values t.values, chk (update-chk chk top gen)) 30 | :: 31 | ++ update-chk 32 | |= [chk=@ top=@ gen=(list @ux)] 33 | =/ is (gulf 0 4) 34 | |- ?~ is chk 35 | ?: =(1 (dis 1 (rsh [0 i.is] top))) 36 | $(is t.is, chk (mix chk (snag i.is gen))) 37 | $(is t.is) 38 | -- 39 | :: 40 | ++ expand-hrp 41 | |= hrp=tape 42 | ^- (list @) 43 | =/ front (turn hrp |=(p=@tD (rsh [0 5] p))) 44 | =/ back (turn hrp |=(p=@tD (dis 31 p))) 45 | (zing ~[front ~[0] back]) 46 | :: 47 | ++ verify-checksum 48 | |= [hrp=tape data-and-checksum=(list @)] 49 | ^- ? 50 | %- |=(a=@ =(1 a)) 51 | %- polymod 52 | (weld (expand-hrp hrp) data-and-checksum) 53 | :: 54 | ++ checksum 55 | |= [hrp=tape data=(list @)] 56 | ^- (list @) 57 | :: xor 1 with the polymod 58 | :: 59 | =/ pmod=@ 60 | %+ mix 1 61 | %- polymod 62 | (zing ~[(expand-hrp hrp) data (reap 6 0)]) 63 | %+ turn (gulf 0 5) 64 | |=(i=@ (dis 31 (rsh [0 (mul 5 (sub 5 i))] pmod))) 65 | :: 66 | ++ charset-to-value 67 | |= c=@tD 68 | ^- (unit @) 69 | (find ~[c] charset) 70 | ++ value-to-charset 71 | |= value=@ 72 | ^- (unit @tD) 73 | ?: (gth value 31) ~ 74 | `(snag value charset) 75 | :: 76 | ++ is-valid 77 | |= [bech=tape last-1-pos=@] ^- ? 78 | ?& ?|(=((cass bech) bech) =((cuss bech) bech)) :: to upper or to lower is same as bech 79 | (gte last-1-pos 1) 80 | (lte (add last-1-pos 7) (lent bech)) 81 | (lte (lent bech) 90) 82 | (levy bech |=(c=@tD (gte c 33))) 83 | (levy bech |=(c=@tD (lte c 126))) 84 | == 85 | :: data should be 5bit words 86 | :: 87 | ++ encode-raw 88 | |= [hrp=tape data=(list @)] 89 | ^- cord 90 | =/ combined=(list @) 91 | (weld data (checksum hrp data)) 92 | %- crip 93 | (zing ~[hrp "1" (tape (murn combined value-to-charset))]) 94 | ++ decode-raw 95 | |= body=cord 96 | ^- (unit raw-decoded) 97 | =/ bech (cass (trip body)) :: to lowercase 98 | =/ pos (flop (fand "1" bech)) 99 | ?~ pos ~ 100 | =/ last-1=@ i.pos 101 | ?. (is-valid bech last-1) :: check bech32 validity (not segwit validity or checksum) 102 | ~ 103 | =/ hrp (scag last-1 bech) 104 | =/ encoded-data-and-checksum=(list @) 105 | (slag +(last-1) bech) 106 | =/ data-and-checksum=(list @) 107 | %+ murn encoded-data-and-checksum 108 | charset-to-value 109 | ?. =((lent encoded-data-and-checksum) (lent data-and-checksum)) :: ensure all were in CHARSET 110 | ~ 111 | ?. (verify-checksum hrp data-and-checksum) 112 | ~ 113 | =/ checksum-pos (sub (lent data-and-checksum) 6) 114 | `[hrp (scag checksum-pos data-and-checksum) (slag checksum-pos data-and-checksum)] 115 | :: +from-address: BIP173 bech32 address encoding to hex 116 | :: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 117 | :: expects to drop a leading 5-bit 0 (the witness version) 118 | :: 119 | ++ from-address 120 | |= body=cord 121 | ^- hexb 122 | ~| "Invalid bech32 address" 123 | =/ d=(unit raw-decoded) (decode-raw body) 124 | ?> ?=(^ d) 125 | =/ bs=bits (from-atoms:bit 5 data.u.d) 126 | =/ byt-len=@ (div (sub wid.bs 5) 8) 127 | ?> =(5^0b0 (take:bit 5 bs)) 128 | ?> ?| =(20 byt-len) 129 | =(32 byt-len) 130 | == 131 | [byt-len `@ux`dat:(take:bit (mul 8 byt-len) (drop:bit 5 bs))] 132 | :: pubkey is the 33 byte ECC compressed public key 133 | :: 134 | ++ encode-pubkey 135 | |= [=network pubkey=byts] 136 | ^- (unit cord) 137 | ?. =(33 wid.pubkey) 138 | ~|('pubkey must be a 33 byte ECC compressed public key' !!) 139 | =/ prefix (~(get by prefixes) network) 140 | ?~ prefix ~ 141 | :- ~ 142 | %+ encode-raw u.prefix 143 | [0v0 (to-atoms:bit 5 [160 `@ub`dat:(hash-160 pubkey)])] 144 | -- 145 | -------------------------------------------------------------------------------- /tanote/lib/azimuthio.hoon: -------------------------------------------------------------------------------- 1 | /- rpc=json-rpc 2 | /+ ethereum, azimuth, strandio 3 | =, strand=strand:strandio 4 | =, jael 5 | |% 6 | ++ tract azimuth:contracts:azimuth 7 | ++ fetch-point 8 | |= [url=@ta who=ship] 9 | =/ m (strand ,point:azimuth) 10 | ^- form:m 11 | =/ =request:rpc:ethereum 12 | :+ %eth-call 13 | =- [from=~ to=tract gas=~ price=~ value=~ data=-] 14 | (encode-call:rpc:ethereum 'points(uint32)' [%uint `@`who]~) 15 | [%label %latest] 16 | ;< jon=json bind:m (request-rpc url `'point' request) 17 | =/ res=cord (so:dejs:format jon) 18 | =/ =point:eth-noun:azimuth 19 | (decode-results:abi:ethereum res point:eth-type:azimuth) 20 | :: 21 | =/ =request:rpc:ethereum 22 | :+ %eth-call 23 | =- [from=~ to=tract gas=~ price=~ value=~ data=-] 24 | (encode-call:rpc:ethereum 'rights(uint32)' [%uint `@`who]~) 25 | [%label %latest] 26 | ;< jon=json bind:m (request-rpc url `'deed' request) 27 | =/ res=cord (so:dejs:format jon) 28 | =/ =deed:eth-noun:azimuth 29 | (decode-results:abi:ethereum res deed:eth-type:azimuth) 30 | :: 31 | (pure:m (point-from-eth:azimuth who point deed)) 32 | :: 33 | ++ request-rpc 34 | |= [url=@ta id=(unit @t) req=request:rpc:ethereum] 35 | =/ m (strand ,json) 36 | ^- form:m 37 | %+ (retry json) `10 38 | =/ m (strand ,(unit json)) 39 | ^- form:m 40 | |^ 41 | =/ =request:http 42 | :* method=%'POST' 43 | url=url 44 | header-list=['Content-Type'^'application/json' ~] 45 | ^= body 46 | %- some %- as-octt:mimes:html 47 | %- en-json:html 48 | (request-to-json:rpc:ethereum id req) 49 | == 50 | ;< ~ bind:m (send-request:strandio request) 51 | ;< rep=(unit client-response:iris) bind:m 52 | take-maybe-response:strandio 53 | ?~ rep 54 | (pure:m ~) 55 | (parse-response u.rep) 56 | :: 57 | ++ parse-response 58 | |= =client-response:iris 59 | =/ m (strand ,(unit json)) 60 | ^- form:m 61 | ?> ?=(%finished -.client-response) 62 | ?~ full-file.client-response 63 | (pure:m ~) 64 | =/ body=@t q.data.u.full-file.client-response 65 | =/ jon=(unit json) (de-json:html body) 66 | ?~ jon 67 | (pure:m ~) 68 | =, dejs-soft:format 69 | =/ array=(unit (list response:rpc)) 70 | ((ar parse-one-response) u.jon) 71 | ?~ array 72 | =/ res=(unit response:rpc) (parse-one-response u.jon) 73 | ?~ res 74 | (strand-fail:strandio %request-rpc-parse-error >id< ~) 75 | ?: ?=(%error -.u.res) 76 | (strand-fail:strandio %request-rpc-error >id< >+.res< ~) 77 | ?. ?=(%result -.u.res) 78 | (strand-fail:strandio %request-rpc-fail >u.res< ~) 79 | (pure:m `res.u.res) 80 | (strand-fail:strandio %request-rpc-batch >%not-implemented< ~) 81 | :: (pure:m `[%batch u.array]) 82 | :: 83 | ++ parse-one-response 84 | |= =json 85 | ^- (unit response:rpc) 86 | =/ res=(unit [@t ^json]) 87 | %. json 88 | =, dejs-soft:format 89 | (ot id+so result+some ~) 90 | ?^ res `[%result u.res] 91 | ~| parse-one-response=json 92 | :+ ~ %error %- need 93 | %. json 94 | =, dejs-soft:format 95 | (ot id+so error+(ot code+no message+so ~) ~) 96 | -- 97 | :: 98 | ++ retry 99 | |* result=mold 100 | |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))] 101 | =/ m (strand ,result) 102 | =| try=@ud 103 | |- ^- form:m 104 | =* loop $ 105 | ?: =(crash-after `try) 106 | (strand-fail:strandio %retry-too-many ~) 107 | ;< ~ bind:m (backoff:strandio try ~m1) 108 | ;< res=(unit result) bind:m computation 109 | ?^ res 110 | (pure:m u.res) 111 | loop(try +(try)) 112 | :: 113 | ++ get-latest-block 114 | |= url=@ta 115 | =/ m (strand ,block) 116 | ^- form:m 117 | ;< =json bind:m (request-rpc url `'block number' %eth-block-number ~) 118 | (get-block-by-number url (parse-eth-block-number:rpc:ethereum json)) 119 | :: 120 | ++ get-block-by-number 121 | |= [url=@ta =number:block] 122 | =/ m (strand ,block) 123 | ^- form:m 124 | |^ 125 | ;< =json bind:m 126 | (request-rpc url `'block by number' %eth-get-block-by-number number |) 127 | =/ =block (parse-block json) 128 | ?. =(number number.id.block) 129 | (strand-fail:strandio %reorg-detected >number< >block< ~) 130 | (pure:m block) 131 | :: 132 | ++ parse-block 133 | |= =json 134 | ^- block 135 | =< [[&1 &2] |2] 136 | ^- [@ @ @] 137 | ~| json 138 | %. json 139 | =, dejs:format 140 | %- ot 141 | :~ hash+parse-hex-result:rpc:ethereum 142 | number+parse-hex-result:rpc:ethereum 143 | 'parentHash'^parse-hex-result:rpc:ethereum 144 | == 145 | -- 146 | -- 147 | -------------------------------------------------------------------------------- /tanote/lib/tanote.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ note [by=@p as=tape if=[@ux @p] to=(list @p) re=tape text=tape] 3 | +$ history [regards=tape versions=(list note)] 4 | +$ store (list history) 5 | +$ front [tab=tape tags=(set tape) tugs=(set tape) regards=tape histories=store] 6 | ++ add-note-history 7 | |= [n=note h=history] 8 | ^- history 9 | ?: =(regards.h re.n) 10 | ?~ versions.h 11 | [regards.h ~[n]] 12 | [regards.h [n versions.h]] 13 | [re.n ~[n]] 14 | ++ add-note-store 15 | |= [n=note s0=store] 16 | =/ found=history (find-store-regards s0 re.n) 17 | ?: =(found [re.n ~]) 18 | [[re.n ~[n]] s0] 19 | =/ s1=store ~ 20 | |- 21 | ^- store 22 | ?~ s0 23 | s1 24 | =/ h0=history +2:s0 25 | ?: =(re.n regards.h0) 26 | $(s0 +3:s0, s1 [[regards.h0 [n versions.h0]] s1]) 27 | $(s0 +3:s0, s1 [h0 s1]) 28 | ++ default-tags 29 | |= ~ 30 | ^- (set tape) 31 | (sy ~["*" "/"]) 32 | ++ display-tags 33 | |= s=store 34 | ^- (set tape) 35 | (~(uni in (default-tags)) (extract-tags-store s)) 36 | ++ display-backlinks 37 | |= s=store 38 | ^- (set tape) 39 | (extract-backlinks-store s) 40 | ++ extract-backlink 41 | |= [start=@ud text=tape] 42 | =/ cursor=@ud (add 2 start) 43 | =/ max=@ud (lent text) 44 | =/ backlink=tape ~ 45 | |- 46 | ^- tape 47 | ?: =(cursor (dec max)) 48 | ~ 49 | =/ t0=@t (snag cursor text) 50 | =/ t1=@t (snag +(cursor) text) 51 | ?: =(~[t0 t1] "]]") 52 | (flop backlink) 53 | $(cursor +(cursor), backlink [t0 backlink]) 54 | ++ extract-backlinks-history 55 | |= h=history 56 | (extract-backlinks-note (snag 0 versions.h)) 57 | ++ extract-backlinks-note 58 | |= n=note 59 | ^- (set tape) 60 | (~(uni in (sy ~[as.n])) (extract-backlinks-tape (index-backlinks text.n) text.n)) 61 | ++ extract-backlinks-store 62 | |= s=store 63 | =/ backlinks=(set tape) ~ 64 | |- 65 | ^- (set tape) 66 | ?~ s 67 | backlinks 68 | $(s +3:s, backlinks (~(uni in backlinks) (extract-backlinks-history +2:s))) 69 | ++ extract-backlinks-tape 70 | |= [starts=(list @ud) text=tape] 71 | =/ backlinks=(set tape) ~ 72 | |- 73 | ^- (set tape) 74 | ?~ starts 75 | backlinks 76 | $(starts +3:starts, backlinks (~(put in backlinks) (extract-backlink +2:starts text))) 77 | ++ extract-tag 78 | |= [oi=@ud text=tape] 79 | =/ max=@ (lent text) 80 | =/ allowed=tape "#-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~" 81 | =/ tag=tape ~ 82 | |- 83 | ^- tape 84 | ?: =(oi max) 85 | (flop tag) 86 | =/ t=@t (snag oi text) 87 | ?~ (find ~[t] allowed) 88 | (flop tag) 89 | $(oi +(oi), tag [t tag]) 90 | ++ extract-tags-history 91 | |= h=history 92 | (extract-tags-note (snag 0 versions.h)) 93 | ++ extract-tags-note 94 | |= n=note 95 | ^- (set tape) 96 | (extract-tags-tape (index-tags text.n) text.n) 97 | ++ extract-tags-store 98 | |= s=store 99 | =/ tags=(set tape) ~ 100 | |- 101 | ^- (set tape) 102 | ?~ s 103 | tags 104 | $(s +3:s, tags (~(uni in tags) (extract-tags-history +2:s))) 105 | ++ extract-tags-tape 106 | |= [starts=(list @ud) text=tape] 107 | =/ tags=(set tape) ~ 108 | |- 109 | ^- (set tape) 110 | ?~ starts 111 | tags 112 | $(starts +3:starts, tags (~(put in tags) (extract-tag +2:starts text))) 113 | ++ filter-front-regards 114 | |= f=front 115 | ^- front 116 | ?~ regards.f 117 | f 118 | [tab=tab.f tags=tags.f tugs=tugs.f regards=regards.f histories=~[(find-store-regards histories.f regards.f)]] 119 | ++ filter-front-tugs 120 | |= f=front 121 | ^- front 122 | ?~ tugs.f 123 | f 124 | [tab=tab.f tags=tags.f tugs=tugs.f regards=regards.f histories=(filter-store-tags histories.f tugs.f)] 125 | ++ find-store-regards 126 | |= [s=store regards=tape] 127 | |- 128 | ^- history 129 | ?~ s 130 | [regards ~] 131 | =/ h=history +2:s 132 | ?: =(regards.h regards) 133 | h 134 | $(s +3:s) 135 | ++ filter-store-tag 136 | |= [unfiltered=store tag=tape] 137 | =/ filtered=store ~ 138 | |- 139 | ^- store 140 | ?~ unfiltered 141 | filtered 142 | ?: (~(has in (extract-tags-history +2:unfiltered)) tag) 143 | $(unfiltered +3:unfiltered, filtered [+2:unfiltered filtered]) 144 | $(unfiltered +3:unfiltered) 145 | ++ filter-store-tags 146 | |= [unfiltered=store tags=(set tape)] 147 | =/ filtered=store ~ 148 | |- 149 | ^- store 150 | ?~ unfiltered 151 | filtered 152 | ?: .= tags 153 | (~(int in tags) (extract-tags-history +2:unfiltered)) 154 | $(unfiltered +3:unfiltered, filtered [+2:unfiltered filtered]) 155 | $(unfiltered +3:unfiltered) 156 | ++ index-backlinks 157 | |= text=tape 158 | (fand "[[" text) 159 | ++ index-tags 160 | |= text=tape 161 | (weld (fand "#" text) (fand "~" text)) 162 | ++ list-regards-store 163 | |= s=store 164 | =/ regards=(list tape) ~ 165 | |- 166 | ^- (list tape) 167 | ?~ s 168 | regards 169 | =/ h=history +2:s 170 | $(s +3:s, regards [regards.h regards]) 171 | -- 172 | :: DO NOT EDIT THIS FILE. Auto-generated from default tanote.md by lit. 173 | -------------------------------------------------------------------------------- /tanote/sur/hark-store.hoon: -------------------------------------------------------------------------------- 1 | ^? 2 | :: 3 | :: %hark-store: Notification, unreads store 4 | :: 5 | :: Timeboxing & binning: 6 | :: 7 | :: Unread notifications accumulate in $unreads. They are grouped by 8 | :: their $bin. A notification may become read by either: 9 | :: a) being read by a %read-count or %read-each or %read-note 10 | :: b) being read by a %seen 11 | :: 12 | :: If a) then we insert the corresponding bin into $reads at the 13 | :: current timestamp 14 | :: If b) then we empty $unreads and move all bins to $reads at the 15 | :: current timestamp 16 | :: 17 | :: Unread tracking: 18 | :: Unread tracking has two 'modes' which may be used concurrently, 19 | :: if necessary. 20 | :: 21 | :: count: 22 | :: This stores the unreads as a simple atom, describing the number 23 | :: of unread items. May be increased with %unread-count and 24 | :: set to zero with %read-count. Ideal for high-frequency linear 25 | :: datastructures, e.g. chat 26 | :: each: 27 | :: This stores the unreads as a set of paths, describing the set of 28 | :: unread items. Unreads may be added to the set with %unread-each 29 | :: and removed with %read-each. Ideal for non-linear, low-frequency 30 | :: datastructures, e.g. blogs 31 | :: 32 | |% 33 | :: $place: A location, under which landscape stores stats 34 | :: 35 | :: .desk must match q.byk.bowl 36 | :: Examples: 37 | :: A chat: 38 | :: [%landscape /~dopzod/urbit-help] 39 | :: A note in a notebook: 40 | :: [%landscape /~darrux-landes/feature-requests/12374893234232] 41 | :: A group: 42 | :: [%hark-group-hook /~bitbet-bolbel/urbit-community] 43 | :: Comments on a link 44 | :: [%landscape /~dabben-larbet/urbit-in-the-news/17014118450499614194868/2] 45 | :: 46 | +$ place [=desk =path] 47 | :: 48 | :: $bin: Identifier for grouping notifications 49 | :: 50 | :: Examples 51 | :: A mention in a chat: 52 | :: [/mention %landscape /~dopzod/urbit-help] 53 | :: New messages in a chat 54 | :: [/message %landscape /~dopzod/urbit-help] 55 | :: A new comment in a notebook: 56 | :: [/comment %landscape /~darrux-landes/feature-requests/12374893234232/2] 57 | :: 58 | +$ bin [=path =place] 59 | :: 60 | :: $lid: Reference to a timebox 61 | :: 62 | +$ lid 63 | $% [%archive =time] 64 | [%seen ~] 65 | [%unseen ~] 66 | == 67 | :: $content: Notification content 68 | +$ content 69 | $% [%ship =ship] 70 | [%text =cord] 71 | == 72 | :: 73 | :: $body: A notification body 74 | :: 75 | +$ body 76 | $: title=(list content) 77 | content=(list content) 78 | =time 79 | binned=path 80 | link=path 81 | == 82 | :: 83 | +$ notification 84 | [date=@da =bin body=(list body)] 85 | :: $timebox: Group of notificatons 86 | +$ timebox 87 | (map bin notification) 88 | :: $archive: Archived notifications, ordered by time 89 | +$ archive 90 | ((mop @da timebox) gth) 91 | :: 92 | +$ action 93 | $% :: hook actions 94 | :: 95 | :: %add-note: add a notification 96 | [%add-note =bin =body] 97 | :: 98 | :: %del-place: Underlying resource disappeared, remove all 99 | :: associated notifications 100 | [%del-place =place] 101 | :: %unread-count: Change unread count by .count 102 | [%unread-count =place inc=? count=@ud] 103 | :: %unread-each: Add .path to list of unreads for .place 104 | [%unread-each =place =path] 105 | :: %saw-place: Update last-updated for .place to now.bowl 106 | [%saw-place =place time=(unit time)] 107 | :: store actions 108 | :: 109 | :: %archive: archive single notification 110 | :: if .time is ~, then archiving unread notification 111 | :: else, archiving read notification 112 | [%archive =lid =bin] 113 | :: %read-count: set unread count to zero 114 | [%read-count =place] 115 | :: %read-each: remove path from unreads for .place 116 | [%read-each =place =path] 117 | :: %read-note: Read note at .bin 118 | [%read-note =bin] 119 | :: %archive-all: Archive all notifications 120 | [%archive-all ~] 121 | :: %opened: User opened notifications, reset timeboxing logic. 122 | :: 123 | [%opened ~] 124 | :: 125 | :: XX: previously in hark-store, now deprecated 126 | :: the hooks responsible for creating notifications may offer pokes 127 | :: similar to this 128 | :: [%read-graph =resource] 129 | :: [%read-group =resource] 130 | :: [%remove-graph =resource] 131 | :: 132 | == 133 | :: .stats: Statistics for a .place 134 | :: 135 | +$ stats 136 | $: count=@ud 137 | each=(set path) 138 | last=@da 139 | timebox=(unit @da) 140 | == 141 | :: 142 | +$ update 143 | $% action 144 | :: %more: more updates 145 | [%archived =time =lid =notification] 146 | [%more more=(list update)] 147 | :: %note-read: note has been read with timestamp 148 | [%note-read =time =bin] 149 | [%added =notification] 150 | :: %timebox: description of timebox. 151 | :: 152 | [%timebox =lid =(list notification)] 153 | :: %place-stats: description of .stats for a .place 154 | [%place-stats =place =stats] 155 | :: %place-stats: stats for all .places 156 | [%all-stats places=(map place stats)] 157 | == 158 | -- 159 | 160 | -------------------------------------------------------------------------------- /tanote/gen/testlib.hoon: -------------------------------------------------------------------------------- 1 | /+ tanote 2 | :- %say 3 | |= * 4 | :- %noun 5 | =/ test0=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~ "test" "This is a test."] 6 | =/ test1=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~[~ponhec-picwen] "test" "This is a test."] 7 | =/ test2=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~[~ponhec-picwen ~nocsyx-lassul] "test" "This is a test."] 8 | =/ tagbl0=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~[~ponhec-picwen ~nocsyx-lassul] "tag and backlink" "This is a test with a #tag and a [[backlink]]."] 9 | =/ test10=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~ "another test" "This is a #test with a [[backlink]]."] 10 | =/ test11=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~[~ponhec-picwen] "another test" "This is another #test with two #tag and two [[backlink]] for [[tanote]]."] 11 | =/ test12=note:tanote [~ponhec-picwen "tester" [0x0 ~ponhec-picwen] ~[~ponhec-picwen ~nocsyx-lassul] "another test" "This is another #test with an #array of #tag and more [[backlink]] for [[tanote]] [[test data]]."] 12 | =/ history0=history:tanote ["test" ~[test2 test1 test0]] 13 | =/ history1=history:tanote ["another test" ~[test12 test11 test10]] 14 | =/ latest-history0=note:tanote (snag 0 versions.history0) 15 | =/ store0=store:tanote ~[history0 history1] 16 | :- (default-tags:tanote) 17 | :- .= (default-tags:tanote) 18 | (sy ~["/" "*"]) 19 | :- (index-tags:tanote "This is a test.") 20 | :- .= (index-tags:tanote "This is a test.") 21 | ~ 22 | :- (index-tags:tanote "This is a #hash test.") 23 | :- .= (index-tags:tanote "This is a #hash test.") 24 | ~[10] 25 | :- (index-tags:tanote "This is a multiple-#hash ~ponhec-picwen.") 26 | :- .= (index-tags:tanote "This is a multiple-#hash ~ponhec-picwen.") 27 | ~[19 25] 28 | :- .= (index-backlinks:tanote "This is a test.") 29 | ~ 30 | :- .= (index-backlinks:tanote "This is a [[hash]] test.") 31 | ~[10] 32 | :- .= (index-backlinks:tanote "This is a multiple-[[hash]] [[~ponhec-picwen]].") 33 | ~[19 28] 34 | :- .= (extract-tag:tanote 10 "This is a #hash test.") 35 | "#hash" 36 | :- .= (extract-tag:tanote 19 "This is a multiple-#hash #test.") 37 | "#hash" 38 | :- .= (extract-tag:tanote 25 "This is a multiple-#hash ~ponhec-picwen.") 39 | "~ponhec-picwen" 40 | :- .= (extract-tags-tape:tanote ~ "This is a test.") 41 | ~ 42 | :- (extract-tags-tape:tanote ~[10] "This is a #hash test.") 43 | :- .= (extract-tags-tape:tanote ~[10] "This is a #hash test.") 44 | (sy ~["#hash"]) 45 | :- (extract-tags-tape:tanote ~[19 25] "This is a multiple-#hash ~ponhec-picwen.") 46 | :- .= (extract-tags-tape:tanote ~[19 25] "This is a multiple-#hash ~ponhec-picwen.") 47 | (sy ~["#hash" "~ponhec-picwen"]) 48 | :- .= (extract-backlink:tanote 10 "This is a [[hash]] test.") 49 | "hash" 50 | :- .= (extract-backlink:tanote 19 "This is a multiple-[[hash]] [[test]].") 51 | "hash" 52 | :- (extract-backlink:tanote 28 "This is a multiple-[[hash]] [[test]].") 53 | :- .= (extract-backlink:tanote 28 "This is a multiple-[[hash]] [[test]].") 54 | "test" 55 | :- .= (extract-backlinks-tape:tanote ~ "This is a test.") 56 | ~ 57 | :- (extract-backlinks-tape:tanote ~[10] "This is a [[hash]] test.") 58 | :- .= (extract-backlinks-tape:tanote ~[10] "This is a [[hash]] test.") 59 | (sy ~["hash"]) 60 | :- (extract-backlinks-tape:tanote ~[19 28] "This is a multiple-[[link]] [[~ponhec-picwen]].") 61 | :- .= (extract-backlinks-tape:tanote ~[19 28] "This is a multiple-[[link]] [[~ponhec-picwen]].") 62 | (sy ~["link" "~ponhec-picwen"]) 63 | :- test0 64 | :- test1 65 | :- test2 66 | :- `history:tanote`["test" ~[test2 test1 test0]] 67 | :- .= history0 68 | `history:tanote`["test" ~[test2 test1 test0]] 69 | :- .= regards.history0 70 | "test" 71 | :- .= versions.history0 72 | ~[test2 test1 test0] 73 | :- .= +2:versions.history0 74 | test2 75 | :- .= (snag 0 versions.history0) 76 | test2 77 | :- .= latest-history0 78 | test2 79 | :- .= to.latest-history0 80 | ~[~ponhec-picwen ~nocsyx-lassul] 81 | :- .= by.latest-history0 82 | ~ponhec-picwen 83 | :- .= as.latest-history0 84 | "tester" 85 | :- .= if.latest-history0 86 | [0x0 ~ponhec-picwen] 87 | :- .= re.latest-history0 88 | "test" 89 | :- .= text.latest-history0 90 | "This is a test." 91 | :- .= (extract-tags-tape:tanote (index-tags:tanote text.latest-history0) text.latest-history0) 92 | ~ 93 | :- .= (extract-backlinks-tape:tanote (index-backlinks:tanote text.latest-history0) text.latest-history0) 94 | ~ 95 | :- .= (extract-tags-tape:tanote (index-tags:tanote text.tagbl0) text.tagbl0) 96 | (sy ~["#tag"]) 97 | :- .= (extract-backlinks-tape:tanote (index-backlinks:tanote text.tagbl0) text.tagbl0) 98 | (sy ~["backlink"]) 99 | :- .= (extract-tags-note:tanote tagbl0) 100 | (sy ~["#tag"]) 101 | :- .= (extract-backlinks-note:tanote tagbl0) 102 | (sy ~["backlink"]) 103 | :- .= (extract-tags-history:tanote history0) 104 | ~ 105 | :- .= (extract-backlinks-history:tanote history0) 106 | ~ 107 | :- .= (extract-tags-history:tanote history1) 108 | (sy ~["#array" "#tag" "#test"]) 109 | :- .= (extract-backlinks-history:tanote history1) 110 | (sy ~["backlink" "tanote" "test data"]) 111 | :- store0 112 | :- .= (extract-tags-store:tanote store0) 113 | (sy ~["#array" "#tag" "#test"]) 114 | :- .= (extract-backlinks-store:tanote store0) 115 | (sy ~["backlink" "tanote" "test data"]) 116 | ~ 117 | :: DO NOT EDIT THIS FILE. Auto-generated from verbose testlib.md by lit. 118 | -------------------------------------------------------------------------------- /tanote/lib/strand.hoon: -------------------------------------------------------------------------------- 1 | |% 2 | +$ card card:agent:gall 3 | +$ input 4 | $% [%poke =cage] 5 | [%sign =wire =sign-arvo] 6 | [%agent =wire =sign:agent:gall] 7 | [%watch =path] 8 | == 9 | +$ strand-input [=bowl in=(unit input)] 10 | +$ tid @tatid 11 | +$ bowl 12 | $: our=ship 13 | src=ship 14 | tid=tid 15 | mom=(unit tid) 16 | wex=boat:gall 17 | sup=bitt:gall 18 | eny=@uvJ 19 | now=@da 20 | byk=beak 21 | == 22 | :: 23 | :: cards: cards to send immediately. These will go out even if a 24 | :: later stage of the computation fails, so they shouldn't have 25 | :: any semantic effect on the rest of the system. 26 | :: Alternately, they may record an entry in contracts with 27 | :: enough information to undo the effect if the computation 28 | :: fails. 29 | :: wait: don't move on, stay here. The next sign should come back 30 | :: to this same callback. 31 | :: skip: didn't expect this input; drop it down to be handled 32 | :: elsewhere 33 | :: cont: continue computation with new callback. 34 | :: fail: abort computation; don't send effects 35 | :: done: finish computation; send effects 36 | :: 37 | ++ strand-output-raw 38 | |* a=mold 39 | $~ [~ %done *a] 40 | $: cards=(list card) 41 | $= next 42 | $% [%wait ~] 43 | [%skip ~] 44 | [%cont self=(strand-form-raw a)] 45 | [%fail err=(pair term tang)] 46 | [%done value=a] 47 | == 48 | == 49 | :: 50 | ++ strand-form-raw 51 | |* a=mold 52 | $-(strand-input (strand-output-raw a)) 53 | :: 54 | :: Abort strand computation with error message 55 | :: 56 | ++ strand-fail 57 | |= err=(pair term tang) 58 | |= strand-input 59 | [~ %fail err] 60 | :: 61 | :: Asynchronous transcaction monad. 62 | :: 63 | :: Combo of four monads: 64 | :: - Reader on input 65 | :: - Writer on card 66 | :: - Continuation 67 | :: - Exception 68 | :: 69 | ++ strand 70 | |* a=mold 71 | |% 72 | ++ output (strand-output-raw a) 73 | :: 74 | :: Type of an strand computation. 75 | :: 76 | ++ form (strand-form-raw a) 77 | :: 78 | :: Monadic pure. Identity computation for bind. 79 | :: 80 | ++ pure 81 | |= arg=a 82 | ^- form 83 | |= strand-input 84 | [~ %done arg] 85 | :: 86 | :: Monadic bind. Combines two computations, associatively. 87 | :: 88 | ++ bind 89 | |* b=mold 90 | |= [m-b=(strand-form-raw b) fun=$-(b form)] 91 | ^- form 92 | |= input=strand-input 93 | =/ b-res=(strand-output-raw b) 94 | (m-b input) 95 | ^- output 96 | :- cards.b-res 97 | ?- -.next.b-res 98 | %wait [%wait ~] 99 | %skip [%skip ~] 100 | %cont [%cont ..$(m-b self.next.b-res)] 101 | %fail [%fail err.next.b-res] 102 | %done [%cont (fun value.next.b-res)] 103 | == 104 | :: 105 | :: The strand monad must be evaluted in a particular way to maintain 106 | :: its monadic character. +take:eval implements this. 107 | :: 108 | ++ eval 109 | |% 110 | :: Indelible state of a strand 111 | :: 112 | +$ eval-form 113 | $: =form 114 | == 115 | :: 116 | :: Convert initial form to eval-form 117 | :: 118 | ++ from-form 119 | |= =form 120 | ^- eval-form 121 | form 122 | :: 123 | :: The cases of results of +take 124 | :: 125 | +$ eval-result 126 | $% [%next ~] 127 | [%fail err=(pair term tang)] 128 | [%done value=a] 129 | == 130 | :: 131 | ++ validate-mark 132 | |= [in=* =mark =bowl] 133 | ^- cage 134 | =+ .^ =dais:clay %cb 135 | /(scot %p our.bowl)/[q.byk.bowl]/(scot %da now.bowl)/[mark] 136 | == 137 | =/ res (mule |.((vale.dais in))) 138 | ?: ?=(%| -.res) 139 | ~|(%spider-mark-fail (mean leaf+"spider: ames vale fail {}" p.res)) 140 | [mark p.res] 141 | :: 142 | :: Take a new sign and run the strand against it 143 | :: 144 | ++ take 145 | :: cards: accumulate throughout recursion the cards to be 146 | :: produced now 147 | =| cards=(list card) 148 | |= [=eval-form =strand-input] 149 | ^- [[(list card) =eval-result] _eval-form] 150 | =* take-loop $ 151 | =. in.strand-input 152 | ?~ in.strand-input ~ 153 | =/ in u.in.strand-input 154 | ?. ?=(%agent -.in) `in 155 | ?. ?=(%fact -.sign.in) `in 156 | :: 157 | :- ~ 158 | :+ %agent wire.in 159 | [%fact (validate-mark q.q.cage.sign.in p.cage.sign.in bowl.strand-input)] 160 | :: run the strand callback 161 | :: 162 | =/ =output (form.eval-form strand-input) 163 | :: add cards to cards 164 | :: 165 | =. cards 166 | %+ welp 167 | cards 168 | :: XX add tag to wires? 169 | cards.output 170 | :: case-wise handle next steps 171 | :: 172 | ?- -.next.output 173 | %wait [[cards %next ~] eval-form] 174 | %skip [[cards %next ~] eval-form] 175 | %fail [[cards %fail err.next.output] eval-form] 176 | %done [[cards %done value.next.output] eval-form] 177 | %cont 178 | :: recurse to run continuation with initialization input 179 | :: 180 | %_ take-loop 181 | form.eval-form self.next.output 182 | strand-input [bowl.strand-input ~] 183 | == 184 | == 185 | -- 186 | -- 187 | -- 188 | :: 189 | -------------------------------------------------------------------------------- /tanote/lib/hark-store.hoon: -------------------------------------------------------------------------------- 1 | /- sur=hark-store 2 | ^? 3 | =, sur 4 | =< [. sur] 5 | |% 6 | 7 | ++ enjs 8 | =, enjs:format 9 | |% 10 | ++ update 11 | |= upd=^update 12 | ^- json 13 | %+ frond -.upd 14 | ?+ -.upd a+~ 15 | %added (notification +.upd) 16 | %add-note (add-note +.upd) 17 | %timebox (timebox +.upd) 18 | %more (more +.upd) 19 | %read-each (read-each +.upd) 20 | %read-count (place +.upd) 21 | %unread-each (read-each +.upd) 22 | %unread-count (unread-count +.upd) 23 | %saw-place (saw-place +.upd) 24 | %all-stats (all-stats +.upd) 25 | %del-place (place +.upd) 26 | ::%read-note (index +.upd) 27 | ::%note-read (note-read +.upd) 28 | %archived (archived +.upd) 29 | == 30 | :: 31 | ++ add-note 32 | |= [bi=^bin bo=^body] 33 | %- pairs 34 | :~ bin+(bin bi) 35 | body+(body bo) 36 | == 37 | :: 38 | ++ saw-place 39 | |= [p=^place t=(unit ^time)] 40 | %- pairs 41 | :~ place+(place p) 42 | time+?~(t ~ (time u.t)) 43 | == 44 | :: 45 | ++ archived 46 | |= [t=^time l=^lid n=^notification] 47 | %- pairs 48 | :~ lid+(lid l) 49 | time+s+(scot %ud t) 50 | notification+(notification n) 51 | == 52 | :: 53 | ++ note-read 54 | |= * 55 | (pairs ~) 56 | :: 57 | ++ all-stats 58 | |= places=(map ^place ^stats) 59 | ^- json 60 | :- %a 61 | ^- (list json) 62 | %+ turn ~(tap by places) 63 | |= [p=^place s=^stats] 64 | %- pairs 65 | :~ stats+(stats s) 66 | place+(place p) 67 | 68 | == 69 | :: 70 | ++ stats 71 | |= s=^stats 72 | ^- json 73 | %- pairs 74 | :~ each+a+(turn ~(tap in each.s) (cork spat (lead %s))) 75 | last+(time last.s) 76 | count+(numb count.s) 77 | == 78 | ++ more 79 | |= upds=(list ^update) 80 | ^- json 81 | a+(turn upds update) 82 | :: 83 | ++ place 84 | |= =^place 85 | %- pairs 86 | :~ desk+s+desk.place 87 | path+s+(spat path.place) 88 | == 89 | :: 90 | ++ bin 91 | |= =^bin 92 | %- pairs 93 | :~ place+(place place.bin) 94 | path+s+(spat path.bin) 95 | == 96 | ++ notification 97 | |= ^notification 98 | ^- json 99 | %- pairs 100 | :~ time+(time date) 101 | bin+(^bin bin) 102 | body+(bodies body) 103 | == 104 | ++ bodies 105 | |= bs=(list ^body) 106 | ^- json 107 | a+(turn bs body) 108 | :: 109 | ++ contents 110 | |= cs=(list ^content) 111 | ^- json 112 | a+(turn cs content) 113 | :: 114 | ++ content 115 | |= c=^content 116 | ^- json 117 | %+ frond -.c 118 | ?- -.c 119 | %ship s+(scot %p ship.c) 120 | %text s+cord.c 121 | == 122 | :: 123 | ++ body 124 | |= ^body 125 | ^- json 126 | %- pairs 127 | :~ title+(contents title) 128 | content+(contents content) 129 | time+(^time time) 130 | link+s+(spat link) 131 | == 132 | :: 133 | ++ binned-notification 134 | |= [=^bin =^notification] 135 | %- pairs 136 | :~ bin+(^bin bin) 137 | notification+(^notification notification) 138 | == 139 | ++ lid 140 | |= l=^lid 141 | ^- json 142 | %+ frond -.l 143 | ?- -.l 144 | ?(%seen %unseen) ~ 145 | %archive s+(scot %ud time.l) 146 | == 147 | :: 148 | ++ timebox 149 | |= [li=^lid l=(list ^notification)] 150 | ^- json 151 | %- pairs 152 | :~ lid+(lid li) 153 | notifications+a+(turn l notification) 154 | == 155 | :: 156 | ++ read-each 157 | |= [p=^place pax=^path] 158 | %- pairs 159 | :~ place+(place p) 160 | path+(path pax) 161 | == 162 | :: 163 | ++ unread-count 164 | |= [p=^place inc=? count=@ud] 165 | %- pairs 166 | :~ place+(place p) 167 | inc+b+inc 168 | count+(numb count) 169 | == 170 | -- 171 | ++ dejs 172 | =, dejs:format 173 | |% 174 | ++ ship (su ;~(pfix sig fed:ag)) 175 | :: TODO: fix +stab 176 | :: 177 | ++ pa 178 | |= j=json 179 | ^- path 180 | ?> ?=(%s -.j) 181 | ?: =('/' p.j) / 182 | (stab p.j) 183 | :: 184 | ++ place 185 | %- ot 186 | :~ desk+so 187 | path+pa 188 | == 189 | :: 190 | ++ bin 191 | %- ot 192 | :~ path+pa 193 | place+place 194 | == 195 | :: 196 | ++ read-each 197 | %- ot 198 | :~ place+place 199 | path+pa 200 | == 201 | :: 202 | :: parse date as @ud 203 | :: TODO: move to zuse 204 | ++ sd 205 | |= jon=json 206 | ^- @da 207 | ?> ?=(%s -.jon) 208 | `@da`(rash p.jon dem:ag) 209 | :: 210 | ++ lid 211 | %- of 212 | :~ archive+sd 213 | unseen+ul 214 | seen+ul 215 | == 216 | :: 217 | ++ archive 218 | %- ot 219 | :~ lid+lid 220 | bin+bin 221 | == 222 | ++ content 223 | %- of 224 | :~ text+so 225 | ship+ship 226 | == 227 | :: 228 | ++ body 229 | %- ot 230 | :~ title+(ar content) 231 | content+(ar content) 232 | time+di 233 | binned+pa 234 | link+pa 235 | == 236 | :: 237 | ++ add-note 238 | %- ot 239 | :~ bin+bin 240 | body+body 241 | == 242 | :: 243 | ++ action 244 | ^- $-(json ^action) 245 | %- of 246 | :~ archive-all+ul 247 | archive+archive 248 | opened+ul 249 | read-count+place 250 | read-each+read-each 251 | read-note+bin 252 | add-note+add-note 253 | == 254 | -- 255 | -- 256 | -------------------------------------------------------------------------------- /tanote/sur/sole.hoon: -------------------------------------------------------------------------------- 1 | :: 2 | :::: /hoon/sole/sur 3 | :: 4 | ^? 5 | |% 6 | +$ sole-action :: sole to app 7 | $: id=@ta :: duct id 8 | $= dat 9 | $% :: [%abo ~] :: reset interaction 10 | [%det sole-change] :: command line edit 11 | [%ret ~] :: submit and clear 12 | [%clr ~] :: exit context 13 | [%tab pos=@ud] :: tab complete 14 | == :: 15 | == 16 | +$ sole-buffer (list @c) :: command state 17 | +$ sole-change :: network change 18 | $: ler=sole-clock :: destination clock 19 | haw=@uvH :: source hash 20 | ted=sole-edit :: state change 21 | == :: 22 | +$ sole-clock [own=@ud his=@ud] :: vector clock 23 | +$ sole-edit :: shared state change 24 | $% [%del p=@ud] :: delete one at 25 | [%ins p=@ud q=@c] :: insert at 26 | [%mor p=(list sole-edit)] :: combination 27 | [%nop ~] :: no-op 28 | [%set p=sole-buffer] :: discontinuity 29 | == :: 30 | +$ sole-effect :: app to sole 31 | $% [%bel ~] :: beep 32 | [%blk p=@ud q=@c] :: blink+match char at 33 | [%bye ~] :: close session 34 | [%clr ~] :: clear screen 35 | [%det sole-change] :: edit command 36 | [%err p=@ud] :: error point 37 | [%klr p=styx] :: styled text line 38 | [%mor p=(list sole-effect)] :: multiple effects 39 | [%nex ~] :: save clear command 40 | [%pro sole-prompt] :: set prompt 41 | [%sag p=path q=*] :: save to jamfile 42 | [%sav p=path q=@] :: save to file 43 | [%tab p=(list [=cord =tank])] :: tab-complete list 44 | [%tan p=(list tank)] :: classic tank 45 | :: [%taq p=tanq] :: modern tank 46 | [%txt p=tape] :: text line 47 | [%url p=@t] :: activate url 48 | == :: 49 | +$ sole-command :: command state 50 | $: pos=@ud :: cursor position 51 | say=sole-share :: cursor 52 | == :: 53 | +$ sole-prompt :: prompt definition 54 | $: vis=? :: command visible 55 | tag=term :: history mode 56 | cad=styx :: caption 57 | == :: 58 | +$ sole-share :: symmetric state 59 | $: ven=sole-clock :: our vector clock 60 | leg=(list sole-edit) :: unmerged edits 61 | buf=sole-buffer :: sole state 62 | == :: 63 | :: :: 64 | :: :: 65 | ++ sole-dialog :: standard dialog 66 | |* out=$-(* *) :: output structure 67 | $-(sole-input (sole-result out)) :: output function 68 | :: :: 69 | +$ sole-input tape :: prompt input 70 | ++ sole-result :: conditional result 71 | |* out=$-(* *) :: output structure 72 | $@(@ud (sole-product out)) :: error position 73 | :: :: 74 | ++ sole-product :: success result 75 | |* out=$-(* *) :: 76 | %+ pair (list tank) :: 77 | %+ each (unit out) :: ~ is abort 78 | (pair sole-prompt (sole-dialog out)) :: ask and continue 79 | :: :: 80 | +$ sole-gen :: XX virtual type 81 | $% [%say $-((sole-args) (cask))] :: direct noun 82 | [%ask $-((sole-args) (sole-product (cask)))] :: dialog 83 | == :: 84 | ++ sole-args :: generator arguments 85 | |* _[* *] :: 86 | ,[[now=@da eny=@uvJ bek=beak] [,+<- ,+<+]] :: 87 | -- 88 | -------------------------------------------------------------------------------- /tanote/lib/docket.hoon: -------------------------------------------------------------------------------- 1 | /- *docket 2 | |% 3 | :: 4 | ++ mime 5 | |% 6 | +$ draft 7 | $: title=(unit @t) 8 | info=(unit @t) 9 | color=(unit @ux) 10 | glob-http=(unit [=url hash=@uvH]) 11 | glob-ames=(unit [=ship hash=@uvH]) 12 | base=(unit term) 13 | site=(unit path) 14 | image=(unit url) 15 | version=(unit version) 16 | website=(unit url) 17 | license=(unit cord) 18 | == 19 | :: 20 | ++ finalize 21 | |= =draft 22 | ^- (unit docket) 23 | ?~ title.draft ~ 24 | ?~ info.draft ~ 25 | ?~ color.draft ~ 26 | ?~ version.draft ~ 27 | ?~ website.draft ~ 28 | ?~ license.draft ~ 29 | =/ href=(unit href) 30 | ?^ site.draft `[%site u.site.draft] 31 | ?~ base.draft ~ 32 | ?^ glob-http.draft 33 | `[%glob u.base hash.u.glob-http %http url.u.glob-http]:draft 34 | ?~ glob-ames.draft 35 | ~ 36 | `[%glob u.base hash.u.glob-ames %ames ship.u.glob-ames]:draft 37 | ?~ href ~ 38 | =, draft 39 | :- ~ 40 | :* %1 41 | u.title 42 | u.info 43 | u.color 44 | u.href 45 | image 46 | u.version 47 | u.website 48 | u.license 49 | == 50 | :: 51 | ++ from-clauses 52 | =| =draft 53 | |= cls=(list clause) 54 | ^- (unit docket) 55 | =* loop $ 56 | ?~ cls (finalize draft) 57 | =* clause i.cls 58 | =. draft 59 | ?- -.clause 60 | %title draft(title `title.clause) 61 | %info draft(info `info.clause) 62 | %color draft(color `color.clause) 63 | %glob-http draft(glob-http `[url hash]:clause) 64 | %glob-ames draft(glob-ames `[ship hash]:clause) 65 | %base draft(base `base.clause) 66 | %site draft(site `path.clause) 67 | %image draft(image `url.clause) 68 | %version draft(version `version.clause) 69 | %website draft(website `website.clause) 70 | %license draft(license `license.clause) 71 | == 72 | loop(cls t.cls) 73 | :: 74 | ++ to-clauses 75 | |= d=docket 76 | ^- (list clause) 77 | %- zing 78 | :~ :~ title+title.d 79 | info+info.d 80 | color+color.d 81 | version+version.d 82 | website+website.d 83 | license+license.d 84 | == 85 | ?~ image.d ~ ~[image+u.image.d] 86 | ?: ?=(%site -.href.d) ~[site+path.href.d] 87 | =/ ref=glob-reference glob-reference.href.d 88 | :~ base+base.href.d 89 | ?- -.location.ref 90 | %http [%glob-http url.location.ref hash.ref] 91 | %ames [%glob-ames ship.location.ref hash.ref] 92 | == == == 93 | :: 94 | ++ spit-clause 95 | |= =clause 96 | ^- tape 97 | %+ weld " {(trip -.clause)}+" 98 | ?+ -.clause "'{(trip +.clause)}'" 99 | %color (scow %ux color.clause) 100 | %site (spud path.clause) 101 | :: 102 | %glob-http 103 | "['{(trip url.clause)}' {(scow %uv hash.clause)}]" 104 | :: 105 | %glob-ames 106 | "[{(scow %p ship.clause)} {(scow %uv hash.clause)}]" 107 | :: 108 | %version 109 | =, version.clause 110 | "[{(scow %ud major)} {(scow %ud minor)} {(scow %ud patch)}]" 111 | == 112 | :: 113 | ++ spit-docket 114 | |= dock=docket 115 | ^- tape 116 | ;: welp 117 | ":~\0a" 118 | `tape`(zing (join "\0a" (turn (to-clauses dock) spit-clause))) 119 | "\0a==" 120 | == 121 | -- 122 | :: 123 | ++ enjs 124 | =, enjs:format 125 | |% 126 | :: 127 | ++ charge-update 128 | |= u=^charge-update 129 | ^- json 130 | %+ frond -.u 131 | ^- json 132 | ?- -.u 133 | %del-charge s+desk.u 134 | :: 135 | %initial 136 | %- pairs 137 | %+ turn ~(tap by initial.u) 138 | |=([=desk c=^charge] [desk (charge c)]) 139 | :: 140 | %add-charge 141 | %- pairs 142 | :~ desk+s+desk.u 143 | charge+(charge charge.u) 144 | == 145 | == 146 | :: 147 | ++ num 148 | |= a=@u 149 | ^- ^tape 150 | =/ p=json (numb a) 151 | ?> ?=(%n -.p) 152 | (trip p.p) 153 | :: 154 | ++ version 155 | |= v=^version 156 | ^- json 157 | :- %s 158 | %- crip 159 | "{(num major.v)}.{(num minor.v)}.{(num patch.v)}" 160 | :: 161 | ++ merge 162 | |= [a=json b=json] 163 | ^- json 164 | ?> &(?=(%o -.a) ?=(%o -.b)) 165 | [%o (~(uni by p.a) p.b)] 166 | :: 167 | ++ href 168 | |= h=^href 169 | %+ frond -.h 170 | ?- -.h 171 | %site s+(spat path.h) 172 | %glob 173 | %- pairs 174 | :~ base+s+base.h 175 | glob-reference+(glob-reference glob-reference.h) 176 | == 177 | == 178 | :: 179 | ++ glob-reference 180 | |= ref=^glob-reference 181 | %- pairs 182 | :~ hash+s+(scot %uv hash.ref) 183 | location+(glob-location location.ref) 184 | == 185 | :: 186 | ++ glob-location 187 | |= loc=^glob-location 188 | ^- json 189 | %+ frond -.loc 190 | ?- -.loc 191 | %http s+url.loc 192 | %ames s+(scot %p ship.loc) 193 | == 194 | :: 195 | ++ charge 196 | |= c=^charge 197 | %+ merge (docket docket.c) 198 | %- pairs 199 | :~ chad+(chad chad.c) 200 | == 201 | :: 202 | ++ docket 203 | |= d=^docket 204 | ^- json 205 | %- pairs 206 | :~ title+s+title.d 207 | info+s+info.d 208 | color+s+(scot %ux color.d) 209 | href+(href href.d) 210 | image+?~(image.d ~ s+u.image.d) 211 | version+(version version.d) 212 | license+s+license.d 213 | website+s+website.d 214 | == 215 | :: 216 | ++ chad 217 | |= c=^chad 218 | %+ frond -.c 219 | ?+ -.c ~ 220 | %hung s+err.c 221 | == 222 | -- 223 | -- 224 | -------------------------------------------------------------------------------- /tanote/lib/jose.hoon: -------------------------------------------------------------------------------- 1 | /+ primitive-rsa, *pkcs 2 | =* rsa primitive-rsa 3 | |% 4 | :: +en-base64url: url-safe base64 encoding, without padding 5 | :: 6 | ++ en-base64url 7 | ~(en base64:mimes:html | &) 8 | :: +de-base64url: url-safe base64 decoding, without padding 9 | :: 10 | ++ de-base64url 11 | ~(de base64:mimes:html | &) 12 | :: |octn: encode/decode unsigned atoms as big-endian octet stream 13 | :: 14 | ++ octn 15 | |% 16 | ++ en |=(a=@u `octs`[(met 3 a) (swp 3 a)]) 17 | ++ de |=(a=octs `@u`(rev 3 p.a q.a)) 18 | -- 19 | :: +eor: explicit sort order comparator 20 | :: 21 | :: Lookup :a and :b in :lit, and pass their indices to :com. 22 | :: 23 | ++ eor 24 | |= [com=$-([@ @] ?) lit=(list)] 25 | |= [a=* b=*] 26 | ^- ? 27 | (fall (bind (both (find ~[a] lit) (find ~[b] lit)) com) |) 28 | :: +en-json-sort: json encoding with sorted object keys 29 | :: 30 | :: XX move %zuse with sorting optional? 31 | :: 32 | ++ en-json-sort :: XX rename 33 | |^ |=([sor=$-(^ ?) val=json] (apex val sor "")) 34 | :: :: ++apex:en-json:html 35 | ++ apex 36 | =, en-json:html 37 | |= [val=json sor=$-(^ ?) rez=tape] 38 | ^- tape 39 | ?~ val (weld "null" rez) 40 | ?- -.val 41 | %a 42 | :- '[' 43 | =. rez [']' rez] 44 | !. 45 | ?~ p.val rez 46 | |- 47 | ?~ t.p.val ^$(val i.p.val) 48 | ^$(val i.p.val, rez [',' $(p.val t.p.val)]) 49 | :: 50 | %b (weld ?:(p.val "true" "false") rez) 51 | %n (weld (trip p.val) rez) 52 | %s 53 | :- '"' 54 | =. rez ['"' rez] 55 | =+ viz=(trip p.val) 56 | !. 57 | |- ^- tape 58 | ?~ viz rez 59 | =+ hed=(jesc i.viz) 60 | ?: ?=([@ ~] hed) 61 | [i.hed $(viz t.viz)] 62 | (weld hed $(viz t.viz)) 63 | :: 64 | %o 65 | :- '{' 66 | =. rez ['}' rez] 67 | =/ viz 68 | %+ sort ~(tap by p.val) 69 | |=((pair) (sor (head p) (head q))) 70 | ?~ viz rez 71 | !. 72 | |- ^+ rez 73 | ?~ t.viz ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) 74 | =. rez [',' $(viz t.viz)] 75 | ^$(val [%s p.i.viz], rez [':' ^$(val q.i.viz)]) 76 | == 77 | -- 78 | :: %/lib/jose 79 | :: 80 | :: |jwk: json representations of cryptographic keys (rfc7517) 81 | :: 82 | :: Url-safe base64 encoding of key parameters in big-endian byte order. 83 | :: RSA-only for now 84 | :: 85 | ++ jwk 86 | |% 87 | :: |en:jwk: encoding of json cryptographic keys 88 | :: 89 | ++ en 90 | => |% 91 | :: +numb:en:jwk: base64-url encode big-endian number 92 | :: 93 | ++ numb (corl en-base64url en:octn) 94 | -- 95 | |% 96 | :: +pass:en:jwk: json encode public key 97 | :: 98 | ++ pass 99 | |= k=key:rsa 100 | ^- json 101 | [%o (my kty+s+'RSA' n+s+(numb n.pub.k) e+s+(numb e.pub.k) ~)] 102 | :: +ring:en:jwk: json encode private key 103 | :: 104 | ++ ring 105 | |= k=key:rsa 106 | ^- json 107 | ~| %rsa-need-ring 108 | ?> ?=(^ sek.k) 109 | :- %o %- my :~ 110 | kty+s+'RSA' 111 | n+s+(numb n.pub.k) 112 | e+s+(numb e.pub.k) 113 | d+s+(numb d.u.sek.k) 114 | p+s+(numb p.u.sek.k) 115 | q+s+(numb q.u.sek.k) 116 | == 117 | -- 118 | :: |de:jwk: decoding of json cryptographic keys 119 | :: 120 | ++ de 121 | =, dejs-soft:format 122 | => |% 123 | :: +numb:de:jwk: parse base64-url big-endian number 124 | :: 125 | ++ numb (cu (cork de-base64url (lift de:octn)) so) 126 | -- 127 | |% 128 | :: +pass:de:jwk: decode json public key 129 | :: 130 | ++ pass 131 | %+ ci 132 | =/ a (unit @ux) 133 | |= [kty=@t n=a e=a] 134 | ^- (unit key:rsa) 135 | =/ pub (both n e) 136 | ?~(pub ~ `[u.pub ~]) 137 | (ot kty+(su (jest 'RSA')) n+numb e+numb ~) 138 | :: +ring:de:jwk: decode json private key 139 | :: 140 | ++ ring 141 | %+ ci 142 | =/ a (unit @ux) 143 | |= [kty=@t n=a e=a d=a p=a q=a] 144 | ^- (unit key:rsa) 145 | =/ pub (both n e) 146 | =/ sek :(both d p q) 147 | ?:(|(?=(~ pub) ?=(~ sek)) ~ `[u.pub sek]) 148 | (ot kty+(su (jest 'RSA')) n+numb e+numb d+numb p+numb q+numb ~) 149 | -- 150 | :: |thumb:jwk: "thumbprint" json-encoded key (rfc7638) 151 | :: 152 | ++ thumb 153 | |% 154 | :: +pass:thumb:jwk: thumbprint json-encoded public key 155 | :: 156 | ++ pass 157 | |= k=key:rsa 158 | (en-base64url 32 (shax (crip (en-json-sort aor (pass:en k))))) 159 | :: +ring:thumb:jwk: thumbprint json-encoded private key 160 | :: 161 | ++ ring !! 162 | -- 163 | -- 164 | :: |jws: json web signatures (rfc7515) 165 | :: 166 | :: Note: flattened signature form only. 167 | :: 168 | ++ jws 169 | |% 170 | :: +sign:jws: sign json value 171 | :: 172 | ++ sign 173 | |= [k=key:rsa pro=json lod=json] 174 | |^ ^- json 175 | =. pro header 176 | =/ protect=cord (encode pro) 177 | =/ payload=cord (encode lod) 178 | :- %o %- my :~ 179 | protected+s+protect 180 | payload+s+payload 181 | signature+s+(sign protect payload) 182 | == 183 | :: +header:sign:jws: set signature algorithm in header 184 | :: 185 | ++ header 186 | ?> ?=([%o *] pro) 187 | ^- json 188 | [%o (~(put by p.pro) %alg s+'RS256')] 189 | :: +encode:sign:jws: encode json for signing 190 | :: 191 | :: Alphabetically sort object keys, url-safe base64 encode 192 | :: the serialized json. 193 | :: 194 | ++ encode 195 | |= jon=json 196 | %- en-base64url 197 | %- as-octt:mimes:html 198 | (en-json-sort aor jon) 199 | :: +sign:sign:jws: compute signature 200 | :: 201 | :: Url-safe base64 encode in big-endian byte order. 202 | :: 203 | ++ sign 204 | |= [protect=cord payload=cord] 205 | =/ msg=@t (rap 3 ~[protect '.' payload]) 206 | =/ sig=@ud (~(sign rs256 k) (met 3 msg) msg) 207 | =/ len=@ud (met 3 n.pub.k) 208 | (en-base64url len (rev 3 len sig)) 209 | -- 210 | :: +verify:jws: verify signature 211 | :: 212 | ++ verify !! 213 | -- 214 | -- 215 | --------------------------------------------------------------------------------