mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-17 03:44:34 +03:00
Merge remote-tracking branch 'upstream/test' into test
This commit is contained in:
commit
4aba7d1204
@ -90,7 +90,7 @@
|
||||
++ poke-helm-reset (wrap poke-reset):from-helm
|
||||
++ poke-helm-send-hi (wrap poke-send-hi):from-helm
|
||||
++ poke-helm-verb (wrap poke-verb):from-helm
|
||||
++ poke-hood-begin (wrap poke-begin):from-helm
|
||||
++ poke-helm-begin (wrap poke-begin):from-helm
|
||||
++ poke-hood-sync (wrap poke-sync):from-kiln
|
||||
++ poke-kiln-cp (wrap poke-cp):from-kiln
|
||||
++ poke-kiln-label (wrap poke-label):from-kiln
|
||||
|
@ -413,7 +413,7 @@
|
||||
vix=(bex +((cut 0 [25 2] mag))) :: width of sender
|
||||
tay=(cut 0 [27 5] mag) :: message type
|
||||
==
|
||||
?> =(0 vez)
|
||||
?> =(2 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 0]
|
||||
:~ [3 2]
|
||||
[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]
|
||||
?. =(0 (end 0 3 pac)) [~ fox]
|
||||
?. =(2 (end 0 3 pac)) [~ fox]
|
||||
=+ kec=(bite pac)
|
||||
?: (goop p.p.kec) [~ fox]
|
||||
?. (~(has by urb.ton.fox) q.p.kec)
|
||||
|
@ -882,7 +882,7 @@
|
||||
%= +>.$
|
||||
lim (max (fall lem lim) lim)
|
||||
hit.dom hit
|
||||
let.dom let
|
||||
let.dom (max let let.dom)
|
||||
hut.ran hut
|
||||
lat.ran lat
|
||||
==
|
||||
@ -1451,9 +1451,13 @@
|
||||
++ make-nako
|
||||
|= [a=aeon b=aeon]
|
||||
^- nako
|
||||
:+ hit.dom
|
||||
let.dom
|
||||
?~ =(0 b)
|
||||
:+ ?> (lte b let.dom)
|
||||
|-
|
||||
?: =(b let.dom)
|
||||
hit.dom
|
||||
$(hit.dom (~(del by hit.dom) let.dom), let.dom (dec let.dom))
|
||||
b
|
||||
?: =(0 b)
|
||||
[~ ~]
|
||||
(data-twixt-takos (~(get by hit.dom) a) (aeon-to-tako b))
|
||||
::
|
||||
@ -1483,8 +1487,8 @@
|
||||
far
|
||||
=+ gar=(lobe-to-blob lob)
|
||||
?- -.gar
|
||||
%direct (~(put in far) lob)
|
||||
%delta (~(put in $(lob q.q.gar)) lob)
|
||||
%direct (~(put in far) lob)
|
||||
%delta (~(put in $(lob q.q.gar)) lob)
|
||||
%indirect (~(put in $(lob r.gar)) lob)
|
||||
==
|
||||
::
|
||||
@ -1504,9 +1508,8 @@
|
||||
|= p=tako :: XX slow
|
||||
^- (set tako)
|
||||
=+ y=(tako-to-yaki p)
|
||||
=+ t=(~(put in *(set tako)) p)
|
||||
%+ roll p.y
|
||||
=< .(s t)
|
||||
=< .(s (~(put in *(set tako)) p))
|
||||
|= [q=tako s=(set tako)]
|
||||
?: (~(has in s) q) :: already done
|
||||
s :: hence skip
|
||||
@ -2455,9 +2458,13 @@
|
||||
?^ bem
|
||||
u.bem
|
||||
[[?>(?=(^ fat.ruf) p.n.fat.ruf) %base %ud 1] ~]
|
||||
=+ rom=(~(got by fat.ruf) p.bem)
|
||||
=+ dos=(~(got by dos.rom) q.bem)
|
||||
?: =(0 let.dom.dos)
|
||||
=+ rom=(~(get by fat.ruf) p.bem)
|
||||
?~ rom
|
||||
~
|
||||
=+ dos=(~(get by dos.u.rom) q.bem)
|
||||
?~ dos
|
||||
~
|
||||
?: =(0 let.dom.u.dos)
|
||||
=+ cos=(mode-to-soba ~ s.bem q.q.hic r.q.hic)
|
||||
=+ ^- [one=(list ,[path miso]) two=(list ,[path miso])]
|
||||
%+ skid q.cos
|
||||
@ -2471,7 +2478,7 @@
|
||||
:~ [hen %pass /one %c %info p.bem q.bem %& p.cos one]
|
||||
[hen %pass /two %c %info p.bem q.bem %& p.cos two]
|
||||
==
|
||||
=+ yak=(~(got by hut.ran.ruf) (~(got by hit.dom.dos) let.dom.dos))
|
||||
=+ yak=(~(got by hut.ran.ruf) (~(got by hit.dom.u.dos) let.dom.u.dos))
|
||||
=+ cos=(mode-to-soba q.yak (flop s.bem) q.q.hic r.q.hic)
|
||||
[hen %pass / %c %info p.bem q.bem %& cos]~
|
||||
::
|
||||
|
@ -141,10 +141,10 @@
|
||||
=+ yen=(scot %p (shax :(mix %ticket eny now)))
|
||||
=+ ^= beg ^- [his=@p tic=@p yen=@t ges=gens]
|
||||
[p.kyz q.kyz yen ges]
|
||||
=+ cag=`cage`[%hood-begin !>(beg)]
|
||||
=+ cmd=[%hood %poke `cage`[%helm-begin !>(beg)]]
|
||||
%= +>.$
|
||||
moz
|
||||
:_(moz [hen %pass ~ %g %deal [our our] %hood %poke cag])
|
||||
:_(moz [hen %pass ~ %g %deal [our our] cmd])
|
||||
==
|
||||
%veer (dump kyz)
|
||||
%vega (dump kyz)
|
||||
@ -360,7 +360,7 @@
|
||||
[~ ~]
|
||||
80
|
||||
0
|
||||
(tuba "<awaiting {(trip p.kyz)}>")
|
||||
(tuba "<awaiting {(trip p.kyz)}, this may take a few minutes>")
|
||||
==
|
||||
--
|
||||
|% :: poke/peek pattern
|
||||
|
@ -44,7 +44,7 @@
|
||||
== == ::
|
||||
$: %f :: by %ford
|
||||
$% [%made p=@uvH q=gage] ::
|
||||
[%news ~] ::
|
||||
[%news p=@uvH] ::
|
||||
== == ::
|
||||
$: @tas :: by any
|
||||
$% [%crud p=@tas q=(list tank)] ::
|
||||
@ -58,7 +58,7 @@
|
||||
[%hi p=mark ~] :: outbound HTTP
|
||||
[%si ~] :: response done
|
||||
[%of p=ixor q=$|(~ whir-of)] :: associated view
|
||||
[%on p=span:,@uvH ~] :: dependency
|
||||
[%on ~] :: dependency
|
||||
== ::
|
||||
++ whir-of ,[p=span:ship q=term r=wire] :: path in dock
|
||||
-- ::
|
||||
@ -99,7 +99,7 @@
|
||||
++ honk $%([%nice ~] [%mean p=ares]) :: old gall result
|
||||
++ even :: client event
|
||||
$% [%mean p=[dock path] q=ares]
|
||||
[%news p=@uv]
|
||||
[%news p=@uvH]
|
||||
[%rush p=[dock path] q=json]
|
||||
==
|
||||
::
|
||||
@ -694,16 +694,15 @@
|
||||
(give-json 200 ~ (joba %beat %b &))
|
||||
::
|
||||
%news :: dependency updated
|
||||
?. ?=([%on ^] tee)
|
||||
?. ?=([%on ~] tee)
|
||||
~&(e/lost/[tee hen] +>.$)
|
||||
=+ dep=(slav %uv p.tee)
|
||||
%+ roll (~(tap in (~(get ju liz) dep)))
|
||||
=< .(con ..axon(liz (~(del by liz) dep)))
|
||||
%+ roll (~(tap in (~(get ju liz) p.sih)))
|
||||
=< .(con ..axon(liz (~(del by liz) p.sih)))
|
||||
|= [sus=(each duct ixor) con=_..axon]
|
||||
=. ..axon con
|
||||
?- -.sus
|
||||
%& (give-json(hen p.sus) 205 ~ %b &)
|
||||
%| (get-even:(ire-ix p.sus) [%news dep])
|
||||
%| (get-even:(ire-ix p.sus) +.sih)
|
||||
==
|
||||
::
|
||||
%made
|
||||
@ -941,7 +940,7 @@
|
||||
=+ had=(~(has by liz) a)
|
||||
=. liz (~(put ju liz) a b)
|
||||
?: had done
|
||||
(pass-note on//(scot %uv a) %f [%wasp our a])
|
||||
(pass-note on/~ %f [%wasp our a])
|
||||
::
|
||||
++ parse
|
||||
^- (each perk httr)
|
||||
@ -1429,7 +1428,8 @@
|
||||
++ poll
|
||||
|= a=@u ^+ ..ix
|
||||
?: =(a p.eve)
|
||||
?^ ude ~&(e/ix/wait/replaced=p.u.ude abet(u.ude [hen &]))
|
||||
?^ ude :: ~& e/ix/wait/replaced=p.u.ude :: XX needs %thud handling
|
||||
abet(u.ude [hen &])
|
||||
=. era (add ~s30 now)
|
||||
(pass-note:abet(ude [~ hen &]) of//[ire] [%b %wait era])
|
||||
?: (gth a p.eve) ~|(seq-high/cur=p.eve !!)
|
||||
|
@ -70,7 +70,7 @@
|
||||
== ::
|
||||
++ task :: problem in progress
|
||||
$: nah=duct :: cause
|
||||
[bek=beak kas=silk] :: problem
|
||||
[bek=beak kas=silk] :: problem
|
||||
keg=(map (pair term beam) cage) :: block results
|
||||
kig=[p=@ud q=(map ,@ud ,[p=care q=beam])] :: blocks
|
||||
== ::
|
||||
@ -240,7 +240,7 @@
|
||||
%sent
|
||||
=- [[%done ~] +>.$(mow (weld - mow))]
|
||||
^- (list move)
|
||||
%+ weld (turn (~(tap in p.dap)) |=(hen=duct [hen %give %news ~]))
|
||||
%+ weld (turn (~(tap in p.dap)) |=(hen=duct [hen %give %news dep]))
|
||||
=. q.dap (~(del in q.dap) bem)
|
||||
%+ turn (~(tap in q.dap)) :: cancel outstanding
|
||||
|= bem=beam
|
||||
@ -255,12 +255,12 @@
|
||||
?~ dep
|
||||
~&(dep-empty/hen +>.$)
|
||||
?: =(dep 0vtest) :: upstream testing
|
||||
+>.$(mow :_(mow [hen %give %news ~]))
|
||||
+>.$(mow :_(mow [hen %give %news dep]))
|
||||
=+ dap=(~(get by deh.bay) dep)
|
||||
?~ dap ~&(dep-missed/dep +>.$) :: XX ~| !!
|
||||
:: ~& awap/[dep u.dap]
|
||||
?- -.u.dap
|
||||
%done +>.$(mow :_(mow [hen %give %news ~]))
|
||||
%done +>.$(mow :_(mow [hen %give %news dep]))
|
||||
%sent
|
||||
=. p.u.dap (~(put in p.u.dap) hen)
|
||||
+>.$(deh.bay (~(put by deh.bay) dep u.dap))
|
||||
|
@ -481,26 +481,26 @@
|
||||
==
|
||||
::
|
||||
++ les ^- (list ,@da)
|
||||
:~ ~2012.7.1 ~2009.1.1 ~2006.1.1 ~1999.1.1 ~1997.7.1 ~1996.1.1
|
||||
~1994.7.1 ~1993.7.1 ~1992.7.1 ~1991.1.1 ~1990.1.1 ~1988.1.1
|
||||
~1985.7.1 ~1983.7.1 ~1982.7.1 ~1981.7.1 ~1980.1.1 ~1979.1.1
|
||||
~1978.1.1 ~1977.1.1 ~1976.1.1 ~1975.1.1 ~1974.1.1 ~1973.1.1
|
||||
~1972.7.1
|
||||
:~ ~2015.7.1 ~2012.7.1 ~2009.1.1 ~2006.1.1 ~1999.1.1 ~1997.7.1
|
||||
~1996.1.1 ~1994.7.1 ~1993.7.1 ~1992.7.1 ~1991.1.1 ~1990.1.1
|
||||
~1988.1.1 ~1985.7.1 ~1983.7.1 ~1982.7.1 ~1981.7.1 ~1980.1.1
|
||||
~1979.1.1 ~1978.1.1 ~1977.1.1 ~1976.1.1 ~1975.1.1 ~1974.1.1
|
||||
~1973.1.1 ~1972.7.1
|
||||
==
|
||||
++ lef ^- (list ,@da)
|
||||
:~ ~2012.6.30..23.59.59 ~2008.12.31..23.59.58
|
||||
~2005.12.31..23.59.57 ~1998.12.31..23.59.56
|
||||
~1997.6.30..23.59.55 ~1995.12.31..23.59.54
|
||||
~1994.6.30..23.59.53 ~1993.6.30..23.59.52
|
||||
~1992.6.30..23.59.51 ~1990.12.31..23.59.50
|
||||
~1989.12.31..23.59.49 ~1987.12.31..23.59.48
|
||||
~1985.6.30..23.59.47 ~1983.6.30..23.59.46
|
||||
~1982.6.30..23.59.45 ~1981.6.30..23.59.44
|
||||
~1979.12.31..23.59.43 ~1978.12.31..23.59.42
|
||||
~1977.12.31..23.59.41 ~1976.12.31..23.59.40
|
||||
~1975.12.31..23.59.39 ~1974.12.31..23.59.38
|
||||
~1973.12.31..23.59.37 ~1972.12.31..23.59.36
|
||||
~1972.6.30..23.59.35
|
||||
:~ ~2015.6.30..23.59.59 ~2012.6.30..23.59.59
|
||||
~2008.12.31..23.59.58 ~2005.12.31..23.59.57
|
||||
~1998.12.31..23.59.56 ~1997.6.30..23.59.55
|
||||
~1995.12.31..23.59.54 ~1994.6.30..23.59.53
|
||||
~1993.6.30..23.59.52 ~1992.6.30..23.59.51
|
||||
~1990.12.31..23.59.50 ~1989.12.31..23.59.49
|
||||
~1987.12.31..23.59.48 ~1985.6.30..23.59.47
|
||||
~1983.6.30..23.59.46 ~1982.6.30..23.59.45
|
||||
~1981.6.30..23.59.44 ~1979.12.31..23.59.43
|
||||
~1978.12.31..23.59.42 ~1977.12.31..23.59.41
|
||||
~1976.12.31..23.59.40 ~1975.12.31..23.59.39
|
||||
~1974.12.31..23.59.38 ~1973.12.31..23.59.37
|
||||
~1972.12.31..23.59.36 ~1972.6.30..23.59.35
|
||||
==
|
||||
--
|
||||
::
|
||||
@ -2552,7 +2552,7 @@
|
||||
++ gift-ford :: out result <-$
|
||||
$% [%made p=@uvH q=gage] :: computed result
|
||||
[%mass p=mass] :: memory usage
|
||||
[%news ~] :: fresh depends
|
||||
[%news p=@uvH] :: fresh depends
|
||||
== ::
|
||||
++ kiss-ford :: in request ->$
|
||||
$% [%exec p=@p q=(unit bilk)] :: make / kill
|
||||
|
@ -6,7 +6,10 @@
|
||||
::::
|
||||
!:
|
||||
|= $: [now=@da eny=@uvI bec=beak]
|
||||
[arg=[pax=path pot=@tas ~] ~]
|
||||
[[pax=path pot=$|(~ [v=@tas ~])] ~]
|
||||
==
|
||||
?~ pot
|
||||
=+ bem=(need (tome pax))
|
||||
$(pot ~[?^(s.bem i.s.bem q.bem)])
|
||||
:- %kiln-mount
|
||||
[pax pot]:arg
|
||||
[pax v.pot]
|
||||
|
@ -8,11 +8,16 @@
|
||||
!:
|
||||
=> |%
|
||||
++ begs ,[his=@p tic=@p yen=@t ges=gens]
|
||||
++ scug |*([a=@ b=(pole)] ?~(b ~ ?~(a ~ [-.b $(b +.b, a (dec a))])))
|
||||
--
|
||||
|= $: [now=@da eny=@uvI bec=beak]
|
||||
[~ ~]
|
||||
[arg=_(scug *@ ~[his=*@p tic=*@p]) ~]
|
||||
==
|
||||
^- (sole-result (cask begs))
|
||||
=- ?~ arg -
|
||||
=+ (fun.q.q his.arg)
|
||||
?~ +.arg -
|
||||
(fun.q.q tic.arg)
|
||||
%+ sole-lo
|
||||
[%& %helm-begin "your ship: ~"]
|
||||
%+ sole-go fed:ag
|
||||
|
@ -63,7 +63,7 @@
|
||||
%- ~(gas in *(set well))
|
||||
=+ myr=(clan our)
|
||||
?: =(%pawn myr)
|
||||
[[%base %dojo] ~]
|
||||
[[%base %talk] [%base %dojo] ~]
|
||||
?: =(%earl myr) ~
|
||||
[[%home %talk] [%home %dojo] ~]
|
||||
::
|
||||
@ -72,8 +72,8 @@
|
||||
%- ~(gas in *(set gill))
|
||||
^- (list gill)
|
||||
=+ myr=(clan our)
|
||||
?: =(%pawn myr)
|
||||
[[our %dojo] ~]
|
||||
:: ?: =(%pawn myr)
|
||||
:: [[our %dojo] ~]
|
||||
?: =(%earl myr)
|
||||
=+ dad=(sein our)
|
||||
[[dad %talk] [dad %dojo] ~]
|
||||
|
@ -79,6 +79,11 @@
|
||||
^+ +>
|
||||
?~(+< +> $(+< t.+<, +> (emit i.+<)))
|
||||
::
|
||||
++ render
|
||||
|= [mez=tape sud=desk who=ship syd=desk]
|
||||
:^ %palm [" " ~ ~ ~] leaf/mez
|
||||
~[leaf/"from {<sud>}" leaf/"on {<who>}" leaf/"to {<syd>}"]
|
||||
::
|
||||
++ poke-mount
|
||||
|= kiln-mount
|
||||
=+ bem=(tome pax)
|
||||
@ -100,15 +105,13 @@
|
||||
++ poke-sync ::
|
||||
|= hos=kiln-sync
|
||||
?: (~(has by syn) hos)
|
||||
=+ "already syncing from {<sud.hos>} on {<her.hos>} to {<syd.hos>}"
|
||||
abet:(spam leaf/- ~)
|
||||
abet:(spam (render "already syncing" [sud her syd]:hos) ~)
|
||||
abet:abet:start:(auto hos)
|
||||
::
|
||||
++ poke-unsync ::
|
||||
|= hus=kiln-unsync
|
||||
?. (~(has by syn) hus)
|
||||
=+ "not syncing from {<sud.hus>} on {<her.hus>} to {<syd.hus>}"
|
||||
abet:(spam leaf/- ~)
|
||||
abet:(spam (render "not syncing" [sud her syd]:hus) ~)
|
||||
%* . abet:abet:stop:(auto hus)
|
||||
syn (~(del by syn) hus)
|
||||
==
|
||||
@ -182,8 +185,9 @@
|
||||
::
|
||||
++ spam
|
||||
|= mes=(list tank)
|
||||
%- emit
|
||||
[%poke /kiln/spam [our %talk] (said our %kiln now eny mes)]
|
||||
((slog 0 mes) ..spam)
|
||||
:: %- emit :: XX not displayed/immediately
|
||||
:: [%poke /kiln/spam [our %talk] (said our %kiln now eny mes)]
|
||||
::
|
||||
++ auto
|
||||
|= kiln-sync
|
||||
@ -199,7 +203,7 @@
|
||||
::
|
||||
++ spam |*(* %_(+> ..auto (^spam +<)))
|
||||
++ stop
|
||||
=> (spam leaf/"ended autosync from {<sud>} on {<her>} to {<syd>}" ~)
|
||||
=> (spam (render "ended autosync" sud her syd) ~)
|
||||
%- blab :_ ~
|
||||
:* ust %warp
|
||||
/kiln/sync/[syd]/(scot %p her)/[sud]
|
||||
@ -207,11 +211,9 @@
|
||||
==
|
||||
::
|
||||
++ start
|
||||
:: XX remove feedback for demo
|
||||
:: =. . %- spam
|
||||
:: [leaf/"activated sync from {<sud>} on {<her>} to {<syd>}" ~]
|
||||
=> (spam (render "activated sync" sud her syd) ~)
|
||||
%- blab
|
||||
:~ [ost %mont /mount syd our syd /]
|
||||
:~ :: [ost %mont /mount syd our syd /]
|
||||
:* ost %warp
|
||||
/kiln/sync/[syd]/(scot %p her)/[sud]
|
||||
[our her] sud ~ %sing %w [%da now] /
|
||||
@ -221,8 +223,8 @@
|
||||
|= rot=riot
|
||||
?~ rot
|
||||
%^ spam
|
||||
leaf/"bad %writ response on sync"
|
||||
leaf/"from {<sud>} on {<her>} to {<syd>}"
|
||||
leaf/"bad %writ response"
|
||||
(render "on sync" sud her syd)
|
||||
~
|
||||
=. let ?. ?=(%w p.p.u.rot) let ((hard ,@ud) q.q.r.u.rot)
|
||||
%- blab :_ ~
|
||||
@ -240,9 +242,9 @@
|
||||
=. +>.$
|
||||
%- spam
|
||||
?: ?=(%& -.mes)
|
||||
[leaf/"sync succeeded from {<sud>} on {<her>} to {<syd>}" ~]
|
||||
[(render "sync succeeded" sud her syd) ~]
|
||||
?+ p.p.mes
|
||||
:* leaf/"sync failed from {<sud>} on {<her>} to {<syd>}"
|
||||
:* (render "sync failed" sud her syd)
|
||||
leaf/"please manually merge the desks with"
|
||||
leaf/":+merge %{(trip syd)} {(scow %p her)} %{(trip sud)}"
|
||||
leaf/""
|
||||
@ -251,8 +253,8 @@
|
||||
==
|
||||
::
|
||||
%no-ali-desk
|
||||
:~ leaf/"sync activated from {<sud>} on {<her>} to {<syd>}"
|
||||
leaf/"note: {<sud>} on {<her>} is a blank desk"
|
||||
:~ (render "sync activated" sud her syd)
|
||||
leaf/"note: blank desk {<sud>} on {<her>}"
|
||||
==
|
||||
==
|
||||
%- blab :_ ~
|
||||
|
@ -33,7 +33,7 @@ window.urb.req = function(method,url,params,json,cb) {
|
||||
if(res.data.reload)
|
||||
res.reload = res.data.reload
|
||||
} catch(e) {
|
||||
if(urb.wall !== false) document.write(this.responseText) // XX
|
||||
// if(urb.wall !== false) document.write(this.responseText) // XX
|
||||
err = {
|
||||
message:"Failed to parse JSON",
|
||||
raw:this.responseText
|
||||
|
@ -154,7 +154,8 @@
|
||||
%^ cat 3 ' '
|
||||
%^ cat 3 `@t`(scot %p bos)
|
||||
%^ cat 3 '/'
|
||||
bos
|
||||
bod
|
||||
|
||||
:- bob
|
||||
:- ~['------------']
|
||||
:- bas
|
||||
|
@ -11,146 +11,246 @@ You can find them in `/main/app`.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:begin`](#begin)
|
||||
### [`:?begin`](#begin)
|
||||
|
||||
`~zod/try=> :begin [~ship-name [~valid-ticket-for-ship]]`
|
||||
`~zod:dojo> :?begin [~ship-name [~valid-ticket-for-ship]]`
|
||||
|
||||
Start a ship. `:begin` collects all of the necessary information to
|
||||
Start a ship. `:?begin` collects all of the necessary information to
|
||||
start an Urbit ship. Takes an option `[~ship-name]` or
|
||||
`[~ship-name [~valid-ticket-for-ship]]` pair.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:cat`](#cat)
|
||||
### [`+cat`](#cat)
|
||||
|
||||
`~zod/try=> :cat path-to-file [...]`
|
||||
`~zod:dojo> +cat /path/to/file [...]`
|
||||
|
||||
"cat" a file. `:cat` either prints a file, or concatenates and then
|
||||
"cat" a file. `+cat` either prints a file, or concatenates and then
|
||||
prints multiple files to the terminal.
|
||||
|
||||
~zod:dojo> +cat %/spec/nock/5/txt
|
||||
> +cat %/spec/nock/5/txt
|
||||
/~zod/home/~2015.6.29..22.33.04..fc76/spec/nock/5/txt
|
||||
A noun is an atom or a cell.
|
||||
…
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:cp`](#cp)
|
||||
### [`|cp`](#cp)
|
||||
|
||||
`~zod/try=> :cp /path/to/source /path/to/destination`
|
||||
`~zod:dojo> |cp /path/to/source /path/to/destination`
|
||||
|
||||
Copy a file to a given location.
|
||||
|
||||
~zod:dojo> |cp %/spec/nock/5/txt %/try/6/txt
|
||||
> |cp %/spec/nock/5/txt %/try/6/txt
|
||||
+ /~zod/home/2/try/6/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:grep`](#grep)
|
||||
### [`grep`](#grep)
|
||||
|
||||
`~zod/try=> :grep 'literal'`
|
||||
<mark>GONE</mark>
|
||||
|
||||
<s>`~zod:dojo> :grep 'literal'`
|
||||
|
||||
"grep" a file or standard input. Currently only supports a literal cord,
|
||||
but will eventuall support regular expressions.
|
||||
but will eventuall support regular expressions.</s>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:hi`](#hi)
|
||||
### [`|hi`](#hi)
|
||||
|
||||
`~zod/try=> :hi ~ship ["message"]`
|
||||
`~zod:dojo> |hi ~ship ["message"]`
|
||||
|
||||
Send a ship a message which is empty by default, becoming their neighbor
|
||||
in the process. Often used to ping ships to check connectivity.
|
||||
|
||||
|
||||
~zod:dojo> |hi ~doznec
|
||||
> |hi ~doznec
|
||||
ames: czar zod.urbit.org: ip .192.241.195.84
|
||||
>=
|
||||
hi ~doznec succesful
|
||||
; ~doznec is your neighbor
|
||||
; ~doznec is your neighbor
|
||||
|
||||
and on ~doznec
|
||||
|
||||
~doznec:dojo>
|
||||
< ~zod:
|
||||
; ~zod is your neighbor
|
||||
|
||||
|
||||
send a message
|
||||
|
||||
~zod:dojo> |hi ~doznec "say something"
|
||||
>=
|
||||
hi ~doznec succesful
|
||||
|
||||
and on ~doznec
|
||||
|
||||
< ~zod: say something
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:into`](#into)
|
||||
|
||||
`~zod/try=> :into /path/to/file 'contents'`
|
||||
<mark>GONE</mark>
|
||||
|
||||
<s>
|
||||
`~zod:dojo> :into /path/to/file 'contents'`
|
||||
|
||||
Write text to a file. If the specified file does not exist, create a
|
||||
file by that name. If it does exist, replace its contents.
|
||||
</s>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:label`](#label)
|
||||
### [`|label`](#label)
|
||||
|
||||
`~zod/try=> :label %path %label`
|
||||
<mark>GONE? returns file not found</mark>
|
||||
|
||||
<s>
|
||||
`~zod:dojo> |label %path %label`
|
||||
|
||||
"label". Add a label to a change number.
|
||||
|
||||
~zod/try=> :label %try %zebra
|
||||
~zod:dojo> |label %try %zebra
|
||||
= new /~zod/try/3
|
||||
~zod/try=> :ls /=try/zebra
|
||||
~zod:dojo> :ls /=try/zebra
|
||||
readme
|
||||
|
||||
Note that adding a label is part of the delta stream and creates a new
|
||||
change number, `3`.
|
||||
</s>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:ls`](#ls)
|
||||
### [`+ls`](#ls)
|
||||
|
||||
`~zod/try=> :ls path/to/directory`
|
||||
`~zod:dojo> :+ls path/to/directory`
|
||||
|
||||
"ls". List files at a path. Unlike "ls" in Unix, the current path `%`
|
||||
must be explicitly given (you cannot call `:ls` with no arguments to
|
||||
must be explicitly given (you cannot call `+ls` with no arguments to
|
||||
display the files at the current path).
|
||||
|
||||
~zod:dojo> +ls %try
|
||||
> +ls %/try/
|
||||
readme/md
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:mv`](#mv)
|
||||
### [`|mount`](#mount)
|
||||
|
||||
`~zod/try=> :mv /path/to/source /path/to/destination`
|
||||
`~zod:dojo> |mount /path/to/directory/version %mount-point`
|
||||
|
||||
Your files are not synced to unix by default.
|
||||
To sync a subtree to unix, run `|mount /path/to/directory %mount-point`.
|
||||
This will sync it into <pier>/<mount-point>.
|
||||
If you want to sync your whole home desk into f0/home, for example,
|
||||
run `|mount % %home` You can also [`|unmount`](#unmount).
|
||||
|
||||
~zod:dojo> |mount /~zod/base/0 %base
|
||||
> |mount /~zod/base %base
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`|mv`](#mv)
|
||||
|
||||
`~zod:dojo> |mv /path/to/source /path/to/destination`
|
||||
|
||||
Move a file to a given location, creating a new revision of the source
|
||||
that omits the moved file.
|
||||
|
||||
~zod:dojo> |mv %/try/6/txt %/try/7/txt
|
||||
> |mv %/try/6/txt %/try/7/txt
|
||||
+ /~zod/home/3/try/7/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:reload`](#reload)
|
||||
### [`|reload`](#reload)
|
||||
|
||||
`~zod/try=> :reload %vane-name [...]`
|
||||
`~zod:dojo> |reload %vane-name [...]`
|
||||
|
||||
Reload the standard library (zuse) and/or arvo vanes. If zuse is
|
||||
reloaded, vanes depending on the changes must be reloaded as well. For
|
||||
example `:reload %zuse %ford` is necessary to make use of changes in
|
||||
example `|reload %zuse %ford` is necessary to make use of changes in
|
||||
application code or the REPL.
|
||||
|
||||
Possible values for %vane-name see [Overview](overview "overview"):
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:reset`](#reset)
|
||||
|
||||
`~zod/try=> :reset`
|
||||
|
||||
Reloads all vanes. See [`:reset`] for reloading only or a specific vane.
|
||||
~zod:dojo> |reload %zuse
|
||||
[%tang /~zod/home/~2015.6.29..23.50.29..134d/arvo/zuse ~hillyx-salhet]
|
||||
> |reload %zuse
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:rm`](#rm)
|
||||
### [`|reset`](#reset)
|
||||
|
||||
`~zod/try=> :rm /path/to/source`
|
||||
`~zod:dojo> |reset`
|
||||
|
||||
Reloads all vanes. See [`|reload`](#reload) for reloading only or a specific vane.
|
||||
|
||||
~zod:dojo> |reset
|
||||
[%vega-start /~zod/home/~2015.6.29..23.51.42..f335/arvo/hoon]
|
||||
%vega-parsed
|
||||
[%vega-compiled %163 163]
|
||||
%hoon-load
|
||||
[%tang /~zod/home/~2015.6.29..23.51.42..f335/arvo/zuse ~hillyx-salhet]
|
||||
[%vane %a /~zod/home/~2015.6.29..23.51.42..f335/arvo/ames ~tilwyl-talren]
|
||||
%ames-reload
|
||||
[%vane %c /~zod/home/~2015.6.29..23.51.42..f335/arvo/clay ~molmur-panlus]
|
||||
[%vane %d /~zod/home/~2015.6.29..23.51.42..f335/arvo/dill ~sicbet-miphes]
|
||||
[%vane %e /~zod/home/~2015.6.29..23.51.42..f335/arvo/eyre ~solrux-sibnep]
|
||||
[gub=30 hov=19 ged=18 ded=1 pox=1 ask=1 kes=1 ney=35 dop=1 liz=1 wup=1 sop=1 wix=1]
|
||||
[%vane %f /~zod/home/~2015.6.29..23.51.42..f335/arvo/ford ~librem-sopseg]
|
||||
[%vane %g /~zod/home/~2015.6.29..23.51.42..f335/arvo/gall ~sidsub-fasrev]
|
||||
[%vane %t /~zod/home/~2015.6.29..23.51.42..f335/arvo/time ~ritwyn-lanrev]
|
||||
> |reset
|
||||
<<<reset>>>
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`|rm`](#rm)
|
||||
|
||||
`~zod:dojo> |rm /path/to/source`
|
||||
|
||||
Remove a file.
|
||||
|
||||
~zod:dojo> |rm %/try/7/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:solid`](#solid)
|
||||
### [`+solid`](#solid)
|
||||
|
||||
`~zod/try=> :solid`
|
||||
`~zod:dojo> +solid`
|
||||
|
||||
compiles a kernel into a new full urbit.pill
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:sync`](#sync)
|
||||
### [`|sync`](#sync)
|
||||
|
||||
`:sync %source-desk ~hidduc-posmeg %target-desk`
|
||||
`~zod:dojo> |sync %source-desk ~hidduc-posmeg %target-desk`
|
||||
|
||||
Sets up a subscription to the source desk on the target ship name to the
|
||||
target desk on your ship.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:ticket`](#ticket)
|
||||
### [`+ticket`](#ticket)
|
||||
|
||||
`~zod/try=> :ticket ~ship-name`
|
||||
`~zod:dojo> +ticket ~ship-name`
|
||||
|
||||
Creates a will for a ship. `:ticket` outputs the ticket for a Urbit
|
||||
Creates a will for a ship. `+ticket` outputs the ticket for a Urbit
|
||||
ship. Takes an option `[~ship-name]`. On destroyes this command creates
|
||||
a yacht and takes the option \`[\~yacht-name-destroyer-name]
|
||||
|
||||
@ -158,7 +258,10 @@ a yacht and takes the option \`[\~yacht-name-destroyer-name]
|
||||
|
||||
### [`:thumb`](#thumb)
|
||||
|
||||
`~zod/try=> :thumb ~ship-name`
|
||||
<mark>GONE</mark>
|
||||
|
||||
<s>
|
||||
`~zod:dojo> :thumb ~ship-name`
|
||||
|
||||
Show the ships information. Only works if you issued a [`:hi`]
|
||||
[\`\~ship-name] beforehand.
|
||||
@ -168,21 +271,37 @@ This command is not avaible since the switch from batz to `%gall`!
|
||||
Use this for the time beeing: - will:
|
||||
`~zod/try=> ((hard (unit gcos)) .^(%a /=gcos=/~ship-name))` - raw will:
|
||||
`~zod/try=> ((hard will) .^(%a /=will=/~ship-name))`
|
||||
</s>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:unsync`](#unsync)
|
||||
### [`|unmount`](#unmount)
|
||||
|
||||
`:unsync %source-desk ~hidduc-posmeg %target-desk`
|
||||
`~zod:dojo> |unmount /path/to/directory`
|
||||
|
||||
Your files are not synced to unix by default.
|
||||
To sync a subtree to unix, run [`|mount`](#mount).
|
||||
You can unmount with either `|unmount /path/to/directory`
|
||||
or `|unmount %mount-point`.
|
||||
|
||||
~zod:dojo> |unmount %base
|
||||
> |unmount %base
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`|unsync`](#unsync)
|
||||
|
||||
`~zod:dojo> |unsync %source-desk ~hidduc-posmeg %target-desk`
|
||||
|
||||
Cancels the subscription to the source desk on the target ship name to
|
||||
the target desk on your ship.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:verb`](#verb)
|
||||
### [`|verb`](#verb)
|
||||
|
||||
`~zod/try=> :verb`
|
||||
`~zod:dojo> |verb`
|
||||
|
||||
Turn verbose arvo mode on/off.
|
||||
|
||||
@ -220,9 +339,9 @@ You'll see events, internal cards, and effects.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### [`:ye`](#ye)
|
||||
### [`|ye`](#ye)
|
||||
|
||||
`~zod/try=> :ye ["message"]`
|
||||
`~zod:dojo> |ye ["message"]`
|
||||
|
||||
Send a message to all ships. Often used to announce a continuity breach.
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
Guides
|
||||
======
|
||||
|
||||
These guides are designed to get you oriented in urbit.
|
||||
|
||||
Each one covers a specific topic. Although it's not necessary to follow
|
||||
them in order, they do get increasingly complex.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
@ -1,813 +0,0 @@
|
||||
`%ford` Guide
|
||||
=============
|
||||
|
||||
#### basic `hoon` and talking to the web
|
||||
|
||||
<div class="short">
|
||||
|
||||
`%ford` is the arvo vane that handles asset management and publishing.
|
||||
We use `%ford` to compose our files when programming, and also to bundle
|
||||
files together for the web.
|
||||
|
||||
This guide assumes that you have installed and started your urbit.
|
||||
Assuming you cloned the repo into `/$URB_DIR` you should be able to find
|
||||
the unix mirror of your ship's filesystem in
|
||||
`/$URB_DIR/$PIER/$SHIP-NAME`. All of the filesystem paths in this guide
|
||||
are relative to that Unix directory.
|
||||
|
||||
Also, we refer to `http://ship-name.urbit.org/` in our URLs, but you can
|
||||
also use `http://localhost:8080/` if you prefer to just talk to your
|
||||
machine directly.
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
1. Let's publish a webpage
|
||||
--------------------------
|
||||
|
||||
#### In
|
||||
|
||||
/main/pub/fab/guide/exercise/1/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 1
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 1 — Simple HTML
|
||||
;p: As you may notice, urbit has no problem talking to the web.
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/1/
|
||||
|
||||
#### What did you just do?
|
||||
|
||||
The code you just wrote is urbit's native programming langauge, hoon.
|
||||
Generating HTML with hoon is similar to writing [jade]() or other
|
||||
similar HTML shorthand. In hoon, this shorthand is called [`++sail`]()
|
||||
and it's a native part of the hoon language.
|
||||
|
||||
In `++sail` node-names are prefixed with a `;` and closed with a `==`.
|
||||
Nodes that have text content and are only on one line use a `:`, such as
|
||||
our `;h1:` above, and are closed implicitly with a new line. Nodes with
|
||||
no content are closed with another `;`, such as `;br;`.
|
||||
|
||||
You can find more information about `++sail` in our [rune library
|
||||
documentation]().
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
2. Let's do some programming on the page.
|
||||
-----------------------------------------
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/2/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 2
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 2 — Call a function
|
||||
;p: Although it may be obvious, 2+2={<(add 2 2)>}
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/2/
|
||||
|
||||
### What's going on there?
|
||||
|
||||
Clearly, the code `(add 2 2)` is generating `4`, and it's not too hard
|
||||
to see why. `add` is one of the library functions that are a part of
|
||||
`hoon.hoon`. Try replacing `(add 2 2)` with `(sub 2 (add 2 2))`. You can
|
||||
find documentation for the full hoon library in the [library
|
||||
reference]().
|
||||
|
||||
Since the product of `(add 2 2)` is a number, we need a few extra things
|
||||
to have it print properly. In `++sail` we use `{` and `}` to do string
|
||||
interpolation. Everything after the `:` is expected to be a string, so
|
||||
we need to tell the parser when we start writing code. The `<` and `>`
|
||||
inside our `{` `}` are converting our result `4`, a number, to the
|
||||
string `"4"`. hoon is a strongly typed language kind of like haskell, so
|
||||
we need to explicitly convert our types.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
3. Let's assign some variables.
|
||||
-------------------------------
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/3/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
=+ ^= a 1
|
||||
=+ b=2
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 3
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 3 — Assignment
|
||||
;p: a={<a>}
|
||||
;p: b={<b>}
|
||||
;p: a+b={<(add a b)>}
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/3/
|
||||
|
||||
#### How does that work?
|
||||
|
||||
The first thing you should notice in this example is the `=+` at the top
|
||||
of our file. `=+` is a rune. hoon is a programming with no reserved
|
||||
words. We don't use `if` `this` or `function` at all. Instead, runes
|
||||
have their own pronunciation. `=+` is pronounced 'tislus'. You can find
|
||||
the table of pronunciation [here](). In hoon you construct your
|
||||
programs using runes, which are two character ascii pairs. You can see
|
||||
the whole set of runes in the [rune index]().
|
||||
|
||||
`=+` pushes an expression on to our subject. The subject in hoon is
|
||||
similar to `this` in other languages. hoon being a functional language
|
||||
if we want something to be available further on in our computation we
|
||||
need to attach it to the subject first.
|
||||
|
||||
The second thing you should notice is the `^- manx`. Here the rune
|
||||
`[^-]()` is used to cast our product to a [++manx](), which you can
|
||||
think of like the hoon MIME type for XML. Using a `^-` is not required,
|
||||
but helps us produce more informative error messages when we generate a
|
||||
type error or mismatch.
|
||||
|
||||
Looking at the rendered page it's clear that we're assigning `a` to be
|
||||
`1` and `b` to be `2`. Looking at the code, however, you can see that
|
||||
we're doing this in two different ways. Runes in hoon can have irregular
|
||||
forms, and `^=` is one of them. The first two lines of our example are
|
||||
doing the same thing, where `a=2` is simply the irregular form of
|
||||
`^= a 2`. You can see the full list of irregular forms [here]().
|
||||
|
||||
Looking at the simple computation on the page, you can try changing the
|
||||
values of `a` and `b` to any integers to produce similar results.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
4. Let's build our own computation
|
||||
----------------------------------
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/4/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
|%
|
||||
++ start 1
|
||||
++ end 10
|
||||
++ length
|
||||
|= [s=@ud e=@ud]
|
||||
(sub e s)
|
||||
--
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 4
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 4 — Cores
|
||||
;p: We'll be starting at {<start>}
|
||||
;p: And ending at {<end>}
|
||||
;p: Looks like a length of {<(length start end)>}
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
(and be sure to put two spaces between `++` and arm names)
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/4/
|
||||
|
||||
### What's happening?
|
||||
|
||||
As you can see from the output, we have written a little function that
|
||||
takes two numbers, `s` and `e` and returns their difference. The first
|
||||
thing to notice about our code is the first rune. `|%` is a `core` rune.
|
||||
You can think of cores like functions or objects in other languages.
|
||||
`|%` runes contain an arbitrary number of arms, denoted with either `++`
|
||||
or `+-` and closed with `--`.
|
||||
|
||||
Each arm has a value, either static data (in the case of `++start` and
|
||||
`++end`) or a gate (in the case of `++length`). A gate is a kind of
|
||||
core. Gates only have one arm and are quite similar to a function in
|
||||
other languages. We use `|=` to construct our gate. Runes in hoon are
|
||||
generally categorized by their first character. `|` indicates a rune
|
||||
having to do with cores. You can find all of the `|` runes in the [rune
|
||||
library]().
|
||||
|
||||
Our `++length` [gate]() takes two arguments, `s` and `e`. In hoon we
|
||||
call the data passed in to a gate the 'sample'. Every `|=` has two
|
||||
parts: the sample type and the computation, also known as a `tile` and a
|
||||
`twig`. Casually, `[s=@ud e=@ud]` means that the gate takes two
|
||||
arguments, labelled going forward as `s` and `e`, and required to both
|
||||
be `@ud` or unsigned decimal. Our computation, `(sub e s)` simply
|
||||
computes the difference between `e` and `s`.
|
||||
|
||||
`@ud` is an odor. Odors aren't quite types, but they're similar. You'll
|
||||
learn the difference by example as we progress, and you can always refer
|
||||
to the [odor index]().
|
||||
|
||||
You probably also noticed our indentation. In general hoon has both tall
|
||||
and wide forms. In tall form, hoon uses two spaces for indentation and
|
||||
is back-stepped so nested code doesn't drift away toward the right
|
||||
margin. In wide form we use parenthesis just like almost everyone else.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
5.
|
||||
--
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/5/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
|%
|
||||
++ dist ,[start=@ud end=@ud]
|
||||
++ length
|
||||
|= [d=dist]
|
||||
(sub end.d start.d)
|
||||
--
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 5
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 5 — Cores
|
||||
;p: How long does it take to get from 2 to 20? {<(length 2 20)>}
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/5/
|
||||
|
||||
#### What's the difference?
|
||||
|
||||
Clearly we're producing the same result as before, but we're doing it in
|
||||
a different way.
|
||||
|
||||
The first line in our gate, `++length` always specifies the sample tile.
|
||||
As you can see here, our sample tile is actually a `++dist`, the body of
|
||||
which, `,[start=@ud end=@ud]` looks very similar to our previous example
|
||||
in that it accepts two `@ud`. The important difference is that `++dist`
|
||||
is now defined in a way that can be re-used. hoon is a strongly typed
|
||||
language, but it encourages the creation of your own types using what we
|
||||
call tiles.
|
||||
|
||||
At a high level you can think of hoon as being composed of two things,
|
||||
tiles and twigs. Twigs are the actual AST structures that get consumed
|
||||
by the compiler. Tiles reduce to twigs and provide major affordances for
|
||||
the programmer. If you're interested in learning about tiles more deeply
|
||||
you can find an in-depth explanation in the [tile overview]().
|
||||
|
||||
It should suffice, for now, to say that we create tiles in the same way
|
||||
that you would think of creating type definitions in another language.
|
||||
The primary way we do this is with `$` runes you can find more about
|
||||
them in the [`$` section]() of the rune library.
|
||||
|
||||
In this specific example we are using the `$,` tile rune in its
|
||||
irregular form, `,`. `,` generates a validator from the given
|
||||
expression. In effect, `++dist` uses the type system to only produce
|
||||
cells that appear in the form `[start=@ud end=@ud]`. When we use it in
|
||||
our `++length` gate we assert that our input must be validated by
|
||||
`++dist`. To test that out, you can try passing something that isn't an
|
||||
unsigned decimal (or `@ud`) to `++length`. Try replacing `(length 2 20)`
|
||||
with `(length 2 'a')`. As we continue you'll see how this pattern can be
|
||||
quite useful.
|
||||
|
||||
One other thing to point out which may be immediately confusing coming
|
||||
from other languages is the order of addressing `start` and `end`. We
|
||||
call these labels faces, and we address them in the opposite order than
|
||||
you're usually familiar with. We still separate our addressing with `.`,
|
||||
but do it from the inside out. Given a tuple such as
|
||||
`[a=1 b=[c=[d=2 e=3]]]` we can address the value of `e` with `e.c.b`.
|
||||
You can read more about how faces work in the commentary on `++type`
|
||||
[here]().
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
6.
|
||||
--
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/6/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
|%
|
||||
++ fib
|
||||
|= x=@
|
||||
?: (lte x 2)
|
||||
1
|
||||
(add $(x (dec x)) $(x (sub x 2)))
|
||||
--
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: Exercise 6
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: Exercise 6 — Loops
|
||||
;p: {<(fib 1)>}, {<(fib 2)>}, {<(fib 3)>}, {<(fib 4)>}
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/6/
|
||||
|
||||
#### What is that doing?
|
||||
|
||||
We're printing a few members of the [fibonacci sequence]() by
|
||||
calling our arm `++fib` with a few values. The fibonacci sequence is a
|
||||
fairly straight forward algorithm: `F(n-1) + F(n-2)` where `F(1) = 1`
|
||||
and `F(2) = 1`. As is obvious from the formula, generating the fibonacci
|
||||
value at any number requires us to recurse, or loop. Let's walk through
|
||||
the code.
|
||||
|
||||
Our example here should look similar to the previous one. We build a
|
||||
core with `|%` and add the arm `++fib`. `++fib` is a gate which takes
|
||||
one argument `x`, an atom. Using [`?:`]() we test if `x` is less
|
||||
than `2` with the library function [`lte`]() to handle our seed
|
||||
values of `F(1) = 1` and `F(2) = 1`. `?:` is a member of the [`?`
|
||||
runes](), related to true / false values, or loobeans. In hoon true
|
||||
and false are `0` and `1` respectively and take the odor `@f`. We tend
|
||||
to say 'yes' and 'no' instead of 'true' and 'false' to keep track of the
|
||||
switch. Our built-in function `lte` produces a loobean, so we evaluate
|
||||
our first line if true, and second if false.
|
||||
|
||||
If `x` is not less than `2` we compute `F(n-1) + F(n-2)` by using `$`.
|
||||
We mentioned previously that a gate is a special kind of core with only
|
||||
one arm, called `$`. Here we're using `$` to mimic the behavior of a
|
||||
loop. You can read the expression `$(x (dec x))` as 'call the gate again
|
||||
with `x` replaced by `(dec x)`. For more on how this works, check out
|
||||
the documentation of [`%=`]() and [`%-`](). With that in mind it
|
||||
should be clear how the last line of `++fib` produces the member of the
|
||||
sequence at a given value `x`.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
7.
|
||||
--
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/7/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
::
|
||||
::
|
||||
:::: /hook/hymn/7/exercise/guide/fab/pub/
|
||||
::
|
||||
/? 314
|
||||
/= gas /$ fuel
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: %ford Example 1
|
||||
==
|
||||
;body
|
||||
;div
|
||||
;h1: %ford Example 1 — Page Variables
|
||||
;div.who: {<(~(get ju aut.ced.gas) 0)>}
|
||||
;div.where: {(spud s.bem.gas)} rev {(scow %ud p.r.bem.gas)}
|
||||
;code
|
||||
;pre: {<gas>}
|
||||
==
|
||||
==
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/7/
|
||||
http://ship-name.urbit.org/gin/del/main/pub/fab/guide/exercise/7/
|
||||
|
||||
Here we're putting our publishing framework, `%ford` to work a little
|
||||
bit. We're printing out some of the parameters our page is passed: who
|
||||
is looking at it, where it is and what revision our desk is on. We have
|
||||
also thrown in all our FCGI parameters in a codeblock for reference.
|
||||
|
||||
To do this we have introduced some new runes, `/?`, `/=` and `/$`. We
|
||||
tend to call runes with a leading `/` "`%ford` runes" since they are
|
||||
used by the `%ford` vane for resource loading and composition. By
|
||||
convention, we indent four spaces after them to make them more obvious.
|
||||
They belong at the top of the file.
|
||||
|
||||
`/?` simply checks for compatibility. In this case the line means 'need
|
||||
urbit 314 or below', or in hoon: `(lte zuse 314)`. `314` is the number
|
||||
in the kelvin versioning system, which you can read about [here]().
|
||||
|
||||
`/=` is similar to the combination of `=+ =^`, or assignment. `/$`
|
||||
calls a parsing function, which we specify as [`++fuel`]() with the
|
||||
[`++beam`]() and [`++path`]() of our current file.
|
||||
`/= gas /$ fuel` is a common way to open your page, since the
|
||||
product of `++fuel` is useful when writing pages to the web. The use of
|
||||
`++fuel` is not enforced — you can also write your own parser.
|
||||
|
||||
Our page is made up of two generated parts: who requested the page, the
|
||||
location of the page and its revision. Both are parsed out of the `gas`
|
||||
variable using some straightforward library functions, [`++ju`](),
|
||||
[`++spud`]() and [`++scow`](). You can follow those links to the
|
||||
library reference to learn more about them. You'll also notice our
|
||||
addressing moving in the opposite direction as you may be used to.
|
||||
`aut.ced.gas` pulls `aut` from inside `ced` from inside `gas`.
|
||||
|
||||
Inside of the `;code` tag we also print (for our own reference) the
|
||||
entire `gas`, so you can take a look at the contents. This can be a
|
||||
helpful trick when debugging. To fully understand what gets put in
|
||||
`gas`, we can take a look at `++fuel` and note that it produces a
|
||||
[`++epic`](), which also contains a [`++cred`](). You can follow
|
||||
those links to learn more about them.
|
||||
|
||||
When we try changing the url from `main` to `gin/del/main` we're
|
||||
using some of the access methods from `%eyre` (the urbit webserver) to
|
||||
pretend to be the urbit `~del`. You can find documentation on those
|
||||
access methods in the `%eyre` commentary, [here]().
|
||||
|
||||
Path and identity are useful, but there are some other parameters worth
|
||||
checking out as well.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
8.
|
||||
--
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/8/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
::
|
||||
::
|
||||
:::: /hook/hymn/8/exercise/guide/fab/pub/
|
||||
::
|
||||
/? 314
|
||||
/= gas /$ fuel
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;title: %ford Example 2
|
||||
==
|
||||
;body
|
||||
;div: Do you have a code?
|
||||
;div: ?code={<(fall (~(get by qix.gas) %code) '')>}
|
||||
==
|
||||
==
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/8/
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/8/?code=yes-i-do
|
||||
|
||||
This is a simple example, showing off another use of
|
||||
`/= gas /$ fuel`. In this case we're just pulling out the value of
|
||||
the `code` query string parameter. You should be able to change that
|
||||
value to any url-safe string and see it appear on the page.
|
||||
|
||||
We're using a few simple library functions to actually pull the value
|
||||
out, [`++fall`]() and [`get:by`](). Query string parameters are
|
||||
stored in `qix.gas` as a `++map`, one of the main container constructs
|
||||
used in hoon. We'll encounter a lot of maps along the way, and you can
|
||||
learn more about them in the [map section]() of the library doc.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
9.
|
||||
--
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/9/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
::
|
||||
::
|
||||
:::: /hook/hymn/exercise/9/guide/fab/pub/
|
||||
::
|
||||
/? 314
|
||||
::
|
||||
// /%%/lib
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;title: %ford Example 3
|
||||
==
|
||||
;body
|
||||
;h1: %ford Example 3
|
||||
;p: {<(fib 1)>}, {<(fib 2)>}, {<(fib 3)>}, {<(fib 4)>}
|
||||
==
|
||||
==
|
||||
|
||||
#### And in
|
||||
|
||||
/pub/fab/guide/exercise/9/lib.hoon
|
||||
|
||||
#### Put
|
||||
|
||||
|%
|
||||
++ fib
|
||||
|= x=@
|
||||
?: (lte x 2)
|
||||
1
|
||||
(add $(x (dec x)) $(x (sub x 2)))
|
||||
--
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/9/
|
||||
|
||||
#### How are they getting combined?
|
||||
|
||||
Clearly this looks a lot like our previous example using `++fib`, only
|
||||
now we're using two separate files. The majority of this code should be
|
||||
familiar to you from example 6, so let's focus on a single line,
|
||||
`// /%%/lib`.
|
||||
|
||||
`//` is a `%ford` rune that loads a resource from a given path. `//` is
|
||||
used as a way to organize project code into separate files, not for
|
||||
loading libraries and structures. We'll show some examples of how urbit
|
||||
handles those things shortly. You can think of `//` as a kind of
|
||||
`include` or `require`. `//` takes a `beam`, an absolute global path in
|
||||
`%clay` — the global urbit filesystem.
|
||||
|
||||
In `%clay` we use `%` to navigate relative paths. `%` is sort of like
|
||||
`.` when moving around the unix file system. Although we put our code in
|
||||
the unix path `/pub/fab/guide/exercise/9/hymn.hook` the file extension
|
||||
is just a hint to the system. `/%/` (the equivalent of a unix `./`)
|
||||
actually resolves to `/pub/fab/guide/exercise/9/hymn`.
|
||||
|
||||
We commonly use two kinds of extensions, `.hoon` for source files and
|
||||
`.hook` for files that generate something else. Since our hymn file is
|
||||
generating html, it's a `.hook`, and our source file is just a `.hoon`.
|
||||
In order to find our file one level up we need two `%%` to get to
|
||||
`/pub/fab/guide/exercise/9/`. Adding `lib` resolve to our neighboring
|
||||
file. You can read more about how `%clay` paths are parsed in the
|
||||
[`%clay` overview](link). It's also pretty easy to try them out using
|
||||
`/=main=`, `/=try`, `/try/a/b/c/d`, etc.
|
||||
and `:ls` in your `%arvo` terminal.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
10.
|
||||
---
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/10/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
::
|
||||
::
|
||||
:::: /hook/hymn/10/exercise/guide/fab/pub/
|
||||
::
|
||||
/? 314
|
||||
/= gas /$ fuel
|
||||
// /%%/lib
|
||||
::
|
||||
=+ ^= arg
|
||||
%+ slav
|
||||
%ud
|
||||
%+ fall
|
||||
%- ~(get by qix.gas) %number
|
||||
'0'
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;title: %ford Example 4
|
||||
==
|
||||
;body
|
||||
;div: {<(fib arg)>}
|
||||
==
|
||||
==
|
||||
|
||||
#### And in
|
||||
|
||||
/pub/fab/guide/exercise/10/lib.hoon
|
||||
|
||||
#### Put
|
||||
|
||||
|%
|
||||
++ fib
|
||||
|= x=@
|
||||
?: (lte x 2)
|
||||
1
|
||||
(add $(x (dec x)) $(x (sub x 2)))
|
||||
--
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/10/
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/10/?number=7
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/10/?number=12
|
||||
|
||||
As you can see by changing the URL, we're now passing our query string
|
||||
parameter to our `++fib` script and printing the output. It's common to
|
||||
pull some data out of the URL and do something with it, but we don't
|
||||
have any type information about our query string parameters and hoon is
|
||||
a strongly typed languge. As you can see, we're calling `++fib` with a
|
||||
parameter `arg`. Let's look closely at how we generate `arg`.
|
||||
|
||||
The first part of our assignment should look familiar from previous
|
||||
example, `=+ ^= arg` puts the face `arg` on the product of our
|
||||
remaining computation. In short, you can read the code that produces
|
||||
`arg` as `(slav %ud (fall (~(get by qix.gas) %number) '0'))`. We use `%`
|
||||
runes to write this in tall form. `%` runes are used for calling gates
|
||||
or evaluating changes. `%+` 'slams' or calls a gate with two arguments,
|
||||
and `%-` 'slams' or calls a gate with one argument. As usual, you can
|
||||
find more about the `%` runes in the [`%` section]() of the rune
|
||||
library.
|
||||
|
||||
To get a value out of our map of query string parameters `qix.gas` we
|
||||
use a method from the [maps library]() that produces a `++unit`.
|
||||
`++unit`s are a common type in hoon used for optional values. A
|
||||
[`++unit`]() is either `~` or `[~ p=value]`. Since we need to
|
||||
specify a value for `(fib arg)` even when someone doesn't enter the
|
||||
query string we use [`++fall`](), which produces either the value of
|
||||
the unit, or the second argument if the `++unit` is null. Since our
|
||||
`qix.gas` has string values in it we specify a string in our second
|
||||
argument, `'0'`. As an aside, `'0'` is different from `"0"` in hoon. You
|
||||
can read about the difference in [`++cord`]() and [`++tape`]().
|
||||
|
||||
Our outermost call, to [`++slav`](), casts our string to a `@ud` —
|
||||
which is the type expected by `++fib`. `++slav` takes the name of an
|
||||
odor and a value, and tries to cast the value to that odor.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
11.
|
||||
---
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/11/hymn.hook
|
||||
|
||||
#### Put
|
||||
|
||||
/= posts /: /%%/lib
|
||||
/; |= a=(list (pair ,@ ,manx))
|
||||
%+ turn
|
||||
a
|
||||
|= [* b=manx]
|
||||
b
|
||||
/@
|
||||
/psal/
|
||||
::
|
||||
^- manx
|
||||
;html
|
||||
;head
|
||||
;meta(charset "utf-8");
|
||||
;title: %ford Example 11
|
||||
==
|
||||
;body
|
||||
;h1: Ford example — Loading Resources by Number
|
||||
;* posts
|
||||
==
|
||||
==
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/11/lib/1.md
|
||||
|
||||
#### Put
|
||||
|
||||
#1
|
||||
|
||||
This is my first post.
|
||||
|
||||
#### In
|
||||
|
||||
/pub/fab/guide/exercise/11/lib/2.md
|
||||
|
||||
#### Put
|
||||
|
||||
#2
|
||||
|
||||
This is my second post.
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/11/
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/11/lib/1/
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/exercise/11/lib/2/
|
||||
|
||||
#### Experiment with it
|
||||
|
||||
Try adding other `.md` files with numeric file names (such as `3.md`) to
|
||||
the `11/lib/` directory to get a feel for what's going on.
|
||||
|
||||
What's happening?
|
||||
|
||||
As you can see, we're loading the markdown files in `11/lib` and putting
|
||||
them in to our page. Let's dive into the code.
|
||||
|
||||
We're using `/=` to assign the `posts` face. `/:` sets the `++beam` for
|
||||
the computation below it. You can think of it sort of like setting an
|
||||
environment variable. Everything below uses our `++beam` `/%%/lib`.
|
||||
|
||||
If we take the next few lines and write them as pseudo code in wide form
|
||||
they might look something like this, `(/; [gate] (/@ /psal/))`. That
|
||||
being the case, let's start at the bottom and move upwards since that's
|
||||
how our data flows. In depth documentation on individual `++horn` runes
|
||||
can be found in the [horn section of the rune library]().
|
||||
|
||||
`/psal/` loads our `psal` mark. Marks are like content types, and we
|
||||
keep them in `/main/mar/`. You can open `/main/mar/psal/door.hook` to
|
||||
see that we specify the ways in which a particular mark can be converted
|
||||
to produced well typed output. The general form of this is [`/mark/`]()
|
||||
where `mark` exists in the `/main/mar/` directory. A `psal` is a partial
|
||||
`hymn`, where `hymn` is the hoon structure for `html`.
|
||||
|
||||
`/@` loads a list of files in numerical order from the previously
|
||||
specified `++beam` using our mark, `psal`. `/@` has a few close
|
||||
relatives. `/&`, for example, reads files by `@da` or absolute date. You
|
||||
can see the rest in the [horn section of the library]().
|
||||
|
||||
`/;` takes the output from `/@` and `/psal/` and passes it to a twig. In
|
||||
this case, a gate. Our `/@` actually produces a [`++list`]() of
|
||||
pairs of `[@ manx]` where the `@` is the filename, and the `manx` is the
|
||||
converted contents. We use [`++turn`](), one of our `++list`
|
||||
operator functions, to iterate through the list and produce only a list
|
||||
of `++manx`. This is the output assigned to `posts`.
|
||||
|
||||
Then, further down, we use [`;*`]() to write the list to the page.
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
12.
|
||||
---
|
||||
|
||||
#### Look in
|
||||
|
||||
/pub/fab/guide/hymn.hook
|
||||
/pub/fab/guide/main.css
|
||||
/pub/fab/guide/main.js
|
||||
|
||||
#### Try it
|
||||
|
||||
http://ship-name.urbit.org/main/pub/fab/guide/
|
||||
|
||||
#### Bring it all together
|
||||
|
||||
It turns out it's pretty easy to pull our examples together into a
|
||||
single blog-like page using what we just covered. We include some css to
|
||||
make things a bit prettier, and this should give you a good jumping off
|
||||
point for experimenting with your own publishing code.
|
||||
|
||||
#### Have fun!
|
@ -1,273 +0,0 @@
|
||||
XX The CLI is under heavy development with, with pieces being folded
|
||||
into the "window manager" `sole` and the new cli `dojo`. Don't expect
|
||||
any of the following to work as described.
|
||||
|
||||
This guide is intended to get you oriented in the Arvo command prompt
|
||||
and give you a tour of some basic utilities. The command prompt comes in
|
||||
two flavors, in a web browser and in a terminal. For the most part
|
||||
they're the same, except that in a browser you can evaluate tall-form
|
||||
Hoon expressions but you can't run readline apps, such as `:talk`.
|
||||
|
||||
Every Arvo command prompt is also a Hoon REPL. The command line is a
|
||||
great place to test out your hoon knowledge. In this guide we're just
|
||||
going to talk about some basic system utilities and get comfortable
|
||||
moving around in `%clay`. If you'd just like to see a list of
|
||||
command-line utilities, you can find the Arvo man pages
|
||||
[here](../arvo/util).
|
||||
|
||||
This rudimentary tour should work well in both places.
|
||||
|
||||
1
|
||||
|
||||
Move around `%clay`
|
||||
|
||||
After finishing the [setup instructions]() you should have an Arvo
|
||||
prompt that looks like this:
|
||||
|
||||
~talsur-todres/try=>
|
||||
|
||||
The path at the beginning of your prompt is actually a path in the
|
||||
global filesystem of Urbit, called `%clay`. Since `%clay` is universal
|
||||
across all of Urbit, each full path starts with a ship name. `%clay` is
|
||||
also versioned on a per-desk basis. Desks are the top-level directories
|
||||
in your pier.
|
||||
|
||||
Moving around `%clay` is simple. There is no equivalent of `cd`.
|
||||
Instead, just type a valid path name at the prompt to move to that
|
||||
directory. Here we'll move to our starting root path in the try desk,
|
||||
`/try=` to the `main` desk:
|
||||
|
||||
~talsur-todres/try=> /=main=
|
||||
=% /~talsur-todres/main/0
|
||||
~talsur-todres/main=>
|
||||
|
||||
We have two shortcuts in `%clay` that are worth noting, `=` and `%`.
|
||||
|
||||
`=` copies in some corresponding part of our current path. In the second
|
||||
line above you can see how the `=` in `/=main=` pull in the
|
||||
`~talsur-todres` and `0` in from our starting directory,
|
||||
`/~talsur-todres/try/0`. It's important to note that our full prompt to
|
||||
start is `/~talsur-todres/try=`, where the trailing `=` indicates the
|
||||
current revision. In the shell, revision `0` never exists — it's used as
|
||||
a pointer to the head.
|
||||
|
||||
`%` is similar to `.` in unix:
|
||||
|
||||
~talsur-todres/main=> %
|
||||
=% /~talsur-todres/main/0
|
||||
~talsur-todres/main=> %%
|
||||
[~.~talsur-todres ~.main ~]
|
||||
~talsur-todres/main=> %%%
|
||||
[~.~talsur-todres ~]
|
||||
~talsur-todres/main=> %%%%
|
||||
~
|
||||
|
||||
When using `%` to move around in `%clay` you need to make sure to use
|
||||
leading and trailing `/` to ensure your path is interpolted correctly:
|
||||
|
||||
~talsur-todres/main=> /%%%/try=
|
||||
=% /~talsur-todres/try/0
|
||||
~talsur-todres/try=>
|
||||
|
||||
2
|
||||
|
||||
Create some revisions
|
||||
|
||||
Let's use `:into`, our simple utility for writing text to a file, to
|
||||
create a new file:
|
||||
|
||||
~talsur-todres/try=> :into %/helo/txt 'helo mars'
|
||||
written
|
||||
~talsur-todres/try=>
|
||||
|
||||
To confirm that our file was written, we can use `:ls`. `:ls` prints a
|
||||
list of directory contents, but requires that you specify a path. `%`
|
||||
will suffice for the current path:
|
||||
|
||||
~talsur-todres/try=> :ls %
|
||||
readme helo
|
||||
~talsur-todres/try=>
|
||||
|
||||
Let's quickly switch back to a unix command prompt to see a few things
|
||||
about both how files are synced between `%clay` and unix, and where your
|
||||
apps live.
|
||||
|
||||
my-pier/talsur-todres/$ ls try
|
||||
helo.txt readme.md
|
||||
my-pier/talsur-todres/$ cat try/helo.txt
|
||||
helo mars
|
||||
|
||||
Here you can see that our files are synced back to unix as they are
|
||||
changed in urbit, and vice-versa. As you change files in unix you'll see
|
||||
those changes appear in `%clay`.
|
||||
|
||||
my-pier/talsur-todres/$ ls base/app/
|
||||
bang grep peek solid tweet
|
||||
began helm poke sync twit
|
||||
begin hi pope talk twitter-auth
|
||||
cat into reboot tease twitter-feed
|
||||
code label reload terminal type
|
||||
cp ls reset test unsync
|
||||
curl matrix rm ticket verb
|
||||
dojo mv shell time wipe
|
||||
gnab nop sole tree ye
|
||||
my-pier/talsur-todres/$ cat base/app/ls/core.hook
|
||||
:: ConCATenate file listings
|
||||
::
|
||||
:::: /hook/core/cat/app
|
||||
::
|
||||
/+ sh-utils
|
||||
// /%%%/ls/subdir
|
||||
!:
|
||||
::::
|
||||
::
|
||||
|_ [hid=hide ~]
|
||||
++ peer ,_`.
|
||||
++ poke--args
|
||||
%+ args-into-gate .
|
||||
|= [arg=(list path)]
|
||||
=- tang/(zing -)
|
||||
%+ turn arg
|
||||
|= pax=path
|
||||
^- tang
|
||||
=+ ark=;;(arch .^(%cy pax))
|
||||
?^ q.ark
|
||||
:- leaf/(spud pax)
|
||||
%+ turn (lore ;;(@t .^(%cx pax)))
|
||||
|=(a=cord leaf/(trip a))
|
||||
?- r.ark :: handle ambiguity
|
||||
~
|
||||
[rose/[" " `~]^~[leaf/"~" (smyt pax)]]~
|
||||
[[@t ~] ~ ~]
|
||||
$(pax (welp pax /[p.n.r.ark]))
|
||||
*
|
||||
=- [palm/[": " ``~]^-]~
|
||||
:~ rose/[" " `~]^~[leaf/"*" (smyt pax)]
|
||||
`tank`(subdir pax r.ark)
|
||||
==
|
||||
==
|
||||
--
|
||||
|
||||
Here you can see that `/base/app` is the main location where our apps
|
||||
are stored, and the contents of the `:ls` app. urbit applications are of
|
||||
course written in hoon, our naitive programming language. Don't worry
|
||||
about the contents of the file for now. Since changes in unix are synced
|
||||
back in to urbit, we can develop urbit programs by simply editing them
|
||||
in our favorite editor and saving them.
|
||||
|
||||
For the time being let's switch back to urbit and update our file with
|
||||
some new content, so we can see how `%clay` stores revisions.
|
||||
|
||||
~talsur-todres/try=> :into %/helo/txt 'gbye mars'
|
||||
written
|
||||
~talsur-todres/try=> :ls /=try/1
|
||||
readme helo
|
||||
~talsur-todres/try=> :cat /=try/1/helo/txt
|
||||
/~talsur-todres/try/9/helo/txt
|
||||
helo mars
|
||||
~talsur-todres/try=> :cat /=try/2/helo/txt
|
||||
/~talsur-todres/try/10/helo/txt
|
||||
gbye mars
|
||||
~talsur-todres/try=> :cat /=try=/helo/txt
|
||||
/~talsur-todres/try/~2014.11.26..01.06.33..c93a/helo/txt
|
||||
gbye mars
|
||||
~talsur-todres/try=>
|
||||
|
||||
Here we use `:ls` to investigate the filesystem across versions. You can
|
||||
see that our `helo` file exists in our first revision. Using the simple
|
||||
`:cat` command we can print the contents of `/=try/helo/txt` in its two
|
||||
separate, versioned states.
|
||||
|
||||
We can even move to a different version of our desk and look around:
|
||||
|
||||
~talsur-todres/try=> /=try/1
|
||||
=% /~talsur-todres/try/1
|
||||
~talsur-todres/try/1> :ls %
|
||||
readme helo
|
||||
~talsur-todres/try/1>
|
||||
|
||||
This is sort of like being in a detached HEAD in git.
|
||||
|
||||
3
|
||||
|
||||
Start a yacht
|
||||
|
||||
Each Urbit destroyer can delegate around four billion yachts. Yachts are
|
||||
also urbit ships, but are pegged to their parent identity, and are set
|
||||
up to mirror their filesystem. We can generate a `[ship: ticket]` pair
|
||||
for a yacht by using the `:ticket` utility:
|
||||
|
||||
~talsur-todres/try=> :ticket ~talsur-todres-talsur-todres
|
||||
~talsur-todres-talsur-todres: ~figpem-fapmyl-wacsud-racwyd
|
||||
|
||||
Every yacht for a particular destroyer ends in the same `ship-name`, and
|
||||
has every possible destroyer prefix. For example,
|
||||
`~tasfyn-partyv-talsur-todres` is also a valid yacht from
|
||||
`~talsur-todres`.
|
||||
|
||||
Start up a new `vere` process with something like `bin/vere -c yacht`.
|
||||
Then run `:begin` and enter the `[ship: ticket]` pair you just generated
|
||||
when prompted. When the process is complete you should get a
|
||||
`; ~talsur-todres-talsur-todres :y1: is your neighbor` message on your
|
||||
destroyer. To confirm that everything is working properly, you can use
|
||||
`:hi` to send a message:
|
||||
|
||||
~talsur-todres/try=> :hi ~talsur-todres-talsur-todres "whats up"
|
||||
hi ~talsur-todres-talsur-todres successful
|
||||
~talsur-todres/try=>
|
||||
|
||||
Which will appear on your new yacht:
|
||||
|
||||
< ~talsur-todres: whats up
|
||||
~talsur-todres-talsur-todres/try=>
|
||||
|
||||
You should also see the contents of your `/try` desk mirrored on your
|
||||
yacht:
|
||||
|
||||
~talsur-todres-talsur-todres/try=> :ls %
|
||||
readme helo
|
||||
~talsur-todres-talsur-todres/try=>
|
||||
|
||||
Making another change on your destroyer should automatically propagate
|
||||
down to your yacht:
|
||||
|
||||
~talsur-todres/try=> :into %/helo/txt 'back to mars'
|
||||
written
|
||||
~talsur-todres/try=>
|
||||
|
||||
[%merge-fine ~talsur-todres %try]
|
||||
~talsur-todres-talsur-todres/try=> :cat %/helo/txt
|
||||
back to mars
|
||||
~talsur-todres-talsur-todres/try=>
|
||||
|
||||
4
|
||||
|
||||
Move files around
|
||||
|
||||
Another familiar command line utility is `:mv`:
|
||||
|
||||
~talsur-todres/try=> :mv %/helo/txt %/test/helo/txt
|
||||
moved
|
||||
~talsur-todres/try=>
|
||||
|
||||
[%merge-fine ~talsur-todres %try]
|
||||
~talsur-todres-talsur-todres/try=> :cat %/test/helo/txt
|
||||
back to mars
|
||||
~talsur-todres-talsur-todres/try=>
|
||||
|
||||
In `%clay` we don't use file extensions or folders. A path either does
|
||||
or does not have anything in it. There's no need to do the equivalent of
|
||||
`mkdir` before moving something.
|
||||
|
||||
We also implement the familiar `:rm`:
|
||||
|
||||
~talsur-todres/try=> :rm %/test/helo/txt
|
||||
removed
|
||||
~talsur-todres/try=> :cat %/test/helo/txt
|
||||
file /~talsur-todres/try/~2014.11.26..16.49.52..3f5e/test/helo/txt not available
|
||||
~talsur-todres/try=>
|
||||
|
||||
[%merge-fine ~talsur-todres %try]
|
||||
~talsur-todres-talsur-todres/try=> :cat %/test/helo/txt
|
||||
file /~tasfyn-partyv-talsur-todres/try/~2014.11.26..16.50.15..556b/test/helo/txt not available
|
||||
~talsur-todres-talsur-todres/try=>
|
@ -1,284 +0,0 @@
|
||||
This guide is focussed on storing application state using the `%gall`
|
||||
vane. To show off how we store and distribute data in Urbit we're going
|
||||
to examine a simple webapp. Some of the material here expects that you
|
||||
have looked over the [`%ford` guide](). If you haven't, it's a good idea
|
||||
to start there. There's also more information in the [`%gall`
|
||||
overview]() and [`%gall` commentary]() but it's not necessary that you
|
||||
read those before going forward.
|
||||
|
||||
One important thing to keep in mind is that `%gall` services aren't
|
||||
'started' or 'stopped' as in a unix system. When your files are copied
|
||||
in they are compiled and begin running immediately and permanently.
|
||||
`%gall` services simply wake up when certain events happen.
|
||||
|
||||
If you need to make updates to the structure of your stored data, you
|
||||
write connector functions or (when developing) just throw your existing
|
||||
data away. We'll see examples of how this works, just keep in mind that
|
||||
when we talk about a `%gall` 'service' it has no concept of 'running'.
|
||||
|
||||
Going forward we'll refer to the directory you cloned the repo in as
|
||||
`/$URB_DIR` and assume that your pier is listening for HTTP connections
|
||||
on port `8080`.
|
||||
|
||||
1.
|
||||
|
||||
Get the code.
|
||||
|
||||
Clone the GitHub repository and move the files into your `/main` desk,
|
||||
under the corresponding paths. You will need four files:
|
||||
|
||||
- /main/app/lead/core.hook
|
||||
- /main/pub/lead/hymn.hook
|
||||
- /main/pub/lead/src/main.css
|
||||
- /main/pub/lead/src/main.js
|
||||
|
||||
When everything is in place, try it:
|
||||
|
||||
http://localhost:8080/main/pub/lead/
|
||||
|
||||
That URL should render a page and be self explanatory. Try adding names
|
||||
to the leaderboard and incrementing their scores. It's also fun to open
|
||||
a few tabs and watch how the state gets updated simultaneously.
|
||||
|
||||
2.
|
||||
|
||||
How is the code structured?
|
||||
|
||||
In our `%ford` guide we generated pages by defining all of their
|
||||
possible states, but we didn't exactly store any data. When building
|
||||
applications on top of Urbit we think of them as existing in two natural
|
||||
parts: page resources and state services. Effectively, we think of any
|
||||
Urbit app talking to the web as a single page app whose resources are
|
||||
generated by `%ford` which talks to a `%gall` service if it needs to
|
||||
persist any state. Let's look more closely at the specifics in this
|
||||
simple app.
|
||||
|
||||
When we load our page, we render the contents of our
|
||||
`/main/pub/lead/hymn.hook`. This file should look familiar as
|
||||
[`++sail`](). Our `hymn.hook` file writes the basic HTML elements to the
|
||||
page, and pulls in our supporting CSS and JavaScript resources.
|
||||
|
||||
Our application-specific resources are stored in `/main/pub/lead/src/`.
|
||||
`/main/pub/lead/src/main.css` simply produces the page layout, while
|
||||
`/main/pub/lead/src/main.js` updates the page and sends data.
|
||||
|
||||
We also use two utility scripts: `/gop/hart.js` and
|
||||
`/main/lib/urb.js`. These are the standard libraries for handling
|
||||
data transfer from a browser to Urbit, and are very frequently used.
|
||||
`hart.js` handles the page heartbeat, making regular AJAX requests so we
|
||||
can keep track of subscribers, and `urb.js` offers a more complete set
|
||||
of helper functions. `urb.js` depends on `hart.js`, so that's why
|
||||
`hart.js` always goes in the `<head>`. For complete documentation, check
|
||||
out the [`urb.js` reference]().
|
||||
|
||||
Our application state is stored and distributed to connected clients by
|
||||
`/main/app/lead/core.hook`. Let's take a closer look at how that works.
|
||||
|
||||
At the top of our `core.hook` we have:
|
||||
|
||||
/? 314 :: need urbit 314
|
||||
|
||||
This should be familiar from the `%ford` guide. Here we're requiring
|
||||
that this code run on an Urbit ship where `(lte zuse 314)` is `yes`. In
|
||||
this `core.hook` we only use one `%ford` rune, but this is where we
|
||||
would also pull in any dependencies we might have or use other [`/`
|
||||
runes]().
|
||||
|
||||
Below our `/?` you can see that our code is divided into two sections: a
|
||||
[`|%`]() where we define our models, and a [`|_`]() where we define the
|
||||
body of our program. We'll look at these more closely one at a time.
|
||||
|
||||
3.
|
||||
|
||||
How is our state stored?
|
||||
|
||||
In `/main/app/lead/core.hook`:
|
||||
|
||||
++ axle
|
||||
$% [%0 p=(map ,@t ,@ud)]
|
||||
==
|
||||
|
||||
is the first arm inside our leading `|%` that's important to notice.
|
||||
`++axle` defines the tile for our state. By convention we store our
|
||||
state as a [`$%`](), or labelled cases. We assume that our state can be
|
||||
versioned, so we want its model to be one of many tagged cases. This
|
||||
makes it possible to migrate our state to a new version of the service.
|
||||
Since this is the first version of our app, we tag our state with `%0`.
|
||||
|
||||
In this simple application we're keeping track of pairs of names to
|
||||
scores, and we define that here as `(map ,@t ,@ud)`. You can think of
|
||||
this kind of like an associative array of strings to numbers, or an
|
||||
object with string keys and numeric values.
|
||||
|
||||
When we use `++axle` to define the type of our state it's kind of like
|
||||
declaring a schema definition. There's no secondary data storage layer.
|
||||
Since `%gall` services run permanently your data persists as normal
|
||||
application state. We use tiles the way we normally would to declare the
|
||||
type of data that we're passing around.
|
||||
|
||||
Looking ahead, you can see that our main `|_` takes a `++axle` as part
|
||||
of its sample. Let's look at how that core actually works, to get a
|
||||
sense of what our application is doing.
|
||||
|
||||
4.
|
||||
|
||||
Where do requests go?
|
||||
|
||||
In `/main/app/lead/core.hook`:
|
||||
|
||||
++ peer
|
||||
|= [ost=bone you=ship pax=path]
|
||||
^- [(list move) _+>]
|
||||
?~ pax
|
||||
[[ost %give %rust %json vat-json]~ +>.$]
|
||||
:_ +>.$
|
||||
:_ ~
|
||||
?+ -.pax
|
||||
=- [ost %give %mean -]
|
||||
`[%not-found [%leaf "you need to specify a path"]~]
|
||||
%data
|
||||
=- [ost %give %rush %json -]
|
||||
(joba %conn %b &)
|
||||
==
|
||||
|
||||
is the most important arm to look at first. `++peer` is one of the
|
||||
predefined arms that `%gall` calls when certain events happen. You can
|
||||
find them all in the [`%gall` overview]().
|
||||
|
||||
We 'get a `++peer`' when we get either a HTTP request, or a subscription
|
||||
request. Each time this happens our main `|_` is populated with a
|
||||
`++hide` and our current `++axle` in its sample and `++peer` gets passed
|
||||
three things: `[ost=bone you=ship pax=path]`. The sample in the `|_`
|
||||
that contains `++peer` is our application state and all of the contained
|
||||
arms have access to that sample as part of their context. To change the
|
||||
state we simply produce a new context with changed values.
|
||||
|
||||
Let's look at each of these parts of our context and the sample in
|
||||
`++peer`.
|
||||
|
||||
`++hide`, labelled `hid` in peer's context, gives us some information
|
||||
about the `++request` being passed in. You can look at the specifics in
|
||||
the [`%arvo` `++models`](), but for our purposes we can think of it
|
||||
simply as request metadata.
|
||||
|
||||
`++axle`, labelled as `vat` in peer's context, should be familiar from
|
||||
the discussion in the previous step.
|
||||
|
||||
`ost` is a `++bone`, or an identifier for an `%arvo` duct. 'Duct' is
|
||||
actually a pretty good word for what a ++duct does. Informally, when an
|
||||
event is processed in `%arvo` we patch together our requisite
|
||||
computations with `++ducts`. For example, when we get a network packet,
|
||||
parse it, pass it to the webserver, and then pass it to the application
|
||||
framework we use a `++duct` to make all those connections. In `++peer`
|
||||
our ost just identifies the incoming request by number. We don't have
|
||||
access to the connecting `++duct`, but we use `ost` in the effects we
|
||||
produce so our responses are correctly coupled to the incoming request.
|
||||
|
||||
`you` is a `++ship`, which is just a [`@p`]() or a phonemic string like
|
||||
`~tasfyn- partyv`. `%eyre` does some work to figure out who this is, or
|
||||
uses a submarine name if it can't be determined. You can read more about
|
||||
how we parse identities in `%eyre` in the [`%eyre` reference]().
|
||||
|
||||
`pax` is a `++path`, or a list of `@ta`. In Hoon we most often write
|
||||
paths as you would expect, `/something/like/this`. In `%gall` services
|
||||
requests come in on a specific path, like `/data` or `/`.
|
||||
|
||||
`++peer`, as with any arm that handles events, must produce a pair of a
|
||||
`(list ++move)` and our context, with any intended changes. In this peer
|
||||
we handle two cases, when `pax` is empty, or `~`, when our `pax` is
|
||||
`/data`. We throw an error if `pax` is anything else.
|
||||
|
||||
5.
|
||||
|
||||
What exactly is a list of moves?
|
||||
|
||||
Try pointing your browser at:
|
||||
|
||||
http://localhost:8082/lead/
|
||||
|
||||
to see our response when `pax` in `++peer` is `~`. In our case we use
|
||||
this URL to load the initial state of the application as JSON. This is
|
||||
produced by the line `[[ost %give %rust %json vat-json]~ +>.$]` which
|
||||
produces a single `++move`, and our local context. Let's look more
|
||||
closely at our `++move`.
|
||||
|
||||
++ move ,[p=bone q=[%give gift]] :: output operation
|
||||
|
||||
From our prior discussion we're familiar with a `++bone`, and `++gift`
|
||||
is defined right above in `core.hook`:
|
||||
|
||||
++ gift :: output action
|
||||
$% [%rust gilt] :: total update
|
||||
[%rush gilt] :: partial update
|
||||
[%mean (unit (pair term (list tank)))] :: Error, maybe w/ msg
|
||||
[%nice ~] :: Response message
|
||||
==
|
||||
::
|
||||
|
||||
Which clearly depends on `++gilt`:
|
||||
|
||||
++ gilt :: subscription frame
|
||||
$% [%hymn p=manx] :: html tree
|
||||
[%json p=json] :: json
|
||||
==
|
||||
::
|
||||
|
||||
`++gift` defines the possible actions we can take in the moves that we
|
||||
produce. We can send either partial or total updates with `%rush` or
|
||||
`%rust` respectively. We can also send either an error, `%mean` or
|
||||
default acknowledgement, `%nice`.
|
||||
|
||||
Returning to our original `++move`, `[ost %give %rust %json vat-json]`
|
||||
we can now read it as 'send a total update with `++vat-json` as
|
||||
`++json`'. `++vat-json` simply takes our `(map @t @ud)` and turns it in
|
||||
to JSON.
|
||||
|
||||
Looking at the remainer of `++peer` we can see that it is mostly
|
||||
control-flow that produces a `%mean` if our `pax` is not matched, and a
|
||||
`%rush` if our `pax` is `%data`. We'll revisit this `%data` path later
|
||||
on.
|
||||
|
||||
5.
|
||||
|
||||
How do we change our state?
|
||||
|
||||
All of our state changes happen in `++poke-json`. Incoming messages are
|
||||
handled by `++poke` arms in `%gall` services. If an incoming message has
|
||||
a `%logo` it is appeneded after a `-`. Messages from the web are often
|
||||
sent as JSON, so `++poke- json` is common for services that face the
|
||||
web.
|
||||
|
||||
Let's walk through this part:
|
||||
|
||||
=. p.vat
|
||||
(~(put by p.vat) newl)
|
||||
:_ +>.$
|
||||
:* [ost %give %nice ~]
|
||||
(deliver %upd-lead (joba -.newl [%n (scot %ud +.newl)]))
|
||||
==
|
||||
|
||||
Using [`=.`]() we update the value of `p.vat` in our context using
|
||||
[`put:by`](), one of our map container functions. Then, we produce
|
||||
`+>.$` as our context. Since we have changed the value of `p.vat` within
|
||||
our immediate context, `$`, this is equivalient to updating the state of
|
||||
our service. Changing a value in your context and producing it is all
|
||||
you need to do to update your permanent state. That's one of the main
|
||||
goals of `%gall`, to be a single-level store.
|
||||
|
||||
So, how did we get to this point in `++poke-json`?
|
||||
|
||||
=+ ^= jop
|
||||
^- kiss
|
||||
%- need %. jon
|
||||
=> jo %- of
|
||||
:~ [%new-lead so]
|
||||
[%add-lead so]
|
||||
==
|
||||
|
||||
6.
|
||||
|
||||
`++deliver`
|
||||
|
||||
7.
|
||||
|
||||
main.js
|
@ -1 +0,0 @@
|
||||
A fully featured app using %ford and %gall
|
@ -1,100 +0,0 @@
|
||||
Doing development can be a messy process. Since Urbit ships are meant to
|
||||
last forever it can be convenient to development on a disposable ship as
|
||||
to not permanently destroy any of your own part of the urbit network. In
|
||||
this short guide we're going to go over how to set up a fake network for
|
||||
development on a single physical machine.
|
||||
|
||||
This guide assumes that you have already followed the [setup
|
||||
instructions](). Going forward we'll refer to the directory you cloned
|
||||
the repo in as `/$URB_DIR`.
|
||||
|
||||
1.
|
||||
|
||||
Start a fake `vere` for the carrier `~zod`.
|
||||
|
||||
In `/$URB_DIR`, run
|
||||
|
||||
$ bin/vere -F -I ~zod -c zod
|
||||
|
||||
This will boot `vere` into the carrier `~zod`. Because we're using the
|
||||
flag `-F` `vere` doesn't check any of the keys to confirm that we are in
|
||||
fact the owner of `~zod`. We use `-I` here to signal to `vere` that we
|
||||
want to start an 'imperial' ship, or carrier. `-I` takes a ship name.
|
||||
You can enter any one of the 256 Urbit carriers. More information on
|
||||
`vere` and its command line options can be found [here]().
|
||||
|
||||
You should see `vere` start as usual, although instead of copying its
|
||||
files from a parent ship the files are copied from `urb/zod` inside your
|
||||
Urbit directory.
|
||||
|
||||
For most development tasks, using a fake carrier works really well. You
|
||||
get a very short name, and a safe testing environment. If you need to
|
||||
test out a collection of ships talking to each other, let's keep going.
|
||||
|
||||
2.
|
||||
|
||||
Start a second fake `vere`.
|
||||
|
||||
In a new terminal, cd to `/$URB_DIR` and run:
|
||||
|
||||
$ bin/vere -F -c doznec
|
||||
|
||||
Since we don't specify a carrier with `-I` here, this should boot into a
|
||||
submarine, as if you had started vere normally. In your running fake
|
||||
`~zod` you should see a [`~&`]() alerting you that the sub you just
|
||||
started is your neighbor. This means that a key exchange has happened,
|
||||
and your packets are being transmitted directly. Now, let's get a ticket
|
||||
for a cruiser.
|
||||
|
||||
In your fake `~zod`, ticket a cruiser:
|
||||
|
||||
~zod/try=> :ticket ~doznec
|
||||
|
||||
This line should return a `[ship: ticket]` pair of [`@p`](). You can Now
|
||||
you can return to your submarine and run:
|
||||
|
||||
~sipmyl-wolmeb-haswel-losmyl--dibten-holdyn-dacdyn-natsep/try=> :begin
|
||||
|
||||
Use the `[ship: ticket]` pair you got from your fake `~zod` to complete
|
||||
the `:begin` process for `~doznec`. When finished you should see
|
||||
something like `; ~doznec _doz_ is your neighbor` on your fake `~zod`.
|
||||
|
||||
You can repeat this process on `~doznec`, ticketing destroyers that are
|
||||
children of `~doznec` by running `:ticket` with a valid destroyer.
|
||||
`:ticket` actually takes two arguments, a ship name and a number
|
||||
indicating how many tickets to generate. `~tasfyn-partyv` is the first
|
||||
destroyer under `~doznec`, so you can run `:ticket ~tasfyn-partyv 5` to
|
||||
get five `[ship: ticket]` pairs.
|
||||
|
||||
3.
|
||||
|
||||
Add some files, make sure the network if functioning.
|
||||
|
||||
You should now have a directory `/$URB_DIR/zod`.
|
||||
|
||||
In
|
||||
|
||||
/$URB_DIR/zod/zod/try/test.txt
|
||||
|
||||
Put
|
||||
|
||||
hello from mars
|
||||
|
||||
You should see a sync event on `~zod` indicated by a `+` with the file
|
||||
path, and at least one `%merge-fine` messages on `~doznec`. On your
|
||||
filesystem, you should see the file mirrored in
|
||||
`/$URB_DIR/doznec/doznec/try/test.txt`.
|
||||
|
||||
You can also send a few `:hi` messages over the network. On `~doznec`
|
||||
try:
|
||||
|
||||
~doznec/try=> :hi ~zod "just checking in from urth"
|
||||
|
||||
You should see the message appear on your `~zod` and get a
|
||||
`hi ~zod successful` on your `~doznec`.
|
||||
|
||||
This is a good way to set up a test environment where you can try
|
||||
anything out and break anything you want. When working in these test
|
||||
environments it is usually safest to keep your working files outside of
|
||||
your pier and copy them in. This way you can quickly
|
||||
`rm -rf zod/ && bin/vere -F -I ~zod -c zod` to start again.
|
@ -139,7 +139,7 @@ Produces a [tape]() of the date in UTC format.
|
||||
|
||||
`yed` is a [`date`]().
|
||||
|
||||
~zod/try=> (dust (yore -<-))
|
||||
~zod/try=> (dust (yore ->-))
|
||||
"Tue, 21 Oct 2014 21:35:12 +0000"
|
||||
~zod/try=> (dust [[a=%.y y=2.002] m=10 t=[d=11 h=12 m=20 s=55 f=~]])
|
||||
"Fri, 11 Oct 2002 12:20:55 +0000"
|
||||
@ -282,17 +282,18 @@ beginning with Sunday.
|
||||
Leap second dates
|
||||
|
||||
++ les ^- (list ,@da)
|
||||
:~ ~2012.7.1 ~2009.1.1 ~2006.1.1 ~1999.1.1 ~1997.7.1 ~1996.1.1
|
||||
~1994.7.1 ~1993.7.1 ~1992.7.1 ~1991.1.1 ~1990.1.1 ~1988.1.1
|
||||
~1985.7.1 ~1983.7.1 ~1982.7.1 ~1981.7.1 ~1980.1.1 ~1979.1.1
|
||||
~1978.1.1 ~1977.1.1 ~1976.1.1 ~1975.1.1 ~1974.1.1 ~1973.1.1
|
||||
~1972.7.1
|
||||
:~ ~2015.7.1 ~2012.7.1 ~2009.1.1 ~2006.1.1 ~1999.1.1 ~1997.7.1
|
||||
~1996.1.1 ~1994.7.1 ~1993.7.1 ~1992.7.1 ~1991.1.1 ~1990.1.1
|
||||
~1988.1.1 ~1985.7.1 ~1983.7.1 ~1982.7.1 ~1981.7.1 ~1980.1.1
|
||||
~1979.1.1 ~1978.1.1 ~1977.1.1 ~1976.1.1 ~1975.1.1 ~1974.1.1
|
||||
~1973.1.1 ~1972.7.1
|
||||
==
|
||||
|
||||
Produces a list of the (absolute) dates ([`@da`]) of the 25 leap seconds
|
||||
|
||||
~zod/try=/hom> les:yu
|
||||
~[
|
||||
~2015.7.1
|
||||
~2012.7.1
|
||||
~2009.1.1
|
||||
~2006.1.1
|
||||
@ -329,19 +330,19 @@ Produces a list of the (absolute) dates ([`@da`]) of the 25 leap seconds
|
||||
Back-shifted leap second dates
|
||||
|
||||
++ lef ^- (list ,@da)
|
||||
:~ ~2012.6.30..23.59.59 ~2008.12.31..23.59.58
|
||||
~2005.12.31..23.59.57 ~1998.12.31..23.59.56
|
||||
~1997.6.30..23.59.55 ~1995.12.31..23.59.54
|
||||
~1994.6.30..23.59.53 ~1993.6.30..23.59.52
|
||||
~1992.6.30..23.59.51 ~1990.12.31..23.59.50
|
||||
~1989.12.31..23.59.49 ~1987.12.31..23.59.48
|
||||
~1985.6.30..23.59.47 ~1983.6.30..23.59.46
|
||||
~1982.6.30..23.59.45 ~1981.6.30..23.59.44
|
||||
~1979.12.31..23.59.43 ~1978.12.31..23.59.42
|
||||
~1977.12.31..23.59.41 ~1976.12.31..23.59.40
|
||||
~1975.12.31..23.59.39 ~1974.12.31..23.59.38
|
||||
~1973.12.31..23.59.37 ~1972.12.31..23.59.36
|
||||
~1972.6.30..23.59.35
|
||||
:~ ~2015.6.30..23.59.59 ~2012.6.30..23.59.59
|
||||
~2008.12.31..23.59.58 ~2005.12.31..23.59.57
|
||||
~1998.12.31..23.59.56 ~1997.6.30..23.59.55
|
||||
~1995.12.31..23.59.54 ~1994.6.30..23.59.53
|
||||
~1993.6.30..23.59.52 ~1992.6.30..23.59.51
|
||||
~1990.12.31..23.59.50 ~1989.12.31..23.59.49
|
||||
~1987.12.31..23.59.48 ~1985.6.30..23.59.47
|
||||
~1983.6.30..23.59.46 ~1982.6.30..23.59.45
|
||||
~1981.6.30..23.59.44 ~1979.12.31..23.59.43
|
||||
~1978.12.31..23.59.42 ~1977.12.31..23.59.41
|
||||
~1976.12.31..23.59.40 ~1975.12.31..23.59.39
|
||||
~1974.12.31..23.59.38 ~1973.12.31..23.59.37
|
||||
~1972.12.31..23.59.36 ~1972.6.30..23.59.35
|
||||
==
|
||||
::
|
||||
|
||||
@ -350,6 +351,7 @@ Galactc Time equivalents of the UTC leap second dates in [`++les`](/doc/hoon/lib
|
||||
|
||||
~zod/try=/hom> lef:yu
|
||||
~[
|
||||
~2015.6.30..23.59.59
|
||||
~2012.6.30..23.59.59
|
||||
~2008.12.31..23.59.58
|
||||
~2005.12.31..23.59.57
|
||||
|
@ -464,3 +464,16 @@ Compute direct senior.
|
||||
~del
|
||||
~zod/main=> (sein ~ractul-fodsug-sibryg-modsyl--difrun-mirfun-filrec-patmet)
|
||||
~zod
|
||||
|
||||
Compute Phonemic base.
|
||||
|
||||
~zod/main=> (saxo ~rabdec-monfer)
|
||||
~[~rabdec-monfer ~dalnel ~del]
|
||||
~zod/main=> `@rd`~rabdec-monfer
|
||||
0x5fd25
|
||||
[%rlyd 0x5.fd25]
|
||||
0b1.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000
|
||||
~zod/main=> `@p`0x5.fd25
|
||||
~rabdec-monfer
|
||||
|
||||
For `@rd` and `@p` see the [odors](../reference/odors) reference
|
||||
|
@ -1,84 +1,84 @@
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
@ -1,84 +1,84 @@
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-black.woff");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -4,42 +4,42 @@
|
||||
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau.woff")
|
||||
font-weight 400
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-italic.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-italic.woff")
|
||||
font-weight 400
|
||||
font-style italic
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-medium.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-medium.woff")
|
||||
font-weight 500
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff")
|
||||
font-weight 500
|
||||
font-style italic
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-bold.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-bold.woff")
|
||||
font-weight 600
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-bolditalic.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff")
|
||||
font-weight 600
|
||||
font-style italic
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-super.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-super.woff")
|
||||
font-weight 600
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "bau"
|
||||
src url("https://storage.googleapis.com/urbit-extra/bau-superitalic.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff")
|
||||
font-weight 600
|
||||
font-style italic
|
||||
|
||||
@ -49,21 +49,21 @@
|
||||
|
||||
@font-face
|
||||
font-family "scp"
|
||||
src url("https://storage.googleapis.com/urbit-extra/scp-extralight.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/scp-extralight.woff")
|
||||
font-weight 200
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "scp"
|
||||
src url("https://storage.googleapis.com/urbit-extra/scp-light.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/scp-light.woff")
|
||||
font-weight 300
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "scp"
|
||||
src url("https://storage.googleapis.com/urbit-extra/scp-regular.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/scp-regular.woff")
|
||||
font-weight 400
|
||||
font-style normal
|
||||
@font-face
|
||||
font-family "scp"
|
||||
src url("https://storage.googleapis.com/urbit-extra/scp-medium.woff")
|
||||
src url("//storage.googleapis.com/urbit-extra/scp-medium.woff")
|
||||
font-weight 500
|
||||
font-style normal
|
@ -1,72 +1,72 @@
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-italic.woff");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-mediumitalic.woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bold.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-bolditalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-super.woff");
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "bau";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/bau-superitalic.woff");
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-extralight.woff");
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-light.woff");
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-regular.woff");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "scp";
|
||||
src: url("https://storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
src: url("//storage.googleapis.com/urbit-extra/scp-medium.woff");
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user