whirled_peas 0.4.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/CHANGELOG.md +37 -0
- data/README.md +529 -156
- data/Rakefile +9 -3
- data/bin/reset_cursor +11 -0
- data/bin/screen_test +68 -0
- data/examples/intro.rb +52 -0
- data/examples/scrolling.rb +54 -0
- data/lib/whirled_peas.rb +6 -12
- data/lib/whirled_peas/animator.rb +5 -0
- data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
- data/lib/whirled_peas/animator/easing.rb +72 -0
- data/lib/whirled_peas/animator/frame.rb +5 -0
- data/lib/whirled_peas/animator/frameset.rb +33 -0
- data/lib/whirled_peas/animator/producer.rb +35 -0
- data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
- data/lib/whirled_peas/command.rb +5 -0
- data/lib/whirled_peas/command/base.rb +86 -0
- data/lib/whirled_peas/command/config_command.rb +44 -0
- data/lib/whirled_peas/command/debug.rb +21 -0
- data/lib/whirled_peas/command/fonts.rb +22 -0
- data/lib/whirled_peas/command/frame_command.rb +34 -0
- data/lib/whirled_peas/command/frames.rb +24 -0
- data/lib/whirled_peas/command/help.rb +38 -0
- data/lib/whirled_peas/command/play.rb +108 -0
- data/lib/whirled_peas/command/record.rb +57 -0
- data/lib/whirled_peas/command/still.rb +29 -0
- data/lib/whirled_peas/command_line.rb +23 -228
- data/lib/whirled_peas/config.rb +56 -6
- data/lib/whirled_peas/device.rb +5 -0
- data/lib/whirled_peas/device/null_device.rb +8 -0
- data/lib/whirled_peas/device/output_file.rb +19 -0
- data/lib/whirled_peas/device/screen.rb +26 -0
- data/lib/whirled_peas/errors.rb +2 -0
- data/lib/whirled_peas/graphics.rb +19 -0
- data/lib/whirled_peas/graphics/box_painter.rb +101 -0
- data/lib/whirled_peas/graphics/canvas.rb +118 -0
- data/lib/whirled_peas/graphics/composer.rb +80 -0
- data/lib/whirled_peas/graphics/container_coords.rb +72 -0
- data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
- data/lib/whirled_peas/graphics/container_painter.rb +363 -0
- data/lib/whirled_peas/graphics/debugger.rb +52 -0
- data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
- data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
- data/lib/whirled_peas/graphics/painter.rb +33 -0
- data/lib/whirled_peas/graphics/renderer.rb +32 -0
- data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
- data/lib/whirled_peas/graphics/text_painter.rb +40 -0
- data/lib/whirled_peas/settings.rb +5 -0
- data/lib/whirled_peas/settings/alignment.rb +24 -0
- data/lib/whirled_peas/settings/bg_color.rb +24 -0
- data/lib/whirled_peas/settings/border.rb +101 -0
- data/lib/whirled_peas/settings/box_settings.rb +8 -0
- data/lib/whirled_peas/settings/color.rb +68 -0
- data/lib/whirled_peas/settings/container_settings.rb +223 -0
- data/lib/whirled_peas/settings/debugger.rb +96 -0
- data/lib/whirled_peas/settings/display_flow.rb +27 -0
- data/lib/whirled_peas/settings/element_settings.rb +61 -0
- data/lib/whirled_peas/settings/grid_settings.rb +19 -0
- data/lib/whirled_peas/settings/margin.rb +8 -0
- data/lib/whirled_peas/settings/padding.rb +8 -0
- data/lib/whirled_peas/settings/position.rb +15 -0
- data/lib/whirled_peas/settings/scrollbar.rb +15 -0
- data/lib/whirled_peas/settings/sizing.rb +19 -0
- data/lib/whirled_peas/settings/spacing.rb +58 -0
- data/lib/whirled_peas/settings/text_color.rb +21 -0
- data/lib/whirled_peas/settings/text_settings.rb +15 -0
- data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
- data/lib/whirled_peas/utils/ansi.rb +19 -56
- data/lib/whirled_peas/utils/file_handler.rb +57 -0
- data/lib/whirled_peas/utils/formatted_string.rb +64 -0
- data/lib/whirled_peas/utils/title_font.rb +1 -1
- data/lib/whirled_peas/version.rb +1 -1
- data/screen_test/elements/box.frame +1 -0
- data/screen_test/elements/box.rb +20 -0
- data/screen_test/elements/grid.frame +1 -0
- data/screen_test/elements/grid.rb +13 -0
- data/screen_test/elements/screen_overflow_x.frame +1 -0
- data/screen_test/elements/screen_overflow_x.rb +9 -0
- data/screen_test/elements/screen_overflow_y.frame +1 -0
- data/screen_test/elements/screen_overflow_y.rb +9 -0
- data/screen_test/elements/text.frame +1 -0
- data/screen_test/elements/text.rb +9 -0
- data/screen_test/elements/text_multiline.frame +1 -0
- data/screen_test/elements/text_multiline.rb +9 -0
- data/screen_test/settings/align/box_around.frame +1 -0
- data/screen_test/settings/align/box_around.rb +16 -0
- data/screen_test/settings/align/box_between.frame +1 -0
- data/screen_test/settings/align/box_between.rb +16 -0
- data/screen_test/settings/align/box_center.frame +1 -0
- data/screen_test/settings/align/box_center.rb +21 -0
- data/screen_test/settings/align/box_default.frame +1 -0
- data/screen_test/settings/align/box_default.rb +20 -0
- data/screen_test/settings/align/box_evenly.frame +1 -0
- data/screen_test/settings/align/box_evenly.rb +16 -0
- data/screen_test/settings/align/box_left.frame +1 -0
- data/screen_test/settings/align/box_left.rb +21 -0
- data/screen_test/settings/align/box_right.frame +1 -0
- data/screen_test/settings/align/box_right.rb +21 -0
- data/screen_test/settings/align/children_center.frame +1 -0
- data/screen_test/settings/align/children_center.rb +15 -0
- data/screen_test/settings/align/children_left.frame +1 -0
- data/screen_test/settings/align/children_left.rb +15 -0
- data/screen_test/settings/align/children_right.frame +1 -0
- data/screen_test/settings/align/children_right.rb +15 -0
- data/screen_test/settings/align/grid_center.frame +1 -0
- data/screen_test/settings/align/grid_center.rb +18 -0
- data/screen_test/settings/align/grid_default.frame +1 -0
- data/screen_test/settings/align/grid_default.rb +17 -0
- data/screen_test/settings/align/grid_left.frame +1 -0
- data/screen_test/settings/align/grid_left.rb +18 -0
- data/screen_test/settings/align/grid_right.frame +1 -0
- data/screen_test/settings/align/grid_right.rb +18 -0
- data/screen_test/settings/ansi/bold.frame +1 -0
- data/screen_test/settings/ansi/bold.rb +14 -0
- data/screen_test/settings/ansi/color.frame +1 -0
- data/screen_test/settings/ansi/color.rb +37 -0
- data/screen_test/settings/ansi/underline.frame +1 -0
- data/screen_test/settings/ansi/underline.rb +14 -0
- data/screen_test/settings/border.frame +1 -0
- data/screen_test/settings/border.rb +13 -0
- data/screen_test/settings/flow/box_b2t.frame +1 -0
- data/screen_test/settings/flow/box_b2t.rb +26 -0
- data/screen_test/settings/flow/box_l2r.frame +1 -0
- data/screen_test/settings/flow/box_l2r.rb +26 -0
- data/screen_test/settings/flow/box_r2l.frame +1 -0
- data/screen_test/settings/flow/box_r2l.rb +26 -0
- data/screen_test/settings/flow/box_t2b.frame +1 -0
- data/screen_test/settings/flow/box_t2b.rb +26 -0
- data/screen_test/settings/flow/grid_b2t.frame +1 -0
- data/screen_test/settings/flow/grid_b2t.rb +14 -0
- data/screen_test/settings/flow/grid_l2r.frame +1 -0
- data/screen_test/settings/flow/grid_l2r.rb +14 -0
- data/screen_test/settings/flow/grid_r2l.frame +1 -0
- data/screen_test/settings/flow/grid_r2l.rb +14 -0
- data/screen_test/settings/flow/grid_t2b.frame +1 -0
- data/screen_test/settings/flow/grid_t2b.rb +14 -0
- data/screen_test/settings/height/box.frame +1 -0
- data/screen_test/settings/height/box.rb +13 -0
- data/screen_test/settings/height/box_border_sizing.frame +1 -0
- data/screen_test/settings/height/box_border_sizing.rb +15 -0
- data/screen_test/settings/height/grid.frame +1 -0
- data/screen_test/settings/height/grid.rb +14 -0
- data/screen_test/settings/height/overflow_box.frame +1 -0
- data/screen_test/settings/height/overflow_box.rb +13 -0
- data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
- data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
- data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
- data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
- data/screen_test/settings/height/overflow_grid.frame +1 -0
- data/screen_test/settings/height/overflow_grid.rb +16 -0
- data/screen_test/settings/margin.frame +1 -0
- data/screen_test/settings/margin.rb +16 -0
- data/screen_test/settings/padding.frame +1 -0
- data/screen_test/settings/padding.rb +13 -0
- data/screen_test/settings/position/box_left.frame +1 -0
- data/screen_test/settings/position/box_left.rb +17 -0
- data/screen_test/settings/position/box_left_negative.frame +1 -0
- data/screen_test/settings/position/box_left_negative.rb +17 -0
- data/screen_test/settings/position/box_top.frame +1 -0
- data/screen_test/settings/position/box_top.rb +17 -0
- data/screen_test/settings/position/box_top_negative.frame +1 -0
- data/screen_test/settings/position/box_top_negative.rb +17 -0
- data/screen_test/settings/position/grid_left.frame +1 -0
- data/screen_test/settings/position/grid_left.rb +18 -0
- data/screen_test/settings/position/grid_left_negative.frame +1 -0
- data/screen_test/settings/position/grid_left_negative.rb +18 -0
- data/screen_test/settings/position/grid_top.frame +1 -0
- data/screen_test/settings/position/grid_top.rb +18 -0
- data/screen_test/settings/position/grid_top_negative.frame +1 -0
- data/screen_test/settings/position/grid_top_negative.rb +18 -0
- data/screen_test/settings/scroll/horiz_box.frame +1 -0
- data/screen_test/settings/scroll/horiz_box.rb +17 -0
- data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
- data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
- data/screen_test/settings/scroll/vert_box.frame +1 -0
- data/screen_test/settings/scroll/vert_box.rb +20 -0
- data/screen_test/settings/title_font.frame +1 -0
- data/screen_test/settings/title_font.rb +12 -0
- data/screen_test/settings/valign/box_around.frame +1 -0
- data/screen_test/settings/valign/box_around.rb +17 -0
- data/screen_test/settings/valign/box_between.frame +1 -0
- data/screen_test/settings/valign/box_between.rb +17 -0
- data/screen_test/settings/valign/box_bottom.frame +1 -0
- data/screen_test/settings/valign/box_bottom.rb +17 -0
- data/screen_test/settings/valign/box_default.frame +1 -0
- data/screen_test/settings/valign/box_default.rb +16 -0
- data/screen_test/settings/valign/box_evenly.frame +1 -0
- data/screen_test/settings/valign/box_evenly.rb +17 -0
- data/screen_test/settings/valign/box_middle.frame +1 -0
- data/screen_test/settings/valign/box_middle.rb +17 -0
- data/screen_test/settings/valign/box_top.frame +1 -0
- data/screen_test/settings/valign/box_top.rb +17 -0
- data/screen_test/settings/valign/grid_bottom.frame +1 -0
- data/screen_test/settings/valign/grid_bottom.rb +15 -0
- data/screen_test/settings/valign/grid_default.frame +1 -0
- data/screen_test/settings/valign/grid_default.rb +14 -0
- data/screen_test/settings/valign/grid_middle.frame +1 -0
- data/screen_test/settings/valign/grid_middle.rb +15 -0
- data/screen_test/settings/valign/grid_top.frame +1 -0
- data/screen_test/settings/valign/grid_top.rb +15 -0
- data/screen_test/settings/width/box_border_sizing.frame +1 -0
- data/screen_test/settings/width/box_border_sizing.rb +15 -0
- data/screen_test/settings/width/box_content.frame +1 -0
- data/screen_test/settings/width/box_content.rb +15 -0
- data/screen_test/settings/width/box_default.frame +1 -0
- data/screen_test/settings/width/box_default.rb +14 -0
- data/screen_test/settings/width/grid.frame +1 -0
- data/screen_test/settings/width/grid.rb +14 -0
- data/screen_test/settings/width/overflow_align_center.frame +1 -0
- data/screen_test/settings/width/overflow_align_center.rb +14 -0
- data/screen_test/settings/width/overflow_align_right.frame +1 -0
- data/screen_test/settings/width/overflow_align_right.rb +14 -0
- data/screen_test/settings/width/overflow_box.frame +1 -0
- data/screen_test/settings/width/overflow_box.rb +13 -0
- data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
- data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
- data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
- data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
- data/screen_test/settings/width/overflow_grid.frame +1 -0
- data/screen_test/settings/width/overflow_grid.rb +14 -0
- data/tools/whirled_peas/tools/screen_tester.rb +285 -0
- metadata +213 -15
- data/bin/title_fonts +0 -6
- data/lib/whirled_peas/frame.rb +0 -7
- data/lib/whirled_peas/frame/event_loop.rb +0 -91
- data/lib/whirled_peas/frame/print_consumer.rb +0 -33
- data/lib/whirled_peas/frame/producer.rb +0 -61
- data/lib/whirled_peas/template.rb +0 -5
- data/lib/whirled_peas/template/element.rb +0 -230
- data/lib/whirled_peas/template/settings.rb +0 -530
- data/lib/whirled_peas/ui.rb +0 -5
- data/lib/whirled_peas/ui/canvas.rb +0 -68
- data/lib/whirled_peas/ui/painter.rb +0 -287
- data/lib/whirled_peas/ui/screen.rb +0 -63
- data/lib/whirled_peas/utils/color.rb +0 -101
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 9652a887fc6a68ba5367864a25b4a211674433eae86a2f68db3923e873ab49e8
         | 
| 4 | 
            +
              data.tar.gz: 72926cd288adc3c30393990d88dcc0bca53e2fbfe79d56768e438ffaee2cf3ba
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 9e0124bd724ece36b76e1d527ffb3ccd5a06e9cd7f00c1ae5d0c39445d0c4ed4804d8c2cdc0c3df250f0d927b9927efd97d118fd0fd76bbc42277fda68a674cb
         | 
| 7 | 
            +
              data.tar.gz: '09edc4873598d1363d7d3ef2c548699bcbfa229a8821e458c201608ec9f7e3aba8cf2f081f559edc51c04244267f569e8444b7952b21ab41bfea8a7807c0432a'
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,42 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## v0.8.0 - 2021-01-29
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            BREAKING: `Producer` now responds to `#add_frame` instead of `#send_frame`
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - [67fdc17](https://github.com/tcollier/whirled_peas/tree/67fdc172434cb97f31ca20a674f28aefec6babb3): Add easing functions for frame transitions
         | 
| 8 | 
            +
            - [b888f2e](https://github.com/tcollier/whirled_peas/tree/b888f2e7a3b7c3341300326b417641cc8cf2e89b): Add record and playback functionality to command line tool
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ## v0.7.1 - 2021-01-27
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            - [b98781d](https://github.com/tcollier/whirled_peas/tree/b98781de23a24b596955f25cfc48936c0cc1efac): Fix num_cols bug for vertical grid flow
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            ## v0.7.0 - 2021-01-27
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            BREAKING: the settings for the template now fills the full screen and disallows margin.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            - [b7c12c2](https://github.com/tcollier/whirled_peas/tree/b7c12c2c34d7077b9c2496d05ddd0c6d1eb90699): Update template to fill full screen with border sizing
         | 
| 19 | 
            +
            - [963b819](https://github.com/tcollier/whirled_peas/tree/963b8196f0d046ba03c893f07e5578bf8c88b7a3): Implement vertical alignment
         | 
| 20 | 
            +
            - [4bddd54](https://github.com/tcollier/whirled_peas/tree/4bddd54bec5c8f93d145c285379c1816f313f35e): Add `between`, `around`, and `evenly` alignments
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            ## v0.6.0 - 2021-01-25
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            - [73df2af](https://github.com/tcollier/whirled_peas/tree/73df2af1f1eac37fe94f720dce16da1ed568dade): Add support for scroll bars along both axes
         | 
| 25 | 
            +
            - [f4f44e1](https://github.com/tcollier/whirled_peas/tree/f4f44e1ff6c75ed03cd682e3fa9921401dcd2d00): Implement remaining 3 flow directions for grids
         | 
| 26 | 
            +
            - [c01d083](https://github.com/tcollier/whirled_peas/tree/c01d083e10bf70983109a8def836bb181099f59c): Implement reverse flow directions for grids
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            ## v0.5.0 - 2021-01-25
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            BREAKING: there was a significant amount of structural refactoring in this release. While that aspect did not add or remove any features, it fixed several layout bugs (some known and some unknown), so most template with moderate complexity will now be laid out slightly differently.
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            - [3ddfede](https://github.com/tcollier/whirled_peas/tree/3ddfedee4ab2fadeecbe82c7c9caf25c2988f095): Allow relative positioning of containers
         | 
| 33 | 
            +
            - [507e77c](https://github.com/tcollier/whirled_peas/tree/507e77c551bcb9cc832d5c24e2f24eb1afe4eddc): Add height attribute for container settings
         | 
| 34 | 
            +
            - [af8ef19](https://github.com/tcollier/whirled_peas/tree/af8ef1950edebcd23a57a04982b22a56296ee09b): Add automated screen testing
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            ## v0.4.1 - 2021-01-22
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            - [0f7aa6c](https://github.com/tcollier/whirled_peas/tree/0f7aa6ccc07323230dd602cb43e0341de5a69ad8): Allow relative path for config files
         | 
| 39 | 
            +
             | 
| 3 40 | 
             
            ## v0.4.0 - 2021-01-22
         | 
| 4 41 |  | 
| 5 42 | 
             
            - [7fd6712](https://github.com/tcollier/whirled_peas/tree/7fd6712818c94cdbfd81828277ca67c705e01793): BREAKING: replace `WhirledPeas.start` with command line executable
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,8 +1,24 @@ | |
| 1 1 | 
             
            [](https://travis-ci.com/tcollier/whirled_peas)
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            ```
         | 
| 4 | 
            +
                            ██╗   ██╗██╗███████╗██╗   ██╗ █████╗ ██╗     ██╗███████╗███████╗
         | 
| 5 | 
            +
                            ██║   ██║██║██╔════╝██║   ██║██╔══██╗██║     ██║╚══███╔╝██╔════╝
         | 
| 6 | 
            +
                            ██║   ██║██║███████╗██║   ██║███████║██║     ██║  ███╔╝ █████╗
         | 
| 7 | 
            +
                            ╚██╗ ██╔╝██║╚════██║██║   ██║██╔══██║██║     ██║ ███╔╝  ██╔══╝
         | 
| 8 | 
            +
                             ╚████╔╝ ██║███████║╚██████╔╝██║  ██║███████╗██║███████╗███████╗
         | 
| 9 | 
            +
                              ╚═══╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝╚══════╝╚══════╝
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                                               your code's execution with
         | 
| 4 12 |  | 
| 5 | 
            -
             | 
| 13 | 
            +
                ██╗    ██╗██╗  ██╗██╗██████╗ ██╗     ███████╗██████╗    ██████╗ ███████╗ █████╗ ███████╗
         | 
| 14 | 
            +
                ██║    ██║██║  ██║██║██╔══██╗██║     ██╔════╝██╔══██╗   ██╔══██╗██╔════╝██╔══██╗██╔════╝
         | 
| 15 | 
            +
                ██║ █╗ ██║███████║██║██████╔╝██║     █████╗  ██║  ██║   ██████╔╝█████╗  ███████║███████╗
         | 
| 16 | 
            +
                ██║███╗██║██╔══██║██║██╔══██╗██║     ██╔══╝  ██║  ██║   ██╔═══╝ ██╔══╝  ██╔══██║╚════██║
         | 
| 17 | 
            +
                ╚███╔███╔╝██║  ██║██║██║  ██║███████╗███████╗██████╔╝   ██║     ███████╗██║  ██║███████║
         | 
| 18 | 
            +
                 ╚══╝╚══╝ ╚═╝  ╚═╝╚═╝╚═╝  ╚═╝╚══════╝╚══════╝╚═════╝    ╚═╝     ╚══════╝╚═╝  ╚═╝╚══════╝
         | 
| 19 | 
            +
            ```
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            Easily create terminal-based graphics to visualize the execution of your code. Whirled Peas offers templating inspired by HTML and CSS and provides a lightweight tie-in for your code to produce visual animations with these templates.
         | 
| 6 22 |  | 
| 7 23 | 
             
            ## Installation
         | 
| 8 24 |  | 
| @@ -24,9 +40,8 @@ Or install it yourself as: | |
| 24 40 |  | 
| 25 41 | 
             
            A Whirled Peas application consists of the following pieces
         | 
| 26 42 |  | 
| 27 | 
            -
            - The  | 
| 28 | 
            -
            - The main template factory (required) - builds templates to convert frame events from the  | 
| 29 | 
            -
            - A loading screen template factory (optional) - builds templates to display while content is loading
         | 
| 43 | 
            +
            - The application (required) - the code that is to be visualized, it emits lightweight frame events through a producer
         | 
| 44 | 
            +
            - The main template factory (required) - builds templates to convert frame events from the application into terminal graphics
         | 
| 30 45 |  | 
| 31 46 | 
             
            These pieces are configured as following
         | 
| 32 47 |  | 
| @@ -36,8 +51,8 @@ require 'whirled_peas' | |
| 36 51 |  | 
| 37 52 | 
             
            class TemplateFactory
         | 
| 38 53 | 
             
              def build(frame, args)
         | 
| 39 | 
            -
                WhirledPeas.template do | | 
| 40 | 
            -
                   | 
| 54 | 
            +
                WhirledPeas.template do |composer|
         | 
| 55 | 
            +
                  composer.add_box('Title') do |_, settings|
         | 
| 41 56 | 
             
                    settings.underline = true
         | 
| 42 57 | 
             
                    "Hello #{args[:name]}"
         | 
| 43 58 | 
             
                  end
         | 
| @@ -46,15 +61,15 @@ class TemplateFactory | |
| 46 61 | 
             
              end
         | 
| 47 62 | 
             
            end
         | 
| 48 63 |  | 
| 49 | 
            -
            class  | 
| 64 | 
            +
            class Application
         | 
| 50 65 | 
             
              def start(producer)
         | 
| 51 | 
            -
                producer. | 
| 66 | 
            +
                producer.add_frame('starting', args: { name: 'World' })
         | 
| 52 67 | 
             
                # ...
         | 
| 53 68 | 
             
              end
         | 
| 54 69 | 
             
            end
         | 
| 55 70 |  | 
| 56 71 | 
             
            WhirledPeas.configure do |config|
         | 
| 57 | 
            -
              config. | 
| 72 | 
            +
              config.application = Application.new
         | 
| 58 73 | 
             
              config.template_factory = TemplateFactory.new
         | 
| 59 74 | 
             
            end
         | 
| 60 75 | 
             
            ```
         | 
| @@ -62,34 +77,12 @@ end | |
| 62 77 | 
             
            Then the visualizer is started on the command line with
         | 
| 63 78 |  | 
| 64 79 | 
             
            ```
         | 
| 65 | 
            -
            $ whirled_peas  | 
| 80 | 
            +
            $ whirled_peas play visualize.rb
         | 
| 66 81 | 
             
            ```
         | 
| 67 82 |  | 
| 68 | 
            -
             | 
| 83 | 
            +
            ### Application
         | 
| 69 84 |  | 
| 70 | 
            -
             | 
| 71 | 
            -
            class LoadingTemplateFactory
         | 
| 72 | 
            -
              def build
         | 
| 73 | 
            -
                WhirledPeas.template do |t|
         | 
| 74 | 
            -
                  t.add_box('Loading') do |box, settings|
         | 
| 75 | 
            -
                    settings.set_margin(top: 15)
         | 
| 76 | 
            -
                    settings.auto_margin = true
         | 
| 77 | 
            -
                    settings.full_border(color: :blue, style: :double)
         | 
| 78 | 
            -
                    "Loading..."
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
                end
         | 
| 81 | 
            -
              end
         | 
| 82 | 
            -
            end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
            WhirledPeas.configure do |config|
         | 
| 85 | 
            -
              # ...
         | 
| 86 | 
            -
              config.loading_template_factory = LoadingTemplateFactory.new
         | 
| 87 | 
            -
            end
         | 
| 88 | 
            -
            ```
         | 
| 89 | 
            -
             | 
| 90 | 
            -
            ### Driver
         | 
| 91 | 
            -
             | 
| 92 | 
            -
            The driver is the application code to be visualized. This is typically a lightweight wrapper around an existing application that conforms to the signature below.
         | 
| 85 | 
            +
            The application is code to be visualized that integrates with Whirled Peas by providing the signature below
         | 
| 93 86 |  | 
| 94 87 | 
             
            ```ruby
         | 
| 95 88 | 
             
            # Start the application and pass frame events to the producer to be rendered by the UI
         | 
| @@ -108,71 +101,72 @@ The producer provides a single method | |
| 108 101 | 
             
            # @param name [String] application defined name for the frame. The template factory will be provided this name
         | 
| 109 102 | 
             
            # @param duration [Number] time in seconds this frame should be displayed for (defaults to 1 frame)
         | 
| 110 103 | 
             
            # @param args [Hash<Symbol, Object>] key value pairs to send as arguments to the template factory
         | 
| 111 | 
            -
            def  | 
| 104 | 
            +
            def add_frame(name, duration:, args:)
         | 
| 112 105 | 
             
              # implementation
         | 
| 113 106 | 
             
            end
         | 
| 114 107 | 
             
            ```
         | 
| 115 108 |  | 
| 116 | 
            -
            **IMPORTANT**: the keys  | 
| 109 | 
            +
            **IMPORTANT**: the keys in the `args` hash must be symbols!
         | 
| 117 110 |  | 
| 118 111 | 
             
            #### Example
         | 
| 119 112 |  | 
| 120 113 | 
             
            Simple application that loads a set of numbers and looks for a pair that adds up to 1,000
         | 
| 121 114 |  | 
| 122 115 | 
             
            ```ruby
         | 
| 123 | 
            -
            class  | 
| 116 | 
            +
            class Application
         | 
| 124 117 | 
             
              def start(producer)
         | 
| 125 118 | 
             
                numbers = File.readlines('/path/to/numbers.txt').map(&:to_i)
         | 
| 126 | 
            -
                producer. | 
| 119 | 
            +
                producer.add_frame('load-numbers', duration: 3, args: { numbers: numbers })
         | 
| 127 120 | 
             
                numbers.sort!
         | 
| 128 | 
            -
                producer. | 
| 121 | 
            +
                producer.add_frame('sort-numbers', duration: 3, args: { numbers: numbers })
         | 
| 129 122 | 
             
                low = 0
         | 
| 130 123 | 
             
                high = numbers.length - 1
         | 
| 131 124 | 
             
                while low < high
         | 
| 132 125 | 
             
                  sum = numbers[low] + numbers[high]
         | 
| 133 126 | 
             
                  if sum == 1000
         | 
| 134 | 
            -
                    producer. | 
| 127 | 
            +
                    producer.add_frame('found-pair', duration: 5, args: { low: low, high: high, sum: sum })
         | 
| 135 128 | 
             
                    return
         | 
| 136 129 | 
             
                  elsif sum < 1000
         | 
| 137 | 
            -
                    producer. | 
| 130 | 
            +
                    producer.add_frame('too-low', args: { low: low, high: high, sum: sum })
         | 
| 138 131 | 
             
                    low += 1
         | 
| 139 132 | 
             
                  else
         | 
| 140 | 
            -
                    producer. | 
| 133 | 
            +
                    producer.add_frame('too-high', args: { low: low, high: high, sum: sum })
         | 
| 141 134 | 
             
                    high -= 1
         | 
| 142 135 | 
             
                  end
         | 
| 143 136 | 
             
                end
         | 
| 144 | 
            -
                producer. | 
| 137 | 
            +
                producer.add_frame('no-solution', duration: 5)
         | 
| 145 138 | 
             
              end
         | 
| 146 139 | 
             
            end
         | 
| 147 140 | 
             
            ```
         | 
| 148 141 |  | 
| 149 142 | 
             
            ### Template Factory
         | 
| 150 143 |  | 
| 151 | 
            -
            To render the frame events sent by the  | 
| 152 | 
            -
             | 
| 153 | 
            -
            #### Loading Template Factory
         | 
| 154 | 
            -
             | 
| 155 | 
            -
            `WhirledPeas.start` takes an optional template facotry to build a loading screen. This instance must implement `#build` (taking no arguments). The template returned by that method will be painted while the event loop is waiting for frames. The factory method will be called once per refresh cycle, so it's possible to implement animation.
         | 
| 144 | 
            +
            To render the frame events sent by the application, the application requires a template factory. This factory will be called for each frame event, with the frame name and the arguments supplied by the application. A template factory can be an instance of ruby class and thus can maintain state. Whirled Peas provides a few basic building blocks to make simple, yet elegant terminal-based UIs.
         | 
| 156 145 |  | 
| 157 146 | 
             
            #### Building Blocks
         | 
| 158 147 |  | 
| 159 | 
            -
            A template is created with `WhirledPeas.template`, which yields a ` | 
| 148 | 
            +
            A template is created with `WhirledPeas.template`, which yields a `Composer` object for a `Box` and `BoxSettings`. The composer allows for attaching child elements and the settings for setting layout options. The following attributes of the template's settings will be overridden before it is rendered to ensure that it fills the screen exactly
         | 
| 160 149 |  | 
| 161 | 
            -
             | 
| 150 | 
            +
            - `margin` - all margin will be set to 0
         | 
| 151 | 
            +
            - `width` - will be set to the screen's width
         | 
| 152 | 
            +
            - `height` - will be set to the screen's height
         | 
| 153 | 
            +
            - `sizing` - will be set `:border` to ensure the entire box fits on the screen and fills it entirely.
         | 
| 162 154 |  | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 155 | 
            +
            A `Composer` provides the following methods to add child elements, each of these takes an optional string argument that is set as the name of the element (which can be useful when debugging).
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            - `add_box` - yields a `Composer` for a `Box` and a `BoxSettings`, which will be added to the parent's children
         | 
| 158 | 
            +
            - `add_grid` - yields a `Composer` for a `Grid` and a `GridSettings`, which will be added to the parent's children
         | 
| 165 159 | 
             
            - `add_text` - yields `nil` and a `TextSettings`, which will be added to the parent's children
         | 
| 166 160 |  | 
| 167 161 | 
             
            E.g.
         | 
| 168 162 |  | 
| 169 163 | 
             
            ```ruby
         | 
| 170 | 
            -
            WhirledPeas.template do | | 
| 171 | 
            -
               | 
| 172 | 
            -
               | 
| 173 | 
            -
                 | 
| 164 | 
            +
            WhirledPeas.template do |composer, settings|
         | 
| 165 | 
            +
              settings.bg_color = :blue
         | 
| 166 | 
            +
              composer.add_grid do |composer, settings|
         | 
| 167 | 
            +
                settings.num_cols = 10
         | 
| 174 168 | 
             
                100.times do |i|
         | 
| 175 | 
            -
                   | 
| 169 | 
            +
                  composer.add_text { i }
         | 
| 176 170 | 
             
                end
         | 
| 177 171 | 
             
              end
         | 
| 178 172 | 
             
            end
         | 
| @@ -181,81 +175,351 @@ end | |
| 181 175 | 
             
            The above template can also be broken down into more manageable methods, e.g.
         | 
| 182 176 |  | 
| 183 177 | 
             
            ```ruby
         | 
| 184 | 
            -
            def number_grid( | 
| 178 | 
            +
            def number_grid(_composer, settings)
         | 
| 185 179 | 
             
              settings.num_cols = 10
         | 
| 186 | 
            -
              100.times | 
| 187 | 
            -
                grid.add_text { i }
         | 
| 188 | 
            -
              end
         | 
| 180 | 
            +
              100.times.map(&:itself)
         | 
| 189 181 | 
             
            end
         | 
| 190 182 |  | 
| 191 | 
            -
            WhirledPeas.template do | | 
| 183 | 
            +
            WhirledPeas.template do |composer, settings|
         | 
| 192 184 | 
             
              settings.bg_color = :blue
         | 
| 193 | 
            -
               | 
| 185 | 
            +
              composer.add_grid(&method(:number_grid))
         | 
| 194 186 | 
             
            end
         | 
| 195 187 | 
             
            ```
         | 
| 196 188 |  | 
| 197 | 
            -
            Additionally, if no child element is explicitly added to a ` | 
| 189 | 
            +
            Additionally, if no child element is explicitly added to a `Grid`, but the block returns an array of strings or numbers, those will be converted to `Text` elements and added as children to the `Grid`. For example, these are identical ways to create a grid of strings
         | 
| 198 190 |  | 
| 199 191 | 
             
            ```ruby
         | 
| 200 | 
            -
            template.add_grid do | | 
| 192 | 
            +
            template.add_grid do |composer|
         | 
| 201 193 | 
             
              100.times do |i|
         | 
| 202 | 
            -
                 | 
| 194 | 
            +
                composer.add_text { i }
         | 
| 203 195 | 
             
              end
         | 
| 204 196 | 
             
            end
         | 
| 205 197 |  | 
| 206 | 
            -
            template.add_grid do | 
| 198 | 
            +
            template.add_grid do
         | 
| 207 199 | 
             
              100.times.map(&:itself)
         | 
| 208 200 | 
             
            end
         | 
| 209 201 | 
             
            ```
         | 
| 210 202 |  | 
| 211 | 
            -
            Similarly, if no child element is explicilty added to a ` | 
| 203 | 
            +
            Similarly, if no child element is explicilty added to a `Box`, but the block returns a string or number, that value will be converted to a `Text` and added as a child. For example, these are identical ways to create a box with string content
         | 
| 212 204 |  | 
| 213 205 | 
             
            ```ruby
         | 
| 214 | 
            -
            template.add_box do | | 
| 215 | 
            -
               | 
| 206 | 
            +
            template.add_box do |composer|
         | 
| 207 | 
            +
              composer.add_text { "Hello!" }
         | 
| 216 208 | 
             
            end
         | 
| 217 209 |  | 
| 218 | 
            -
            template.add_box do | 
| 210 | 
            +
            template.add_box do
         | 
| 219 211 | 
             
              "Hello!"
         | 
| 220 212 | 
             
            end
         | 
| 221 213 | 
             
            ```
         | 
| 222 214 |  | 
| 223 215 | 
             
            #### Settings
         | 
| 224 216 |  | 
| 225 | 
            -
            Each element type has an associated settings type, which provide a custom set of options to format the output.  | 
| 217 | 
            +
            Each element type has an associated settings type, which provide a custom set of options to format the output. Child settings will inherit from the parent, where applicable
         | 
| 226 218 | 
             
            The available settigs are
         | 
| 227 219 |  | 
| 228 | 
            -
            | Setting | 
| 229 | 
            -
            |  | 
| 230 | 
            -
            | `align` | 
| 231 | 
            -
            | ` | 
| 232 | 
            -
            | ` | 
| 233 | 
            -
            | ` | 
| 234 | 
            -
            | ` | 
| 235 | 
            -
            | ` | 
| 236 | 
            -
            | ` | 
| 237 | 
            -
            | `margin` | 
| 238 | 
            -
            | ` | 
| 239 | 
            -
            | ` | 
| 240 | 
            -
            | ` | 
| 241 | 
            -
            | ` | 
| 242 | 
            -
            | ` | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
             | 
| 220 | 
            +
            | Setting      | Description                                                                      | Default    | Availability          | Inherited            |
         | 
| 221 | 
            +
            | ------------ | -------------------------------------------------------------------------------- | ---------- | --------------------- | -------------------- |
         | 
| 222 | 
            +
            | `align`      | Justifies the content in the horizontal direction                                | `:left`    | `Box`, `Grid`         | No                   |
         | 
| 223 | 
            +
            | `bg_color`   | Background color (see [Colors](#colors))                                         |            | `Box`, `Grid`, `Text` | Yes                  |
         | 
| 224 | 
            +
            | `bold`       | `true` makes the font bold                                                       | `false`    | `Box`, `Grid`, `Text` | Yes                  |
         | 
| 225 | 
            +
            | `border`     | Set the border for the lements                                                   | none       | `Box`, `Grid`,        | Only style and color |
         | 
| 226 | 
            +
            | `color`      | Foreground text color (see [Colors](#colors))                                    |            | `Box`, `Grid`, `Text` | Yes                  |
         | 
| 227 | 
            +
            | `flow`       | Flow to display child elements (see [Display Flow](#display-flow))               | `:l2r`     | `Box`, `Grid`         | No                   |
         | 
| 228 | 
            +
            | `height`     | Override the calculated height of an element's content area                      |            | `Box`, `Grid`         | No                   |
         | 
| 229 | 
            +
            | `margin`     | Set the (left, top, right, bottom) margin of the element                         | `0`        | `Box`, `Grid`         | No                   |
         | 
| 230 | 
            +
            | `num_cols`   | Number of columns in the grid (must be set!)                                     |            | `Grid`                | No                   |
         | 
| 231 | 
            +
            | `padding`    | Set the (left, top, right, bottom) padding of the element                        | `0`        | `Box`, `Grid`         | No                   |
         | 
| 232 | 
            +
            | `position`   | Set the (left, top) position of the element relative to parent content area      | `0`        | `Box`, `Grid`         | No                   |
         | 
| 233 | 
            +
            | `scrollbar`  | Display a scroll bar for vertical or horizontal scrolling                        |            | `Box`                 | No                   |
         | 
| 234 | 
            +
            | `sizing`     | Sizing model (`:content` or `:border`) used in conjunction with `width`/`height` | `:content` | `Box`                 | No                   |
         | 
| 235 | 
            +
            | `title_font` | Font used for "large" text (see [Large Text](#large-text), ignores `underline`)  |            | `Text`                | No                   |
         | 
| 236 | 
            +
            | `underline`  | `true` underlines the font                                                       | `false`    | `Box`, `Grid`, `Text` | Yes                  |
         | 
| 237 | 
            +
            | `width`      | Override the calculated width of an element's content area                       |            | `Box`, `Grid`         | No                   |
         | 
| 238 | 
            +
            | `valign`     | Justifies the content in the vertical direction                                  | `:top`     | `Box`, `Grid`         | No                   |
         | 
| 239 | 
            +
             | 
| 240 | 
            +
            ##### Alignment
         | 
| 241 | 
            +
             | 
| 242 | 
            +
            The `align` setting takes one of several values
         | 
| 243 | 
            +
             | 
| 244 | 
            +
            - `:left` - align content starting at the leftmost edge of the container's content area
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            ```
         | 
| 247 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 248 | 
            +
            ┃[child 1][child 2][child 3]            ┃
         | 
| 249 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 250 | 
            +
            ```
         | 
| 251 | 
            +
             | 
| 252 | 
            +
            - `:right` - align content starting at the rightmost edge of the container's content area
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            ```
         | 
| 255 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 256 | 
            +
            ┃            [child 1][child 2][child 3]┃
         | 
| 257 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 258 | 
            +
            ```
         | 
| 259 | 
            +
             | 
| 260 | 
            +
            - `:center` - align content starting in the horizontal center of the container's content area
         | 
| 261 | 
            +
             | 
| 262 | 
            +
            ```
         | 
| 263 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 264 | 
            +
            ┃      [child 1][child 2][child 3]      ┃
         | 
| 265 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 266 | 
            +
            ```
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            - `:between` - distribute children so there is equal space between children no space outside of the children
         | 
| 269 | 
            +
             | 
| 270 | 
            +
            ```
         | 
| 271 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 272 | 
            +
            ┃[child 1]      [child 2]      [child 3]┃
         | 
| 273 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 274 | 
            +
            ```
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            - `:around` - distribute children so that they have equal spacing around them, space between two children is twice the space between an edge and a child.
         | 
| 277 | 
            +
             | 
| 278 | 
            +
            ```
         | 
| 279 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 280 | 
            +
            ┃  [child 1]    [child 2]    [child 3]  ┃
         | 
| 281 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 282 | 
            +
            ```
         | 
| 283 | 
            +
             | 
| 284 | 
            +
            - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
         | 
| 285 | 
            +
             | 
| 286 | 
            +
            ```
         | 
| 287 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 288 | 
            +
            ┃   [child 1]   [child 2]   [child 3]   ┃
         | 
| 289 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 290 | 
            +
            ```
         | 
| 291 | 
            +
             | 
| 292 | 
            +
            The `valign` setting takes one of several values
         | 
| 293 | 
            +
             | 
| 294 | 
            +
            - `:top` - align content starting at the top of the container's content area
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            ```
         | 
| 297 | 
            +
            ┏━━━━━━━━━┓
         | 
| 298 | 
            +
            ┃[child 1]┃
         | 
| 299 | 
            +
            ┃[child 2]┃
         | 
| 300 | 
            +
            ┃[child 3]┃
         | 
| 301 | 
            +
            ┃         ┃
         | 
| 302 | 
            +
            ┃         ┃
         | 
| 303 | 
            +
            ┃         ┃
         | 
| 304 | 
            +
            ┃         ┃
         | 
| 305 | 
            +
            ┃         ┃
         | 
| 306 | 
            +
            ┃         ┃
         | 
| 307 | 
            +
            ┃         ┃
         | 
| 308 | 
            +
            ┃         ┃
         | 
| 309 | 
            +
            ┃         ┃
         | 
| 310 | 
            +
            ┃         ┃
         | 
| 311 | 
            +
            ┃         ┃
         | 
| 312 | 
            +
            ┃         ┃
         | 
| 313 | 
            +
            ┗━━━━━━━━━┛
         | 
| 314 | 
            +
            ```
         | 
| 315 | 
            +
             | 
| 316 | 
            +
            - `:bottom` - align content starting at the bottom of the container's content area
         | 
| 317 | 
            +
             | 
| 318 | 
            +
            ```
         | 
| 319 | 
            +
            ┏━━━━━━━━━┓
         | 
| 320 | 
            +
            ┃         ┃
         | 
| 321 | 
            +
            ┃         ┃
         | 
| 322 | 
            +
            ┃         ┃
         | 
| 323 | 
            +
            ┃         ┃
         | 
| 324 | 
            +
            ┃         ┃
         | 
| 325 | 
            +
            ┃         ┃
         | 
| 326 | 
            +
            ┃         ┃
         | 
| 327 | 
            +
            ┃         ┃
         | 
| 328 | 
            +
            ┃         ┃
         | 
| 329 | 
            +
            ┃         ┃
         | 
| 330 | 
            +
            ┃         ┃
         | 
| 331 | 
            +
            ┃         ┃
         | 
| 332 | 
            +
            ┃[child 1]┃
         | 
| 333 | 
            +
            ┃[child 2]┃
         | 
| 334 | 
            +
            ┃[child 3]┃
         | 
| 335 | 
            +
            ┗━━━━━━━━━┛
         | 
| 336 | 
            +
            ```
         | 
| 337 | 
            +
             | 
| 338 | 
            +
            - `:middle` - align content starting in the vertical middle of the container's content area
         | 
| 339 | 
            +
             | 
| 340 | 
            +
            ```
         | 
| 341 | 
            +
            ┏━━━━━━━━━┓
         | 
| 342 | 
            +
            ┃         ┃
         | 
| 343 | 
            +
            ┃         ┃
         | 
| 344 | 
            +
            ┃         ┃
         | 
| 345 | 
            +
            ┃         ┃
         | 
| 346 | 
            +
            ┃         ┃
         | 
| 347 | 
            +
            ┃         ┃
         | 
| 348 | 
            +
            ┃[child 1]┃
         | 
| 349 | 
            +
            ┃[child 2]┃
         | 
| 350 | 
            +
            ┃[child 3]┃
         | 
| 351 | 
            +
            ┃         ┃
         | 
| 352 | 
            +
            ┃         ┃
         | 
| 353 | 
            +
            ┃         ┃
         | 
| 354 | 
            +
            ┃         ┃
         | 
| 355 | 
            +
            ┃         ┃
         | 
| 356 | 
            +
            ┃         ┃
         | 
| 357 | 
            +
            ┗━━━━━━━━━┛
         | 
| 358 | 
            +
            ```
         | 
| 359 | 
            +
             | 
| 360 | 
            +
            - `:between` - distribute children so there is equal space between children no space outside of the children
         | 
| 361 | 
            +
             | 
| 362 | 
            +
            ```
         | 
| 363 | 
            +
            ┏━━━━━━━━━┓
         | 
| 364 | 
            +
            ┃[child 1]┃
         | 
| 365 | 
            +
            ┃         ┃
         | 
| 366 | 
            +
            ┃         ┃
         | 
| 367 | 
            +
            ┃         ┃
         | 
| 368 | 
            +
            ┃         ┃
         | 
| 369 | 
            +
            ┃         ┃
         | 
| 370 | 
            +
            ┃         ┃
         | 
| 371 | 
            +
            ┃[child 2]┃
         | 
| 372 | 
            +
            ┃         ┃
         | 
| 373 | 
            +
            ┃         ┃
         | 
| 374 | 
            +
            ┃         ┃
         | 
| 375 | 
            +
            ┃         ┃
         | 
| 376 | 
            +
            ┃         ┃
         | 
| 377 | 
            +
            ┃         ┃
         | 
| 378 | 
            +
            ┃[child 3]┃
         | 
| 379 | 
            +
            ┗━━━━━━━━━┛
         | 
| 380 | 
            +
            ```
         | 
| 381 | 
            +
             | 
| 382 | 
            +
            - `:around` - distribute children so that they have equal spacing around them, space between two children is twice the space between an edge and a child.
         | 
| 383 | 
            +
             | 
| 384 | 
            +
            ```
         | 
| 385 | 
            +
            ┏━━━━━━━━━┓
         | 
| 386 | 
            +
            ┃         ┃
         | 
| 387 | 
            +
            ┃         ┃
         | 
| 388 | 
            +
            ┃[child 1]┃
         | 
| 389 | 
            +
            ┃         ┃
         | 
| 390 | 
            +
            ┃         ┃
         | 
| 391 | 
            +
            ┃         ┃
         | 
| 392 | 
            +
            ┃         ┃
         | 
| 393 | 
            +
            ┃[child 2]┃
         | 
| 394 | 
            +
            ┃         ┃
         | 
| 395 | 
            +
            ┃         ┃
         | 
| 396 | 
            +
            ┃         ┃
         | 
| 397 | 
            +
            ┃         ┃
         | 
| 398 | 
            +
            ┃[child 3]┃
         | 
| 399 | 
            +
            ┃         ┃
         | 
| 400 | 
            +
            ┃         ┃
         | 
| 401 | 
            +
            ┗━━━━━━━━━┛
         | 
| 402 | 
            +
            ```
         | 
| 403 | 
            +
             | 
| 404 | 
            +
            - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
         | 
| 405 | 
            +
             | 
| 406 | 
            +
            ```
         | 
| 407 | 
            +
            ┏━━━━━━━━━┓
         | 
| 408 | 
            +
            ┃         ┃
         | 
| 409 | 
            +
            ┃         ┃
         | 
| 410 | 
            +
            ┃         ┃
         | 
| 411 | 
            +
            ┃[child 1]┃
         | 
| 412 | 
            +
            ┃         ┃
         | 
| 413 | 
            +
            ┃         ┃
         | 
| 414 | 
            +
            ┃         ┃
         | 
| 415 | 
            +
            ┃[child 2]┃
         | 
| 416 | 
            +
            ┃         ┃
         | 
| 417 | 
            +
            ┃         ┃
         | 
| 418 | 
            +
            ┃         ┃
         | 
| 419 | 
            +
            ┃[child 3]┃
         | 
| 420 | 
            +
            ┃         ┃
         | 
| 421 | 
            +
            ┃         ┃
         | 
| 422 | 
            +
            ┃         ┃
         | 
| 423 | 
            +
            ┗━━━━━━━━━┛
         | 
| 424 | 
            +
            ```
         | 
| 425 | 
            +
             | 
| 426 | 
            +
            ##### Position
         | 
| 427 | 
            +
             | 
| 428 | 
            +
            Position settings dictate the relative position from where the painter would have preferred to place the container. Negative numbers move the container left/up and positive numbers move it right/down. To set these values, use
         | 
| 429 | 
            +
             | 
| 430 | 
            +
            - `set_position(left:, top:)`
         | 
| 431 | 
            +
             | 
| 432 | 
            +
            ##### Sizing Model
         | 
| 433 | 
            +
             | 
| 434 | 
            +
            The sizing model determines how to interpret the `width` and `height` settings. The default sizing model is `:content`, which sets the width and height of the cotent area, whereas `:border` sets the width and height of the element inlcuding the padding and border and scroll bars.
         | 
| 435 | 
            +
             | 
| 436 | 
            +
            ###### Examples
         | 
| 437 | 
            +
             | 
| 438 | 
            +
            In the examples below, the `~` character represents padding and would not be displayed in the acutal rendered screen.
         | 
| 439 | 
            +
             | 
| 440 | 
            +
            ```ruby
         | 
| 441 | 
            +
            settings.width = 10
         | 
| 442 | 
            +
            settings.height = 3
         | 
| 443 | 
            +
            settings.set_padding(left: 3, top: 1, right: 3, bottom: 1)
         | 
| 444 | 
            +
            settings.full_border
         | 
| 445 | 
            +
             | 
| 446 | 
            +
            ## Content sizing
         | 
| 447 | 
            +
            settings.sizing = :content
         | 
| 448 | 
            +
             | 
| 449 | 
            +
            # Results in the box
         | 
| 450 | 
            +
            #
         | 
| 451 | 
            +
            #   ┏━━━━━━━━━━━━━━━━┓
         | 
| 452 | 
            +
            #   ┃~~~~~~~~~~~~~~~~┃
         | 
| 453 | 
            +
            #   ┃~~~1234567890~~~┃
         | 
| 454 | 
            +
            #   ┃~~~1234567890~~~┃
         | 
| 455 | 
            +
            #   ┃~~~1234567890~~~┃
         | 
| 456 | 
            +
            #   ┃~~~~~~~~~~~~~~~~┃
         | 
| 457 | 
            +
            #   ┗━━━━━━━━━━━━━━━━┛
         | 
| 458 | 
            +
             | 
| 459 | 
            +
            ## Border sizing
         | 
| 460 | 
            +
            settings.sizing = :border
         | 
| 461 | 
            +
             | 
| 462 | 
            +
            # Results in the box
         | 
| 463 | 
            +
            #
         | 
| 464 | 
            +
            #   ┏━━━━━━━━┓
         | 
| 465 | 
            +
            #   ┃~~~12~~~┃
         | 
| 466 | 
            +
            #   ┗━━━━━━━━┛
         | 
| 467 | 
            +
            ```
         | 
| 468 | 
            +
             | 
| 469 | 
            +
            Notice that a box rendered with `:border` sizing would fit exactly in the content area of a box with the same `width` and `height` that is rendered with `:content` sizing. For containers with no padding and no border, the resulting size is the same for either sizing model.
         | 
| 470 | 
            +
             | 
| 471 | 
            +
            ##### Margin
         | 
| 472 | 
            +
             | 
| 473 | 
            +
            Margin settings dictate the spacing on the outside (i.e. outside of the border) of each of the 4 sides of the container independently. To set these values, use
         | 
| 474 | 
            +
             | 
| 475 | 
            +
            - `set_margin(left:, top:, right:, bottom:, horiz:, vert:)` - set any combination of margin (note: setting `horiz` and `left`/`right` or setting `vert` and `top`/`bottom` is not allowed)
         | 
| 476 | 
            +
            - `margin.left=(value)` - set left margin
         | 
| 477 | 
            +
            - `margin.top=(value)` - set top margin
         | 
| 478 | 
            +
            - `margin.right=(value)` - set right margin
         | 
| 479 | 
            +
            - `margin.bottom=(value)` - set bottom margin
         | 
| 480 | 
            +
            - `margin.horiz=(value)` - set left and right margin to the same value
         | 
| 481 | 
            +
            - `margin.vert=(value)` - set top and bottom margin to the same value
         | 
| 482 | 
            +
             | 
| 483 | 
            +
            Note: values cannot be negative
         | 
| 484 | 
            +
             | 
| 485 | 
            +
            ##### Padding
         | 
| 486 | 
            +
             | 
| 487 | 
            +
            Padding settings dictate the spacing on the inside (i.e. inside of the border) of each of the 4 sides of the container independently. To set these values, use
         | 
| 488 | 
            +
             | 
| 489 | 
            +
            - `set_padding(left:, top:, right:, bottom:, horiz:, vert:)` - set any combination of padding (note: setting `horiz` and `left`/`right` or setting `vert` and `top`/`bottom` is not allowed)
         | 
| 490 | 
            +
            - `padding.left=(value)` - set left padding
         | 
| 491 | 
            +
            - `padding.top=(value)` - set top padding
         | 
| 492 | 
            +
            - `padding.right=(value)` - set right padding
         | 
| 493 | 
            +
            - `padding.bottom=(value)` - set bottom padding
         | 
| 494 | 
            +
            - `padding.horiz=(value)` - set left and right padding to the same value
         | 
| 495 | 
            +
            - `padding.vert=(value)` - set top and bottom padding to the same value
         | 
| 496 | 
            +
             | 
| 497 | 
            +
            Note: values cannot be negative
         | 
| 498 | 
            +
             | 
| 499 | 
            +
            ##### Scrollbar
         | 
| 500 | 
            +
             | 
| 501 | 
            +
            Scroll settings dictate whether the scrollbar will be shown when child content is larger the the container's viewport. A scrollbar adds a unit to the dimensions of a container (as opposed to overwriting the leftmost/bottommost padding)
         | 
| 502 | 
            +
             | 
| 503 | 
            +
            - `set_scrollbar(horiz:, vert:)` - set both scrollbar settings
         | 
| 504 | 
            +
            - `scrollbar.horiz=(flag)` - show/hide the horizontal scrollbar
         | 
| 505 | 
            +
            - `scrollbar.vert=(flag)` - show/hide the vertical scrollbar
         | 
| 506 | 
            +
             | 
| 507 | 
            +
            Note: there is a know bug with scrollbars and `center`/`right` alignments. Using `left` alignment is the supported workaround
         | 
| 252 508 |  | 
| 253 509 | 
             
            ##### Border
         | 
| 254 510 |  | 
| 255 511 | 
             
            The border settings consist of 6 boolean values (border are either width 1 or not shown), the 4 obvious values (`left`, `top`, `right`, and `bottom`) along with 2 other values for inner borders (`inner_horiz` and `inner_vert`) in a grid. A border also has a foreground color (defaults to `:white`) and a style. The background color is determined by the `bg_color` of the element. Border values can be set with
         | 
| 256 512 |  | 
| 257 | 
            -
            - ` | 
| 258 | 
            -
            - ` | 
| 513 | 
            +
            - `set_border(left:, top:, right:, bottom:, inner_horiz:, inner_vert:, color:, style:)` - set any combination of border settings
         | 
| 514 | 
            +
            - `full_border(style:, color:)` - set all borders to true and optionally set the style or color
         | 
| 515 | 
            +
            - `border.left=(flag)` - show/hide left border
         | 
| 516 | 
            +
            - `border.top=(flag)` - show/hide top border
         | 
| 517 | 
            +
            - `border.right=(flag)` - show/hide right border
         | 
| 518 | 
            +
            - `border.bottom=(flag)` - show/hide bottom border
         | 
| 519 | 
            +
            - `border.inner_horiz=(flag)` - show/hide inner horizontal border (dividing grid rows)
         | 
| 520 | 
            +
            - `border.inner_vert=(flag)` - show/hide inner vertical border (dividing grid columns)
         | 
| 521 | 
            +
            - `border.color=(text_color)` - set the border color
         | 
| 522 | 
            +
            - `border.style=(style)` - set the border style
         | 
| 259 523 |  | 
| 260 524 | 
             
            Available border styles are
         | 
| 261 525 |  | 
| @@ -296,31 +560,71 @@ Child elements can flow in one of 4 directions | |
| 296 560 | 
             
            - `:l2r` left-to-right
         | 
| 297 561 |  | 
| 298 562 | 
             
            ```
         | 
| 299 | 
            -
             | 
| 563 | 
            +
            # In a Box
         | 
| 564 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 565 | 
            +
            ┃[child 1] [child 2] ... [child N]┃
         | 
| 566 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 567 | 
            +
             | 
| 568 | 
            +
            # In a Grid
         | 
| 569 | 
            +
            ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
         | 
| 570 | 
            +
            ┃[child 1]┃[child 2]┃[child 3]┃
         | 
| 571 | 
            +
            ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
         | 
| 572 | 
            +
            ┃[chiid 4]┃[child 5]┃         ┃
         | 
| 573 | 
            +
            ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
         | 
| 300 574 | 
             
            ```
         | 
| 301 575 |  | 
| 302 576 | 
             
            - `:r2l` right-to-left
         | 
| 303 577 |  | 
| 304 578 | 
             
            ```
         | 
| 305 | 
            -
             | 
| 579 | 
            +
            # In a Box
         | 
| 580 | 
            +
            ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
         | 
| 581 | 
            +
            ┃[child N] [child N - 1] ... [child 1]┃
         | 
| 582 | 
            +
            ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
         | 
| 583 | 
            +
             | 
| 584 | 
            +
            # In a Grid
         | 
| 585 | 
            +
            ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
         | 
| 586 | 
            +
            ┃[child 3]┃[child 2]┃[child 1]┃
         | 
| 587 | 
            +
            ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
         | 
| 588 | 
            +
            ┃         ┃[chiid 5]┃[child 4]┃
         | 
| 589 | 
            +
            ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
         | 
| 306 590 | 
             
            ```
         | 
| 307 591 |  | 
| 308 592 | 
             
            - `:t2b` top-to-bottom
         | 
| 309 593 |  | 
| 310 594 | 
             
            ```
         | 
| 311 | 
            -
             | 
| 312 | 
            -
             | 
| 313 | 
            -
              | 
| 314 | 
            -
            [child  | 
| 595 | 
            +
            # In a Box
         | 
| 596 | 
            +
            ┏━━━━━━━━━┓
         | 
| 597 | 
            +
            ┃[child 1]┃
         | 
| 598 | 
            +
            ┃[child 2]┃
         | 
| 599 | 
            +
            ┃ ...     ┃
         | 
| 600 | 
            +
            ┃[child N]┃
         | 
| 601 | 
            +
            ┗━━━━━━━━━┛
         | 
| 602 | 
            +
             | 
| 603 | 
            +
            # In a Grid
         | 
| 604 | 
            +
            ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
         | 
| 605 | 
            +
            ┃[child 1]┃[child 3]┃[child 5]┃
         | 
| 606 | 
            +
            ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
         | 
| 607 | 
            +
            ┃[child 2]┃[child 4]┃         ┃
         | 
| 608 | 
            +
            ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
         | 
| 315 609 | 
             
            ```
         | 
| 316 610 |  | 
| 317 611 | 
             
            - `:b2t` bottom-to-top
         | 
| 318 612 |  | 
| 319 613 | 
             
            ```
         | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 322 | 
            -
              | 
| 323 | 
            -
            [child 1]
         | 
| 614 | 
            +
            # In a Box
         | 
| 615 | 
            +
            ┏━━━━━━━━━━━━━┓
         | 
| 616 | 
            +
            ┃[child N]    ┃
         | 
| 617 | 
            +
            ┃[child N - 1]┃
         | 
| 618 | 
            +
            ┃ ...         ┃
         | 
| 619 | 
            +
            ┃[child 1]    ┃
         | 
| 620 | 
            +
            ┗━━━━━━━━━━━━━┛
         | 
| 621 | 
            +
             | 
| 622 | 
            +
            # In a Grid
         | 
| 623 | 
            +
            ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
         | 
| 624 | 
            +
            ┃[child 2]┃[child 4]┃         ┃
         | 
| 625 | 
            +
            ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
         | 
| 626 | 
            +
            ┃[child 1]┃[child 3]┃[child 5]┃
         | 
| 627 | 
            +
            ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
         | 
| 324 628 | 
             
            ```
         | 
| 325 629 |  | 
| 326 630 | 
             
            ##### Colors
         | 
| @@ -348,7 +652,7 @@ Many of these also have a "bright" option: | |
| 348 652 |  | 
| 349 653 | 
             
            ##### Large Text
         | 
| 350 654 |  | 
| 351 | 
            -
            The `title_font` setting for ` | 
| 655 | 
            +
            The `title_font` setting for `Text`s converts the standard terminal font into a large block font. The available fonts vary from system to system. Every system will have a `:default` font available, this font could look like
         | 
| 352 656 |  | 
| 353 657 | 
             
            ```
         | 
| 354 658 | 
             
            ██████╗ ███████╗███████╗ █████╗ ██╗   ██╗██╗     ████████╗
         | 
| @@ -373,8 +677,13 @@ Note: when using a title font with WhirledPeas for the first time on a system, t | |
| 373 677 | 
             
            class TemplateFactory
         | 
| 374 678 | 
             
              def build(frame, args)
         | 
| 375 679 | 
             
                set_state(frame, args)
         | 
| 376 | 
            -
                WhirledPeas.template do | | 
| 377 | 
            -
                   | 
| 680 | 
            +
                WhirledPeas.template do |composer, settings|
         | 
| 681 | 
            +
                  settings.flow = :l2r
         | 
| 682 | 
            +
                  settings.align = :center
         | 
| 683 | 
            +
             | 
| 684 | 
            +
                  composer.add_box('Title', &method(:title))
         | 
| 685 | 
            +
                  composer.add_box('Sum', &method(:sum))
         | 
| 686 | 
            +
                  composer.add_grid('NumberGrid', &method(:number_grid))
         | 
| 378 687 | 
             
                end
         | 
| 379 688 | 
             
              end
         | 
| 380 689 |  | 
| @@ -388,93 +697,128 @@ class TemplateFactory | |
| 388 697 | 
             
                @high = args[:high] if args.key?(:high)
         | 
| 389 698 | 
             
              end
         | 
| 390 699 |  | 
| 391 | 
            -
              def title( | 
| 700 | 
            +
              def title(_composer, settings)
         | 
| 392 701 | 
             
                settings.underline = true
         | 
| 393 702 | 
             
                "Pair Finder"
         | 
| 394 703 | 
             
              end
         | 
| 395 704 |  | 
| 396 | 
            -
              def sum( | 
| 705 | 
            +
              def sum(_composer, settings)
         | 
| 397 706 | 
             
                settings.color = @frame == 'found-pair' ? :green : :red
         | 
| 398 707 | 
             
                @sum ? "Sum: #{@sum}" : 'N/A'
         | 
| 399 708 | 
             
              end
         | 
| 400 709 |  | 
| 401 | 
            -
              def number_grid( | 
| 710 | 
            +
              def number_grid(composer, settings)
         | 
| 402 711 | 
             
                settings.full_border
         | 
| 403 712 | 
             
                @numbers.each.with_index do |num, index|
         | 
| 404 | 
            -
                   | 
| 713 | 
            +
                  composer.add_text do |_, settings|
         | 
| 405 714 | 
             
                    settings.bg_color = (@low == index || @high == index) ? :cyan : :white
         | 
| 406 715 | 
             
                    num
         | 
| 407 716 | 
             
                  end
         | 
| 408 717 | 
             
                end
         | 
| 409 718 | 
             
              end
         | 
| 719 | 
            +
            end
         | 
| 720 | 
            +
            ```
         | 
| 410 721 |  | 
| 411 | 
            -
             | 
| 412 | 
            -
                settings.flow = :l2r
         | 
| 413 | 
            -
                settings.auto_margin = true
         | 
| 722 | 
            +
            ### Full usage
         | 
| 414 723 |  | 
| 415 | 
            -
                elem.add_box('Title', &method(:title))
         | 
| 416 | 
            -
                elem.add_box('Sum', &method(:sum))
         | 
| 417 | 
            -
                elem.add_grid('NumberGrid', &method(:number_grid))
         | 
| 418 | 
            -
              end
         | 
| 419 | 
            -
            end
         | 
| 420 724 | 
             
            ```
         | 
| 725 | 
            +
            Usage: whirled_peas <command> [command options]
         | 
| 421 726 |  | 
| 422 | 
            -
             | 
| 727 | 
            +
            Available commands:
         | 
| 423 728 |  | 
| 424 | 
            -
             | 
| 729 | 
            +
                debug     Print template tree for specified frame
         | 
| 730 | 
            +
                fonts     List installed title fonts with sample text
         | 
| 731 | 
            +
                frames    Print out list of frames generated by application
         | 
| 732 | 
            +
                help      Show detailed help for a command
         | 
| 733 | 
            +
                play      Play an animation from an application or prerecorded file
         | 
| 734 | 
            +
                record    Record animation to a file
         | 
| 735 | 
            +
                still     Show the specified still frame
         | 
| 736 | 
            +
            ```
         | 
| 425 737 |  | 
| 426 | 
            -
            ####  | 
| 738 | 
            +
            #### `debug`
         | 
| 427 739 |  | 
| 428 | 
            -
             | 
| 740 | 
            +
            Print the template tree for specified frame.
         | 
| 429 741 |  | 
| 430 742 | 
             
            ```
         | 
| 431 | 
            -
             | 
| 432 | 
            -
             | 
| 433 | 
            -
             | 
| 434 | 
            -
             | 
| 435 | 
            -
             | 
| 743 | 
            +
            # Usage: whirled_peas debug <config file> <frame> [args as a JSON string]
         | 
| 744 | 
            +
            % whirled_peas debug my_app.rb greeting '{"name":"World"}'
         | 
| 745 | 
            +
            * WhirledPeas::Graphics::BoxPainter(TEMPLATE)
         | 
| 746 | 
            +
              - Dimensions(outer=140x27, content=120x15, grid=1x1)
         | 
| 747 | 
            +
              - Settings
         | 
| 748 | 
            +
                WhirledPeas::Settings::BoxSettings
         | 
| 749 | 
            +
                  padding: Padding(left: 10, top: 6, right: 10, bottom: 6)
         | 
| 750 | 
            +
                  align: :center
         | 
| 751 | 
            +
                  width: 120
         | 
| 752 | 
            +
                  flow: :t2b
         | 
| 753 | 
            +
                  bold: true
         | 
| 754 | 
            +
                  bg_color: BgColor(code=107, bright=true)
         | 
| 755 | 
            +
              - Children
         | 
| 756 | 
            +
                * WhirledPeas::Graphics::BoxPainter(Element-1)
         | 
| 757 | 
            +
                  - Dimensions(outer=64x6, content=64x6, grid=1x1)
         | 
| 436 758 | 
             
            ```
         | 
| 437 759 |  | 
| 438 | 
            -
            ####  | 
| 760 | 
            +
            #### `fonts`
         | 
| 439 761 |  | 
| 440 | 
            -
             | 
| 762 | 
            +
            List all installed title fonts with sample text.
         | 
| 441 763 |  | 
| 442 764 | 
             
            ```
         | 
| 443 | 
            -
             | 
| 765 | 
            +
            # Usage: whirled_peas fonts
         | 
| 444 766 | 
             
            ```
         | 
| 445 767 |  | 
| 446 | 
            -
             | 
| 768 | 
            +
            #### `frames`
         | 
| 769 | 
            +
             | 
| 770 | 
            +
            Print out list of frames generated by application.
         | 
| 447 771 |  | 
| 448 772 | 
             
            ```
         | 
| 449 | 
            -
             | 
| 450 | 
            -
             | 
| 451 | 
            -
             | 
| 452 | 
            -
             | 
| 453 | 
            -
                  <default>
         | 
| 454 | 
            -
              - Children
         | 
| 455 | 
            -
                + TitleContainer [WhirledPeas::UI::BoxElement]
         | 
| 773 | 
            +
            # Usage: whirled_peas frames <config file>
         | 
| 774 | 
            +
            % whirled_peas frames my_app.rb
         | 
| 775 | 
            +
            Frame 'intro' displayed for 3 second(s) '{"title":"Foo"}'
         | 
| 776 | 
            +
            Frame 'greet' displayed for 0.3 second(s)
         | 
| 456 777 | 
             
            ...
         | 
| 457 778 | 
             
            ```
         | 
| 458 779 |  | 
| 459 | 
            -
            ####  | 
| 780 | 
            +
            #### `help`
         | 
| 460 781 |  | 
| 461 | 
            -
             | 
| 782 | 
            +
            Print out command-specific help message
         | 
| 462 783 |  | 
| 463 784 | 
             
            ```
         | 
| 464 | 
            -
             | 
| 785 | 
            +
            Usage: whirled_peas help <command>
         | 
| 465 786 | 
             
            ```
         | 
| 466 787 |  | 
| 467 | 
            -
             | 
| 788 | 
            +
            #### `play`
         | 
| 789 | 
            +
             | 
| 790 | 
            +
            Play an animation from an application or prerecorded file
         | 
| 468 791 |  | 
| 469 792 | 
             
            ```
         | 
| 470 | 
            -
             | 
| 471 | 
            -
             | 
| 472 | 
            -
             | 
| 473 | 
            -
             | 
| 474 | 
            -
             | 
| 475 | 
            -
             | 
| 476 | 
            -
             | 
| 477 | 
            -
             | 
| 793 | 
            +
            # Usage: whirled_peas play <config/wpz file>
         | 
| 794 | 
            +
             | 
| 795 | 
            +
            # Play animation directly from app
         | 
| 796 | 
            +
            % whirled_peas play my_app.rb
         | 
| 797 | 
            +
            # Animation plays
         | 
| 798 | 
            +
             | 
| 799 | 
            +
            # Play animation from previously recorded file
         | 
| 800 | 
            +
            % whirled_peas play my_animation.wpz
         | 
| 801 | 
            +
            # Animation plays
         | 
| 802 | 
            +
            ```
         | 
| 803 | 
            +
             | 
| 804 | 
            +
            #### `record`
         | 
| 805 | 
            +
             | 
| 806 | 
            +
            Record animation to a file
         | 
| 807 | 
            +
             | 
| 808 | 
            +
            ```
         | 
| 809 | 
            +
            # Usage: whirled_peas record <config file> <output file>
         | 
| 810 | 
            +
            % whirled_peas record my_app.rb my_animation.wpz
         | 
| 811 | 
            +
            # Record animation to my_animation.wpz
         | 
| 812 | 
            +
            ```
         | 
| 813 | 
            +
             | 
| 814 | 
            +
            #### `still`
         | 
| 815 | 
            +
             | 
| 816 | 
            +
            Show the specified still frame
         | 
| 817 | 
            +
             | 
| 818 | 
            +
            ```
         | 
| 819 | 
            +
            # Usage: whirled_peas still <config file> <frame> [args as a JSON string]
         | 
| 820 | 
            +
            % whirled_peas still my_app.rb greeting '{"name":"World"}'
         | 
| 821 | 
            +
            # Still frame is displayed
         | 
| 478 822 | 
             
            ```
         | 
| 479 823 |  | 
| 480 824 | 
             
            ## Development
         | 
| @@ -483,6 +827,31 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run | |
| 483 827 |  | 
| 484 828 | 
             
            To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
         | 
| 485 829 |  | 
| 830 | 
            +
            ### Testing
         | 
| 831 | 
            +
             | 
| 832 | 
            +
            In addition to standard RSpec tests, WhirledPeas has custom tests for rendered templates. These files live in `screen_test/`. Each ruby file is expected to define a class named `TemplateFactory` that responds to `#build(name, args)` returning a template (the standard template factory role). Each file should also be accompanied by a `.frame` file with the same base name. This file will contain the output of the rendered screen and is considered the correct output when running tests.
         | 
| 833 | 
            +
             | 
| 834 | 
            +
            Note: viewing `.frame` files with `cat` works better than most other text editors.
         | 
| 835 | 
            +
             | 
| 836 | 
            +
            ```
         | 
| 837 | 
            +
             | 
| 838 | 
            +
            Usage: screen_test [file] [options]
         | 
| 839 | 
            +
             | 
| 840 | 
            +
            If not file or options are provide, all tests are run
         | 
| 841 | 
            +
             | 
| 842 | 
            +
            If no file is provided, the supported options are
         | 
| 843 | 
            +
            --help print this usage statement and exit
         | 
| 844 | 
            +
            --view-pending interactively display and optionally save rendered output for each pending test
         | 
| 845 | 
            +
            --view-failed interactively display and optionally save rendered output for each faiing test
         | 
| 846 | 
            +
             | 
| 847 | 
            +
            If the file provide is a screen test, the supported options are
         | 
| 848 | 
            +
            --run run screen test for given file
         | 
| 849 | 
            +
            --view interactively display and optionally save the file's test output
         | 
| 850 | 
            +
            --template print out template tree for the test template
         | 
| 851 | 
            +
            --debug render the test template without displying it, printing out debug information
         | 
| 852 | 
            +
             | 
| 853 | 
            +
            ```
         | 
| 854 | 
            +
             | 
| 486 855 | 
             
            ## Contributing
         | 
| 487 856 |  | 
| 488 857 | 
             
            Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/whirled_peas. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/whirled_peas/blob/master/CODE_OF_CONDUCT.md).
         | 
| @@ -494,3 +863,7 @@ The gem is available as open source under the terms of the [MIT License](https:/ | |
| 494 863 | 
             
            ## Code of Conduct
         | 
| 495 864 |  | 
| 496 865 | 
             
            Everyone interacting in the WhirledPeas project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/whirled_peas/blob/master/CODE_OF_CONDUCT.md).
         | 
| 866 | 
            +
             | 
| 867 | 
            +
            ```
         | 
| 868 | 
            +
             | 
| 869 | 
            +
            ```
         |