whirled_peas 0.4.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +450 -103
  5. data/Rakefile +28 -3
  6. data/examples/intro.rb +52 -0
  7. data/examples/scrolling.rb +53 -0
  8. data/lib/whirled_peas.rb +4 -8
  9. data/lib/whirled_peas/command_line.rb +44 -55
  10. data/lib/whirled_peas/errors.rb +2 -0
  11. data/lib/whirled_peas/frame.rb +0 -1
  12. data/lib/whirled_peas/frame/consumer.rb +30 -0
  13. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  14. data/lib/whirled_peas/frame/event_loop.rb +28 -29
  15. data/lib/whirled_peas/frame/producer.rb +11 -5
  16. data/lib/whirled_peas/graphics.rb +19 -0
  17. data/lib/whirled_peas/graphics/box_painter.rb +101 -0
  18. data/lib/whirled_peas/graphics/canvas.rb +118 -0
  19. data/lib/whirled_peas/graphics/composer.rb +80 -0
  20. data/lib/whirled_peas/graphics/container_coords.rb +72 -0
  21. data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
  22. data/lib/whirled_peas/graphics/container_painter.rb +272 -0
  23. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  24. data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
  25. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  26. data/lib/whirled_peas/graphics/painter.rb +23 -0
  27. data/lib/whirled_peas/graphics/renderer.rb +26 -0
  28. data/lib/whirled_peas/graphics/screen.rb +70 -0
  29. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  30. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  31. data/lib/whirled_peas/settings.rb +5 -0
  32. data/lib/whirled_peas/settings/alignment.rb +24 -0
  33. data/lib/whirled_peas/settings/bg_color.rb +24 -0
  34. data/lib/whirled_peas/settings/border.rb +101 -0
  35. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  36. data/lib/whirled_peas/settings/color.rb +68 -0
  37. data/lib/whirled_peas/settings/container_settings.rb +223 -0
  38. data/lib/whirled_peas/settings/debugger.rb +96 -0
  39. data/lib/whirled_peas/settings/display_flow.rb +27 -0
  40. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  41. data/lib/whirled_peas/settings/grid_settings.rb +19 -0
  42. data/lib/whirled_peas/settings/margin.rb +8 -0
  43. data/lib/whirled_peas/settings/padding.rb +8 -0
  44. data/lib/whirled_peas/settings/position.rb +15 -0
  45. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  46. data/lib/whirled_peas/settings/sizing.rb +19 -0
  47. data/lib/whirled_peas/settings/spacing.rb +58 -0
  48. data/lib/whirled_peas/settings/text_color.rb +21 -0
  49. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  50. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  51. data/lib/whirled_peas/utils/ansi.rb +6 -56
  52. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  53. data/lib/whirled_peas/utils/title_font.rb +1 -1
  54. data/lib/whirled_peas/version.rb +1 -1
  55. data/screen_test/elements/box.frame +1 -0
  56. data/screen_test/elements/box.rb +20 -0
  57. data/screen_test/elements/grid.frame +1 -0
  58. data/screen_test/elements/grid.rb +13 -0
  59. data/screen_test/elements/screen_overflow_x.frame +1 -0
  60. data/screen_test/elements/screen_overflow_x.rb +9 -0
  61. data/screen_test/elements/screen_overflow_y.frame +1 -0
  62. data/screen_test/elements/screen_overflow_y.rb +9 -0
  63. data/screen_test/elements/text.frame +1 -0
  64. data/screen_test/elements/text.rb +9 -0
  65. data/screen_test/elements/text_multiline.frame +1 -0
  66. data/screen_test/elements/text_multiline.rb +9 -0
  67. data/screen_test/settings/align/box_around.frame +1 -0
  68. data/screen_test/settings/align/box_around.rb +16 -0
  69. data/screen_test/settings/align/box_between.frame +1 -0
  70. data/screen_test/settings/align/box_between.rb +16 -0
  71. data/screen_test/settings/align/box_center.frame +1 -0
  72. data/screen_test/settings/align/box_center.rb +21 -0
  73. data/screen_test/settings/align/box_default.frame +1 -0
  74. data/screen_test/settings/align/box_default.rb +20 -0
  75. data/screen_test/settings/align/box_evenly.frame +1 -0
  76. data/screen_test/settings/align/box_evenly.rb +16 -0
  77. data/screen_test/settings/align/box_left.frame +1 -0
  78. data/screen_test/settings/align/box_left.rb +21 -0
  79. data/screen_test/settings/align/box_right.frame +1 -0
  80. data/screen_test/settings/align/box_right.rb +21 -0
  81. data/screen_test/settings/align/children_center.frame +1 -0
  82. data/screen_test/settings/align/children_center.rb +15 -0
  83. data/screen_test/settings/align/children_left.frame +1 -0
  84. data/screen_test/settings/align/children_left.rb +15 -0
  85. data/screen_test/settings/align/children_right.frame +1 -0
  86. data/screen_test/settings/align/children_right.rb +15 -0
  87. data/screen_test/settings/align/grid_center.frame +1 -0
  88. data/screen_test/settings/align/grid_center.rb +18 -0
  89. data/screen_test/settings/align/grid_default.frame +1 -0
  90. data/screen_test/settings/align/grid_default.rb +17 -0
  91. data/screen_test/settings/align/grid_left.frame +1 -0
  92. data/screen_test/settings/align/grid_left.rb +18 -0
  93. data/screen_test/settings/align/grid_right.frame +1 -0
  94. data/screen_test/settings/align/grid_right.rb +18 -0
  95. data/screen_test/settings/ansi/bold.frame +1 -0
  96. data/screen_test/settings/ansi/bold.rb +14 -0
  97. data/screen_test/settings/ansi/color.frame +1 -0
  98. data/screen_test/settings/ansi/color.rb +37 -0
  99. data/screen_test/settings/ansi/underline.frame +1 -0
  100. data/screen_test/settings/ansi/underline.rb +14 -0
  101. data/screen_test/settings/border.frame +1 -0
  102. data/screen_test/settings/border.rb +13 -0
  103. data/screen_test/settings/flow/box_b2t.frame +1 -0
  104. data/screen_test/settings/flow/box_b2t.rb +26 -0
  105. data/screen_test/settings/flow/box_l2r.frame +1 -0
  106. data/screen_test/settings/flow/box_l2r.rb +26 -0
  107. data/screen_test/settings/flow/box_r2l.frame +1 -0
  108. data/screen_test/settings/flow/box_r2l.rb +26 -0
  109. data/screen_test/settings/flow/box_t2b.frame +1 -0
  110. data/screen_test/settings/flow/box_t2b.rb +26 -0
  111. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  112. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  113. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  114. data/screen_test/settings/flow/grid_l2r.rb +14 -0
  115. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  116. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  117. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  118. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  119. data/screen_test/settings/height/box.frame +1 -0
  120. data/screen_test/settings/height/box.rb +13 -0
  121. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  122. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  123. data/screen_test/settings/height/grid.frame +1 -0
  124. data/screen_test/settings/height/grid.rb +14 -0
  125. data/screen_test/settings/height/overflow_box.frame +1 -0
  126. data/screen_test/settings/height/overflow_box.rb +13 -0
  127. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  128. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  129. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  130. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  131. data/screen_test/settings/height/overflow_grid.frame +1 -0
  132. data/screen_test/settings/height/overflow_grid.rb +16 -0
  133. data/screen_test/settings/margin.frame +1 -0
  134. data/screen_test/settings/margin.rb +16 -0
  135. data/screen_test/settings/padding.frame +1 -0
  136. data/screen_test/settings/padding.rb +13 -0
  137. data/screen_test/settings/position/box_left.frame +1 -0
  138. data/screen_test/settings/position/box_left.rb +17 -0
  139. data/screen_test/settings/position/box_left_negative.frame +1 -0
  140. data/screen_test/settings/position/box_left_negative.rb +17 -0
  141. data/screen_test/settings/position/box_top.frame +1 -0
  142. data/screen_test/settings/position/box_top.rb +17 -0
  143. data/screen_test/settings/position/box_top_negative.frame +1 -0
  144. data/screen_test/settings/position/box_top_negative.rb +17 -0
  145. data/screen_test/settings/position/grid_left.frame +1 -0
  146. data/screen_test/settings/position/grid_left.rb +18 -0
  147. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  148. data/screen_test/settings/position/grid_left_negative.rb +18 -0
  149. data/screen_test/settings/position/grid_top.frame +1 -0
  150. data/screen_test/settings/position/grid_top.rb +18 -0
  151. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  152. data/screen_test/settings/position/grid_top_negative.rb +18 -0
  153. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  154. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  155. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  156. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  157. data/screen_test/settings/scroll/vert_box.frame +1 -0
  158. data/screen_test/settings/scroll/vert_box.rb +20 -0
  159. data/screen_test/settings/title_font.frame +1 -0
  160. data/screen_test/settings/title_font.rb +12 -0
  161. data/screen_test/settings/valign/box_around.frame +1 -0
  162. data/screen_test/settings/valign/box_around.rb +17 -0
  163. data/screen_test/settings/valign/box_between.frame +1 -0
  164. data/screen_test/settings/valign/box_between.rb +17 -0
  165. data/screen_test/settings/valign/box_bottom.frame +1 -0
  166. data/screen_test/settings/valign/box_bottom.rb +17 -0
  167. data/screen_test/settings/valign/box_default.frame +1 -0
  168. data/screen_test/settings/valign/box_default.rb +16 -0
  169. data/screen_test/settings/valign/box_evenly.frame +1 -0
  170. data/screen_test/settings/valign/box_evenly.rb +17 -0
  171. data/screen_test/settings/valign/box_middle.frame +1 -0
  172. data/screen_test/settings/valign/box_middle.rb +17 -0
  173. data/screen_test/settings/valign/box_top.frame +1 -0
  174. data/screen_test/settings/valign/box_top.rb +17 -0
  175. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  176. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  177. data/screen_test/settings/valign/grid_default.frame +1 -0
  178. data/screen_test/settings/valign/grid_default.rb +14 -0
  179. data/screen_test/settings/valign/grid_middle.frame +1 -0
  180. data/screen_test/settings/valign/grid_middle.rb +15 -0
  181. data/screen_test/settings/valign/grid_top.frame +1 -0
  182. data/screen_test/settings/valign/grid_top.rb +15 -0
  183. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  184. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  185. data/screen_test/settings/width/box_content.frame +1 -0
  186. data/screen_test/settings/width/box_content.rb +15 -0
  187. data/screen_test/settings/width/box_default.frame +1 -0
  188. data/screen_test/settings/width/box_default.rb +14 -0
  189. data/screen_test/settings/width/grid.frame +1 -0
  190. data/screen_test/settings/width/grid.rb +14 -0
  191. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  192. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  193. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  194. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  195. data/screen_test/settings/width/overflow_box.frame +1 -0
  196. data/screen_test/settings/width/overflow_box.rb +13 -0
  197. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  198. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  199. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  200. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  201. data/screen_test/settings/width/overflow_grid.frame +1 -0
  202. data/screen_test/settings/width/overflow_grid.rb +14 -0
  203. data/tools/whirled_peas/tools/screen_tester.rb +233 -0
  204. metadata +191 -12
  205. data/bin/title_fonts +0 -6
  206. data/lib/whirled_peas/frame/print_consumer.rb +0 -33
  207. data/lib/whirled_peas/template.rb +0 -5
  208. data/lib/whirled_peas/template/element.rb +0 -230
  209. data/lib/whirled_peas/template/settings.rb +0 -530
  210. data/lib/whirled_peas/ui.rb +0 -5
  211. data/lib/whirled_peas/ui/canvas.rb +0 -68
  212. data/lib/whirled_peas/ui/painter.rb +0 -287
  213. data/lib/whirled_peas/ui/screen.rb +0 -63
  214. data/lib/whirled_peas/utils/color.rb +0 -101
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 740b5ae88bfdd0f6dfbf4b1ef9e220a4298ddd8f4d8b01d62e904e3bfb4e109b
4
- data.tar.gz: 1e78f0bf1664187825441258909a750c74455017266d01b4b64d5cdd7c609572
3
+ metadata.gz: 55ddf23151c866304cbe5213073c9ac9bd3c7b17139737acf1fe2f6678e6248f
4
+ data.tar.gz: 31d26322b45af3d06c2f64c019fde32cebfe87638852c87857fa0113dc3bdc11
5
5
  SHA512:
6
- metadata.gz: '0960008e3b09aae39cf0655ff57d6dde8859bd3437844b68b37fd72b49bc04199dae2fa5544ba219f795d87f5b5ada80d56f0e96f005eaffddbd74de67d4037c'
7
- data.tar.gz: ce998b69ac1db491577cdfaaaa4b35fb79a0bd07d24c622f426e38b1ff3eb0851ff10c90d24b8b7f48dc1b97dd01c11f93960a011c2611df201f3d86c45ce65a
6
+ metadata.gz: 7be414e153881ff228f8780e11887be61844d1f719c1b19d50888cf7c2caf3d2171dd992c6694604672209f5e7457b35eebba7498dd60bb1d21e717c467f0a6c
7
+ data.tar.gz: d27958378cfd0fe6728ef547559f07258ecafb2481df0d1994d3cf13802ae14ad414c212d2186f8e36ecb00be608d8abc3c6ccb918109a0114cc9585ed431735
@@ -6,3 +6,4 @@ rvm:
6
6
  - 2.7.2
7
7
  - 3.0.0
8
8
  before_install: gem install bundler -v 2.1.4
9
+ script: bundle exec rake ci
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.7.1 - 2021-01-27
4
+
5
+ - [b98781d](https://github.com/tcollier/whirled_peas/tree/b98781de23a24b596955f25cfc48936c0cc1efac): Fix num_cols bug for vertical grid flow
6
+
7
+ ## v0.7.0 - 2021-01-27
8
+
9
+ BREAKING: the settings for the template now fills the full screen and disallows margin.
10
+
11
+ - [b7c12c2](https://github.com/tcollier/whirled_peas/tree/b7c12c2c34d7077b9c2496d05ddd0c6d1eb90699): Update template to fill full screen with border sizing
12
+ - [963b819](https://github.com/tcollier/whirled_peas/tree/963b8196f0d046ba03c893f07e5578bf8c88b7a3): Implement vertical alignment
13
+ - [4bddd54](https://github.com/tcollier/whirled_peas/tree/4bddd54bec5c8f93d145c285379c1816f313f35e): Add `between`, `around`, and `evenly` alignments
14
+
15
+ ## v0.6.0 - 2021-01-25
16
+
17
+ - [73df2af](https://github.com/tcollier/whirled_peas/tree/73df2af1f1eac37fe94f720dce16da1ed568dade): Add support for scroll bars along both axes
18
+ - [f4f44e1](https://github.com/tcollier/whirled_peas/tree/f4f44e1ff6c75ed03cd682e3fa9921401dcd2d00): Implement remaining 3 flow directions for grids
19
+ - [c01d083](https://github.com/tcollier/whirled_peas/tree/c01d083e10bf70983109a8def836bb181099f59c): Implement reverse flow directions for grids
20
+
21
+ ## v0.5.0 - 2021-01-25
22
+
23
+ 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.
24
+
25
+ - [3ddfede](https://github.com/tcollier/whirled_peas/tree/3ddfedee4ab2fadeecbe82c7c9caf25c2988f095): Allow relative positioning of containers
26
+ - [507e77c](https://github.com/tcollier/whirled_peas/tree/507e77c551bcb9cc832d5c24e2f24eb1afe4eddc): Add height attribute for container settings
27
+ - [af8ef19](https://github.com/tcollier/whirled_peas/tree/af8ef1950edebcd23a57a04982b22a56296ee09b): Add automated screen testing
28
+
29
+ ## v0.4.1 - 2021-01-22
30
+
31
+ - [0f7aa6c](https://github.com/tcollier/whirled_peas/tree/0f7aa6ccc07323230dd602cb43e0341de5a69ad8): Allow relative path for config files
32
+
33
+ ## v0.4.0 - 2021-01-22
34
+
35
+ - [7fd6712](https://github.com/tcollier/whirled_peas/tree/7fd6712818c94cdbfd81828277ca67c705e01793): BREAKING: replace `WhirledPeas.start` with command line executable
36
+ - [2535342](https://github.com/tcollier/whirled_peas/tree/25353424f1ab4af4880f44eb7ddd28afefbbb9b2): Add support for loading screen
37
+ - [7388fc2](https://github.com/tcollier/whirled_peas/tree/7388fc2eacdc8045b725311c11d650d6b8654be8): Add support for title fonts
38
+ - [b345155](https://github.com/tcollier/whirled_peas/tree/b345155b1c212cabe73f9a2562ac8dbbedbbb6df): Add command to list title fonts to executable
39
+ - [d3a8324](https://github.com/tcollier/whirled_peas/tree/d3a832496c36985993217ff11b6d83dd4697c4ed): Add commands for debugging application to executable
40
+
3
41
  ## v0.3.0 - 2021-01-21
4
42
 
5
43
  - [617f802](https://github.com/tcollier/whirled_peas/tree/617f8027d6688a2ec81a3e594e529c94485cee85): BREAKING: send frames directly to EventLoop (`Producer#send` renamed to `Producer#send_frame`)
data/README.md CHANGED
@@ -1,8 +1,24 @@
1
1
  [![Build Status](https://travis-ci.com/tcollier/whirled_peas.svg?branch=main)](https://travis-ci.com/tcollier/whirled_peas)
2
2
 
3
- # WhirledPeas
3
+ ```
4
+ ██╗ ██╗██╗███████╗██╗ ██╗ █████╗ ██╗ ██╗███████╗███████╗
5
+ ██║ ██║██║██╔════╝██║ ██║██╔══██╗██║ ██║╚══███╔╝██╔════╝
6
+ ██║ ██║██║███████╗██║ ██║███████║██║ ██║ ███╔╝ █████╗
7
+ ╚██╗ ██╔╝██║╚════██║██║ ██║██╔══██║██║ ██║ ███╔╝ ██╔══╝
8
+ ╚████╔╝ ██║███████║╚██████╔╝██║ ██║███████╗██║███████╗███████╗
9
+ ╚═══╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝╚══════╝╚══════╝
10
+
11
+ your code's execution with
12
+
13
+ ██╗ ██╗██╗ ██╗██╗██████╗ ██╗ ███████╗██████╗ ██████╗ ███████╗ █████╗ ███████╗
14
+ ██║ ██║██║ ██║██║██╔══██╗██║ ██╔════╝██╔══██╗ ██╔══██╗██╔════╝██╔══██╗██╔════╝
15
+ ██║ █╗ ██║███████║██║██████╔╝██║ █████╗ ██║ ██║ ██████╔╝█████╗ ███████║███████╗
16
+ ██║███╗██║██╔══██║██║██╔══██╗██║ ██╔══╝ ██║ ██║ ██╔═══╝ ██╔══╝ ██╔══██║╚════██║
17
+ ╚███╔███╔╝██║ ██║██║██║ ██║███████╗███████╗██████╔╝ ██║ ███████╗██║ ██║███████║
18
+ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝
19
+ ```
4
20
 
5
- Visualize your code's execution with Whirled Peas!
21
+ Easily create terminal-based graphics to visual 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,9 @@ Or install it yourself as:
24
40
 
25
41
  A Whirled Peas application consists of the following pieces
26
42
 
27
- 1. [REQUIRED] The driver, which emits lightweight frame events
28
- 1. [REQUIRED] The main template factory, which builds templates to convert frame events from the driver into terminal graphics
29
- 1. [OPTIONAL] A loading screen template factory, which is used while content is loading
43
+ - The driver (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 driver into terminal graphics
45
+ - A loading screen template factory (optional) - builds templates to display while content is loading
30
46
 
31
47
  These pieces are configured as following
32
48
 
@@ -36,10 +52,10 @@ require 'whirled_peas'
36
52
 
37
53
  class TemplateFactory
38
54
  def build(frame, args)
39
- WhirledPeas.template do |body|
40
- body.add_box('Title') do |_, settings|
55
+ WhirledPeas.template do |composer|
56
+ composer.add_box('Title') do |_, settings|
41
57
  settings.underline = true
42
- "Hello #{args['name']}"
58
+ "Hello #{args[:name]}"
43
59
  end
44
60
  # ...
45
61
  end
@@ -48,7 +64,7 @@ end
48
64
 
49
65
  class Driver
50
66
  def start(producer)
51
- producer.send_frame('starting', args: { 'name' => 'World' })
67
+ producer.send_frame('starting', args: { name: 'World' })
52
68
  # ...
53
69
  end
54
70
  end
@@ -67,13 +83,13 @@ $ whirled_peas start visualize.rb
67
83
 
68
84
  The optional loading screen can be configured like
69
85
 
70
- ````ruby
86
+ ```ruby
71
87
  class LoadingTemplateFactory
72
88
  def build
73
- WhirledPeas.template do |t|
74
- t.add_box('Loading') do |box, settings|
89
+ WhirledPeas.template do |composer|
90
+ composer.add_box('Loading') do |_, settings|
75
91
  settings.set_margin(top: 15)
76
- settings.auto_margin = true
92
+ settings.align = :center
77
93
  settings.full_border(color: :blue, style: :double)
78
94
  "Loading..."
79
95
  end
@@ -98,7 +114,7 @@ The driver is the application code to be visualized. This is typically a lightwe
98
114
  def start(producer)
99
115
  # application code here
100
116
  end
101
- ````
117
+ ```
102
118
 
103
119
  The producer provides a single method
104
120
 
@@ -107,12 +123,14 @@ The producer provides a single method
107
123
  #
108
124
  # @param name [String] application defined name for the frame. The template factory will be provided this name
109
125
  # @param duration [Number] time in seconds this frame should be displayed for (defaults to 1 frame)
110
- # @param args [Hash] key value pairs to send as arguments to the template factory
126
+ # @param args [Hash<Symbol, Object>] key value pairs to send as arguments to the template factory
111
127
  def send_frame(name, duration:, args:)
112
128
  # implementation
113
129
  end
114
130
  ```
115
131
 
132
+ **IMPORTANT**: the keys in the `args` hash must be symbols!
133
+
116
134
  #### Example
117
135
 
118
136
  Simple application that loads a set of numbers and looks for a pair that adds up to 1,000
@@ -146,31 +164,36 @@ end
146
164
 
147
165
  ### Template Factory
148
166
 
149
- To render the frame events sent by the driver, 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 driver. A template factory can be a simple ruby class and thus can maintain state. Whirled Peas provides a few basic building blocks to make simple, yet elegant terminal-based UIs.
167
+ To render the frame events sent by the driver, 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 driver. 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.
150
168
 
151
169
  #### Loading Template Factory
152
170
 
153
- `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.
171
+ `WhirledPeas.configure` takes an optional template factory 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.
154
172
 
155
173
  #### Building Blocks
156
174
 
157
- A template is created with `WhirledPeas.template`, which yields a `Template` object and `TemplateSettings`. This template object is a `ComposableElement`, which allows for attaching child elements and setting layout options. `GridElement` and `BoxElement` are two other composable elements and `TextElement` is a simple element that can hold a text/number value and has layout options, but cannot have any child elements.
175
+ 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
176
+
177
+ - `margin` - all margin will be set to 0
178
+ - `width` - will be set to the screen's width
179
+ - `height` - will be set to the screen's height
180
+ - `sizing` - will be set `:border` to ensure the entire box fits on the screen and fills it entirely.
158
181
 
159
- A `ComposableElement` 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).
182
+ 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).
160
183
 
161
- - `add_box` - yields a `ComposableElement` and a `BoxSettings`, which will be added to the parent's children
162
- - `add_grid` - yields a `ComposableElement` and a `GridSettings`, which will be added to the parent's children
184
+ - `add_box` - yields a `Composer` for a `Box` and a `BoxSettings`, which will be added to the parent's children
185
+ - `add_grid` - yields a `Composer` for a `Grid` and a `GridSettings`, which will be added to the parent's children
163
186
  - `add_text` - yields `nil` and a `TextSettings`, which will be added to the parent's children
164
187
 
165
188
  E.g.
166
189
 
167
190
  ```ruby
168
- WhirledPeas.template do |template, template_settings|
169
- template_settings.bg_color = :blue
170
- template.add_grid do |grid, grid_settings|
171
- grid_settings.num_cols = 10
191
+ WhirledPeas.template do |composer, settings|
192
+ settings.bg_color = :blue
193
+ composer.add_grid do |composer, settings|
194
+ settings.num_cols = 10
172
195
  100.times do |i|
173
- grid.add_text { i }
196
+ composer.add_text { i }
174
197
  end
175
198
  end
176
199
  end
@@ -179,81 +202,351 @@ end
179
202
  The above template can also be broken down into more manageable methods, e.g.
180
203
 
181
204
  ```ruby
182
- def number_grid(grid, settings)
205
+ def number_grid(_composer, settings)
183
206
  settings.num_cols = 10
184
- 100.times do |i|
185
- grid.add_text { i }
186
- end
207
+ 100.times.map(&:itself)
187
208
  end
188
209
 
189
- WhirledPeas.template do |template, settings|
210
+ WhirledPeas.template do |composer, settings|
190
211
  settings.bg_color = :blue
191
- template.add_grid(&method(:number_grid))
212
+ composer.add_grid(&method(:number_grid))
192
213
  end
193
214
  ```
194
215
 
195
- Additionally, if no child element is explicitly added to a `GridElement`, but the block returns an array of strings or numbers, those will be converted to `TextElements` and added as children to the `GridElement`. For example, these are identical ways to create a grid of strings
216
+ 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
196
217
 
197
218
  ```ruby
198
- template.add_grid do |g|
219
+ template.add_grid do |composer|
199
220
  100.times do |i|
200
- g.add_text { i }
221
+ composer.add_text { i }
201
222
  end
202
223
  end
203
224
 
204
- template.add_grid do |g|
225
+ template.add_grid do
205
226
  100.times.map(&:itself)
206
227
  end
207
228
  ```
208
229
 
209
- Similarly, if no child element is explicilty added to a `BoxElement`, but the block returns a string or number, that value will be converted to a `TextElement` and added as a child. For example, these are identical ways to create a box with string content
230
+ 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
210
231
 
211
232
  ```ruby
212
- template.add_box do |b|
213
- b.add_text { "Hello!" }
233
+ template.add_box do |composer|
234
+ composer.add_text { "Hello!" }
214
235
  end
215
236
 
216
- template.add_box do |b|
237
+ template.add_box do
217
238
  "Hello!"
218
239
  end
219
240
  ```
220
241
 
221
242
  #### Settings
222
243
 
223
- Each element type has an associated settings type, which provide a custom set of options to format the output. Parent settings may be merged into child settings (assuming the child supports those settings)
244
+ 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
224
245
  The available settigs are
225
246
 
226
- | Setting | Description | Default | Availability | Merged? |
227
- | ------------- | ------------------------------------------------------------------ | ------- | --------------------------------- | ------- |
228
- | `align` | Justifies the text (allowed values: `:left`, `:center`, `:right`) | `:left` | `Box`, `Grid`, `Text` | Yes |
229
- | `auto_margin` | Evenly distribute side margin (overrides left/right in `margin`) | `false` | `Box`, `Grid` | Yes |
230
- | `bg_color` | Background color (see [Colors](#colors)) | | `Box`, `Grid`, `Template`, `Text` | Yes |
231
- | `bold` | `true` makes the font bold | `false` | `Box`, `Grid`, `Template`, `Text` | Yes |
232
- | `border` | Set the border for the lements | none | `Box`, `Grid`, | Yes |
233
- | `color` | Foreground text color (see [Colors](#colors)) | | `Box`, `Grid`, `Template`, `Text` | Yes |
234
- | `flow` | Flow to display child elements (see [Display Flow](#display-flow)) | `:l2r` | `Box` | Yes |
235
- | `margin` | Set the (left, top, right, bottom) margin of the element | `0` | `Box`, `Grid` | Yes |
236
- | `padding` | Set the (left, top, right, bottom) padding of the element | `0` | `Box`, `Grid` | Yes |
237
- | `title_font` | Font used to create "large" text (see [Large Text](#large-text)) | | `Text` |
238
- | `transpose` | Display grid elements top-to-bottom, then left-to-right | `false` | `Grid` | No |
239
- | `underline` | `true` underlines the font | `false` | `Box`, `Grid`, `Template`, `Text` | Yes |
240
- | `width` | Override the calculated with of an element | | `Box`, `Grid`, `Text` | No |
241
-
242
- ##### Margin and Padding
243
-
244
- Margin and padding settings allow for setting the spacing on each of the 4 sides of the element independently. The set these values, use
245
-
246
- - `clear_margin` - sets all margin values to 0
247
- - `set_margin(left:, top:, right:, bottom:)`
248
- - `clear_padding` - sets all margin values to 0
249
- - `set_padding(left:, top:, right:, bottom:)`
247
+ | Setting | Description | Default | Availability | Inherited |
248
+ | ------------ | -------------------------------------------------------------------------------- | ---------- | --------------------- | -------------------- |
249
+ | `align` | Justifies the content in the horizontal direction | `:left` | `Box`, `Grid` | No |
250
+ | `bg_color` | Background color (see [Colors](#colors)) | | `Box`, `Grid`, `Text` | Yes |
251
+ | `bold` | `true` makes the font bold | `false` | `Box`, `Grid`, `Text` | Yes |
252
+ | `border` | Set the border for the lements | none | `Box`, `Grid`, | Only style and color |
253
+ | `color` | Foreground text color (see [Colors](#colors)) | | `Box`, `Grid`, `Text` | Yes |
254
+ | `flow` | Flow to display child elements (see [Display Flow](#display-flow)) | `:l2r` | `Box`, `Grid` | No |
255
+ | `height` | Override the calculated height of an element's content area | | `Box`, `Grid` | No |
256
+ | `margin` | Set the (left, top, right, bottom) margin of the element | `0` | `Box`, `Grid` | No |
257
+ | `num_cols` | Number of columns in the grid (must be set!) | | `Grid` | No |
258
+ | `padding` | Set the (left, top, right, bottom) padding of the element | `0` | `Box`, `Grid` | No |
259
+ | `position` | Set the (left, top) position of the element relative to parent content area | `0` | `Box`, `Grid` | No |
260
+ | `scrollbar` | Display a scroll bar for vertical or horizontal scrolling | | `Box` | No |
261
+ | `sizing` | Sizing model (`:content` or `:border`) used in conjunction with `width`/`hieght` | `:content` | `Box` | No |
262
+ | `title_font` | Font used for "large" text (see [Large Text](#large-text), ignores `underline`) | | `Text` | No |
263
+ | `underline` | `true` underlines the font | `false` | `Box`, `Grid`, `Text` | Yes |
264
+ | `width` | Override the calculated width of an element's content area | | `Box`, `Grid` | No |
265
+ | `valign` | Justifies the content in the vertical direction | `:top` | `Box`, `Grid` | No |
266
+
267
+ ##### Alignment
268
+
269
+ The `align` setting takes one of several values
270
+
271
+ - `:left` - align content starting at the leftmost edge of the container's content area
272
+
273
+ ```
274
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
275
+ ┃[child 1][child 2][child 3] ┃
276
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
277
+ ```
278
+
279
+ - `:right` - align content starting at the rightmost edge of the container's content area
280
+
281
+ ```
282
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
283
+ ┃ [child 1][child 2][child 3]┃
284
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
285
+ ```
286
+
287
+ - `:center` - align content starting in the horizontal center of the container's content area
288
+
289
+ ```
290
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
291
+ ┃ [child 1][child 2][child 3] ┃
292
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
293
+ ```
294
+
295
+ - `:between` - distribute children so there is equal space between children no space outside of the children
296
+
297
+ ```
298
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
299
+ ┃[child 1] [child 2] [child 3]┃
300
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
301
+ ```
302
+
303
+ - `: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.
304
+
305
+ ```
306
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
307
+ ┃ [child 1] [child 2] [child 3] ┃
308
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
309
+ ```
310
+
311
+ - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
312
+
313
+ ```
314
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
315
+ ┃ [child 1] [child 2] [child 3] ┃
316
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
317
+ ```
318
+
319
+ The `valign` setting takes one of several values
320
+
321
+ - `:top` - align content starting at the top of the container's content area
322
+
323
+ ```
324
+ ┏━━━━━━━━━┓
325
+ ┃[child 1]┃
326
+ ┃[child 2]┃
327
+ ┃[child 3]┃
328
+ ┃ ┃
329
+ ┃ ┃
330
+ ┃ ┃
331
+ ┃ ┃
332
+ ┃ ┃
333
+ ┃ ┃
334
+ ┃ ┃
335
+ ┃ ┃
336
+ ┃ ┃
337
+ ┃ ┃
338
+ ┃ ┃
339
+ ┃ ┃
340
+ ┗━━━━━━━━━┛
341
+ ```
342
+
343
+ - `:bottom` - align content starting at the bottom of the container's content area
344
+
345
+ ```
346
+ ┏━━━━━━━━━┓
347
+ ┃ ┃
348
+ ┃ ┃
349
+ ┃ ┃
350
+ ┃ ┃
351
+ ┃ ┃
352
+ ┃ ┃
353
+ ┃ ┃
354
+ ┃ ┃
355
+ ┃ ┃
356
+ ┃ ┃
357
+ ┃ ┃
358
+ ┃ ┃
359
+ ┃[child 1]┃
360
+ ┃[child 2]┃
361
+ ┃[child 3]┃
362
+ ┗━━━━━━━━━┛
363
+ ```
364
+
365
+ - `:middle` - align content starting in the vertical middle of the container's content area
366
+
367
+ ```
368
+ ┏━━━━━━━━━┓
369
+ ┃ ┃
370
+ ┃ ┃
371
+ ┃ ┃
372
+ ┃ ┃
373
+ ┃ ┃
374
+ ┃ ┃
375
+ ┃[child 1]┃
376
+ ┃[child 2]┃
377
+ ┃[child 3]┃
378
+ ┃ ┃
379
+ ┃ ┃
380
+ ┃ ┃
381
+ ┃ ┃
382
+ ┃ ┃
383
+ ┃ ┃
384
+ ┗━━━━━━━━━┛
385
+ ```
386
+
387
+ - `:between` - distribute children so there is equal space between children no space outside of the children
388
+
389
+ ```
390
+ ┏━━━━━━━━━┓
391
+ ┃[child 1]┃
392
+ ┃ ┃
393
+ ┃ ┃
394
+ ┃ ┃
395
+ ┃ ┃
396
+ ┃ ┃
397
+ ┃ ┃
398
+ ┃[child 2]┃
399
+ ┃ ┃
400
+ ┃ ┃
401
+ ┃ ┃
402
+ ┃ ┃
403
+ ┃ ┃
404
+ ┃ ┃
405
+ ┃[child 3]┃
406
+ ┗━━━━━━━━━┛
407
+ ```
408
+
409
+ - `: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.
410
+
411
+ ```
412
+ ┏━━━━━━━━━┓
413
+ ┃ ┃
414
+ ┃ ┃
415
+ ┃[child 1]┃
416
+ ┃ ┃
417
+ ┃ ┃
418
+ ┃ ┃
419
+ ┃ ┃
420
+ ┃[child 2]┃
421
+ ┃ ┃
422
+ ┃ ┃
423
+ ┃ ┃
424
+ ┃ ┃
425
+ ┃[child 3]┃
426
+ ┃ ┃
427
+ ┃ ┃
428
+ ┗━━━━━━━━━┛
429
+ ```
430
+
431
+ - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
432
+
433
+ ```
434
+ ┏━━━━━━━━━┓
435
+ ┃ ┃
436
+ ┃ ┃
437
+ ┃ ┃
438
+ ┃[child 1]┃
439
+ ┃ ┃
440
+ ┃ ┃
441
+ ┃ ┃
442
+ ┃[child 2]┃
443
+ ┃ ┃
444
+ ┃ ┃
445
+ ┃ ┃
446
+ ┃[child 3]┃
447
+ ┃ ┃
448
+ ┃ ┃
449
+ ┃ ┃
450
+ ┗━━━━━━━━━┛
451
+ ```
452
+
453
+ ##### Position
454
+
455
+ 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
456
+
457
+ - `set_position(left:, top:)`
458
+
459
+ ##### Sizing Model
460
+
461
+ 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.
462
+
463
+ ###### Examples
464
+
465
+ In the examples below, the `~` character represents padding and would not be displayed in the acutal rendered screen.
466
+
467
+ ```ruby
468
+ settings.width = 10
469
+ settings.height = 3
470
+ settings.set_padding(left: 3, top: 1, right: 3, bottom: 1)
471
+ settings.full_border
472
+
473
+ ## Content sizing
474
+ settings.sizing = :content
475
+
476
+ # Results in the box
477
+ #
478
+ # ┏━━━━━━━━━━━━━━━━┓
479
+ # ┃~~~~~~~~~~~~~~~~┃
480
+ # ┃~~~1234567890~~~┃
481
+ # ┃~~~1234567890~~~┃
482
+ # ┃~~~1234567890~~~┃
483
+ # ┃~~~~~~~~~~~~~~~~┃
484
+ # ┗━━━━━━━━━━━━━━━━┛
485
+
486
+ ## Border sizing
487
+ settings.sizing = :border
488
+
489
+ # Results in the box
490
+ #
491
+ # ┏━━━━━━━━┓
492
+ # ┃~~~12~~~┃
493
+ # ┗━━━━━━━━┛
494
+ ```
495
+
496
+ 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.
497
+
498
+ ##### Margin
499
+
500
+ 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
501
+
502
+ - `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)
503
+ - `margin.left=(value)` - set left margin
504
+ - `margin.top=(value)` - set top margin
505
+ - `margin.right=(value)` - set right margin
506
+ - `margin.bottom=(value)` - set bottom margin
507
+ - `margin.horiz=(value)` - set left and right margin to the same value
508
+ - `margin.vert=(value)` - set top and bottom margin to the same value
509
+
510
+ Note: values cannot be negative
511
+
512
+ ##### Padding
513
+
514
+ 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
515
+
516
+ - `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)
517
+ - `padding.left=(value)` - set left padding
518
+ - `padding.top=(value)` - set top padding
519
+ - `padding.right=(value)` - set right padding
520
+ - `padding.bottom=(value)` - set bottom padding
521
+ - `padding.horiz=(value)` - set left and right padding to the same value
522
+ - `padding.vert=(value)` - set top and bottom padding to the same value
523
+
524
+ Note: values cannot be negative
525
+
526
+ ##### Scrollbar
527
+
528
+ 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)
529
+
530
+ - `set_scrollbar(horiz:, vert:)` - set both scrollbar settings
531
+ - `scrollbar.horiz=(flag)` - show/hide the horizontal scrollbar
532
+ - `scrollbar.vert=(flag)` - show/hide the vertical scrollbar
533
+
534
+ Note: there is a know bug with scrollbars and `center`/`right` alignments. Using `left` alignment is the supported workaround
250
535
 
251
536
  ##### Border
252
537
 
253
538
  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
254
539
 
255
- - `clear_border` - sets all border positions to `false`
256
- - `set_border(left:, top:, right:, bottom:, inner_horiz:, inner_vert:, color:, style:)`
540
+ - `set_border(left:, top:, right:, bottom:, inner_horiz:, inner_vert:, color:, style:)` - set any combination of border settings
541
+ - `full_border(style:, color:)` - set all borders to true and optionally set the style or color
542
+ - `border.left=(flag)` - show/hide left border
543
+ - `border.top=(flag)` - show/hide top border
544
+ - `border.right=(flag)` - show/hide right border
545
+ - `border.bottom=(flag)` - show/hide bottom border
546
+ - `border.inner_horiz=(flag)` - show/hide inner horizontal border (dividing grid rows)
547
+ - `border.inner_vert=(flag)` - show/hide inner vertical border (dividing grid columns)
548
+ - `border.color=(text_color)` - set the border color
549
+ - `border.style=(style)` - set the border style
257
550
 
258
551
  Available border styles are
259
552
 
@@ -294,31 +587,71 @@ Child elements can flow in one of 4 directions
294
587
  - `:l2r` left-to-right
295
588
 
296
589
  ```
297
- [child 1] [child 2] ... [child N]
590
+ # In a Box
591
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
592
+ ┃[child 1] [child 2] ... [child N]┃
593
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
594
+
595
+ # In a Grid
596
+ ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
597
+ ┃[child 1]┃[child 2]┃[child 3]┃
598
+ ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
599
+ ┃[chiid 4]┃[child 5]┃ ┃
600
+ ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
298
601
  ```
299
602
 
300
603
  - `:r2l` right-to-left
301
604
 
302
605
  ```
303
- [child N] [child N - 1] ... [child 1]
606
+ # In a Box
607
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
608
+ ┃[child N] [child N - 1] ... [child 1]┃
609
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
610
+
611
+ # In a Grid
612
+ ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
613
+ ┃[child 3]┃[child 2]┃[child 1]┃
614
+ ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
615
+ ┃ ┃[chiid 5]┃[child 4]┃
616
+ ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
304
617
  ```
305
618
 
306
619
  - `:t2b` top-to-bottom
307
620
 
308
621
  ```
309
- [child 1]
310
- [child 2]
311
- ...
312
- [child N]
622
+ # In a Box
623
+ ┏━━━━━━━━━┓
624
+ ┃[child 1]┃
625
+ [child 2]
626
+ ┃ ... ┃
627
+ ┃[child N]┃
628
+ ┗━━━━━━━━━┛
629
+
630
+ # In a Grid
631
+ ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
632
+ ┃[child 1]┃[child 3]┃[child 5]┃
633
+ ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
634
+ ┃[child 2]┃[child 4]┃ ┃
635
+ ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
313
636
  ```
314
637
 
315
638
  - `:b2t` bottom-to-top
316
639
 
317
640
  ```
318
- [child N]
319
- [child N - 1]
320
- ...
321
- [child 1]
641
+ # In a Box
642
+ ┏━━━━━━━━━━━━━┓
643
+ ┃[child N] ┃
644
+ [child N - 1]
645
+ ┃ ... ┃
646
+ ┃[child 1] ┃
647
+ ┗━━━━━━━━━━━━━┛
648
+
649
+ # In a Grid
650
+ ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
651
+ ┃[child 2]┃[child 4]┃ ┃
652
+ ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
653
+ ┃[child 1]┃[child 3]┃[child 5]┃
654
+ ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
322
655
  ```
323
656
 
324
657
  ##### Colors
@@ -346,7 +679,7 @@ Many of these also have a "bright" option:
346
679
 
347
680
  ##### Large Text
348
681
 
349
- The `title_font` setting for `TextElement`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
682
+ 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
350
683
 
351
684
  ```
352
685
  ██████╗ ███████╗███████╗ █████╗ ██╗ ██╗██╗ ████████╗
@@ -371,8 +704,13 @@ Note: when using a title font with WhirledPeas for the first time on a system, t
371
704
  class TemplateFactory
372
705
  def build(frame, args)
373
706
  set_state(frame, args)
374
- WhirledPeas.template do |t|
375
- t.add_box('Body', &method(:body))
707
+ WhirledPeas.template do |composer, settings|
708
+ settings.flow = :l2r
709
+ settings.align = :center
710
+
711
+ composer.add_box('Title', &method(:title))
712
+ composer.add_box('Sum', &method(:sum))
713
+ composer.add_grid('NumberGrid', &method(:number_grid))
376
714
  end
377
715
  end
378
716
 
@@ -386,34 +724,25 @@ class TemplateFactory
386
724
  @high = args[:high] if args.key?(:high)
387
725
  end
388
726
 
389
- def title(_elem, settings)
727
+ def title(_composer, settings)
390
728
  settings.underline = true
391
729
  "Pair Finder"
392
730
  end
393
731
 
394
- def sum(_elem, settings)
732
+ def sum(_composer, settings)
395
733
  settings.color = @frame == 'found-pair' ? :green : :red
396
734
  @sum ? "Sum: #{@sum}" : 'N/A'
397
735
  end
398
736
 
399
- def number_grid(elem, settings)
737
+ def number_grid(composer, settings)
400
738
  settings.full_border
401
739
  @numbers.each.with_index do |num, index|
402
- g.add_text do |_, settings|
740
+ composer.add_text do |_, settings|
403
741
  settings.bg_color = (@low == index || @high == index) ? :cyan : :white
404
742
  num
405
743
  end
406
744
  end
407
745
  end
408
-
409
- def body(elem, settings)
410
- settings.flow = :l2r
411
- settings.auto_margin = true
412
-
413
- elem.add_box('Title', &method(:title))
414
- elem.add_box('Sum', &method(:sum))
415
- elem.add_grid('NumberGrid', &method(:number_grid))
416
- end
417
746
  end
418
747
  ```
419
748
 
@@ -441,19 +770,21 @@ Displays a single frame for several seconds
441
770
  $ whirled_peas <config file> play_frame move '{"direction":"N"}'
442
771
  ```
443
772
 
444
- Adding the `--debug` flag will result in just printing out the template's debug information, e.g.
773
+ Adding the `--template` flag will result in printing out debug information for the template, e.g.
445
774
 
446
775
  ```
447
- $ whirled_peas <config file> play_frame move '{"direction":"N"}' --debug
448
- + TEMPLATE [WhirledPeas::UI::Template]
776
+ $ whirled_peas <config file> play_frame move '{"direction":"N"}' --template
777
+ + TEMPLATE [WhirledPeas::Graphics::BoxPainter]
449
778
  - Settings
450
- WhirledPeas::UI::TemplateSettings
779
+ WhirledPeas::Settings::BoxSettings
451
780
  <default>
452
781
  - Children
453
- + TitleContainer [WhirledPeas::UI::BoxElement]
782
+ + TitleContainer [WhirledPeas::Graphics::BoxPainter]
454
783
  ...
455
784
  ```
456
785
 
786
+ Note: the `list_frames` command will print out frame names and arguments formatted for this command
787
+
457
788
  #### loading
458
789
 
459
790
  Displays the configured loading screen for several seconds
@@ -462,16 +793,16 @@ Displays the configured loading screen for several seconds
462
793
  $ whirled_peas <config file> loading
463
794
  ```
464
795
 
465
- Adding the `--debug` flag will result in just printing out the loading template's debug information, e.g.
796
+ Adding the `--template` flag will result in just printing out the loading template's debug information, e.g.
466
797
 
467
798
  ```
468
- $ whirled_peas <config file> loading --debug
469
- + TEMPLATE [WhirledPeas::UI::Template]
799
+ $ whirled_peas <config file> loading --template
800
+ + TEMPLATE [WhirledPeas::Graphics::BoxPainter]
470
801
  - Settings
471
- WhirledPeas::UI::TemplateSettings
802
+ WhirledPeas::Settings::BoxSettings
472
803
  <default>
473
804
  - Children
474
- + TitleContainer [WhirledPeas::UI::BoxElement]
805
+ + TitleContainer [WhirledPeas::Graphics::BoxPainter]
475
806
  ...
476
807
  ```
477
808
 
@@ -481,6 +812,22 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
481
812
 
482
813
  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).
483
814
 
815
+ ### Testing
816
+
817
+ In addition to standard RSpec tests, WhirledPeas has custom tests for rendered templates. These files live in `screen_test/rendered`. 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.
818
+
819
+ Note: viewing `.frame` files with `cat` works better than most other text editors.
820
+
821
+ The following rake tasks are provided to interact with the screen tests
822
+
823
+ - `screen_test` runs all screen tests in the `screen_test/rendered` directory
824
+ - `screen_test:debug[path/to/file.rb]` render the screen without printing it, this allows for debug print statments in the code to appear in the terminal
825
+ - `screen_test:template[path/to/file.rb]` print the rendered template debug tree
826
+ - `screen_test:run[path/to/file.rb]` runs a single screen test
827
+ - `screen_test:save[path/to/file.rb]` saves the output generated by the template in the `.frame` file, overwriting any existing file
828
+ - `screen_test:view[path/to/file.rb]` views the output generated by the template
829
+ - `screen_test:update_all[path/to/file.rb]` interactively step through each pending or failed screen test to compare/set the expected output
830
+
484
831
  ## Contributing
485
832
 
486
833
  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).