mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-17 11:51:32 +03:00
Merge branch 'cabdone' into cabmold
Conflicts: urb/urbit.pill urb/zod/arvo/hoon.hoon
This commit is contained in:
commit
7f0e092da6
@ -83,7 +83,7 @@
|
||||
[[& y] m d h.t m.t s.t (div (mul ms.t 0x1.0000) 1.000) ~]
|
||||
++ parse-day (parsf ;"{dem}\-{dem}\-{dem}")
|
||||
++ parse-seconds (parsf ;"{dem}:{dem}:{dem}{(optional ;~(pfix dot dem))}")
|
||||
++ optional |*(fel=_rule ;~(pose fel (easy 0)))
|
||||
++ optional |*(fel=rule ;~(pose fel (easy 0)))
|
||||
++ parse-zone
|
||||
;~ pose
|
||||
(cold [& 0 0] (jest 'Z'))
|
||||
|
@ -114,7 +114,7 @@
|
||||
::
|
||||
++ dp-command-line ;~(sfix dp-command (just '\0a'))
|
||||
++ dp-variable :: %verb or %brev
|
||||
|* [sym=_rule src=_rule]
|
||||
|* [sym=rule src=rule]
|
||||
%- cook :_ ;~(plug sym (punt src))
|
||||
|= [a=term b=(unit dojo-source)] ^- dojo-command
|
||||
?~(b [%brev a] [[%verb a] u.b])
|
||||
@ -183,7 +183,7 @@
|
||||
==
|
||||
::
|
||||
++ dp-twig-punt :: twig of unit
|
||||
|*(a=_rule ;~(pose (stag [%bczp %null] a) (easy [%bczp %null])))
|
||||
|*(a=rule ;~(pose (stag [%bczp %null] a) (easy [%bczp %null])))
|
||||
::
|
||||
++ dp-case-twig
|
||||
|= a=coin ^- (unit twig)
|
||||
|
@ -716,7 +716,7 @@
|
||||
==
|
||||
::
|
||||
++ rail
|
||||
|* [wid=_rule tal=_rule]
|
||||
|* [wid=rule tal=rule]
|
||||
?. tol wid
|
||||
;~(pose wid tal)
|
||||
::
|
||||
|
@ -136,7 +136,7 @@
|
||||
,[p=a q=b r=c s=d] ::
|
||||
:: XX move to zuse
|
||||
++ ring ,@ :: private key
|
||||
++ rule |=(tub=nail `edge`[p.tub ~ ~ tub]) :: parsing rule
|
||||
++ rule $+(nail edge)
|
||||
++ span ,@ta :: text-atom (ASCII)
|
||||
++ spot ,[p=path q=pint] :: range in file
|
||||
++ tang (list tank) :: bottom-first error
|
||||
@ -4337,6 +4337,10 @@
|
||||
++ stab :: parse cord to path
|
||||
=+ fel=;~(pfix fas (more fas urs:ab))
|
||||
|=(zep=@t `path`(rash zep fel))
|
||||
|
||||
|
||||
|
||||
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
:: section 2eM, regular-expressions ::
|
||||
::
|
||||
@ -4531,7 +4535,7 @@
|
||||
::
|
||||
++ mink
|
||||
~/ %mink
|
||||
|= [[sub=* fol=*] sky=$+(* (unit))]
|
||||
|= [[sub=* fol=*] sky=_+(* (unit))]
|
||||
=+ tax=*(list ,[@ta *])
|
||||
|- ^- tone
|
||||
?@ fol
|
||||
@ -4605,7 +4609,7 @@
|
||||
==
|
||||
::
|
||||
++ mock
|
||||
|= [[sub=* fol=*] sky=$+(* (unit))]
|
||||
|= [[sub=* fol=*] sky=_+(* (unit))]
|
||||
(mook (mink [sub fol] sky))
|
||||
::
|
||||
++ mook
|
||||
@ -4656,20 +4660,20 @@
|
||||
==
|
||||
::
|
||||
++ mang
|
||||
|= [[gat=* sam=*] sky=$+(* (unit))]
|
||||
|= [[gat=* sam=*] sky=_+(* (unit))]
|
||||
^- (unit)
|
||||
=+ ton=(mong [[gat sam] sky])
|
||||
?.(?=([0 *] ton) ~ [~ p.ton])
|
||||
::
|
||||
++ mong
|
||||
|= [[gat=* sam=*] sky=$+(* (unit))]
|
||||
|= [[gat=* sam=*] sky=_+(* (unit))]
|
||||
^- toon
|
||||
?. &(?=(^ gat) ?=(^ +.gat))
|
||||
[%2 ~]
|
||||
(mock [[-.gat [sam +>.gat]] -.gat] sky)
|
||||
::
|
||||
++ mung
|
||||
|= [[gat=* sam=*] sky=$+(* (unit))]
|
||||
|= [[gat=* sam=*] sky=_+(* (unit))]
|
||||
^- tone
|
||||
?. &(?=(^ gat) ?=(^ +.gat))
|
||||
[%2 ~]
|
||||
@ -6145,7 +6149,7 @@
|
||||
(weld ~(ram re (show d -.gar)) $(i (add 2 i), gar +.gar))
|
||||
::
|
||||
++ shop
|
||||
|= [aug=* vel=$+(a=@ tape)]
|
||||
|= [aug=* vel=_+(a=@ tape)]
|
||||
^- tank
|
||||
?: ?=(@ aug)
|
||||
[%leaf (vel aug)]
|
||||
@ -6182,7 +6186,7 @@
|
||||
++ rub `tape`['0' 'b' (rum 2 ~ |=(b=@ (add '0' b)))]
|
||||
++ rud (rum 10 ~ |=(b=@ (add '0' b)))
|
||||
++ rum
|
||||
|= [b=@ c=tape d=$+(@ @)]
|
||||
|= [b=@ c=tape d=_+(@ @)]
|
||||
^- tape
|
||||
?: =(0 a)
|
||||
[(d 0) c]
|
||||
@ -6245,7 +6249,7 @@
|
||||
^- type
|
||||
?:(|(=(%void der) =(%void s.bid)) %void [%bull bid der])
|
||||
::
|
||||
++ cain |=(vax=vase (sell vax)) :: $+(vase tank) for #>
|
||||
++ cain |=(vax=vase (sell vax)) :: _+(vase tank) for #>
|
||||
++ cell :: make %cell type
|
||||
~/ %cell
|
||||
|= [hed=type tal=type]
|
||||
@ -6493,8 +6497,8 @@
|
||||
|= txt=@
|
||||
q:(~(mint ut %noun) %noun (ream txt))
|
||||
::
|
||||
++ noah |=(vax=vase (pave vax)) :: $+(vase tape) for #<
|
||||
++ onan |=(vix=vise (seer vix)) :: $+(vise vase) for !>
|
||||
++ noah |=(vax=vase (pave vax)) :: _+(vase tape) for #<
|
||||
++ onan |=(vix=vise (seer vix)) :: _+(vise vase) for !>
|
||||
++ rain :: parse with % path
|
||||
|= [bon=path txt=@]
|
||||
^- twig
|
||||
@ -6560,7 +6564,7 @@
|
||||
^- vase
|
||||
[[%cell p.hed p.tal] [q.hed q.tal]]
|
||||
::
|
||||
++ skol :: $+(type tank) for ~!
|
||||
++ skol :: _+(type tank) for ~!
|
||||
|= typ=type ^- tank
|
||||
~(duck ut typ)
|
||||
::
|
||||
@ -6807,7 +6811,7 @@
|
||||
++ whip
|
||||
|= axe=axis
|
||||
=+ ^= tun
|
||||
|= noy=$+(* twig)
|
||||
|= noy=_+(* twig)
|
||||
^- twig
|
||||
?@ nag
|
||||
=+ luz=[%cnts [[~ 1] ~] [[[%& axe] ~] bunt(sec [%axil %cell])] ~]
|
||||
@ -6984,7 +6988,7 @@
|
||||
==
|
||||
::
|
||||
[%cbpm *] [%bush boil(gen p.gen) boil(gen q.gen)]
|
||||
[%cbls *] [%weed [%brts [%herb p.gen] [%bctr %herb q.gen]]]
|
||||
[%cbls *] [%weed [%brls [%herb p.gen] [%bctr %herb q.gen]]]
|
||||
[%cbts *] [%bark p.gen boil(gen q.gen)]
|
||||
[%cbwt *] =+ (turn p.gen |=(a=twig boil(gen a)))
|
||||
?~(- [%axil %void] [%fern -])
|
||||
@ -9650,12 +9654,12 @@
|
||||
?:(tol ;~(pose ;~(pfix gap $:har(tol &)) dur) dur)
|
||||
::
|
||||
++ rung
|
||||
|* [dif=_rule tuq=* har=_exqa]
|
||||
|* [dif=rule tuq=* har=_exqa]
|
||||
;~(pfix dif (stag tuq (toad har)))
|
||||
::
|
||||
++ gunk ~+((glue muck))
|
||||
++ muck ?:(tol gap ace)
|
||||
++ butt |*(zor=_rule ?:(tol ;~(sfix zor ;~(plug gap duz)) zor))
|
||||
++ butt |*(zor=rule ?:(tol ;~(sfix zor ;~(plug gap duz)) zor))
|
||||
++ loaf ?:(tol howl toil)
|
||||
++ lobe ?:(tol tall wide)
|
||||
++ exqa |.(loaf)
|
||||
@ -9887,14 +9891,14 @@
|
||||
?:(tol ;~(pose ;~(pfix gap $:har(tol &)) dur) dur)
|
||||
::
|
||||
++ rune :: build rune
|
||||
|* [dif=_rule tuq=* har=_expa]
|
||||
|* [dif=rule tuq=* har=_expa]
|
||||
;~(pfix dif (stag tuq (toad har)))
|
||||
::
|
||||
++ glop ~+((glue mash)) :: separated by space
|
||||
++ gunk ~+((glue muck)) :: separated list
|
||||
++ butt |* zor=_rule :: closing == if tall
|
||||
++ butt |* zor=rule :: closing == if tall
|
||||
?:(tol ;~(sfix zor ;~(plug gap duz)) zor)
|
||||
++ ulva |* zor=_rule :: closing -- and tall
|
||||
++ ulva |* zor=rule :: closing -- and tall
|
||||
?.(tol fail ;~(sfix zor ;~(plug gap dun)))
|
||||
++ hank (most muck loaf) :: gapped twigs
|
||||
++ loaf ?:(tol tall wide) :: hoon, current width
|
||||
@ -10162,7 +10166,7 @@
|
||||
(stag %leaf (stag %n (cold ~ sig)))
|
||||
==
|
||||
++ wart
|
||||
|* zor=_rule
|
||||
|* zor=rule
|
||||
%+ here
|
||||
|= [a=pint b=twig]
|
||||
?:(bug [%zpcb [wer a] b] b)
|
||||
@ -10346,15 +10350,15 @@
|
||||
== ::
|
||||
++ desk ,@tas :: ship desk case spur
|
||||
++ cage (cask vase) :: global metadata
|
||||
++ cask |*(a=_,* (pair mark a)) :: global data
|
||||
++ cask |*(a+_+(* *) (pair mark a)) :: global data
|
||||
++ cuff :: permissions
|
||||
$: p=(unit (set monk)) :: can be read by
|
||||
q=(set monk) :: caused or created by
|
||||
== ::
|
||||
++ curd ,[p=@tas q=*] :: typeless card
|
||||
++ duct (list wire) :: causal history
|
||||
++ hypo |*(a=$+(* *) (pair type a)) :: type associated
|
||||
++ hobo |* a=$+(* *) :: kiss wrapper
|
||||
++ hypo |*(a=_+(* *) (pair type a)) :: type associated
|
||||
++ hobo |* a=_+(* *) :: kiss wrapper
|
||||
$? $% [%soft p=*] ::
|
||||
== ::
|
||||
a ::
|
||||
@ -10379,7 +10383,7 @@
|
||||
++ milt ,[p=* q=*] :: metavase
|
||||
++ monk (each ship ,[p=@tas q=@ta]) :: general identity
|
||||
++ mold :: new kernel action
|
||||
|* [a=$+(* *) b=$+(* *)] :: forward/reverse
|
||||
|* [a=_+(* *) b=_+(* *)] :: forward/reverse
|
||||
$% [%pass p=path q=a] :: advance
|
||||
[%slip p=a] :: lateral
|
||||
[%sick p=b] :: lame refactoring
|
||||
@ -10392,9 +10396,9 @@
|
||||
++ pone (list ,[p=@tas q=vise]) :: kernel modules, old
|
||||
++ ship ,@p :: network identity
|
||||
++ sink (trel bone ship path) :: subscription
|
||||
++ sled $+ [(unit (set monk)) term beam] :: namespace function
|
||||
++ sled _+ [(unit (set monk)) term beam] :: namespace function
|
||||
(unit (unit cage)) ::
|
||||
++ slad $+ [(unit (set monk)) term beam] :: undertyped
|
||||
++ slad _+ [(unit (set monk)) term beam] :: undertyped
|
||||
(unit (unit (cask))) ::
|
||||
++ slut $+(* (unit (unit))) :: old namespace
|
||||
++ vile :: reflexive constants
|
||||
|
@ -578,12 +578,12 @@
|
||||
++ frac ;~(plug dot digs) :: Fractional part
|
||||
:: whitespace
|
||||
++ spac (star (mask [`@`9 `@`10 `@`13 ' ' ~]))
|
||||
++ ws |*(sef=_rule ;~(pfix spac sef))
|
||||
++ ws |*(sef=rule ;~(pfix spac sef))
|
||||
:: plumbing
|
||||
++ mayb |*(bus=_rule ;~(pose bus (easy "")))
|
||||
++ mayb |*(bus=rule ;~(pose bus (easy "")))
|
||||
++ twel |=([a=tape b=tape] (weld a b))
|
||||
++ piec
|
||||
|* bus=_rule
|
||||
|* bus=rule
|
||||
(cook |=(a=@ [a ~]) bus)
|
||||
--
|
||||
::
|
||||
@ -878,7 +878,7 @@
|
||||
(zm (~(run by p.jon) wit))
|
||||
::
|
||||
++ op :: parse keys of map
|
||||
|* [fel=_rule wit=fist]
|
||||
|* [fel=rule wit=fist]
|
||||
%+ cu mo
|
||||
%- ci :_ (om wit)
|
||||
|= a=(map cord ,_(need *wit))
|
||||
@ -975,11 +975,11 @@
|
||||
==
|
||||
::
|
||||
++ scanf :: formatted scan
|
||||
|* [tape (pole ,_:/(*$&(_rule tape)))]
|
||||
|* [tape (pole ,_:/(*$&(rule tape)))]
|
||||
=> .(+< [a b]=+<)
|
||||
(scan a (parsf b))
|
||||
++ parsf :: make parser from:
|
||||
|^ |* a=(pole ,_:/(*$&(_rule tape))) :: ;"chars{rule}chars"
|
||||
|^ |* a=(pole ,_:/(*$&(rule tape))) :: ;"chars{rule}chars"
|
||||
%- cook :_ (bill (norm a))
|
||||
|* (list)
|
||||
?~ +< ~
|
||||
@ -988,7 +988,7 @@
|
||||
::
|
||||
:: .= (norm [;"{n}, {n}"]:n=dim:ag) ~[[& dim] [| ", "] [& dim]]:ag
|
||||
++ norm
|
||||
|* (pole ,_:/(*$&(_rule tape)))
|
||||
|* (pole ,_:/(*$&(rule tape)))
|
||||
?~ +< ~
|
||||
=> .(+< [i=+<- t=+<+])
|
||||
:_ t=$(+< t)
|
||||
@ -1002,7 +1002,7 @@
|
||||
:: .= (bill ~[[& dim] [| ", "] [& dim]]:ag)
|
||||
:: ;~(plug dim ;~(pfix com ace ;~(plug dim (easy)))):ag
|
||||
++ bill
|
||||
|* (list (each ,_rule tape))
|
||||
|* (list (each rule tape))
|
||||
?~ +< (easy ~)
|
||||
?: ?=(| -.i) ;~(pfix (jest (crip p.i)) $(+< t))
|
||||
%+ cook |*([* *] [i t]=+<)
|
||||
|
@ -60,20 +60,20 @@
|
||||
=+ neu=(weld (reap sto ' ') t.q.tub)
|
||||
(next tub(q neu))
|
||||
::
|
||||
++ whif |*(a=_rule ;~(sfix a (star ace)))
|
||||
++ ahed |*(a=_rule ;~(simu a (easy ~)))
|
||||
++ opts |*(a=_rule ;~((bend) (easy ~) a))
|
||||
++ lots |*([a=@u b=_rule] ;~(pfix (stun [a a] b) (star b)))
|
||||
++ leas |*(a=_rule ;~(pfix ;~(less (stun 4^4 ace) (stun 0^3 ace)) a))
|
||||
++ whif |*(a=rule ;~(sfix a (star ace)))
|
||||
++ ahed |*(a=rule ;~(simu a (easy ~)))
|
||||
++ opts |*(a=rule ;~((bend) (easy ~) a))
|
||||
++ lots |*([a=@u b=rule] ;~(pfix (stun [a a] b) (star b)))
|
||||
++ leas |*(a=rule ;~(pfix ;~(less (stun 4^4 ace) (stun 0^3 ace)) a))
|
||||
++ pech
|
||||
|* a=_[rule rule]
|
||||
|* a=[rule rule]
|
||||
|= tub=nail
|
||||
^- (like (each ,_(wonk (-.a)) ,_(wonk (+.a))))
|
||||
%. tub
|
||||
;~(pose (stag %& -.a) (stag %| +.a))
|
||||
::
|
||||
++ lite :: literal matched
|
||||
|* a=_rule
|
||||
|* a=rule
|
||||
|= tub=nail ^- (like tape)
|
||||
=+ vex=(a tub)
|
||||
?~ q.vex vex
|
||||
@ -89,13 +89,6 @@
|
||||
|= tub=nail
|
||||
^- (like a)
|
||||
[[0 0] ~ (a q.tub) [0 0] ~]
|
||||
:: ++ vary :: XX types
|
||||
:: |= a=tape
|
||||
:: ?~ a !! :: XX cast to _(b)
|
||||
:: |* b=_|=(_rule rule)
|
||||
:: ?~ t.a (b (just i.a))
|
||||
:: ;~(pose (b (just i.a)) $(a t.a))
|
||||
::
|
||||
-- ==
|
||||
=~
|
||||
|%
|
||||
@ -269,7 +262,7 @@
|
||||
(pexp nore(rec " "))
|
||||
==
|
||||
++ pexp
|
||||
|* cha=_rule
|
||||
|* cha=rule
|
||||
=+ chu=;~(less pel per cha)
|
||||
|- :: XX Chesterton fence
|
||||
%+ knee *tape |. ~+
|
||||
@ -287,7 +280,7 @@
|
||||
==
|
||||
++ titl
|
||||
%. ~[soq^soq doq^doq pel^per]
|
||||
|* a=(pole ,_[rule rule])
|
||||
|* a=(pole ,[rule rule])
|
||||
?~ a fail
|
||||
;~ pose
|
||||
(ifix -.a (star ;~(pose esc htm-enty ;~(less ->.a prn))))
|
||||
@ -485,7 +478,7 @@
|
||||
:(strip nobas (star ace) (flop a))
|
||||
::
|
||||
++ scab
|
||||
|* [a=tape b=_rule]
|
||||
|* [a=tape b=rule]
|
||||
(wonk (b [1 1] a))
|
||||
::
|
||||
++ donp
|
||||
@ -515,7 +508,7 @@
|
||||
++ hrul
|
||||
%+ cold [%hrul ~]
|
||||
%. ~[tar hep cab] :: (vary "*-_")
|
||||
|* a=(pole ,_rule)
|
||||
|* a=(pole rule)
|
||||
?~ a fail
|
||||
;~(pose ;~(plug (lots 3 (whif -.a)) (ahed eol)) $(a +.a))
|
||||
::
|
||||
@ -632,14 +625,14 @@
|
||||
==
|
||||
::
|
||||
++ snack :: advance by parser
|
||||
|* a=_rule
|
||||
|* a=rule
|
||||
^- [(unit ,_(wonk (a))) nail]
|
||||
=+ vex=(a tub)
|
||||
?~ q.vex [~ tub]
|
||||
[`p q]:u.q.vex
|
||||
::
|
||||
++ snake :: advance with trace
|
||||
|* fel=_rule
|
||||
|* fel=rule
|
||||
=- (snack (here - fel))
|
||||
|*([[[@ a=@u] [@ b=@u]] c=*] [p=(sub b a) q=c])
|
||||
::
|
||||
|
@ -92,7 +92,7 @@
|
||||
::
|
||||
++ lose |=(a=tape [[;lost:"{a}"]~ lum])
|
||||
++ chomp
|
||||
|* [tap=tape fel=_rule]
|
||||
|* [tap=tape fel=rule]
|
||||
^- [(unit ,_(wonk *fel)) _lum]
|
||||
=+ vex=(fel 1^1 tap)
|
||||
?~ q.vex [~ lum]
|
||||
@ -185,7 +185,7 @@
|
||||
::
|
||||
++ lose |=(a=tape [[;lost:"{a}"]~ lim])
|
||||
++ chomp
|
||||
|* [tap=tape fel=_rule]
|
||||
|* [tap=tape fel=rule]
|
||||
^- [(unit ,_(wonk *fel)) _lim]
|
||||
=+ vex=(fel 1^1 tap)
|
||||
?~ q.vex [~ lim]
|
||||
|
@ -20,7 +20,7 @@
|
||||
==
|
||||
|%
|
||||
++ op :: parse keys of map
|
||||
|* [fel=_rule wit=fist]
|
||||
|* [fel=rule wit=fist]
|
||||
%+ cu mo
|
||||
%- ci :_ (om wit)
|
||||
|= a=(map cord ,_(need *wit))
|
||||
@ -42,14 +42,14 @@
|
||||
::
|
||||
++ lake |*(a=_,* $+(json (unit a)))
|
||||
++ peach
|
||||
|* a=_[rule rule]
|
||||
|* a=[rule rule]
|
||||
|= tub=nail
|
||||
^- (like (each ,_(wonk (-.a)) ,_(wonk (+.a))))
|
||||
%. tub
|
||||
;~(pose (stag %& -.a) (stag %| +.a))
|
||||
::
|
||||
++ head-rush
|
||||
|* a=_rule
|
||||
|* a=rule
|
||||
|* [b=cord c=*]
|
||||
=+ nit=(rush b a)
|
||||
?~ nit ~
|
||||
|
@ -151,7 +151,7 @@
|
||||
~
|
||||
==
|
||||
++ op :: parse keys of map
|
||||
|* [fel=_rule wit=fist]
|
||||
|* [fel=rule wit=fist]
|
||||
%+ cu mo
|
||||
%- ci :_ (om wit)
|
||||
|= a=(map cord ,_(need *wit))
|
||||
@ -173,7 +173,7 @@
|
||||
::
|
||||
++ lake |*(a=_,* $+(json (unit a)))
|
||||
++ head-rush
|
||||
|* a=_rule
|
||||
|* a=rule
|
||||
|* [b=cord c=*]
|
||||
=+ nit=(rush b a)
|
||||
?~ nit ~
|
||||
|
@ -26,7 +26,7 @@
|
||||
[~ a]
|
||||
[[- c] a]:[(rsh 3 2 i.a) $(a t.a)]
|
||||
[(b `wain`c) a]
|
||||
++ keen |*(_[a=,* b=rule] |=(c=nail `(like a)`(b c)))
|
||||
++ keen |*([a=* b=rule] |=(c=nail `(like a)`(b c)))
|
||||
++ parse
|
||||
|* [hed=?(~ $|(@tas tape)) tal=(pole)]
|
||||
?~ hed (..$ tal)
|
||||
@ -38,7 +38,7 @@
|
||||
(some q.p.a)
|
||||
::
|
||||
++ advance
|
||||
|* [a=wain b=_rule] ^+ [(wonk *b) a]
|
||||
|* [a=wain b=rule] ^+ [(wonk *b) a]
|
||||
?~(a !! ~|(i.a [(rash i.a b) t.a]))
|
||||
--
|
||||
!:
|
||||
|
@ -106,7 +106,7 @@
|
||||
[p=*(list tank) q=[%& ~]] ::
|
||||
:: ::
|
||||
++ sole-go :: parse by rule
|
||||
|* [sef=_rule fun=$+(* *)] ::
|
||||
|* [sef=rule fun=$+(* *)] ::
|
||||
|= txt=sole-input ::
|
||||
=+ vex=(sef [0 0] txt) ::
|
||||
?: |(!=((lent txt) q.p.vex) ?=(~ q.vex)) ::
|
||||
|
Loading…
Reference in New Issue
Block a user