Urbit Developers
  • Lightning Tutorials

    • Introduction
    • Build a Groups App
    • Build a Chat App
    • Build a Voting App
    • Core Curriculum

      • Hoon School

        • Introduction
        • 1. Hoon Syntax
        • 2. Azimuth (Urbit ID)
        • 3. Gates (Functions)
        • 4. Molds (Types)
        • 5. Cores
        • 6. Trees and Addressing
        • 7. Libraries
        • 8. Testing Code
        • 9. Text Processing I
        • 10. Cores and Doors
        • 11. Data Structures
        • 12. Type Checking
        • 13. Conditional Logic
        • 14. Subject-Oriented Programming
        • 15. Text Processing II
        • 16. Functional Programming
        • 17. Text Processing III
        • 18. Generic and Variant Cores
        • 19. Mathematics
        • App School I

          • Introduction
          • 1. Arvo
          • 2. The Agent Core
          • 3. Imports and Aliases
          • 4. Lifecycle
          • 5. Cards
          • 6. Pokes
          • 7. Structures and Marks
          • 8. Subscriptions
          • 9. Vanes
          • 10. Scries
          • 11. Failure
          • 12. Next Steps
          • Appendix: Types
          • App School II (Full-Stack)

            • Introduction
            • 1. Types
            • 2. Agent
            • 3. JSON
            • 4. Marks
            • 5. Eyre
            • 6. React app setup
            • 7. React app logic
            • 8. Desk and glob
            • 9. Summary
          • Environment Setup
          • Additional Guides

            • Hoon Workbook

              • Competitive Programming
              • ABC Blocks
              • Gleichniszahlenreihe
              • Rhonda Numbers
              • Roman Numerals
              • Solitaire Cipher
              • Luhn Number
              • Water Towers
              • App Workbook

                • Building a CLI App
                • Debugging Wrapper
                • Host a Website
                • Serving a JS Game
                • Ship Monitoring
                • Styled Text
                • Threads

                  • Fundamentals
                  • Bind
                  • Input
                  • Output
                  • Summary
                • Aqua Tests
                • Remote Scry
                • Command-Line Apps
                • HTTP API
                • Eyre noun channels
                • JSON
                • Generators
                • Parsing Text
                • Sail (HTML)
                • Udon (Markdown-esque)
                • Software Distribution
                • Strings
                • Unit Tests
                • Vases
                Urbit Developers
                • Lightning Tutorials

                  • Introduction
                  • Build a Groups App
                  • Build a Chat App
                  • Build a Voting App
                  • Core Curriculum

                    • Hoon School

                      • Introduction
                      • 1. Hoon Syntax
                      • 2. Azimuth (Urbit ID)
                      • 3. Gates (Functions)
                      • 4. Molds (Types)
                      • 5. Cores
                      • 6. Trees and Addressing
                      • 7. Libraries
                      • 8. Testing Code
                      • 9. Text Processing I
                      • 10. Cores and Doors
                      • 11. Data Structures
                      • 12. Type Checking
                      • 13. Conditional Logic
                      • 14. Subject-Oriented Programming
                      • 15. Text Processing II
                      • 16. Functional Programming
                      • 17. Text Processing III
                      • 18. Generic and Variant Cores
                      • 19. Mathematics
                      • App School I

                        • Introduction
                        • 1. Arvo
                        • 2. The Agent Core
                        • 3. Imports and Aliases
                        • 4. Lifecycle
                        • 5. Cards
                        • 6. Pokes
                        • 7. Structures and Marks
                        • 8. Subscriptions
                        • 9. Vanes
                        • 10. Scries
                        • 11. Failure
                        • 12. Next Steps
                        • Appendix: Types
                        • App School II (Full-Stack)

                          • Introduction
                          • 1. Types
                          • 2. Agent
                          • 3. JSON
                          • 4. Marks
                          • 5. Eyre
                          • 6. React app setup
                          • 7. React app logic
                          • 8. Desk and glob
                          • 9. Summary
                        • Environment Setup
                        • Additional Guides

                          • Hoon Workbook

                            • Competitive Programming
                            • ABC Blocks
                            • Gleichniszahlenreihe
                            • Rhonda Numbers
                            • Roman Numerals
                            • Solitaire Cipher
                            • Luhn Number
                            • Water Towers
                            • App Workbook

                              • Building a CLI App
                              • Debugging Wrapper
                              • Host a Website
                              • Serving a JS Game
                              • Ship Monitoring
                              • Styled Text
                              • Threads

                                • Fundamentals
                                • Bind
                                • Input
                                • Output
                                • Summary
                              • Aqua Tests
                              • Remote Scry
                              • Command-Line Apps
                              • HTTP API
                              • Eyre noun channels
                              • JSON
                              • Generators
                              • Parsing Text
                              • Sail (HTML)
                              • Udon (Markdown-esque)
                              • Software Distribution
                              • Strings
                              • Unit Tests
                              • Vases
                              Guides/Additional Guides/App Workbook

                              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

                              %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 |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

                              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:

                              • ++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

                              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

                              %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

                              A klr effect uses a styx, or styled text string. The relevant data structures are in /sys/lull.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:

                              ^- 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

                              Agent Logic

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

                              /app/track7.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
                              --

                              <-

                              Ship Monitoring

                              Edit this page on GitHub

                              Last modified August 30, 2023