Merge branch 'nobreach' into moretalk

This commit is contained in:
Anton Dyudin 2015-09-29 12:31:29 -07:00
commit 9dd386d4b2
31 changed files with 1871 additions and 745 deletions

View File

@ -10,7 +10,7 @@
!: :: ::
=> |% :: external structures
++ house :: all state
$: %2
$: %3
hoc=(map bone session) :: conversations
== ::
++ session :: per conversation
@ -23,14 +23,17 @@
buf=tape :: multiline buffer
== ::
++ dojo-command ::
$% [%flat p=path q=dojo-source] :: noun to unix atom
[%pill p=path q=dojo-source] :: noun to unix pill
:: [%tree p=path q=dojo-source] :: noun to unix tree
[%file p=beam q=dojo-source] :: save to clay
[%http p=?(%post %put) q=purl r=dojo-source] :: http outbound
[%poke p=goal q=dojo-source] :: make and poke
[%show p=dojo-source] :: print
[%verb p=term q=(unit dojo-source)] :: store variable
$& (pair dojo-sink dojo-source) :: route value
[%brev p=term] :: unbind variable
++ dojo-sink ::
$% [%flat p=path] :: atom to unix
[%pill p=path] :: noun to unix pill
:: [%tree p=path] :: noun to unix tree
[%file p=beam] :: save to clay
[%http p=?(%post %put) q=purl] :: http outbound
[%poke p=goal] :: poke app
[%show p=?(0 1 2 3)] :: print val/type/twig
[%verb p=term] :: store variable
== ::
++ dojo-source :: construction node
$: p=@ud :: assembly index
@ -104,26 +107,30 @@
++ dp :: dojo parser
|%
++ dp-default-app %hood
++ dp-specify
|= [gol=goal mod=dojo-model]
^- (pair goal dojo-source)
[gol [0 [%ge mod(q.p [q.gol q.p.mod])]]]
++ dp-message :: %poke
|= [gol=goal mod=dojo-model] ^- dojo-command
[[%poke gol] [0 [%ge mod(q.p [q.gol q.p.mod])]]]
::
++ dp-command-line ;~(sfix dp-command (just '\0a'))
++ dp-variable :: %verb or %brev
|* [sym=_rule src=_rule]
%- cook :_ ;~(plug sym (punt src))
|= [a=term b=(unit dojo-source)] ^- dojo-command
?~(b [%brev a] [[%verb a] u.b])
::
++ dp-command :: ++dojo-command
%+ knee *dojo-command |. ~+
;~ pose
;~ plug (cold %poke bar)
%+ cook dp-specify
;~ pfix bar
%+ cook dp-message
(stag [our.hid dp-default-app] dp-model)
==
::
;~ plug (cold %poke col)
;~ pfix col
%+ cook
|= [a=goal b=$&(dojo-model dojo-source)]
^- (pair goal dojo-source)
?@ -.b [a b]
(dp-specify a b)
?@ -.b [[%poke a] b]
(dp-message a b)
;~ plug
dp-goal
;~ pose
@ -133,21 +140,26 @@
==
==
::
;~(plug (cold %file tar) dp-beam ;~(pfix ace dp-source))
;~(plug (cold %flat pat) (most fas sym) ;~(pfix ace dp-source))
;~(plug (cold %pill dot) (most fas sym) ;~(pfix ace dp-source))
;~(plug (cold %http lus) (easy %post) auri:epur ;~(pfix ace dp-source))
;~(plug (cold %http hep) (easy %put) auri:epur ;~(pfix ace dp-source))
;~(plug (cold %verb tis) sym (punt ;~(pfix ace dp-source)))
;~ plug (cold %verb fas)
;~(pfix tis (dp-variable sym ;~(pfix ace dp-source)))
;~ pfix fas
;~ pose
;~(plug (cold %arc hep) (punt ;~(pfix gap dp-hooves)))
;~(plug (cold %lib lus) (punt ;~(pfix gap dp-hooves)))
(stag %dir :(stag ~ 0 %ex %clsg dp-poor))
(dp-variable (cold %arc hep) ;~(pfix gap dp-hooves))
(dp-variable (cold %lib lus) ;~(pfix gap dp-hooves))
:(stag [%verb %dir] 0 %ex %clsg dp-poor)
==
==
::
(stag %show dp-source)
;~((glue ace) dp-sink dp-source)
(stag [%show %0] dp-source)
==
++ dp-sink
;~ pose
;~(plug (cold %file tar) dp-beam)
;~(plug (cold %flat pat) (most fas sym))
;~(plug (cold %pill dot) (most fas sym))
;~(plug (cold %http lus) (easy %post) auri:epur)
;~(plug (cold %http hep) (easy %put) auri:epur)
(stag %show (cook ?(1 2 3) (cook lent (stun [1 3] wut))))
==
++ dp-hooves :: hoof list
:(stag 0 %ex %clsg (cook |=(a=tusk a) (most ;~(plug com gaw) dp-hoof)))
@ -196,17 +208,17 @@
==
++ dp-beam :: ++beam
%+ cook |=(a=path =+((tome a) ?^(- u [he-beak (flop a)])))
=+ vez=(vang & dp-path)
=+ vez=(vang | dp-path)
(sear plex:vez (stag %clsg poor:vez))
::
++ dp-model ;~(plug dp-server dp-config) :: ++dojo-model
++ dp-path (tope he-beam) :: ++path
++ dp-server (stag 0 (most fas sym)) :: ++dojo-server
++ dp-twig tall:(vang & dp-path) :: ++twig
++ dp-poor poor:(vang & (tope dir)) :: (list ++twig)
++ dp-twig tall:(vang | dp-path) :: ++twig
++ dp-poor poor:(vang | (tope dir)) :: (list ++twig)
++ dp-value :: ++dojo-source
;~ pose
(stag %tu (ifix [kel ker] (most ace dp-source)))
(stag %tu (ifix [sel ser] (most ace dp-source)))
(stag %ex dp-twig)
==
::
@ -262,25 +274,11 @@
++ dy-init-command :: ++dojo-command
|= mad=dojo-command
^+ [mad +>]
?- -.mad
%file =^(src +>.$ (dy-init-source q.mad) [mad(q src) +>.$])
%flat =^(src +>.$ (dy-init-source q.mad) [mad(q src) +>.$])
%pill =^(src +>.$ (dy-init-source q.mad) [mad(q src) +>.$])
%poke =^(src +>.$ (dy-init-source q.mad) [mad(q src) +>.$])
%show =^(src +>.$ (dy-init-source p.mad) [mad(p src) +>.$])
%verb =^(src +>.$ (dy-init-source-unit q.mad) [mad(q src) +>.$])
%http
=. r.mad [0 %as %mime r.mad]
=^ src +>.$ (dy-init-source r.mad)
[mad(r src) +>.$]
==
::
++ dy-init-source-unit :: (unit dojo-source)
|= urc=(unit dojo-source)
^+ [urc +>]
?~ urc [~ +>]
=^ src +> (dy-init-source u.urc)
[`src +>.$]
?@ -.mad [mad +>.$]
=. q.mad
?+(-.p.mad q.mad %http [0 %as %mime q.mad])
=^ src +>.$ (dy-init-source q.mad)
[mad(q src) +>.$]
::
++ dy-init-source :: ++dojo-source
|= src=dojo-source
@ -291,6 +289,13 @@
==
[src +>.$(num +(num), job (~(put by job) src))]
::
++ dy-init-source-unit :: (unit dojo-source)
|= urc=(unit dojo-source)
^+ [urc +>]
?~ urc [~ +>]
=^ src +> (dy-init-source u.urc)
[`src +>.$]
::
++ dy-init-build :: ++dojo-build
|= bul=dojo-build
^+ [bul +>]
@ -390,36 +395,9 @@
::
++ dy-over :: finish construction
^+ +>
?- -.mad
%poke
%- he-card(poy ~)
:* %deal
/poke
[our.hid p.p.mad]
q.p.mad
%poke
(~(got by rez) p.q.mad)
==
::
%file
%- he-card(poy ~) :*
%info
/file
our.hid
(foal (tope p.mad) (~(got by rez) p.q.mad))
==
::
%flat
=+ out=q.q:(~(got by rez) p.q.mad)
?^ out
(dy-rash %tan [%leaf "not an atom"]~)
(dy-rash %sav p.mad out)
::
%pill
(dy-rash %sag p.mad q.q:(~(got by rez) p.q.mad))
::
%verb
?~ q.mad
?: ?=([%show 3] -.mad)
(dy-rash %tan (dy-show-source q.mad) ~) :: XX separate command
?: ?=(%brev -.mad)
=. var (~(del by var) p.mad)
=< dy-amok
?+ p.mad .
@ -428,11 +406,13 @@
%arc .(arc ~)
%dir .(dir [[our.hid %home ud/0] /])
==
=+ cay=(~(got by rez) p.u.q.mad)
=. var (~(put by var) p.mad cay)
~| bad-set/[p.mad p.q.cay]
=+ cay=(~(got by rez) p.q.mad)
?- -.p.mad
%verb
=. var (~(put by var) p.p.mad cay)
~| bad-set/[p.p.mad p.q.cay]
=< dy-amok
?+ p.mad .
?+ p.p.mad .
%eny ~|(%entropy-is-eternal !!)
%now ~|(%time-is-immutable !!)
%our ~|(%self-is-immutable !!)
@ -442,21 +422,53 @@
=- +(..dy (he-diff %tan - ~))
rose/[" " `~]^~[leaf/"=%" (smyt (tope he-beak s.dir))]
==
::
%poke
%- he-card(poy ~)
:* %deal
/poke
[our.hid p.p.p.mad]
q.p.p.mad
%poke
cay
==
::
%file
%- he-card(poy ~) :*
%info
/file
our.hid
(foal (tope p.p.mad) cay)
==
::
%flat
?^ q.q.cay
(dy-rash %tan [%leaf "not an atom"]~)
(dy-rash %sav p.p.mad q.q.cay)
::
%pill
(dy-rash %sag p.p.mad q.q.cay)
::
%http
=+ cay=(~(got by rez) p.r.mad)
?> ?=(%mime p.cay)
=+ mim=;;(mime q.q.cay)
=+ maf=(~(add ja *math) content-type/(moon p.mim))
(dy-eyre /show [q.mad p.mad maf ~ q.mim])
(dy-eyre /show [q.p.mad p.p.mad maf ~ q.mim])
::
%show
(dy-show (~(got by rez) p.p.mad))
%+ dy-print cay
?- p.p.mad
0 ~
1 ~[[%rose [~ " " ~] (skol p.q.cay) ~] [%rose [~ " " ~] >p.cay< ~]]
2 [%rose [~ " " ~] (dy-show-type-noun p.q.cay) ~]~
==
==
::
++ dy-show
|= cay=cage
++ dy-show |=(cay=cage (dy-print cay ~))
++ dy-print
|= [cay=cage tan=tang]
%+ dy-rash %tan
%- welp :_ tan
?+ p.cay [(sell q.cay)]~
%tang ;;(tang q.q.cay)
%httr
@ -468,6 +480,53 @@
(turn `wain`?~(r.hit ~ (lore q.u.r.hit)) trip)
==
::
++ dy-show-type-noun
|= a=type ^- tank
=- >[-]<
|- ^- $? $% [%atom @tas]
[%cell _$ _$]
[%cube * _$]
[%face @tas _$]
[%fork _$ _$]
[%hold (list ,[_$ twig])]
==
wain :: "<|core|>"
?(%noun %void)
==
?+ a a
[?(%cube %face) ^] a(q $(a q.a))
[?(%cell %fork) ^] a(p $(a p.a), q $(a q.a))
[%bull ^] $(a q.a)
[%core ^] `wain`/core
[%hold *] a(p (turn p.a |=([b=type c=twig] [^$(a b) c])))
==
::
++ dy-show-source
|= a=dojo-source ^- tank
=- >[-]<
=+ `[@ bil=dojo-build]`a
|- ^- $& [_$ _$]
$? twig
$% [%ur purl]
[%dv path]
[%as mark _$]
[%do twig _$]
[%ge path (list ,_$) (map term (unit ,_$))]
==
==
?- -.bil
?(%ur %dv) bil
%ex p.bil
%tu ?~ p.bil !!
|-
?~ t.p.bil ^$(bil q.i.p.bil)
[^$(bil q.i.p.bil) $(p.bil t.p.bil)]
%as bil(q $(bil q.q.bil))
%do bil(q $(bil q.q.bil))
%ge :+ %ge q.p.p.bil
[(turn p.q.p.bil ..$) (~(run by q.q.p.bil) (lift ..$))]
==
::
++ dy-edit :: handle edit
|= cal=sole-change
^+ +>+>
@ -643,6 +702,8 @@
|= nex=@ud
^+ +>+>
?> ?=(~ cud)
?: ?=([%show 3] -.mad)
dy-over
?: =(nex num)
dy-over
dy-make(cud `[nex (~(got by job) nex)])
@ -836,12 +897,17 @@
=+ session-1==+(*session ,_-(poy *(unit)))
=+ session-0==+(*session-1 ,[_say syd=desk * _|2.-])
:: ,_`..prep
=+ hoze=$%([%0 p=(map bone session-0)] [%1 p=(map bone session-1)])
=+ ^= hoze
$% [%0 p=(map bone session-0)]
[%1 p=(map bone session-1)]
[%2 p=(map bone session-1)]
==
|= old=(unit ?(house hoze)) ^+ [~ ..prep]
?~ old `..prep
?- -.u.old
%2 `..prep(+<+ u.old)
%1 `..prep(+<+ [%2 (~(run by p.u.old) |=(session-1 +<(poy ~)))])
%3 `..prep(+<+ u.old)
%2 `..prep(+<+ [%3 (~(run by p.u.old) |=(session-1 +<(poy ~)))])
%1 `..prep(+<+ [%3 (~(run by p.u.old) |=(session-1 +<(poy ~)))])
%0 =< ^$(u.old [%1 (~(run by p.u.old) .)])
|= sos=session-0 ^- session-1
[-.sos [[our.hid syd.sos ud/0] /] |3.sos]

View File

@ -56,6 +56,11 @@
~? ?=(^ saw) [%kiln-spam-lame u.saw]
[~ +>]
::
++ coup-kiln-reload ::
|= [way=wire saw=(unit tang)]
~? ?=(^ saw) [%kiln-reload-lame u.saw]
[~ +>]
::
++ coup-drum-phat (wrap take-coup-phat):from-drum
++ coup-helm-hi (wrap coup-hi):from-helm
++ diff-sole-effect-drum-phat (wrap diff-sole-effect-phat):from-drum
@ -97,16 +102,20 @@
++ poke-kiln-cp (wrap poke-cp):from-kiln
++ poke-kiln-label (wrap poke-label):from-kiln
++ poke-kiln-merge (wrap poke-merge):from-kiln
++ poke-kiln-cancel (wrap poke-cancel):from-kiln
++ poke-kiln-mount (wrap poke-mount):from-kiln
++ poke-kiln-mv (wrap poke-mv):from-kiln
++ poke-kiln-rm (wrap poke-rm):from-kiln
++ poke-kiln-schedule (wrap poke-schedule):from-kiln
++ poke-kiln-sync (wrap poke-sync):from-kiln
++ poke-kiln-start-autoload (wrap poke-start-autoload):from-kiln
++ poke-kiln-autoload (wrap poke-autoload):from-kiln
++ poke-kiln-unmount (wrap poke-unmount):from-kiln
++ poke-kiln-unsync (wrap poke-unsync):from-kiln
++ poke-will (wrap poke-will):from-helm
++ quit-drum-phat (wrap quit-phat):from-drum
++ reap-drum-phat (wrap reap-phat):from-drum
++ woot-helm (wrap take-woot):from-helm
++ writ-kiln-sync (wrap take-writ):from-kiln
++ writ-kiln-autoload (wrap take-writ-autoload):from-kiln
++ writ-kiln-sync (wrap take-writ-sync):from-kiln
--

View File

@ -24,7 +24,8 @@
::
|_ $: bowl
client
connected=_|
connected=_| :: subscribed to talk
count=@ud :: # messages from talk
unordered=(map ,[@uvH @u] (pair ship flesh:work-stuff:talk))
==
++ at
@ -82,7 +83,7 @@
|= up=update
^+ +>
?- -.up
%add ?>(?=(%comment +<.up) (send-change %add-comment +>.up))
%add ?>(?=(%comment +<.up) (send-change %add-comment our +>.up))
%doer
?- +<.up
%release (send-change %set-doer ~)
@ -114,6 +115,7 @@
%- unit
$: client
_|
@ud
(map ,[@uvH @u] (pair ship flesh:work-stuff:talk))
==
^- [(list move) _+>.$]
@ -124,7 +126,7 @@
?: connected
[~ .]
:_ .(connected %&) :_ ~
[ost %peer /peering [our %talk] /f/(main:talk our)/0]
[ost %peer /peering [our %talk] /f/(main:talk our)/(scot %ud count)]
::
++ process-duty
|= [when=@da her=ship from=(set station:talk) action=duty:work-stuff:talk]
@ -256,7 +258,7 @@
%set-done tax.u.tax(done ?.(don.meat.action ~ `when))
%add-comment
%= tax.u.tax
discussion [[when her com.meat.action] discussion.tax.u.tax]
discussion [[when [who com]:meat.action] discussion.tax.u.tax]
==
==
=+ ooo=(~(get by unordered) id.action +(version.action))
@ -309,28 +311,25 @@
abut:send-create:(at | +.cod)
==
::
:: XX maybe need to check that we haven't received this message before
:: by keeping a counter of last message received
:: XX definitely do this!
:: XX handle and test the disconnection case
::
:: XX test the disconnection case
++ diff-talk-report
|= [way=wire rep=report:talk]
^- [(list move) _+>.$]
?> ?=(%grams -.rep)
|- ^- [(list move) _+>.^$]
?~ q.rep [~ +>.^$]
=. count +(count)
=* her p.i.q.rep
=* when p.r.q.i.q.rep
=* said r.r.q.i.q.rep
?. ?=(%tax -.said)
$(p.rep +(p.rep), q.rep t.q.rep)
=+ ^- from=(set station:talk)
%- sa ^- (list station:talk)
%+ murn (~(tap by q.q.i.q.rep))
=> talk
|= [par=partner *]
`(unit station)`?.(?=(%& -.par) ~ `p.par)
?. ?=(%tax -.said)
$(p.rep +(p.rep), q.rep t.q.rep)
=^ mos +>.^$ (process-duty when her from +.said)
=^ mof +>.^$ $(p.rep +(p.rep), q.rep t.q.rep)
[(weld mos mof) +>.^$]

View File

@ -413,7 +413,7 @@
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
tay=(cut 0 [27 5] mag) :: message type
==
?> =(4 vez)
?> =(5 vez)
?> =(chk (end 0 20 (mug bod)))
:+ [(end 3 wix bod) (cut 3 [wix vix] bod)]
(kins tay)
@ -433,7 +433,7 @@
=+ tay=(ksin q.kec)
%+ mix
%+ can 0
:~ [3 4]
:~ [3 5]
[20 (mug bod)]
[2 yax]
[2 qax]
@ -1018,7 +1018,7 @@
++ gnaw :: gnaw:am
|= [kay=cape ryn=lane pac=rock] :: process packet
^- [p=(list boon) q=fort]
?. =(4 (end 0 3 pac)) [~ fox]
?. =(5 (end 0 3 pac)) [~ fox]
=+ kec=(bite pac)
?: (goop p.p.kec) [~ fox]
?. (~(has by urb.ton.fox) q.p.kec)

View File

@ -162,11 +162,7 @@
mer=mer.jod
==
=* red ->
=| yel=(list ,[p=duct q=gift])
=| byn=(list ,[p=duct q=riot])
=| reg=(list ,[p=duct q=gift])
=| say=(list ,[p=duct q=path r=ship s=[p=@ud q=riff]])
=| tag=(list move)
=| mow=(list move)
|%
++ abet
^- [(list move) raft]
@ -176,23 +172,7 @@
ruf(hoy (~(put by hoy.ruf) her rug))
=+ dos=(~(put by dos.u.rom) syd [qyx dom dok mer])
ruf(fat (~(put by fat.ruf) her [(need hun) dos]))
;: weld
%+ turn (flop yel)
|=([a=duct b=gift] [(need hun) %give b])
::
%+ turn (flop reg)
|=([a=duct b=gift] [a %give b])
::
%+ turn (flop byn)
|=([a=duct b=riot] [a %give [%writ b]])
::
%+ turn (flop say)
|= [a=duct b=path c=ship d=[p=@ud q=riff]]
:- a
[%pass b %a %wont [our c] [%c %question p.q.d (scot %ud p.d) ~] q.d]
::
tag
==
(flop mow)
::
++ aver :: read
|= mun=mood
@ -260,6 +240,14 @@
(mule |.(`~`~|([%expected-path got=p.pax] !!)))
$(tay t.tay, can (~(put by can) ((hard path) q.q.pax) q.i.tay))
::
++ emit
|= mof=move
%_(+> mow [mof mow])
::
++ emil
|= mof=(list move)
%_(+> mow (welp mof mow))
::
++ balk :: read and send
|= [hen=duct cay=(unit (each cage lobe)) mun=mood]
^+ +>
@ -268,18 +256,18 @@
::
++ bait
|= [hen=duct tym=@da]
%_(+> tag :_(tag [hen %pass /tyme %t %wait tym]))
(emit hen %pass /tyme %t %wait tym)
::
++ best
|= [hen=duct tym=@da]
%_(+> tag :_(tag [hen %pass /tyme %t %rest tym]))
(emit hen %pass /tyme %t %rest tym)
::
++ blab :: ship result
|= [hen=duct mun=mood dat=(each cage lobe)]
^+ +>
?: ?=(%& -.dat)
+>.$(byn [[hen ~ [p.mun q.mun syd] r.mun p.dat] byn])
=- +>.$(tag [- tag])
(emit hen %give %writ ~ [p.mun q.mun syd] r.mun p.dat)
%- emit
:* hen %pass [%blab p.mun (scot q.mun) syd r.mun]
%f %exec our ~ [her syd q.mun] (lobe-to-silk:ze r.mun p.dat)
==
@ -295,7 +283,15 @@
::
++ blub :: ship stop
|= hen=duct
%_(+> byn [[hen ~] byn])
(emit hen %give %writ ~)
::
++ print-to-dill
|= [car=@tD tan=tank]
(emit (need hun) %give %note car tan)
::
++ send-over-ames
|= [a=duct b=path c=ship d=[p=@ud q=riff]]
(emit a %pass b %a %wont [our c] [%c %question p.q.d (scot %ud p.d) ~] q.d)
::
++ duce :: produce request
|= rov=rove
@ -309,8 +305,10 @@
?. ?=([%sing %v *] rav) rav
[%many %| [%ud let.dom] `case`q.p.rav r.p.rav]
=+ inx=nix.u.ref
=. +>+.$
=< ?>(?=(^ ref) .)
(send-over-ames hen [(scot %ud inx) ~] her inx syd ~ vaw)
%= +>+.$
say [[hen [(scot %ud inx) ~] her [inx syd ~ vaw]] say]
nix.u.ref +(nix.u.ref)
bom.u.ref (~(put by bom.u.ref) inx [hen vaw])
fod.u.ref (~(put by fod.u.ref) hen inx)
@ -335,9 +333,7 @@
=+ mus=(skim can |=(paf=path =(pax (scag (lent pax) paf))))
?~ mus
+>.$
%_ +>.$
tag
:_ tag
%- emit
:* hen %pass [%ergoing (scot %p her) syd ~] %f
%exec our ~ [her syd %da now] %tabl
^- (list (pair silk silk))
@ -351,7 +347,6 @@
[%$ p.-]
(lobe-to-silk:ze a p.-)
==
==
::
++ ease :: release request
^+ .
@ -364,8 +359,10 @@
|- ^+ +.$
=+ nux=(~(get by fod.u.ref) hen)
?~ nux +.$
=. +.$
=< ?>(?=(^ ref) .)
(send-over-ames hen [(scot %ud u.nux) ~] her u.nux syd ~)
%= +.$
say [[hen [(scot %ud u.nux) ~] her [u.nux syd ~]] say]
fod.u.ref (~(del by fod.u.ref) hen)
bom.u.ref (~(del by bom.u.ref) u.nux)
==
@ -422,31 +419,19 @@
(duce `rove`[%many p.rav ptr q.q.rav r.q.rav ear])
==
::
++ echa :: announce raw
|= [wen=@da mer=mizu]
^+ +>
%= +>
reg ~& %merge-announce reg
:: yel [[hen %note '=' %leaf ~] yel] :: XX do better
==
::
++ echo :: announce changes
|= [wen=@da lem=nuri]
^+ +>
%_ +>.$
yel
=+ pre=`path`~[(scot %p her) syd (scot %ud let.dom)]
?- -.lem
| :_ yel
[hen %note '=' %leaf :(weld (trip p.lem) " " (spud pre))]
& |- ^+ yel
?~ p.lem yel
:_ $(p.lem t.p.lem)
:- hen
:+ %note
| (print-to-dill '=' %leaf :(weld (trip p.lem) " " (spud pre)))
& |- ^+ +>.^$
?~ p.lem +>.^$
=. +>.^$
%+ print-to-dill
?-(-.q.i.p.lem %del '-', %ins '+', %dif ':')
[%leaf (spud (weld pre p.i.p.lem))]
==
$(p.lem t.p.lem)
==
::
++ edit :: apply changes
@ -472,72 +457,8 @@
?& ?=([?(%hoon %hook) *] (flop pax))
?=(%mime p.p.mis)
==
=- %_ +>.$
tag (welp - tag)
dok
:- ~
:* %+ turn del
|= [pax=path mis=miso]
?> ?=(%del -.mis)
pax
::
%+ turn ink
|= [pax=path mis=miso]
^- (pair path cage)
?> ?=(%ins -.mis)
=+ =>((flop pax) ?~(. %$ i))
[pax - [%atom %t] ((hard ,@t) +>.q.q.p.mis)]
::
~
::
%- mo
%+ turn dif
|= [pax=path mis=miso]
?> ?=(%dif -.mis)
[pax p.mis]
::
~
::
%- mo
%+ turn mut
|= [pax=path mis=miso]
?> ?=(%mut -.mis)
[pax p.mis]
::
~
::
~
::
%- mo ^- (list (pair path mime))
;: welp
^- (list (pair path mime))
%+ murn ins
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%ins -.mis)
?. ?=(%mime p.p.mis)
~
`[pax ((hard mime) q.q.p.mis)]
::
^- (list (pair path mime))
%+ murn ink
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%ins -.mis)
?> ?=(%mime p.p.mis)
`[pax ((hard mime) q.q.p.mis)]
::
^- (list (pair path mime))
%+ murn mut
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%mut -.mis)
?. ?=(%mime p.p.mis)
~
`[pax ((hard mime) q.q.p.mis)]
==
==
==
=. +>.$
%- emil
^- (list move)
:~ :* hen %pass
[%inserting (scot %p her) syd (scot %da wen) ~]
@ -574,6 +495,60 @@
[%cast - [%$ p.mis]]
==
==
%_ +>.$
dok
:- ~
:* (turn del |=([pax=path mis=miso] ?>(?=(%del -.mis) pax)))
::
%+ turn ink
|= [pax=path mis=miso]
^- (pair path cage)
?> ?=(%ins -.mis)
=+ =>((flop pax) ?~(. %$ i))
[pax - [%atom %t] ((hard ,@t) +>.q.q.p.mis)]
::
~
::
(mo (turn dif |=([pax=path mis=miso] ?>(?=(%dif -.mis) [pax p.mis]))))
::
~
::
(mo (turn mut |=([pax=path mis=miso] ?>(?=(%mut -.mis) [pax p.mis]))))
::
~
::
~
::
%- mo ^- (list (pair path mime))
;: welp
^- (list (pair path mime))
%+ murn ins
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%ins -.mis)
?. ?=(%mime p.p.mis)
~
`[pax ((hard mime) q.q.p.mis)]
::
^- (list (pair path mime))
%+ murn ink
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%ins -.mis)
?> ?=(%mime p.p.mis)
`[pax ((hard mime) q.q.p.mis)]
::
^- (list (pair path mime))
%+ murn mut
|= [pax=path mis=miso]
^- (unit (pair path mime))
?> ?=(%mut -.mis)
?. ?=(%mime p.p.mis)
~
`[pax ((hard mime) q.q.p.mis)]
==
==
==
::
++ silkify
|= [wen=@da pax=path mis=miso]
@ -691,8 +666,7 @@
%+ turn cat
|= [pax=path cay=cage]
[pax (page-to-lobe:ze [p q.q]:cay)]
=- %_(+>.$ tag [- tag])
^- move
%- emit
:* hen %pass
[%mutating (scot %p her) syd (scot %da wen) ~]
%f %exec our ~ [her syd %da wen] %tabl
@ -733,11 +707,8 @@
^+ +>
:: ~& %taking-patch
?: ?=(%| -.res)
%_ +>.$
dok ~
yel
[[hen %note '!' %rose [" " "" ""] leaf/"clay patch failed" p.res] yel]
==
=. dok ~
(print-to-dill '!' %rose [" " "" ""] leaf/"clay patch failed" p.res)
:: ~& %editing
=+ ^- sim=(list (pair path misu))
?~ dok
@ -795,10 +766,7 @@
=+ can=(mo sim)
:: ~& %forming-ergo
:: =- ~& %formed-ergo -
%_ +>.$
dok ~
tag
:_ tag
%- emit(dok ~)
:* hen %pass [%ergoing (scot %p her) syd ~] %f
%exec our ~ [her syd %da now] %tabl
^- (list (pair silk silk))
@ -817,16 +785,12 @@
[%$ p.-]
(lobe-to-silk:ze a p.-)
==
==
::
++ take-ergo
|= res=gage
^+ +>
?: ?=(%| -.res)
%_ +>.$
yel
[[hen %note '!' %rose [" " "" ""] leaf/"clay ergo failed" p.res] yel]
==
(print-to-dill '!' %rose [" " "" ""] leaf/"clay ergo failed" p.res)
?~ hez ~|(%no-sync-duct !!)
=+ ^- can=(map path (unit mime))
%- mo ^- mode
@ -839,24 +803,19 @@
~
`((hard mime) q.q.mim)
=+ mus=(must-ergo (turn (~(tap by can)) head))
%= +>.$
reg
%- welp :_ reg
%- emil
%+ turn (~(tap by mus))
|= [pot=term len=@ud pak=(set path)]
:* u.hez %ergo pot
:* u.hez %give %ergo pot
%+ turn (~(tap in pak))
|= pax=path
[(slag len pax) (~(got by can) pax)]
==
==
::
++ checkout-ankh
|= hat=(map path lobe)
^+ +>
%_ +>.$
tag
:_ tag
%- emit
:* hen %pass [%patching (scot %p her) syd ~] %f
%exec our :^ ~ [her syd %da now] %tabl
^- (list (pair silk silk))
@ -866,7 +825,6 @@
:- [%$ %path-hash !>([a b])]
(lobe-to-silk:ze a b)
==
==
::
++ apply-foreign-update :: apply subscription
|= $: lem=(unit ,@da) :: complete up to
@ -1016,34 +974,10 @@
!!
==
::
++ rand-to-rant
|= rut=rand
^+ +>
~| [%x-over-network-not-implemented [p q -.r]:rut hen] !!
:: =- %_(+>.$ tag [- tag])
:: :* hen
:: [%foreign-plops (scot %p our) (scot %p her) syd ~]
:: %f %exec our ~ %tabl
:: ^- (list (pair silk silk))
:: %+ turn (~(tap in pop))
:: |= a=plop
:: ?- -.a
:: %delta
:: :- [%$ %blob !>([%delta p.a q.a *cage])]
:: [%vale p.r.a q.r.a]
:: ::
:: %direct
:: :- [%$ %blob !>([%direct p.a *cage])]
:: [%vale p.q.a q.q.a]
:: ::
:: %indirect ~| %foreign-indirect-not-implemented !!
:: ==
:: ==
::
++ validate-x
|= [car=care cas=case pax=path peg=page]
^+ +>
=- %_(+>.$ tag [- tag])
%- emit
:* hen %pass
[%foreign-x (scot %p our) (scot %p her) syd car (scot cas) pax]
%f %exec our ~ [her syd cas]
@ -1065,8 +999,8 @@
++ validate-plops
|= [cas=case lem=(unit ,@da) pop=(set plop)]
^+ +>
=- %_(+>.$ tag [- tag])
=+ lum=(scot %da (fall lem *@da))
%- emit
:* hen %pass
[%foreign-plops (scot %p our) (scot %p her) syd lum ~]
%f %exec our ~ [her syd cas] %tabl
@ -1074,15 +1008,8 @@
%+ turn (~(tap in pop))
|= a=plop
?- -.a
%delta
:- [%$ %blob !>([%delta p.a q.a *page])]
[%vale p.r.a q.r.a]
::
%direct
:- [%$ %blob !>([%direct p.a *page])]
[%vale p.q.a q.q.a]
::
%indirect ~| %foreign-indirect-not-implemented !!
%delta [[%$ %blob !>([%delta p.a q.a *page])] [%vale p.r.a q.r.a]]
%direct [[%$ %blob !>([%direct p.a *page])] [%vale p.q.a q.q.a]]
==
==
::
@ -1101,7 +1028,6 @@
?- -.bol
%delta [-.bol p.bol q.bol p.cay q.q.cay]
%direct [-.bol p.bol p.cay q.q.cay]
%indirect ~| %plop-indirect-not-implemented !!
==
%^ apply-foreign-update
lem
@ -1219,6 +1145,15 @@
(bleb p.i.xiq +(u.nab) ?:(p.q.i.xiq ~ `[u.nab u.huy]))
==
==
++ drop-me
^+ .
?~ mer
.
%- emit(mer ~) ^- move :*
hen.u.mer %give %mere %| %user-interrupt
>sor.u.mer< >our< >cas.u.mer< >gem.u.mer< ~
==
::
++ ze
|%
++ aeon-to-tako ~(got by hit.dom)
@ -1231,7 +1166,6 @@
?- -
%delta p.q
%direct p.q
%indirect p.q
==
++ lobe-to-silk :: XX maybe move hoo{n,k} stuff here
|= [pax=path lob=lobe]
@ -1249,7 +1183,6 @@
=+ bol=(~(got by lat.ran) lob)
?- -.bol
%direct [%volt q.bol]
%indirect [%volt q.bol]
%delta ~| delta/q.q.bol
[%pact $(lob q.q.bol) [%volt r.bol]]
==
@ -1482,7 +1415,6 @@
?- -.gar
%direct (~(put in far) lob)
%delta (~(put in $(lob q.q.gar)) lob)
%indirect (~(put in $(lob r.gar)) lob)
==
::
++ data-twixt-takos
@ -1530,6 +1462,15 @@
~
```[%null [%atom %n] ~]
::
++ read-v
|= [yon=aeon pax=path]
^- (unit (unit ,[%dome (hypo dome)]))
?: (lth yon let.dom)
~
?: (gth yon let.dom)
`~
``[%dome -:!>(*dome) dom]
::
++ read-x
|= [yon=aeon pax=path]
^- (unit (unit (each cage lobe)))
@ -1556,8 +1497,6 @@
=+ bol=(lobe-to-blob u.lob)
?: ?=(%direct -.bol)
((hard ,@t) q.q.bol)
?: ?=(%indirect -.bol)
((hard ,@t) q.q.bol)
?> ?=(%delta -.bol)
=+ txt=$(u.lob q.q.bol)
?> ?=(%txt-diff p.r.bol)
@ -1611,6 +1550,8 @@
?^(r.mun [~ ~] [~ ~ %& %aeon !>(yon)])
?: ?=(%u p.mun)
(read-u yon r.mun)
?: ?=(%v p.mun)
(bind (read-v yon r.mun) (curr bind (cury same %&)))
?: ?=(%x p.mun)
(read-x yon r.mun)
?: ?=(%y p.mun)
@ -1645,7 +1586,7 @@
:: %- ~(run by hat)
:: |= a=lobe
:: =+ (lobe-to-blob a)
:: ?-(-.- %direct q.-, %indirect q.-, %delta !!)
:: ?-(-.- %direct q.-, %delta !!)
::`+>.$(ank.dom (checkout-ankh -), let.dom yon)
::
++ update-lat :: update-lat:ze
@ -1716,7 +1657,17 @@
^+ ..me
?: don
..me(mer `dat)
..me(mer ~, reg :_(reg [hen %mere gon.dat]))
=. mer ~
=> (emit hen.dat %give %mere gon.dat)
..me
::
++ emit
|= move
%_(+> ..ze (^emit +<))
::
++ emil
|= (list move)
%_(+> ..ze (^emil +<))
::
++ route
|= [sat=term res=(each riot gage)]
@ -1759,7 +1710,7 @@
::
++ fetch-ali
^+ .
=- %_(+ tag [- tag], wat.dat %ali)
%- emit(wat.dat %ali)
:* hen %pass
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali %ali ~]
%c %warp [p.bob p.ali] q.ali
@ -1937,7 +1888,7 @@
++ diff-bas
|= [nam=term yak=yaki oth=(trel ship desk case) yuk=yaki]
^+ +>
=- %_(+>.$ tag [- tag])
%- emit
:* hen %pass
=+ (cat 3 %diff- nam)
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali - ~]
@ -1982,15 +1933,18 @@
|= [pax=path lob=lobe]
(~(has by q.bas.dat) pax)
=. cal.dal.dat
%- mo
%+ skim (~(tap by q.bas.dat))
%- mo ^- (list (pair path lobe))
%+ murn (~(tap by q.bas.dat))
|= [pax=path lob=lobe]
^- (unit (pair path lobe))
=+ a=(~(get by q.ali.dat) pax)
=+ b=(~(get by q.bob.dat) pax)
?& ?=(^ a)
?. ?& ?=(^ a)
!=([~ lob] a)
=([~ lob] b)
==
~
`[pax +.a]
=. can.dal.dat p.can
=. old.dal.dat
%- mo ^- (list ,[path ~])
@ -2022,15 +1976,18 @@
|= [pax=path lob=lobe]
(~(has by q.bas.dat) pax)
=. cal.dob.dat
%- mo
%+ skim (~(tap by q.bas.dat))
%- mo ^- (list (pair path lobe))
%+ murn (~(tap by q.bas.dat))
|= [pax=path lob=lobe]
^- (unit (pair path lobe))
=+ a=(~(get by q.ali.dat) pax)
=+ b=(~(get by q.bob.dat) pax)
?& ?=(^ b)
?. ?& ?=(^ b)
!=([~ lob] b)
=([~ lob] a)
==
~
`[pax +.b]
=. can.dob.dat p.can
=. old.dob.dat
%- mo ^- (list ,[path ~])
@ -2046,7 +2003,7 @@
|- ^+ +.$
?+ gem.dat ~| [%merge-weird-gem gem.dat] !!
?(%mate %meld)
=- %_(+.$ tag [- tag], wat.dat %merge)
%- emit(wat.dat %merge)
:* hen %pass
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali %merge ~]
%f %exec p.bob ~ [p.bob q.bob da/now] %tabl
@ -2080,7 +2037,7 @@
::
++ build
^+ .
=- %_(+ tag [- tag], wat.dat %build)
%- emit(wat.dat %build)
:* hen %pass
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali %build ~]
%f %exec p.bob ~ [p.bob q.bob da/now] %tabl
@ -2119,7 +2076,7 @@
%- ~(urn by con)
|= [pax=path *]
(~(got by q.bas.dat) pax)
=. con :: add/del conflict
=. con :: change/del conflict
%- ~(uni by con)
%- mo ^- (list ,[path *])
%+ skim (~(tap by old.dal.dat))
@ -2128,7 +2085,7 @@
~| %strange-add-and-del
!!
(~(has by can.dob.dat) pax)
=. con :: add/del conflict
=. con :: change/del conflict
%- ~(uni by con)
%- mo ^- (list ,[path *])
%+ skim (~(tap by old.dob.dat))
@ -2175,6 +2132,13 @@
[(lobe-to-mark u.-) u.-]
[p q.q]:cay
[(~(put by hat) pax p.bol) (~(put by lat) p.bol bol)]
:: ~& old=(~(run by old) mug)
:: ~& newdal=(~(run by new.dal.dat) mug)
:: ~& newdob=(~(run by new.dob.dat) mug)
:: ~& caldal=(~(run by cal.dal.dat) mug)
:: ~& caldob=(~(run by cal.dob.dat) mug)
:: ~& hot=(~(run by hot) mug)
:: ~& cas=(~(run by cas) mug)
=+ ^- hat=(map path lobe) :: all the content
%- ~(uni by old)
%- ~(uni by new.dal.dat)
@ -2183,6 +2147,7 @@
%- ~(uni by cal.dob.dat)
%- ~(uni by hot)
cas
:: ~& > hat=(~(run by hat) mug)
=+ ^- del=(map path ,?)
(~(run by (~(uni by old.dal.dat) old.dob.dat)) |=(~ %|))
=. gon.dat [%& (sa (turn (~(tap by con)) head))]
@ -2201,11 +2166,11 @@
::
++ checkout
^+ .
=- %_(+ tag [- tag], wat.dat %checkout)
=+ ^- val=beak
?: ?=(%init gem.dat)
[p.ali q.ali cas.dat]
[p.bob q.bob da/now]
%- emit(wat.dat %checkout)
:* hen %pass
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali %checkout ~]
%f %exec p.bob ~ val %tabl
@ -2244,7 +2209,6 @@
::
++ ergo
^+ .
=- %_(+ tag [- tag], wat.dat %ergo)
=+ ^- sum=(set path)
=+ (must-ergo (turn (~(tap by erg.dat)) head))
=+ (turn (~(tap by -)) (corl tail tail))
@ -2256,6 +2220,7 @@
?: ?=(%init gem.dat)
[p.ali q.ali cas.dat]
[p.bob q.bob da/now]
%- emit(wat.dat %ergo)
:* hen %pass
[%merge (scot %p p.bob) q.bob (scot %p p.ali) q.ali %ergo ~]
%f %exec p.bob ~ val %tabl
@ -2292,18 +2257,16 @@
(error:he %ergo-no-hez ~)
?: ?=(%| -.gon.dat)
+>.$
%* done he
reg
=+ mus=(must-ergo (turn (~(tap by erg.dat)) head))
%- welp :_ reg
=< done:he
%- emil
%+ turn (~(tap by mus))
|= [pot=term len=@ud pak=(set path)]
:* u.hez %ergo pot
:* u.hez %give %ergo pot
%+ turn (~(tap in pak))
|= pax=path
[(slag len pax) (~(got by can) pax)]
==
==
::
++ he
|%
@ -2350,7 +2313,6 @@
=+ bol=(~(got by lat.ran) lob)
?- -.bol
%direct [%volt q.bol]
%indirect [%volt q.bol]
%delta [%pact $(lob q.q.bol) [%volt r.bol]]
==
::
@ -2408,6 +2370,20 @@
%boat
:_ ..^$
[hen %give %hill (turn (~(tap by mon.ruf)) head)]~
::
%drop
=^ mos ruf
=+ den=((de now hen ruf) [. .]:p.q.hic q.q.hic)
abet:drop-me:den
[mos ..^$]
::
%info
?: =(%$ q.q.hic)
[~ ..^$]
=^ mos ruf
=+ den=((de now hen ruf) [. .]:p.q.hic q.q.hic)
abet:(exec:den now r.q.hic)
[mos ..^$]
::
%init
:_ %_ ..^$
@ -2422,14 +2398,6 @@
::
~
==
::
%info
?: =(%$ q.q.hic)
[~ ..^$]
=^ mos ruf
=+ den=((de now hen ruf) [. .]:p.q.hic q.q.hic)
abet:(exec:den now r.q.hic)
[mos ..^$]
::
%into
=. hez.ruf `hen

View File

@ -216,6 +216,7 @@
=. +> (sync %home our %base)
=. +> ?. ?=(?(%king %czar) can) +>
(sync %kids our %base)
=. +> autoload
=. +> peer
|- ^+ +>+
?~ myt +>+
@ -255,7 +256,18 @@
%_ +>.$
moz
:_ moz
[hen %pass ~ %g %deal [our our] ram %poke %hood-sync -:!>(syn) syn]
:* hen %pass /sync %g %deal [our our]
ram %poke %hood-sync -:!>(syn) syn
==
==
::
++ autoload
%_ .
moz
:_ moz
:* hen %pass /autoload %g %deal [our our]
ram %poke %kiln-start-autoload [%cube ~ [%atom %n]] ~
==
==
::
++ pump :: send diff ack

View File

@ -148,6 +148,7 @@
::
++ fcgi :: credential caboose
|= [quy=quay ced=cred] ^- coin
~& fcgi/[`@uv`(mug ced) quy]
:* %many
[%$ %ta ~]
[%blob ced]
@ -431,13 +432,14 @@
urb.waspFrom = function(sel,attr){
Array.prototype.map.call(document.querySelectorAll(sel),
function(ele){
if(!ele[attr] || (new URL(ele[attr])).host != document.location.host) return;
if(!ele[attr] || (new URL(ele[attr])).host != document.location.host)
return;
var xhr = new XMLHttpRequest()
xhr.open("HEAD", ele[attr])
xhr.send()
xhr.onload = function(){
var tag = JSON.parse(this.getResponseHeader("etag"))
if(tag) urb.wasp(tag)
var dep = this.getResponseHeader("etag")
if(dep) urb.wasp(JSON.parse(dep.substr(2)))
}})}
if(urb.wasp){urb.waspFrom('script','src'); urb.waspFrom('link','href')}
'''
@ -771,7 +773,7 @@
==
~| q.q.cay
=+ ((hard ,[mit=mite rez=octs]) q.q.cay)
=+ dep=(crip (pojo %s (scot %uv p.sih)))
=+ dep=(crip "W/{(pojo %s (scot %uv p.sih))}")
(give-thou 200 ~[etag/dep content-type/(moon mit)] ~ rez)
==
==

View File

@ -499,6 +499,19 @@
++ dash :: process cache
|= cof=cafe
^+ +>
~? |
:+ %dash (lent (skim (~(tap in p.cof)) |=(a=calx ?=(%bake -.a))))
=. q.cof (~(dif by q.cof) jav.bay)
=+ num=10
%. |= a=(list calx)
=+ len=(lent a)
=- [len (scag num (turn a f)) ?:((gth len num) %etc ~)]
=+ dewe=|=(beam +<(s ?+(s s [@ %web *] t.t.s)))
f=|=(b=calx [-.b ?+(-.b ~ %bake [p.q.b (tope (dewe q.q.b))])])
%~ run by
=< `(jar term calx)`(~(rep by q.cof) .)
|= [[* a=calx] b=(jar term calx)]
(~(add ja b) -.a a)
%_(+> jav.bay q.cof)
::
++ diff :: diff
@ -1866,7 +1879,6 @@
::
++ load :: highly forgiving
|= old=axle
::=. pol.old (~(run by pol.old) |=(baby +<(jav ~)))
..^$(+>- old)
::=. old
:: ?. ?=([%0 *] old) old :: remove at 1

View File

@ -1122,6 +1122,7 @@
%deal `%g
%exec `%f
%flog `%d
%drop `%c
%info `%c
%merg `%c
%mont `%c

View File

@ -696,6 +696,7 @@
$(a t.a)
::
++ murn :: maybe transform
~/ %murn
|* [a=(list) b=$+(* (unit))]
|-
?~ a ~
@ -705,6 +706,7 @@
[i=u.c t=$(a t.a)]
::
++ reap :: replicate
~/ %reap
|* [a=@ b=*]
|- ^- (list ,_b)
?~ a ~
@ -727,6 +729,7 @@
$(a t.a, b b(+<+ (b i.a +<+.b)))
::
++ skid :: separate
~/ %skid
|* [a=(list) b=$+(* ?)]
|- ^+ [p=a q=a]
?~ a [~ ~]

View File

@ -1836,7 +1836,6 @@
++ blob :: fs blob
$% [%delta p=lobe q=[p=mark q=lobe] r=page] :: delta on q
[%direct p=lobe q=page] :: immediate
[%indirect p=lobe q=page r=lobe s=page] :: both
== ::
++ boat (map (pair bone wire) (trel bean ship path)) :: outgoing subs
++ boon :: fort output
@ -2360,6 +2359,7 @@
== ::
++ kiss-clay :: in request ->$
$% [%boat ~] :: pier rebooted
[%drop p=@p q=@tas] :: cancel pending merge
[%info p=@p q=@tas r=nori] :: internal edit
[%init p=@p] :: report install
[%into p=@tas q=? r=mode] :: external edit

13
gen/hood/autoload.hoon Normal file
View File

@ -0,0 +1,13 @@
::
:::: /hoon/autoload/hood/gen
::
/? 314
::
::::
!:
:- %say
|= $: [now=@da eny=@uvI bec=beak]
[arg=?(~ [? ~]) ~]
==
:- %kiln-autoload
`(unit ,?)`?~(arg ~ `-.arg)

View File

@ -70,113 +70,552 @@
font-weight: 500;
font-style: normal;
}
@font-face {
font-family: "scp";
src: url("//storage.googleapis.com/urbit-extra/scp-bold.woff");
font-weight: 600;
font-style: normal;
body,
html {
font-family: "bau", "Helvetica Neue", helvetica, arial, sans-serif;
}
@font-face {
font-family: "scp";
src: url("//storage.googleapis.com/urbit-extra/scp-black.woff");
font-weight: 700;
font-style: normal;
}
html,
body {
margin: 0;
padding: 0;
}
html,
input,
button,
body {
font-family: "bau";
font-size: 18px;
}
pre,
code,
.mono {
font-family:"scp";
pre,
li:before,
.spin,
#bred a,
h3.time {
font-family: "scp", "Courier New", courier, monospace;
}
#c {
width: 32rem;
margin-left: -16rem;
position: absolute;
left: 50%;
body,
html {
font-size: 18px;
font-weight: 400;
line-height: 1.6rem;
-webkit-text-size-adjust: none;
}
a {
color: #000;
text-decoration: none;
border-bottom: 2px solid #000;
display: inline-block;
line-height: 0.8rem;
}
hr {
display: inline-block;
width: 6rem;
border: 0;
border-top: 2px solid #f4f4f4;
}
h1 {
font-size: 1.6rem;
font-weight: 500;
margin-top: 4rem;
}
h1:after {
content: "\2014";
margin-left: 1rem;
}
#c pre {
font-size: .6rem;
h2,
h3 {
margin: 0;
margin-top: 2rem;
}
#pass {
width: 32rem;
}
button {
border: .3rem solid #000;
background-color: #fff;
font-size: 1rem;
padding: .3rem;
h1,
h2,
h3,
h4,
strong {
font-weight: 500;
}
.sig {
font-weight: 400;
font-size: 2rem;
display: inline;
vertical-align: middle;
h4 {
margin-bottom: 0.3rem;
}
span#ship {
font-family: 'bau';
font-weight: 400;
font-size: 1.2rem;
text-transform: uppercase;
letter-spacing: .1rem;
h5 {
font-style: italic;
font-weight: 200;
margin: 0;
}
h1 code,
h2 code,
h3 code {
font-size: inherit;
padding: 0.3rem;
}
pre,
code {
font-size: 0.8rem;
}
pre {
background-color: #f5f5f5;
padding: 0.3rem;
margin-left: -0.3rem;
}
code {
line-height: 1.2rem;
background-color: #f4f4f4;
margin-top: -0.05rem;
padding: 0.2rem;
display: inline-block;
min-width: 1rem;
}
input {
font-family: 'scp';
ul {
list-style: none;
padding: 0;
}
li:before {
content: "+";
padding-right: 0.3rem;
font-size: 0.8rem;
font-weight: 600;
}
#nav,
#cont {
left: 50%;
}
#cont {
width: 42rem;
margin-left: -21rem;
background-color: #fff;
z-index: 1;
}
#nav {
position: fixed;
top: 0rem;
width: 57rem;
padding-top: 1rem;
z-index: 0;
margin-left: -32rem;
overflow: hidden;
opacity: 0;
transition: opacity 1s ease-in-out;
}
#nav.moving {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
#nav:hover {
opacity: 1;
transition: opacity 0.3s ease-in-out;
}
#cont {
position: absolute;
top: 0;
margin-bottom: 9rem;
}
.loading {
display: inline-block;
}
.spin {
color: #fff;
padding: 0.6rem;
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.1rem;
z-index: 3;
}
.loading > .spin {
background-color: #555;
}
#body .loading > .spin {
background-color: #000;
}
.spin.state-0:before {
content: "\2599";
}
.spin.state-1:before {
content: "\259B";
}
.spin.state-2:before {
content: "\259C";
}
.spin.state-3:before {
content: "\259F";
}
#load.load {
display: inline-block;
font-weight: 500;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(10,10,10,0.4);
opacity: 1;
transition: opacity 1s ease-in-out;
z-index: 4;
}
img.logo {
height: 2rem;
width: 2rem;
}
h3.time {
margin-top: 0.3rem;
font-size: 0.7rem;
font-weight: 200;
}
#nav .links > div {
display: inline-block;
vertical-align: top;
}
#nav #sibs {
width: 8rem;
transition: margin-top 0.3s ease-in-out;
overflow: hidden;
}
#nav #sibs > div {
height: 20px;
margin-bottom: 4px;
}
.focus #sibs {
margin-top: 0 !important;
transition: margin-top 0.3s ease-in-out;
}
#nav a,
.list > li > a {
text-transform: uppercase;
font-size: 0.7rem;
font-weight: 200;
letter-spacing: 1px;
white-space: nowrap;
}
.list > li > a {
border-bottom: none;
margin-bottom: 0.3rem;
}
#nav a,
.list > li > a h1 {
border-bottom: 1px solid #000;
margin-right: 0.3rem;
}
#nav .active a {
font-weight: 500;
text-decoration: none;
}
#up {
padding-right: 1rem;
margin-top: -0.3rem;
}
#sides {
float: right;
}
#sides a {
margin-right: 0.6rem;
}
#nav .arow-up,
#nav .arow-next,
#nav .arow-prev {
width: 0;
height: 0;
border: 0.4rem solid transparent;
}
#nav .arow-up {
border-bottom: 0.6rem solid #000;
}
#nav .arow-next {
border-left: 0.6rem solid #000;
}
#nav .arow-prev {
border-right: 0.6rem solid #000;
}
#bred {
width: 5rem;
padding-right: 1rem;
text-align: right;
font-size: 0.6rem;
white-space: nowrap;
overflow: hidden;
}
#bred a {
text-transform: lowercase;
vertical-align: top;
}
#bred > div {
float: right;
}
#bred > div > div {
display: inline-block;
margin-top: -0.2rem;
}
#bred a,
#kids a {
margin-right: 0.3rem;
}
#bred a {
margin-left: 0.3rem;
}
.short {
width: 32rem;
}
.list h1,
.list li a > div p {
margin: 0;
}
.list li a > div,
.list li a > div p {
display: inline;
}
span#ship,
input {
border: none;
padding: .3rem;
outline: none;
border-bottom: 3px solid #555;
.list li a > div p {
margin-left: 0.3rem;
}
.list li a > div p:first-child {
margin-left: 0;
}
.list li a > div p code {
font-size: 0.7rem;
font-weight: 400;
text-transform: none;
}
.list li a h1 code {
text-transform: lowercase;
border-bottom: 1px solid #000;
}
.list li a code {
padding: 0.2rem;
}
.list h1,
.list li a > div div {
display: inline;
}
.list li a > div div {
margin-left: 0.6rem;
overflow: hidden;
}
.list h1 {
font-size: 0.7rem;
}
.list.posts .post {
margin-bottom: 2rem;
}
.list.posts .post h1 {
text-transform: none;
font-size: 1.6rem;
line-height: 1.8rem;
margin-bottom: 1rem;
display: block;
}
.list.posts .post h2 {
font-size: 0.7rem;
font-weight: 400;
line-height: 1rem;
margin-top: 0;
}
.list.posts li.post:before {
content: "";
}
div.root h1 {
margin-bottom: 2rem;
}
div.root .list .sub {
margin-left: 0;
margin-right: 0.6rem;
}
div.root > p {
width: 27rem;
margin-top: 2rem;
}
h2.sub {
font-size: 0.7rem;
font-weight: 400;
line-height: 1rem;
letter-spacing: 1px;
margin-top: 0;
text-transform: uppercase;
}
div.post h1 {
font-size: 2.8rem;
line-height: 4rem;
display: block;
margin-top: 1rem;
margin-bottom: 1rem;
}
div.post h2 {
line-height: 1rem;
letter-spacing: 1px;
}
div.post h2 {
margin-top: 4rem;
}
div.post h2 {
font-size: 1.2rem;
font-weight: 500;
}
div.post p {
font-size: 1.2rem;
line-height: 2.2rem;
}
div.post li p {
display: inline;
}
div.toc {
margin-top: 3rem;
margin-bottom: 3rem;
}
div.toc h1,
div.toc h2,
div.toc h3,
div.toc h4 {
font-weight: 400;
cursor: pointer;
text-decoration: underline;
font-size: 1.2rem;
margin-top: 0.3rem;
margin-bottom: 0.3rem;
}
div.toc h2 {
margin-left: 1rem;
}
div.toc h3 {
margin-left: 2rem;
}
div.toc h4 {
margin-left: 3rem;
}
div.toc h1.t {
font-weight: 500;
font-size: 2rem;
text-decoration: none;
margin-bottom: 2rem;
}
#body .CodeMirror {
font-size: 0.8rem;
line-height: 1rem;
}
#body .CodeMirror .cm-header {
font-weight: 200;
}
#body .CodeMirror-gutters {
background-color: #fff;
padding-right: 1rem;
margin-left: -1rem;
}
.error {
color: #f91733;
}
.warning {
background-color: #ff3537;
padding: 1rem;
width: 18rem;
margin: 2rem 0;
color: #fff;
}
.warning a {
color: inherit;
border-color: #fff;
}
.warning h1 {
font-size: 1rem;
}
.warning h1,
.warning p {
margin: 0 0.3rem;
}
.warning.w {
width: auto;
}
@media only screen and (max-width: 1170px) {
#nav,
#nav > div,
#nav.up,
#nav.top,
#nav > .focus {
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
}
#nav {
position: fixed;
top: 0;
opacity: 1;
width: 42rem;
margin-left: -21rem;
background-color: #fff;
z-index: 2;
}
#nav.m-down,
#nav.m-up {
position: absolute;
}
#nav.m-down.m-fixed {
position: fixed;
top: 0;
}
#nav > div {
max-height: 1rem;
overflow: hidden;
transition: max-height 0.3s ease-in-out;
}
#nav > .focus {
max-height: 40rem;
transition: max-height 0.3s ease-in-out;
}
#cont {
top: 3rem;
}
}
@media only screen and (min-width: 320px) and (max-width: 1024px) {
body,
html {
font-size: 21px;
}
#nav,
#cont {
width: 94%;
padding-left: 3%;
margin-left: 0;
}
#nav {
position: fixed;
padding-top: 0;
opacity: 1;
left: 0;
background-color: #fff;
z-index: 2;
}
#nav > div {
max-height: 1.4rem;
}
#nav > div {
padding-top: 0.6rem;
}
#nav #sibs {
width: 18rem;
}
#nav #sibs > div {
height: 20px;
line-height: 20px;
}
#nav a {
display: inline-block;
font-size: 0.7rem;
}
#nav #sides {
float: right;
}
#nav .arow-up,
#nav .arow-next,
#nav .arow-prev {
margin-right: 0;
border: 0.4rem solid transparent;
}
#nav .arow-up {
border-bottom: 0.6rem solid #000;
}
#nav .arow-next {
border-left: 0.6rem solid #000;
}
#nav .arow-prev {
margin-right: 1rem;
border-right: 0.6rem solid #000;
}
#cont {
top: 3rem;
left: 0;
padding-bottom: 9rem;
}
#cont h1:first-child {
margin-top: 0;
}
.short {
width: 100%;
}
}
@media only screen and (min-device-width: 320px) and (max-device-width: 480px) {
#c {
width: 16rem;
margin-left: -8rem;
#nav > div {
max-height: 1.6rem;
}
#pass {
width: 16rem;
#nav a {
font-size: 0.7rem;
}
input {
-webkit-appearance: none;
border-radius: 0;
#nav #sibs > div {
height: 20px;
line-height: 20px;
}
}

View File

@ -10,6 +10,7 @@
++ kiln-pith ::
$: rem=(map desk kiln-desk) ::
syn=(map kiln-sync ,[let=@ud ust=bone]) ::
autoload=? ::
== ::
++ kiln-desk :: per-desk state
$: auto=? :: escalate on failure
@ -54,6 +55,7 @@
=> |% :: arvo structures
++ card ::
$% [%exec wire @p ~ [beak silk]] ::
[%drop wire @p @tas] ::
[%info wire @p @tas nori] ::
[%mont wire @tas @p @tas path] ::
[%ogre wire $|(@tas beam)] ::
@ -64,6 +66,8 @@
++ pear :: poke fruit
$% [%talk-command command:talk] ::
[%kiln-merge kiln-merge] ::
[%helm-reload (list term)] ::
[%helm-reset ~] ::
== ::
++ move (pair bone card) :: user-level move
--
@ -118,6 +122,10 @@
|= kiln-merge
abet:abet:(merge:(work syd) ali sud gim)
::
++ poke-cancel
|= syd=desk
abet:(emit %drop /cancel our syd)
::
++ do-info
|= [mez=tape tor=toro]
abet:(emit:(spam leaf/mez ~) %info /kiln our tor)
@ -148,6 +156,25 @@
=+ old=;;((map ,@da cord) (fall (file where) ~))
(foal where %sched !>((~(put by old) tym eve)))
::
++ poke-autoload
|= lod=(unit ,?)
?^ lod
abet(autoload u.lod)
=< abet(autoload !autoload)
(spam leaf/"turning autoload o{?:(autoload "ff" "n")}" ~)
::
++ poke-start-autoload
|= ~
=< abet
%- emil
%+ turn
`(list term)`~[%ames %behn %clay %dill %eyre %ford %gall %zuse %hoon]
|= syd=term
^- card
:* %warp /kiln/autoload/[syd] [our our] %home ~
%next %y da/now /arvo/[syd]/hoon
==
::
++ take |=(way=wire ?>(?=([@ ~] way) (work i.way))) :: general handler
++ take-mere ::
|= [way=wire are=(each (set path) (pair term tang))]
@ -171,7 +198,7 @@
==
abet:abet:(mere:(auto hos) mes)
::
++ take-writ ::
++ take-writ-sync ::
|= [way=wire rot=riot]
?> ?=([@ @ @ ~] way)
=+ ^- hos=kiln-sync
@ -181,6 +208,24 @@
==
abet:abet:(writ:(auto hos) rot)
::
++ take-writ-autoload
|= [way=wire rot=riot]
?> ?=([@ ~] way)
?> ?=(^ rot)
=+ syd=(slav %tas i.way)
=. +>.$
?. autoload
+>.$
?: ?=(%hoon syd)
(emit %poke /kiln/reload/[syd] [our %hood] %helm-reset ~)
(emit %poke /kiln/reload/[syd] [our %hood] %helm-reload ~[syd])
=. +>.$
%- emit :*
%warp /kiln/autoload/[syd] [our our] %home ~
%next %y da/now /arvo/[syd]/hoon
==
abet
::
++ spam
|= mes=(list tank)
((slog mes) ..spam)
@ -244,7 +289,7 @@
?+ p.p.mes
:* (render "sync failed" sud her syd)
leaf/"please manually merge the desks with"
leaf/":+merge %{(trip syd)} {(scow %p her)} %{(trip sud)}"
leaf/"|merge %{(trip syd)} {(scow %p her)} %{(trip sud)}"
leaf/""
leaf/"error code: {<p.p.mes>}"
q.p.mes
@ -457,7 +502,7 @@
"""
done setting up scratch space in {<[-]>}
please resolve the following conflicts and run
:+merge {<syd>} our {<[-]>}
|merge {<syd>} our {<[-]>}
"""
%^ tanks-if-any
"annotated conflicts in:" annotated

View File

@ -63,7 +63,8 @@
%set-tags =+(feh "{(tr-term -.feh)} {<tag>}")
%set-title =+(feh "{(tr-term -.feh)} {<(trip til)>}")
%set-description =+(feh "{(tr-term -.feh)} {<(trip des)>}")
%add-comment =+(feh "{(tr-term -.feh)} {<(trip com)>}")
%add-comment =+ feh
"{(tr-term -.feh)} {(scow %p who)} {<(trip com)>}"
==
--
--

View File

@ -71,7 +71,7 @@
set-title/so
set-description/so
set-done/bo
add-comment/so
add-comment/(ot ship/(su fed:ag) com/so ~)
==
--
++ grow-work-duty
@ -123,7 +123,7 @@
%set-title [%s til]
%set-description [%s des]
%set-done [%b don]
%add-comment [%s com]
%add-comment (jobe ship/(jope who) com/[%s com] ~)
==
--
++ grab

View File

@ -1,11 +0,0 @@
<div class="root">
# Log —
<search/>
<list dataPreview="true" dataType="post"></list>
Please direct all questions or inquiries to [urbit@urbit.org](mailto:urbit@urbit.org). You can also subscribe to the [urbit-dev]() mailing list or follow [@urbit_]() on twitter.
</div>

View File

@ -1,10 +0,0 @@
<div class="post">
# Technical demo — Part ii
<h2 class="sub">2015 07 16</h2>
<h2 class="sub">Curtis, Galen, Philip, Anton and Henry</h2>
<iframe src="https://player.vimeo.com/video/133395510?color=fff&amp;title=0&amp;byline=0&amp;portrait=0" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>

View File

@ -1,10 +0,0 @@
<div class="post">
# Technical demo — Part i
<h2 class="sub">2015-07-17</h2>
<h2 class="sub">Curtis, Galen, Philip, Anton and Henry</h2>
<iframe src="https://player.vimeo.com/video/133395510?color=fff&amp;title=0&amp;byline=0&amp;portrait=0" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>

View File

@ -1,14 +0,0 @@
---
title: Advantages
---
<div class="post">
# Concrete advantages of urbit
<h2 class="sub">2015-7-18</h2>
<h2 class="sub">Philip Monk</h2>
# Item 1
# Item 2
</div>

View File

@ -0,0 +1,415 @@
# clay
## high-level
clay is the primary filesystem for the arvo operating system,
which is the core of an urbit. The architecture of clay is
intrinsically connected with arvo, but we assume no knowledge of
either arvo or urbit. We will point out only those features of
arvo that are necessary for an understanding of clay, and we will
do so only when they arise.
The first relevant feature of arvo is that it is a deterministic
system where input and output are defined as a series of events
and effects. The state of arvo is simply a function of its event
log. None of the effects from an event are emitted until the
event is entered in the log and persisted, either to disk or
another trusted source of persistence, such as a Kafka cluster.
Consequently, arvo is a single-level store: everything in its
state is persistent.
In a more traditional OS, everything in RAM can be erased at any
time by power failure, and is always erased on reboot. Thus, a
primary purpose of a filesystem is to ensure files persist across
power failures and reboots. In arvo, both power failures and
reboots are special cases of suspending computation, which is
done safely since our event log is already persistent. Therefore,
clay is not needed in arvo for persistence. Why, then, do we have a
filesystem? There are two answers to this question.
First, clay provides a filesystem tree, which is a convenient
user interface for some applications. Unix has the useful concept
of virtual filesystems, which are used for everything from direct
access to devices, to random number generators, to the /proc
tree. It is easy and intuitive to read from and write to a
filesystem tree.
Second, clay has a distributed revision control system baked into
it. Traditional filesystems are not revision controlled, so
userspace software -- such as git -- is written on top of them to
do so. clay natively provides the same functionality as modern
DVCSes, and more.
clay has two other unique properties that we'll cover later on:
it supports typed data and is referentially transparent.
### Revision Control
Every urbit has one or more "desks", which are independently
revision-controlled branches. Each desk contains its own mark
definitions, apps, doc, and so forth.
Traditionally, an urbit has at least a base and a home desk. The
base desk has all the system software from the distribution. the
home desk is a fork of base with all the stuff specific to the
user of the urbit.
A desk is a series of numbered commits, the most recent of which
represents the current state of the desk. A commit is composed of
(1) an absolute time when it was created, (2) a list of zero or
more parents, and (3) a map from paths to data.
Most commits have exactly one parent, but the initial commit on a
desk may have zero parents, and merge commits have more than one
parent.
The non-meta data is stored in the map of paths to data. It's
worth noting that no constraints are put on this map, so, for
example, both /a/b and /a/b/c could have data. This is impossible
in a traditional Unix filesystem since it means that /a/b is both
a file and a directory. Conventionally, the final element in the
path is its mark -- much like a filename extension in Unix. Thus,
/doc/readme.md in Unix is stored as /doc/readme/md in urbit.
The data is not stored directly in the map; rather, a hash of the
data is stored, and we maintain a master blob store. Thus, if the
same data is referred to in multiple commits (as, for example,
when a file doesn't change between commits), only the hash is
duplicated.
In the master blob store, we either store the data directly, or
else we store a diff against another blob. The hash is dependent
only on the data within and not on whether or not it's stored
directly, so we may on occasion rearrange the contents of the
blob store for performance reasons.
Recall that a desk is a series of numbered commits. Not every
commit in a desk must be numbered. For example, if the base desk
has had 50 commits since home was forked from it, then a merge
from base to home will only add a single revision number to home,
although the full commit history will be accessible by traversing
the parentage of the individual commits.
We do guarantee that the first commit is numbered 1, commits are
numbered consecutively after that (i.e. there are no "holes"),
the topmost commit is always numbered, and every numbered commit
is an ancestor of every later numbered commit.
There are three ways to refer to particular commits in the
revision history. Firstly, one can use the revision number.
Secondly, one can use any absolute time between the one numbered
commit and the next (inclusive of the first, exclusive of the
second). Thirdly, every desk has a map of labels to revision
numbers. These labels may be used to refer to specific commits.
Additionally, clay is a global filesystem, so data on other urbit
is easily accessible the same way as data on our local urbit. In
general, the path to a particular revision of a desk is
/~urbit-name/desk-name/revision. Thus, to get /try/readme/md
from revision 5 of the home desk on ~sampel-sipnym, we refer to
/~sampel-sipnym/home/5/try/readme/md. Clay's namespace is thus
global and referentially transparent.
XXX reactivity here?
### A Typed Filesystem
Since clay is a general filesystem for storing data of arbitrary
types, in order to revision control correctly it needs to be
aware of types all the way through. Traditional revision control
does an excellent job of handling source code, so for source code
we act very similar to traditional revision control. The
challenge is to handle other data similarly well.
For example, modern VCSs generally support "binary files", which
are files for which the standard textual diffing, patching, and
merging algorithms are not helpful. A "diff" of two binary files
is just a pair of the files, "patching" this diff is just
replacing the old file with the new one, and "merging"
non-identical diffs is always a conflict, which can't even be
helpfully annotated. Without knowing anything about the structure
of a blob of data, this is the best we can do.
Often, though, "binary" files have some internal structure, and
it is possible to create diff, patch, and merge algorithms that
take advantage of this structure. An image may be the result of a
base image with some set of operations applied. With algorithms
aware of this set of operations, not only can revision control
software save space by not having to save every revision of the
image individually, these transformations can be made on parallel
branches and merged at will.
Suppose Alice is tasked with touching up a picture, improving the
color balance, adjusting the contrast, and so forth, while Bob
has the job of cropping the picture to fit where it's needed and
adding textual overlay. Without type-aware revision control,
these changes must be made serially, requiring Alice and Bob to
explicitly coordinate their efforts. With type-aware revision
control, these operations may be performed in parallel, and then
the two changesets can be merged programmatically.
Of course, even some kinds of text files may be better served by
diff, patch, and merge algorithms aware of the structure of the
files. Consider a file containing a pretty-printed JSON object.
Small changes in the JSON object may result in rather significant
changes in how the object is pretty-printed (for example, by
addding an indentation level, splitting a single line into
multiple lines).
A text file wrapped at 80 columns also reacts suboptimally with
unadorned Hunt-McIlroy diffs. A single word inserted in a
paragraph may push the final word or two of the line onto the
next line, and the entire rest of the paragraph may be flagged as
a change. Two diffs consisting of a single added word to
different sentences may be flagged as a conflict. In general,
prose should be diffed by sentence, not by line.
As far as the author is aware, clay is the first generalized,
type-aware revision control system. We'll go into the workings
of this system in some detail.
### Marks
Central to a typed filesystem is the idea of types. In clay, we
call these "marks". A mark is a file that defines a type,
conversion routines to and from the mark, and diff, patch, and
merge routines.
For example, a `%txt` mark may be a list of lines of text, and it
may include conversions to `%mime` to allow it to be serialized
and sent to a browswer or to the unix filesystem. It will also
include Hunt-McIlroy diff, patch, and merge algorithms.
A `%json` mark would be defined as a json object in the code, and
it would have a parser to convert from `%txt` and a printer to
convert back to `%txt`. The diff, patch, and merge algorithms are
fairly straightforward for json, though they're very different
from the text ones.
More formally, a mark is a core with three arms, `++grab`,
`++grow`, and `++grad`. In `++grab` is a series of functions to
convert from other marks to the given mark. In `++grow` is a
series of functions to convert from the given mark to other
marks. In `++grad` is `++diff`, `++pact`, `++join`, and `++mash`.
The types are as follows, in an informal pseudocode:
++ grab:
++ mime: <mime> -> <mark-type>
++ txt: <txt> -> <mark-type>
...
++ grow:
++ mime: <mark-type> -> <mime>
++ txt: <mark-type> -> <txt>
...
++ grad
++ diff: (<mark-type>, <mark-type>) -> <diff-type>
++ pact: (<mark-type>, <diff-type>) -> <mark-type>
++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
++ mash: (<diff-type>, <diff-type>) -> <diff-type>
These types are basically what you would expect. Not every mark
has each of these functions defined -- all of them are optional
in the general case.
In general, for a particular mark, the `++grab` and `++grow` entries
(if they exist) should be inverses of each other.
In `++grad`, `++diff` takes two instances of a mark and produces
a diff of them. `++pact` takes an instance of a mark and patches
it with the given diff. `++join` takes two diffs and attempts to
merge them into a single diff. If there are conflicts, it
produces null. `++mash` takes two diffs and forces a merge,
annotating any conflicts.
In general, if `++diff` called with A and B produces diff D, then
`++pact` called with A and D should produce B. Also, if `++join`
of two diffs does not produce null, then `++mash` of the same
diffs should produce the same result.
Alternately, instead of `++diff`, `++pact`, `++join`, and
`++mash`, a mark can provide the same functionality by defining
`++sted` to be the name of another mark to which we wish to
delegate the revision control responsibilities. Then, before
running any of those functions, clay will convert to the other
mark, and convert back afterward. For example, the `%hoon` mark
is revision-controlled in the same way as `%txt`, so its `++grad`
is simply `++sted %txt`. Of course, `++txt` must be defined in
`++grow` and `++grab` as well.
Every file in clay has a mark, and that mark must have a
fully-functioning `++grad`. Marks are used for more than just
clay, and other marks don't need a `++grad`, but if a piece of
data is to be saved to clay, we must know how to revision-control
it.
Additionally, if a file is to be synced out to unix, then it must
have conversion routines to and from the `%mime` mark.
##Using clay
### Reading and Subscribing
When reading from Clay, there are three types of requests. A
`%sing` request asks for data at single revsion. A `%next`
request asks to be notified the next time there's a change to
given file. A `%many` request asks to be notified on every
change in a desk for a range of changes.
For `%sing` and `%next`, there are generally three things to be
queried. A `%u` request simply checks for the existence of a
file at a path. A `%x` request gets the data in the file at a
path. A `%y` request gets a hash of the data in the file at the
path combined with all its children and their data. Thus, `%y`
of a node changes if it or any of its children change.
A `%sing` request is fulfilled immediately if possible. If the
requested revision is in the future, or is on another ship for
which we don't have the result cached, we don't respond
immediately. If the requested revision is in the future, we wait
until the revision happens before we respond to the request. If
the request is for data on another ship, we pass on the request
to the other ship. In general, Clay subscriptions, like most
things in Urbit, aren't guaranteed to return immediately.
They'll return when they can, and they'll do so in a
referentially transparent manner.
A `%next` request checks query at the given revision, and it
produces the result of the query the next time it changes, along
with the revsion number when it changes. Thus, a `%next` of a
`%u` is triggered when a file is added or deleted, a `%next` of a
`%x` is triggered when a file is added, deleted, or changed, and
a `%next` of a `%y` is triggered when a file or any of its
children is added, deleted, or changed.
A `%many` request is triggered every time the given desk has a
new revision. Unlike a `%next`, a `%many` has both a start and
an end revsion, after which it stops returning. For `%next`, a
single change is reported, and if the caller wishes to hear of
the next change, it must resubscribe. For `%many`, every revsion
from the start to the end triggers a response. Since a `%many`
request doesn't ask for any particular data, there aren't `%u`,
`%x`, and `%y` versions for it.
### Unix sync
One of the primary functions of clay is as a convenient user
interface. While tools exist to use clay from within urbit, it's
often useful to be able to treat clay like any other filesystem
from the Unix perspective -- to "mount" it, as it were.
From urbit, you can run `|mount /path/to/directory %mount-point`,
and this will mount the given clay directory to the mount-point
directory in Unix. Every file is converted to `%mime` before it's
written to Unix, and converted back when read from Unix. The
entire directory is watched (a la Dropbox), and every change is
auto-committed to clay.
### Merging
Merging is a fundamental operation for a distributed revision
control system. At their root, clay's merges are similar to
git's, but with some additions to accomodate typed data. There
are seven different merge strategies.
Throughout our discussion, we'll say that the merge is from
Alice's desk to Bob's. Recall that a commit is a date (for all
new commits this will be the current date), a list of parents,
and the data itself.
A `%init` merge should be used iff it's the first commit to a
desk. The head of Alice's desk is used as the number 1 commit to
Bob's desk. Obviously, the ancestry remains intact through
traversing the parentage of the commit even though previous
commits are not numbered for Bob's desk.
A `%this` merge means to keep what's in Bob's desk, but join the
ancestry. Thus, the new commit has the head of each desk as
parents, but the data is exactly what's in Bob's desk. For those
following along in git, this is the 'ours' merge strategy, not
the '--ours' option to the 'recursive' merge strategy. In other
words, even if Alice makes a change that does not conflict with
Bob, we throw it away. It's Bob's way or the highway.
A `%that` merge means to take what's in Alice's desk, but join
the ancestry. This is the reverse of `%this`.
A `%fine` merge is a "fast-forward" merge. This succeeds iff one
head is in the ancestry of the other. In this case, we use the
descendant as our new head.
For `%meet`, `%mate`, and `%meld` merges, we first find the most
recent common ancestor to use as our merge base. If we have no
common ancestors, then we fail. If we have more than one most
recent common ancestor, then we have a criss-cross situation,
which should be handled delicately. At present, we delicately
throw up our hands and give up, but something akin to git's
'recursive' strategy should be implemented in the future.
There's a functional inclusion ordering on `%fine`, `%meet`,
`%mate`, and `%meld` such that if an earlier strategy would have
succeeded, then every later strategy will produce the same
result. Put another way, every earlier strategy is the same as
every later strategy except with a restricted domain.
A `%meet` merge only succeeds if the changes from the merge base
to Alice's head (hereafter, "Alice's changes") are in different
files than Bob's changes. In this case, the parents are both
Alice's and Bob's heads, and the data is the merge base plus
Alice's changed files plus Bob's changed files.
A `%mate` merge attempts to merge changes to the same file when
both Alice and bob change it. If the merge is clean, we use it;
otherwise, we fail. A merge between different types of changes --
for example, deleting a file vs changing it -- is always a
conflict. If we succeed, the parents are both Alice's and Bob's
heads, and the data is the merge base plus Alice's changed files
plus Bob's changed files plus the merged files.
A `%meld` merge will succeed even if there are conflicts. If
there are conflicts in a file, then we use the merge base's
version of that file, and we produce a set of files with
conflicts. The parents are both Alice's and Bob's heads, and the
data is the merge base plus Alice's changed files plus Bob's
changed files plus the successfully merged files plus the merge
base's version of the conflicting files.
That's the extent of the merge options in clay proper. In
userspace there's a final option `%auto`, which is the most
common. `%auto` checks to see if Bob's desk exists, and if it
doesn't we use a `%init` merge. Otherwise, we progressively try
`%fine`, `%meet`, and `%mate` until one succeeds.
If none succeed, we merge Bob's desk into a scratch desk. Then,
we merge Alice's desk into the scratch desk with the `%meld`
option to force the merge. For each file in the produced set of
conflicting files, we call the `++mash` function for the
appropriate mark, which annotates the conflicts if we know how.
Finally, we display a message to the user informing them of the
scratch desk's existence, which files have annotated conflicts,
and which files have unannotated conflicts. When the user has
resolved the conflicts, they can merge the scratch desk back into
Bob's desk. This will be a `%fine` merge since Bob's head is in
the ancestry of the scratch desk.
### Autosync
Tracking and staying in sync with another desk is another
fundamental operation. We call this "autosync". This doesn't mean
simply mirroring a desk, since that wouldn't allow local changes.
We simply want to apply changes as they are made upstream, as
long as there are no conflicts with local changes.
This is implemented by watching the other desk, and, when it has
changes, merging these changes into our desk with the usual merge
strategies.
Note that it's quite reasonable for two desks to be autosynced to
each other. This results in any change on one desk being mirrored
to the other and vice versa.
Additionally, it's fine to set up an autosync even if one desk,
the other desk, or both desks do not exist. The sync will be
activated when the upstream desk comes into existence and will
create the downstream desk if needed.

View File

@ -102,10 +102,13 @@ hr {
border: 0;
border-top: 2px solid #f4f4f4;
}
h1 {
margin-top: 4rem;
}
h2,
h3 {
margin: 0;
margin-top: 1rem;
margin-top: 2rem;
}
h1,
h2,
@ -433,8 +436,8 @@ div.post li p {
display: inline;
}
div.toc {
margin-top: 6rem;
margin-bottom: 6rem;
margin-top: 3rem;
margin-bottom: 3rem;
}
div.toc h1,
div.toc h2,
@ -444,6 +447,8 @@ div.toc h4 {
cursor: pointer;
text-decoration: underline;
font-size: 1.2rem;
margin-top: 0.3rem;
margin-bottom: 0.3rem;
}
div.toc h2 {
margin-left: 1rem;
@ -458,6 +463,7 @@ div.toc h1.t {
font-weight: 500;
font-size: 2rem;
text-decoration: none;
margin-bottom: 2rem;
}
#body .CodeMirror {
font-size: 0.8rem;
@ -474,6 +480,27 @@ div.toc h1.t {
.error {
color: #f91733;
}
.warning {
background-color: #ff3537;
padding: 1rem;
width: 18rem;
margin: 2rem 0;
color: #fff;
}
.warning a {
color: inherit;
border-color: #fff;
}
.warning h1 {
font-size: 1rem;
}
.warning h1,
.warning p {
margin: 0 0.3rem;
}
.warning.w {
width: auto;
}
@media only screen and (max-width: 1170px) {
#nav,
#nav > div,

View File

@ -32,10 +32,13 @@ hr
border 0
border-top 2px solid #f4f4f4
h1
margin-top 4rem
h2
h3
margin 0
margin-top 1rem
margin-top 2rem
h1
h2
@ -361,8 +364,8 @@ div.post
display inline
div.toc
margin-top 6rem
margin-bottom 6rem
margin-top 3rem
margin-bottom 3rem
h1
h2
@ -372,6 +375,8 @@ div.toc
cursor pointer
text-decoration underline
font-size 1.2rem
margin-top .3rem
margin-bottom .3rem
h2
margin-left 1rem
@ -386,6 +391,7 @@ div.toc
font-weight 500
font-size 2rem
text-decoration none
margin-bottom 2rem
#body .CodeMirror
font-size .8rem
@ -402,4 +408,25 @@ div.toc
.error
color rgba(249,23,51,1)
.warning
background-color rgb(255,53,55)
padding 1rem
width 18rem
margin 2rem 0
color #fff
a
color inherit
border-color #fff
h1
font-size 1rem
h1
p
margin 0 .3rem
.warning.w
width auto
@import 'mobile'

View File

@ -34,10 +34,10 @@ module.exports = (queries, Child, load=_load)-> recl
filterWith: (have,_queries)->
return _queries unless have?
request = {}
for k of _queries
for k of _queries when k isnt 'kids'
request[k] = _queries[k] unless have[k] isnt undefined
if _queries.kids? and have.kids?
if _.isEmpty have.kids
if _queries.kids?
if not have.kids?
request.kids = _queries.kids
else
request.kids = {}

View File

@ -7,4 +7,5 @@ module.exports =
list: require './ListComponent.coffee'
kids: require './KidsComponent.coffee'
toc: require './TocComponent.coffee'
email: require './EmailComponent.coffee'
lost: recl render: -> (div {}, "<lost(", @props.children, ")>")

View File

@ -0,0 +1,45 @@
reactify = require './Reactify.coffee'
recl = React.createClass
{div,p,button,input} = React.DOM
module.exports = recl
displayName: "email"
getInitialState: -> {submit:false,email:""}
onClick: -> @submit()
onKeyUp: (e) ->
email = @$email.val()
valid = (email.indexOf('@') != -1 &&
email.indexOf('.') != -1 &&
email.length > 7 &&
email.split(".")[1].length > 1 &&
email.split("@")[0].length > 0 &&
email.split("@")[1].length > 4)
@$email.toggleClass 'valid',valid
@$email.removeClass 'error'
if e.keyCode is 13
if valid is true
@submit()
e.stopPropagation()
e.preventDefault()
return false
else
@$email.addClass 'error'
submit: ->
$.post @props.dataPath,{email:@$email.val()},() =>
@setState {submit:true}
componentDidMount: -> @$email = $('input.email')
render: ->
if @state.submit is false
cont = [
(input {key:"field",className:"email",placeholder:"your@email.com",@onKeyUp}, @state.email)
(button {key:"submit",className:"submit",@onClick}, "Submit")
]
else
cont = [(div {className:"submitted"},"Got it. Thanks!")]
(p {className:"email"}, cont)

View File

@ -9,29 +9,26 @@ module.exports = query {body:'r'}, recl
hash:null
displayName: "TableOfContents"
_click: (e) ->
document.location.hash = @urlsafe $(e.target).text()
urlsafe: (str) ->
str.toLowerCase().replace(/\ /g, "-").replace(/[^a-z0-9~_.-]/g,"")
_click: (id)->
-> if id then document.location.hash = id
componentDidMount: ->
@int = setInterval @checkHash,100
@st = $(window).scrollTop()
$(window).on 'scroll',@checkScroll
@$headers = $('#toc h1, #toc h2, #toc h3, #toc h4')
# $(window).on 'scroll',@checkScroll
@$headers = $('#toc').children('h1,h2,h3,h4').filter('[id]')
checkScroll: ->
st = $(window).scrollTop()
if Math.abs(@st-st) > 10
hash = null
@st = st
for k,v of @$headers
for v in @$headers
continue if v.tagName is undefined
$h = $ v
hst = $h.offset().top-$h.outerHeight(true)+10
if hst < st
hash = @urlsafe $h.text()
hash = $h.attr('id')
if hst > st and hash isnt @hash and hash isnt null
@hash = "#"+hash
document.location.hash = hash
@ -40,9 +37,9 @@ module.exports = query {body:'r'}, recl
checkHash: ->
if document.location.hash?.length > 0 and document.location.hash isnt @hash
hash = document.location.hash.slice(1)
for k,v of @$headers
for v in @$headers
$h = $ v
if hash is @urlsafe $h.text()
if hash is $h.attr('id')
@hash = document.location.hash
offset = $h.offset().top - $h.outerHeight(true)
setTimeout -> $(window).scrollTop offset
@ -52,20 +49,23 @@ module.exports = query {body:'r'}, recl
componentWillUnmount: ->
clearInterval @int
collectHeaders: (e) ->
hs = [{gn:"h1", ga:{className:"t"}, c:["Table of contents"]}]
for k,v of e
if not v.gn then continue
if v.gn[0] is 'h' and parseInt(v.gn[1]) isnt NaN
hs.push v
return hs
collectHeader: ({gn,ga,c})->
if gn and gn[0] is 'h' and parseInt(gn[1]) isnt NaN
ga = _.clone ga
ga.onClick = @_click ga.id
delete ga.id
{gn,ga,c}
parseHeaders: ->
if @props.body.c
for k,v of @props.body.c
for v in @props.body.c
if v.gn is 'div' and v.ga?.id is "toc"
return {gn:"div", ga:{className:"toc",onClick:@_click}, c:@collectHeaders(v.c)}
return {
gn:"div"
ga:{className:"toc"}
c:[
{gn:"h1", ga:{className:"t"}, c:["Table of contents"]}
(_.filter v.c.map @collectHeader)...
]}
render: -> reactify @parseHeaders()

View File

@ -36,7 +36,7 @@ module.exports = {
},{"../dispatcher/Dispatcher.coffee":13,"../persistence/TreePersistence.coffee":19}],2:[function(require,module,exports){
},{"../dispatcher/Dispatcher.coffee":14,"../persistence/TreePersistence.coffee":20}],2:[function(require,module,exports){
var BodyComponent, CLICK, Links, TreeActions, TreeStore, a, clas, div, query, reactify, recl, ref;
clas = require('classnames');
@ -290,7 +290,7 @@ module.exports = query({
},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":20,"./Async.coffee":3,"./BodyComponent.coffee":4,"./Reactify.coffee":10,"classnames":15}],3:[function(require,module,exports){
},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":21,"./Async.coffee":3,"./BodyComponent.coffee":4,"./Reactify.coffee":11,"classnames":16}],3:[function(require,module,exports){
var TreeActions, TreeStore, _load, code, div, recl, ref, span;
_load = require('./LoadComponent.coffee');
@ -350,12 +350,14 @@ module.exports = function(queries, Child, load) {
}
request = {};
for (k in _queries) {
if (k !== 'kids') {
if (have[k] === void 0) {
request[k] = _queries[k];
}
}
if ((_queries.kids != null) && (have.kids != null)) {
if (_.isEmpty(have.kids)) {
}
if (_queries.kids != null) {
if (have.kids == null) {
request.kids = _queries.kids;
} else {
request.kids = {};
@ -392,7 +394,7 @@ module.exports = function(queries, Child, load) {
},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":20,"./LoadComponent.coffee":9}],4:[function(require,module,exports){
},{"../actions/TreeActions.coffee":1,"../stores/TreeStore.coffee":21,"./LoadComponent.coffee":10}],4:[function(require,module,exports){
var div, query, reactify, recl;
query = require('./Async.coffee');
@ -418,7 +420,7 @@ module.exports = query({
},{"./Async.coffee":3,"./Reactify.coffee":10}],5:[function(require,module,exports){
},{"./Async.coffee":3,"./Reactify.coffee":11}],5:[function(require,module,exports){
var div, recl, ref, textarea;
recl = React.createClass;
@ -455,6 +457,7 @@ module.exports = {
list: require('./ListComponent.coffee'),
kids: require('./KidsComponent.coffee'),
toc: require('./TocComponent.coffee'),
email: require('./EmailComponent.coffee'),
lost: recl({
render: function() {
return div({}, "<lost(", this.props.children, ")>");
@ -464,7 +467,88 @@ module.exports = {
},{"./CodeMirror.coffee":5,"./KidsComponent.coffee":7,"./ListComponent.coffee":8,"./SearchComponent.coffee":11,"./TocComponent.coffee":12}],7:[function(require,module,exports){
},{"./CodeMirror.coffee":5,"./EmailComponent.coffee":7,"./KidsComponent.coffee":8,"./ListComponent.coffee":9,"./SearchComponent.coffee":12,"./TocComponent.coffee":13}],7:[function(require,module,exports){
var button, div, input, p, reactify, recl, ref;
reactify = require('./Reactify.coffee');
recl = React.createClass;
ref = React.DOM, div = ref.div, p = ref.p, button = ref.button, input = ref.input;
module.exports = recl({
displayName: "email",
getInitialState: function() {
return {
submit: false,
email: ""
};
},
onClick: function() {
return this.submit();
},
onKeyUp: function(e) {
var email, valid;
email = this.$email.val();
valid = email.indexOf('@') !== -1 && email.indexOf('.') !== -1 && email.length > 7 && email.split(".")[1].length > 1 && email.split("@")[0].length > 0 && email.split("@")[1].length > 4;
this.$email.toggleClass('valid', valid);
this.$email.removeClass('error');
if (e.keyCode === 13) {
if (valid === true) {
this.submit();
e.stopPropagation();
e.preventDefault();
return false;
} else {
return this.$email.addClass('error');
}
}
},
submit: function() {
return $.post(this.props.dataPath, {
email: this.$email.val()
}, (function(_this) {
return function() {
return _this.setState({
submit: true
});
};
})(this));
},
componentDidMount: function() {
return this.$email = $('input.email');
},
render: function() {
var cont;
if (this.state.submit === false) {
cont = [
input({
key: "field",
className: "email",
placeholder: "your@email.com",
onKeyUp: this.onKeyUp
}, this.state.email), button({
key: "submit",
className: "submit",
onClick: this.onClick
}, "Submit")
];
} else {
cont = [
div({
className: "submitted"
}, "Got it. Thanks!")
];
}
return p({
className: "email"
}, cont);
}
});
},{"./Reactify.coffee":11}],8:[function(require,module,exports){
var a, div, hr, li, query, reactify, recl, ref, ul;
reactify = require('./Reactify.coffee');
@ -504,7 +588,7 @@ module.exports = query({
},{"./Async.coffee":3,"./Reactify.coffee":10}],8:[function(require,module,exports){
},{"./Async.coffee":3,"./Reactify.coffee":11}],9:[function(require,module,exports){
var a, clas, div, h1, li, query, reactify, recl, ref, ul;
clas = require('classnames');
@ -600,7 +684,7 @@ module.exports = query({
},{"./Async.coffee":3,"./Reactify.coffee":10,"classnames":15}],9:[function(require,module,exports){
},{"./Async.coffee":3,"./Reactify.coffee":11,"classnames":16}],10:[function(require,module,exports){
var div, input, recl, ref, textarea;
recl = React.createClass;
@ -641,7 +725,7 @@ module.exports = recl({
},{}],10:[function(require,module,exports){
},{}],11:[function(require,module,exports){
var Virtual, div, load, reactify, recl, ref, rele, span, walk;
recl = React.createClass;
@ -709,7 +793,7 @@ module.exports = _.extend(reactify, {
},{"./LoadComponent.coffee":9}],11:[function(require,module,exports){
},{"./LoadComponent.coffee":10}],12:[function(require,module,exports){
var a, div, input, query, reactify, recl, ref,
slice = [].slice;
@ -848,8 +932,9 @@ module.exports = query({
},{"./Async.coffee":3,"./Reactify.coffee":10}],12:[function(require,module,exports){
var div, query, reactify, recl;
},{"./Async.coffee":3,"./Reactify.coffee":11}],13:[function(require,module,exports){
var div, query, reactify, recl,
slice = [].slice;
query = require('./Async.coffee');
@ -864,35 +949,35 @@ module.exports = query({
}, recl({
hash: null,
displayName: "TableOfContents",
_click: function(e) {
return document.location.hash = this.urlsafe($(e.target).text());
},
urlsafe: function(str) {
return str.toLowerCase().replace(/\ /g, "-").replace(/[^a-z0-9~_.-]/g, "");
_click: function(id) {
return function() {
if (id) {
return document.location.hash = id;
}
};
},
componentDidMount: function() {
this.int = setInterval(this.checkHash, 100);
this.st = $(window).scrollTop();
$(window).on('scroll', this.checkScroll);
return this.$headers = $('#toc h1, #toc h2, #toc h3, #toc h4');
return this.$headers = $('#toc').children('h1,h2,h3,h4').filter('[id]');
},
checkScroll: function() {
var $h, hash, hst, k, ref, results, st, v;
var $h, hash, hst, i, len, ref, results, st, v;
st = $(window).scrollTop();
if (Math.abs(this.st - st) > 10) {
hash = null;
this.st = st;
ref = this.$headers;
results = [];
for (k in ref) {
v = ref[k];
for (i = 0, len = ref.length; i < len; i++) {
v = ref[i];
if (v.tagName === void 0) {
continue;
}
$h = $(v);
hst = $h.offset().top - $h.outerHeight(true) + 10;
if (hst < st) {
hash = this.urlsafe($h.text());
hash = $h.attr('id');
}
if (hst > st && hash !== this.hash && hash !== null) {
this.hash = "#" + hash;
@ -906,15 +991,15 @@ module.exports = query({
}
},
checkHash: function() {
var $h, hash, k, offset, ref, ref1, results, v;
var $h, hash, i, len, offset, ref, ref1, results, v;
if (((ref = document.location.hash) != null ? ref.length : void 0) > 0 && document.location.hash !== this.hash) {
hash = document.location.hash.slice(1);
ref1 = this.$headers;
results = [];
for (k in ref1) {
v = ref1[k];
for (i = 0, len = ref1.length; i < len; i++) {
v = ref1[i];
$h = $(v);
if (hash === this.urlsafe($h.text())) {
if (hash === $h.attr('id')) {
this.hash = document.location.hash;
offset = $h.offset().top - $h.outerHeight(true);
setTimeout(function() {
@ -931,42 +1016,39 @@ module.exports = query({
componentWillUnmount: function() {
return clearInterval(this.int);
},
collectHeaders: function(e) {
var hs, k, v;
hs = [
{
collectHeader: function(arg) {
var c, ga, gn;
gn = arg.gn, ga = arg.ga, c = arg.c;
if (gn && gn[0] === 'h' && parseInt(gn[1]) !== NaN) {
ga = _.clone(ga);
ga.onClick = this._click(ga.id);
delete ga.id;
return {
gn: gn,
ga: ga,
c: c
};
}
},
parseHeaders: function() {
var i, len, ref, ref1, v;
if (this.props.body.c) {
ref = this.props.body.c;
for (i = 0, len = ref.length; i < len; i++) {
v = ref[i];
if (v.gn === 'div' && ((ref1 = v.ga) != null ? ref1.id : void 0) === "toc") {
return {
gn: "div",
ga: {
className: "toc"
},
c: [{
gn: "h1",
ga: {
className: "t"
},
c: ["Table of contents"]
}
];
for (k in e) {
v = e[k];
if (!v.gn) {
continue;
}
if (v.gn[0] === 'h' && parseInt(v.gn[1]) !== NaN) {
hs.push(v);
}
}
return hs;
},
parseHeaders: function() {
var k, ref, ref1, v;
if (this.props.body.c) {
ref = this.props.body.c;
for (k in ref) {
v = ref[k];
if (v.gn === 'div' && ((ref1 = v.ga) != null ? ref1.id : void 0) === "toc") {
return {
gn: "div",
ga: {
className: "toc",
onClick: this._click
},
c: this.collectHeaders(v.c)
}].concat(slice.call(_.filter(v.c.map(this.collectHeader))))
};
}
}
@ -979,7 +1061,7 @@ module.exports = query({
},{"./Async.coffee":3,"./Reactify.coffee":10}],13:[function(require,module,exports){
},{"./Async.coffee":3,"./Reactify.coffee":11}],14:[function(require,module,exports){
var Dispatcher;
Dispatcher = require('flux').Dispatcher;
@ -1001,7 +1083,7 @@ module.exports = _.extend(new Dispatcher(), {
},{"flux":16}],14:[function(require,module,exports){
},{"flux":17}],15:[function(require,module,exports){
var rend;
rend = React.render;
@ -1148,7 +1230,7 @@ $(function() {
},{"./actions/TreeActions.coffee":1,"./components/AnchorComponent.coffee":2,"./components/BodyComponent.coffee":4,"./components/Components.coffee":6,"./persistence/TreePersistence.coffee":19}],15:[function(require,module,exports){
},{"./actions/TreeActions.coffee":1,"./components/AnchorComponent.coffee":2,"./components/BodyComponent.coffee":4,"./components/Components.coffee":6,"./persistence/TreePersistence.coffee":20}],16:[function(require,module,exports){
/*!
Copyright (c) 2015 Jed Watson.
Licensed under the MIT License (MIT), see
@ -1199,7 +1281,7 @@ $(function() {
}());
},{}],16:[function(require,module,exports){
},{}],17:[function(require,module,exports){
/**
* Copyright (c) 2014-2015, Facebook, Inc.
* All rights reserved.
@ -1211,7 +1293,7 @@ $(function() {
module.exports.Dispatcher = require('./lib/Dispatcher')
},{"./lib/Dispatcher":17}],17:[function(require,module,exports){
},{"./lib/Dispatcher":18}],18:[function(require,module,exports){
/*
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
@ -1463,7 +1545,7 @@ var _prefix = 'ID_';
module.exports = Dispatcher;
},{"./invariant":18}],18:[function(require,module,exports){
},{"./invariant":19}],19:[function(require,module,exports){
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
@ -1518,7 +1600,11 @@ var invariant = function(condition, format, a, b, c, d, e, f) {
module.exports = invariant;
},{}],19:[function(require,module,exports){
},{}],20:[function(require,module,exports){
var dedup;
dedup = {};
module.exports = {
get: function(path, query, cb) {
var url;
@ -1526,6 +1612,10 @@ module.exports = {
query = "no-query";
}
url = (window.tree.basepath(path)) + ".json?q=" + (this.encode(query));
if (dedup[url]) {
return;
}
dedup[url] = true;
return $.get(url, {}, function(data) {
if (cb) {
return cb(null, data);
@ -1569,7 +1659,7 @@ module.exports = {
},{}],20:[function(require,module,exports){
},{}],21:[function(require,module,exports){
var EventEmitter, MessageDispatcher, QUERIES, TreeStore, _curr, _data, _tree, clog;
EventEmitter = require('events').EventEmitter;
@ -1609,8 +1699,10 @@ TreeStore = _.extend(EventEmitter.prototype, {
return this.fulfillAt(this.getTree(path.split('/')), path, query);
},
fulfillAt: function(tree, path, query) {
var data, k, ref, sub, t;
var data, have, k, sub, t;
data = this.fulfillLocal(path, query);
have = _data[path];
if (have != null) {
for (k in query) {
t = query[k];
if (!QUERIES[k]) {
@ -1619,15 +1711,22 @@ TreeStore = _.extend(EventEmitter.prototype, {
if (t !== QUERIES[k]) {
throw TypeError("Wrong query type: " + k + ", '" + t + "'");
}
data[k] = (ref = _data[path]) != null ? ref[k] : void 0;
data[k] = have[k];
}
if (query.kids) {
if (have.EMPTY) {
data.kids = {};
} else {
for (k in tree) {
sub = tree[k];
if (data.kids == null) {
data.kids = {};
}
data.kids[k] = this.fulfillAt(sub, path + "/" + k, query.kids);
}
}
}
}
if (!_.isEmpty(data)) {
return data;
}
@ -1678,29 +1777,7 @@ TreeStore = _.extend(EventEmitter.prototype, {
this.loadValues(tree[k], path + "/" + k, v);
}
if (data.kids && _.isEmpty(data.kids)) {
old.body = {
gn: 'div',
c: [
{
gn: 'h1',
ga: {
className: 'error'
},
c: ['Error: Empty path']
}, {
gn: 'div',
c: [
{
gn: 'pre',
c: [this.getCurr()]
}, {
gn: 'span',
c: ['is either empty or does not exist.']
}
]
}
]
};
old.EMPTY = true;
}
return _data[path] = old;
},
@ -1805,7 +1882,7 @@ module.exports = TreeStore;
},{"../dispatcher/Dispatcher.coffee":13,"events":21}],21:[function(require,module,exports){
},{"../dispatcher/Dispatcher.coffee":14,"events":22}],22:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@ -2108,4 +2185,4 @@ function isUndefined(arg) {
return arg === void 0;
}
},{}]},{},[14]);
},{}]},{},[15]);

View File

@ -1,6 +1,9 @@
dedup = {} # XX wrong layer
module.exports =
get: (path,query="no-query",cb) ->
url = "#{window.tree.basepath(path)}.json?q=#{@encode query}"
return if dedup[url]
dedup[url] = true
$.get url, {}, (data) -> if cb then cb null,data
encode: (obj)->
delim = (n)-> Array(n+1).join('_') || '.'

View File

@ -21,12 +21,16 @@ TreeStore = _.extend EventEmitter.prototype, {
fulfill: (path,query) -> @fulfillAt (@getTree path.split '/'),path,query
fulfillAt: (tree,path,query)->
data = @fulfillLocal path, query
have = _data[path]
if have?
for k,t of query when QUERIES[k]
if t isnt QUERIES[k] then throw TypeError "Wrong query type: #{k}, '#{t}'"
data[k] = _data[path]?[k]
data[k] = have[k]
if query.kids
if have.EMPTY
data.kids = {}
for k,sub of tree
else for k,sub of tree
data.kids ?= {}
data.kids[k] = @fulfillAt sub, path+"/"+k, query.kids
data unless _.isEmpty data
@ -54,14 +58,16 @@ TreeStore = _.extend EventEmitter.prototype, {
@loadValues tree[k], path+"/"+k, v
if data.kids && _.isEmpty data.kids
old.body =
gn: 'div'
c: [ {gn:'h1', ga:{className:'error'}, c:['Error: Empty path']}
{gn:'div', c:[
{gn:'pre', c:[@getCurr()]}
{gn:'span', c:['is either empty or does not exist.']}
# {gn:'list'} XX handle empty snip
] }]
old.EMPTY = true
# XX why here?
# old.body =
# gn: 'div'
# c: [ {gn:'h1', ga:{className:'error'}, c:['Error: Empty path']}
# {gn:'div', c:[
# {gn:'pre', c:[@getCurr()]}
# {gn:'span', c:['is either empty or does not exist.']}
# # {gn:'list'} XX handle empty snip
# ] }]
_data[path] = old

View File

@ -93,7 +93,7 @@
[%set-title til=@t] :: set title
[%set-description des=@t] :: XX (list ,@t) :: set description
[%set-done don=?] :: set done
[%add-comment com=@t] :: XX (list ,@t) :: add comment
[%add-comment who=@p com=@t] :: XX (list ,@t) :: add comment
== ::
++ task ::
$: id=@uvH ::