In this tutorial, we examine how to produce
styx styled text strings and output them to the terminal from an agent.
%shoe CLI Session Manager
%shoe is responsible to manage attached agent sessions. It adds a few arms to the standard Gall agent, namely:
++command-parseris the input parser, similar to the work we were carrying out just above. This parses every input and only permits valid keystrokes (think of Dojo real-time parsing).
++tab-listprovides autocompletion options. We can ignore for now.
++on-commandis called whenever a valid command is run. This produces the actual effects.
|linkconnexion to the app.
++on-connectprovides particular session support when a user connects. We can ignore for now.
++on-disconnectprovides particular session support when a user disconnects. We can ignore for now.
To get started with text parsers and CLI agents, we need to focus on
++on-command. But first, the agent's structure and state:
The agent will adopt a two-stage process, wherein a value is put on the stack then the stack is checked for any valid operations.
The input parser can simply accept whole words or single inputs, or parse complex expressions (as Dojo does with Hoon).
This results in a noun of
+$command-type based on the specific application. The example
/app/shoe.hoon agent defines:
+$ command$? %demo%row%table==
and later uses this as:
++ command-parser|= =sole-id:shoe^+ |~(nail *(like [? command]))%+ stag &(perk %demo %row %table ~)
where the unfamiliar parser components are:
++stagadds a label, here
%.yto indicate that the command should be run immediately when it matches. (We won't want this below so we will
++perkparses a fork in the type.
This arm accepts a session ID and a command resulting from
++command-parser. It produces a regular
(quip card _this) so you can modify agent state and produce effects here.
%sole is responsible for producing effects. If you want to yield effects to the command line from your CLI agent (which you often do), this is a great place to work.
%sole-effects are head-tagged by time and produce a variety of terminal effects, from text to bells, colors, and other screen effects.
$styx Styled Text String
klr effect uses a
styx, or styled text string. The relevant data structures are in
+$ deco ?(~ %bl %br %un) :: text decoration+$ stye (pair (set deco) (pair tint tint)) :: decos/bg/fg+$ styl %+ pair (unit deco) :: cascading style(pair (unit tint) (unit tint)) ::+$ styx (list $@(@t (pair styl styx))) :: styled text+$ tint $@ ?(%r %g %b %c %m %y %k %w %~) :: text color[r=@uxD g=@uxD b=@uxD] :: 24bit true color
$decois a text decoration, here
%brbright (bold), and
$tintis a color, either explicitly the terminal red/green/blue/cyan etc. or a 24-bit true color value.
$styecomposes these into a style which will be applied to a string.
$stylsimilarly composes styles together.
$styxpairs styles with cords.
This means that composing styled text correctly can require explicitly nesting statements in rather a complicated way.
For instance, to produce a bold string with hex color
#123456, we could produce the
^- sole-effect:sole:- klr^- styx~[[[`%br ~ `[r=0x12 g=0x34 b=0x56]] 'Hello Mars!' ~]]
Here is an agent that will accept a single character and produce a line with varying random colors of that character.
/+ default-agent, dbug, shoe, sole|%+$ versioned-state$% state-0==+$ state-0 %0+$ card card:agent:shoe+$ command @t--%- agent:dbug=| state-0=* state -^- agent:gall%- (agent:shoe command)^- (shoe:shoe command)|_ =bowl:gall+* this .default ~(. (default-agent this %|) bowl)leather ~(. (default:shoe this command) bowl)++ on-init on-init:default++ on-save !>(state)++ on-load|= old=vase^- (quip card _this)`this(state !<(state-0 old))++ on-poke on-poke:default++ on-peek on-peek:default++ on-arvo on-arvo:default++ on-watch on-watch:default++ on-leave on-leave:default++ on-agent on-agent:default++ on-fail on-fail:default++ command-parser|= =sole-id:shoe^+ |~(nail *(like [? command]))(stag & (boss 256 (more gon qit)))++ on-command|= [=sole-id:shoe =command]^- (quip card _this):_ this^- (list card):~ :+ %shoe ~^- shoe-effect:shoe:- %sole^- sole-effect:sole :- %klr^- styx=/ idx 0=| fx=styx=/ rng ~(. og eny:bowl)|-?: =(80 idx) fx=^ huer rng (rads:rng 256)=^ hueg rng (rads:rng 256)=^ hueb rng (rads:rng 256)%= $idx +(idx)fx `styx`(weld fx `styx`~[[[`%br ~ `[r=`@ux`huer g=`@ux`hueg b=`@ux`hueb]] command ~]])== ==++ can-connect|= =sole-id:shoe^- ??| =(~zod src.bowl)(team:title [our src]:bowl)==++ on-connect on-connect:leather++ on-disconnect on-disconnect:leather++ tab-list tab-list:leather--