# Styled Text

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 <a href="#shoe-cli-session-manager" id="shoe-cli-session-manager"></a>

`%shoe` is responsible to manage attached agent sessions. It adds a few arms to the standard Gall agent, namely:

* `+command-parser` is 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-list` provides autocompletion options. We can ignore for now.
* `+on-command` is called whenever a valid command is run. This produces the actual effects.
* `+can-connect` supports `|dojo/link` connexion to the app.
* `+on-connect` provides particular session support when a user connects. We can ignore for now.
* `+on-disconnect` provides 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 `+command-parser` and `+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.

### `+command-parser` <a href="#command-parser" id="command-parser"></a>

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:

```hoon
+$  command
  $?  %demo
      %row
      %table
  ==
```

and later uses this as:

```hoon
  ++  command-parser                                                                            
    |=  =sole-id:shoe
    ^+  |~(nail *(like [? command]))
    %+  stag  &
    (perk %demo %row %table ~)
```

where the unfamiliar parser components are:

* `+stag` adds a label, here `&` pam `TRUE`/`%.y` to indicate that the command should be run immediately when it matches. (We won't want this below so we will `+stag` a `|` `FALSE`/`%.n`.)
* `+perk` parses a fork in the type.

### `+on-command` <a href="#on-command" id="on-command"></a>

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` Effects <a href="#sole-effects" id="sole-effects"></a>

`%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-effect`s 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 <a href="#styx-styled-text-string" id="styx-styled-text-string"></a>

A `+klr` effect uses a `$styx`, or styled text string. The relevant data structures are in `/sys/lull.hoon`:

```hoon
+$  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
```

* `$deco` is a text decoration, here `%bl` blinking, `%br` bright (bold), and `%un` underlined.
* `$tint` is a color, either explicitly the terminal red/green/blue/cyan etc. or a 24-bit true color value.
* `$stye` composes these into a style which will be applied to a string.
* `$styl` similarly composes styles together.
* `$styx` pairs 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`:

```hoon
^-  sole-effect:sole
:-  %klr
^-  styx
~[[[`%br ~ `[r=0x12 g=0x34 b=0x56]] 'Hello Mars!' ~]]
```

* [\~ropdeb-sormyr, "Styled output - requirements and progress" \~2016.8.2 Urbit fora post](https://github.com/urbit/fora-posts/blob/0238536650dfc284f14295d350f9acada0341480/archive/posts/~2016.8.2..21.19.29..2ab8~.md)

## Agent Logic <a href="#agent-logic" id="agent-logic"></a>

Here is an agent that will accept a single character and produce a line with varying random colors of that character.

**`/app/track7.hoon`**

```hoon
/+  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
--
```
