whirled_peas 0.4.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +37 -0
  5. data/README.md +529 -156
  6. data/Rakefile +9 -3
  7. data/bin/reset_cursor +11 -0
  8. data/bin/screen_test +68 -0
  9. data/examples/intro.rb +52 -0
  10. data/examples/scrolling.rb +54 -0
  11. data/lib/whirled_peas.rb +6 -12
  12. data/lib/whirled_peas/animator.rb +5 -0
  13. data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
  14. data/lib/whirled_peas/animator/easing.rb +72 -0
  15. data/lib/whirled_peas/animator/frame.rb +5 -0
  16. data/lib/whirled_peas/animator/frameset.rb +33 -0
  17. data/lib/whirled_peas/animator/producer.rb +35 -0
  18. data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
  19. data/lib/whirled_peas/command.rb +5 -0
  20. data/lib/whirled_peas/command/base.rb +86 -0
  21. data/lib/whirled_peas/command/config_command.rb +44 -0
  22. data/lib/whirled_peas/command/debug.rb +21 -0
  23. data/lib/whirled_peas/command/fonts.rb +22 -0
  24. data/lib/whirled_peas/command/frame_command.rb +34 -0
  25. data/lib/whirled_peas/command/frames.rb +24 -0
  26. data/lib/whirled_peas/command/help.rb +38 -0
  27. data/lib/whirled_peas/command/play.rb +108 -0
  28. data/lib/whirled_peas/command/record.rb +57 -0
  29. data/lib/whirled_peas/command/still.rb +29 -0
  30. data/lib/whirled_peas/command_line.rb +23 -228
  31. data/lib/whirled_peas/config.rb +56 -6
  32. data/lib/whirled_peas/device.rb +5 -0
  33. data/lib/whirled_peas/device/null_device.rb +8 -0
  34. data/lib/whirled_peas/device/output_file.rb +19 -0
  35. data/lib/whirled_peas/device/screen.rb +26 -0
  36. data/lib/whirled_peas/errors.rb +2 -0
  37. data/lib/whirled_peas/graphics.rb +19 -0
  38. data/lib/whirled_peas/graphics/box_painter.rb +101 -0
  39. data/lib/whirled_peas/graphics/canvas.rb +118 -0
  40. data/lib/whirled_peas/graphics/composer.rb +80 -0
  41. data/lib/whirled_peas/graphics/container_coords.rb +72 -0
  42. data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
  43. data/lib/whirled_peas/graphics/container_painter.rb +363 -0
  44. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  45. data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
  46. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  47. data/lib/whirled_peas/graphics/painter.rb +33 -0
  48. data/lib/whirled_peas/graphics/renderer.rb +32 -0
  49. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  50. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  51. data/lib/whirled_peas/settings.rb +5 -0
  52. data/lib/whirled_peas/settings/alignment.rb +24 -0
  53. data/lib/whirled_peas/settings/bg_color.rb +24 -0
  54. data/lib/whirled_peas/settings/border.rb +101 -0
  55. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  56. data/lib/whirled_peas/settings/color.rb +68 -0
  57. data/lib/whirled_peas/settings/container_settings.rb +223 -0
  58. data/lib/whirled_peas/settings/debugger.rb +96 -0
  59. data/lib/whirled_peas/settings/display_flow.rb +27 -0
  60. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  61. data/lib/whirled_peas/settings/grid_settings.rb +19 -0
  62. data/lib/whirled_peas/settings/margin.rb +8 -0
  63. data/lib/whirled_peas/settings/padding.rb +8 -0
  64. data/lib/whirled_peas/settings/position.rb +15 -0
  65. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  66. data/lib/whirled_peas/settings/sizing.rb +19 -0
  67. data/lib/whirled_peas/settings/spacing.rb +58 -0
  68. data/lib/whirled_peas/settings/text_color.rb +21 -0
  69. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  70. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  71. data/lib/whirled_peas/utils/ansi.rb +19 -56
  72. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  73. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  74. data/lib/whirled_peas/utils/title_font.rb +1 -1
  75. data/lib/whirled_peas/version.rb +1 -1
  76. data/screen_test/elements/box.frame +1 -0
  77. data/screen_test/elements/box.rb +20 -0
  78. data/screen_test/elements/grid.frame +1 -0
  79. data/screen_test/elements/grid.rb +13 -0
  80. data/screen_test/elements/screen_overflow_x.frame +1 -0
  81. data/screen_test/elements/screen_overflow_x.rb +9 -0
  82. data/screen_test/elements/screen_overflow_y.frame +1 -0
  83. data/screen_test/elements/screen_overflow_y.rb +9 -0
  84. data/screen_test/elements/text.frame +1 -0
  85. data/screen_test/elements/text.rb +9 -0
  86. data/screen_test/elements/text_multiline.frame +1 -0
  87. data/screen_test/elements/text_multiline.rb +9 -0
  88. data/screen_test/settings/align/box_around.frame +1 -0
  89. data/screen_test/settings/align/box_around.rb +16 -0
  90. data/screen_test/settings/align/box_between.frame +1 -0
  91. data/screen_test/settings/align/box_between.rb +16 -0
  92. data/screen_test/settings/align/box_center.frame +1 -0
  93. data/screen_test/settings/align/box_center.rb +21 -0
  94. data/screen_test/settings/align/box_default.frame +1 -0
  95. data/screen_test/settings/align/box_default.rb +20 -0
  96. data/screen_test/settings/align/box_evenly.frame +1 -0
  97. data/screen_test/settings/align/box_evenly.rb +16 -0
  98. data/screen_test/settings/align/box_left.frame +1 -0
  99. data/screen_test/settings/align/box_left.rb +21 -0
  100. data/screen_test/settings/align/box_right.frame +1 -0
  101. data/screen_test/settings/align/box_right.rb +21 -0
  102. data/screen_test/settings/align/children_center.frame +1 -0
  103. data/screen_test/settings/align/children_center.rb +15 -0
  104. data/screen_test/settings/align/children_left.frame +1 -0
  105. data/screen_test/settings/align/children_left.rb +15 -0
  106. data/screen_test/settings/align/children_right.frame +1 -0
  107. data/screen_test/settings/align/children_right.rb +15 -0
  108. data/screen_test/settings/align/grid_center.frame +1 -0
  109. data/screen_test/settings/align/grid_center.rb +18 -0
  110. data/screen_test/settings/align/grid_default.frame +1 -0
  111. data/screen_test/settings/align/grid_default.rb +17 -0
  112. data/screen_test/settings/align/grid_left.frame +1 -0
  113. data/screen_test/settings/align/grid_left.rb +18 -0
  114. data/screen_test/settings/align/grid_right.frame +1 -0
  115. data/screen_test/settings/align/grid_right.rb +18 -0
  116. data/screen_test/settings/ansi/bold.frame +1 -0
  117. data/screen_test/settings/ansi/bold.rb +14 -0
  118. data/screen_test/settings/ansi/color.frame +1 -0
  119. data/screen_test/settings/ansi/color.rb +37 -0
  120. data/screen_test/settings/ansi/underline.frame +1 -0
  121. data/screen_test/settings/ansi/underline.rb +14 -0
  122. data/screen_test/settings/border.frame +1 -0
  123. data/screen_test/settings/border.rb +13 -0
  124. data/screen_test/settings/flow/box_b2t.frame +1 -0
  125. data/screen_test/settings/flow/box_b2t.rb +26 -0
  126. data/screen_test/settings/flow/box_l2r.frame +1 -0
  127. data/screen_test/settings/flow/box_l2r.rb +26 -0
  128. data/screen_test/settings/flow/box_r2l.frame +1 -0
  129. data/screen_test/settings/flow/box_r2l.rb +26 -0
  130. data/screen_test/settings/flow/box_t2b.frame +1 -0
  131. data/screen_test/settings/flow/box_t2b.rb +26 -0
  132. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  133. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  134. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  135. data/screen_test/settings/flow/grid_l2r.rb +14 -0
  136. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  137. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  138. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  139. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  140. data/screen_test/settings/height/box.frame +1 -0
  141. data/screen_test/settings/height/box.rb +13 -0
  142. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  143. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  144. data/screen_test/settings/height/grid.frame +1 -0
  145. data/screen_test/settings/height/grid.rb +14 -0
  146. data/screen_test/settings/height/overflow_box.frame +1 -0
  147. data/screen_test/settings/height/overflow_box.rb +13 -0
  148. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  149. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  150. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  151. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  152. data/screen_test/settings/height/overflow_grid.frame +1 -0
  153. data/screen_test/settings/height/overflow_grid.rb +16 -0
  154. data/screen_test/settings/margin.frame +1 -0
  155. data/screen_test/settings/margin.rb +16 -0
  156. data/screen_test/settings/padding.frame +1 -0
  157. data/screen_test/settings/padding.rb +13 -0
  158. data/screen_test/settings/position/box_left.frame +1 -0
  159. data/screen_test/settings/position/box_left.rb +17 -0
  160. data/screen_test/settings/position/box_left_negative.frame +1 -0
  161. data/screen_test/settings/position/box_left_negative.rb +17 -0
  162. data/screen_test/settings/position/box_top.frame +1 -0
  163. data/screen_test/settings/position/box_top.rb +17 -0
  164. data/screen_test/settings/position/box_top_negative.frame +1 -0
  165. data/screen_test/settings/position/box_top_negative.rb +17 -0
  166. data/screen_test/settings/position/grid_left.frame +1 -0
  167. data/screen_test/settings/position/grid_left.rb +18 -0
  168. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  169. data/screen_test/settings/position/grid_left_negative.rb +18 -0
  170. data/screen_test/settings/position/grid_top.frame +1 -0
  171. data/screen_test/settings/position/grid_top.rb +18 -0
  172. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  173. data/screen_test/settings/position/grid_top_negative.rb +18 -0
  174. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  175. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  176. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  177. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  178. data/screen_test/settings/scroll/vert_box.frame +1 -0
  179. data/screen_test/settings/scroll/vert_box.rb +20 -0
  180. data/screen_test/settings/title_font.frame +1 -0
  181. data/screen_test/settings/title_font.rb +12 -0
  182. data/screen_test/settings/valign/box_around.frame +1 -0
  183. data/screen_test/settings/valign/box_around.rb +17 -0
  184. data/screen_test/settings/valign/box_between.frame +1 -0
  185. data/screen_test/settings/valign/box_between.rb +17 -0
  186. data/screen_test/settings/valign/box_bottom.frame +1 -0
  187. data/screen_test/settings/valign/box_bottom.rb +17 -0
  188. data/screen_test/settings/valign/box_default.frame +1 -0
  189. data/screen_test/settings/valign/box_default.rb +16 -0
  190. data/screen_test/settings/valign/box_evenly.frame +1 -0
  191. data/screen_test/settings/valign/box_evenly.rb +17 -0
  192. data/screen_test/settings/valign/box_middle.frame +1 -0
  193. data/screen_test/settings/valign/box_middle.rb +17 -0
  194. data/screen_test/settings/valign/box_top.frame +1 -0
  195. data/screen_test/settings/valign/box_top.rb +17 -0
  196. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  197. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  198. data/screen_test/settings/valign/grid_default.frame +1 -0
  199. data/screen_test/settings/valign/grid_default.rb +14 -0
  200. data/screen_test/settings/valign/grid_middle.frame +1 -0
  201. data/screen_test/settings/valign/grid_middle.rb +15 -0
  202. data/screen_test/settings/valign/grid_top.frame +1 -0
  203. data/screen_test/settings/valign/grid_top.rb +15 -0
  204. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  205. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  206. data/screen_test/settings/width/box_content.frame +1 -0
  207. data/screen_test/settings/width/box_content.rb +15 -0
  208. data/screen_test/settings/width/box_default.frame +1 -0
  209. data/screen_test/settings/width/box_default.rb +14 -0
  210. data/screen_test/settings/width/grid.frame +1 -0
  211. data/screen_test/settings/width/grid.rb +14 -0
  212. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  213. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  214. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  215. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  216. data/screen_test/settings/width/overflow_box.frame +1 -0
  217. data/screen_test/settings/width/overflow_box.rb +13 -0
  218. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  219. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  220. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  221. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  222. data/screen_test/settings/width/overflow_grid.frame +1 -0
  223. data/screen_test/settings/width/overflow_grid.rb +14 -0
  224. data/tools/whirled_peas/tools/screen_tester.rb +285 -0
  225. metadata +213 -15
  226. data/bin/title_fonts +0 -6
  227. data/lib/whirled_peas/frame.rb +0 -7
  228. data/lib/whirled_peas/frame/event_loop.rb +0 -91
  229. data/lib/whirled_peas/frame/print_consumer.rb +0 -33
  230. data/lib/whirled_peas/frame/producer.rb +0 -61
  231. data/lib/whirled_peas/template.rb +0 -5
  232. data/lib/whirled_peas/template/element.rb +0 -230
  233. data/lib/whirled_peas/template/settings.rb +0 -530
  234. data/lib/whirled_peas/ui.rb +0 -5
  235. data/lib/whirled_peas/ui/canvas.rb +0 -68
  236. data/lib/whirled_peas/ui/painter.rb +0 -287
  237. data/lib/whirled_peas/ui/screen.rb +0 -63
  238. data/lib/whirled_peas/utils/color.rb +0 -101
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 563cc06007d90aa0599b61c5366a5d9b2c5224ec2973367b6c358cad95ddaedc
4
- data.tar.gz: fa798abdfb8a8e4fd229f08b964c8ee4f4d480939ece9ddaeb5731c171985504
3
+ metadata.gz: 9652a887fc6a68ba5367864a25b4a211674433eae86a2f68db3923e873ab49e8
4
+ data.tar.gz: 72926cd288adc3c30393990d88dcc0bca53e2fbfe79d56768e438ffaee2cf3ba
5
5
  SHA512:
6
- metadata.gz: 1be24e74d75f87a001b26f216e320d4a4680c48513e48c42047d2c2168a9404471704731df97ced5954facdc4ca7316580f6078db5670e45067c7e8ed3ee4cd3
7
- data.tar.gz: 86f3b995575fc7ff8b6bb83adf368182a684faece1584cffb7b1150bd47ce082adaba5b0d4ce0b83d19d2ec2d795bd31db19d35c990e6d0065698c050161bcd0
6
+ metadata.gz: 9e0124bd724ece36b76e1d527ffb3ccd5a06e9cd7f00c1ae5d0c39445d0c4ed4804d8c2cdc0c3df250f0d927b9927efd97d118fd0fd76bbc42277fda68a674cb
7
+ data.tar.gz: '09edc4873598d1363d7d3ef2c548699bcbfa229a8821e458c201608ec9f7e3aba8cf2f081f559edc51c04244267f569e8444b7952b21ab41bfea8a7807c0432a'
data/.gitignore CHANGED
@@ -11,4 +11,5 @@ Gemfile.lock
11
11
 
12
12
  # rspec failure tracking
13
13
  .rspec_status
14
+ *.wpz
14
15
 
@@ -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,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
  [![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
4
12
 
5
- Visualize your code's execution with Whirled Peas!
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 driver (required) - the code that is to be visualized, it emits lightweight frame events through a producer
28
- - The main template factory (required) - builds templates to convert frame events from the driver into terminal graphics
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 |body|
40
- body.add_box('Title') do |_, settings|
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 Driver
64
+ class Application
50
65
  def start(producer)
51
- producer.send_frame('starting', args: { name: 'World' })
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.driver = Driver.new
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 start visualize.rb
80
+ $ whirled_peas play visualize.rb
66
81
  ```
67
82
 
68
- The optional loading screen can be configured like
83
+ ### Application
69
84
 
70
- ```ruby
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 send_frame(name, duration:, args:)
104
+ def add_frame(name, duration:, args:)
112
105
  # implementation
113
106
  end
114
107
  ```
115
108
 
116
- **IMPORTANT**: the keys for arguments must be symbols.
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 Driver
116
+ class Application
124
117
  def start(producer)
125
118
  numbers = File.readlines('/path/to/numbers.txt').map(&:to_i)
126
- producer.send_frame('load-numbers', duration: 3, args: { numbers: numbers })
119
+ producer.add_frame('load-numbers', duration: 3, args: { numbers: numbers })
127
120
  numbers.sort!
128
- producer.send_frame('sort-numbers', duration: 3, args: { numbers: numbers })
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.send_frame('found-pair', duration: 5, args: { low: low, high: high, sum: sum })
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.send_frame('too-low', args: { low: low, high: high, sum: sum })
130
+ producer.add_frame('too-low', args: { low: low, high: high, sum: sum })
138
131
  low += 1
139
132
  else
140
- producer.send_frame('too-high', args: { low: low, high: high, sum: sum })
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.send_frame('no-solution', duration: 5)
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 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.
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 `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.
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
- 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).
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
- - `add_box` - yields a `ComposableElement` and a `BoxSettings`, which will be added to the parent's children
164
- - `add_grid` - yields a `ComposableElement` and a `GridSettings`, which will be added to the parent's children
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 |template, template_settings|
171
- template_settings.bg_color = :blue
172
- template.add_grid do |grid, grid_settings|
173
- grid_settings.num_cols = 10
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
- grid.add_text { i }
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(grid, settings)
178
+ def number_grid(_composer, settings)
185
179
  settings.num_cols = 10
186
- 100.times do |i|
187
- grid.add_text { i }
188
- end
180
+ 100.times.map(&:itself)
189
181
  end
190
182
 
191
- WhirledPeas.template do |template, settings|
183
+ WhirledPeas.template do |composer, settings|
192
184
  settings.bg_color = :blue
193
- template.add_grid(&method(:number_grid))
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 `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
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 |g|
192
+ template.add_grid do |composer|
201
193
  100.times do |i|
202
- g.add_text { i }
194
+ composer.add_text { i }
203
195
  end
204
196
  end
205
197
 
206
- template.add_grid do |g|
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 `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
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 |b|
215
- b.add_text { "Hello!" }
206
+ template.add_box do |composer|
207
+ composer.add_text { "Hello!" }
216
208
  end
217
209
 
218
- template.add_box do |b|
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. Parent settings may be merged into child settings (assuming the child supports those settings)
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 | Description | Default | Availability | Merged? |
229
- | ------------- | ------------------------------------------------------------------ | ------- | --------------------------------- | ------- |
230
- | `align` | Justifies the text (allowed values: `:left`, `:center`, `:right`) | `:left` | `Box`, `Grid`, `Text` | Yes |
231
- | `auto_margin` | Evenly distribute side margin (overrides left/right in `margin`) | `false` | `Box`, `Grid` | Yes |
232
- | `bg_color` | Background color (see [Colors](#colors)) | | `Box`, `Grid`, `Template`, `Text` | Yes |
233
- | `bold` | `true` makes the font bold | `false` | `Box`, `Grid`, `Template`, `Text` | Yes |
234
- | `border` | Set the border for the lements | none | `Box`, `Grid`, | Yes |
235
- | `color` | Foreground text color (see [Colors](#colors)) | | `Box`, `Grid`, `Template`, `Text` | Yes |
236
- | `flow` | Flow to display child elements (see [Display Flow](#display-flow)) | `:l2r` | `Box` | Yes |
237
- | `margin` | Set the (left, top, right, bottom) margin of the element | `0` | `Box`, `Grid` | Yes |
238
- | `padding` | Set the (left, top, right, bottom) padding of the element | `0` | `Box`, `Grid` | Yes |
239
- | `title_font` | Font used to create "large" text (see [Large Text](#large-text)) | | `Text` |
240
- | `transpose` | Display grid elements top-to-bottom, then left-to-right | `false` | `Grid` | No |
241
- | `underline` | `true` underlines the font | `false` | `Box`, `Grid`, `Template`, `Text` | Yes |
242
- | `width` | Override the calculated with of an element | | `Box`, `Grid`, `Text` | No |
243
-
244
- ##### Margin and Padding
245
-
246
- Margin and padding settings allow for setting the spacing on each of the 4 sides of the element independently. The set these values, use
247
-
248
- - `clear_margin` - sets all margin values to 0
249
- - `set_margin(left:, top:, right:, bottom:)`
250
- - `clear_padding` - sets all margin values to 0
251
- - `set_padding(left:, top:, right:, bottom:)`
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
- - `clear_border` - sets all border positions to `false`
258
- - `set_border(left:, top:, right:, bottom:, inner_horiz:, inner_vert:, color:, style:)`
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
- [child 1] [child 2] ... [child N]
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
- [child N] [child N - 1] ... [child 1]
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
- [child 1]
312
- [child 2]
313
- ...
314
- [child N]
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
- [child N]
321
- [child N - 1]
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 `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
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 |t|
377
- t.add_box('Body', &method(:body))
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(_elem, settings)
700
+ def title(_composer, settings)
392
701
  settings.underline = true
393
702
  "Pair Finder"
394
703
  end
395
704
 
396
- def sum(_elem, settings)
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(elem, settings)
710
+ def number_grid(composer, settings)
402
711
  settings.full_border
403
712
  @numbers.each.with_index do |num, index|
404
- g.add_text do |_, settings|
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
- def body(elem, settings)
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
- ### Debugging
727
+ Available commands:
423
728
 
424
- The `whirled_peas` executable provides some commands that are helpful for debugging.
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
- #### list_frames
738
+ #### `debug`
427
739
 
428
- List the frames sent by the driver
740
+ Print the template tree for specified frame.
429
741
 
430
742
  ```
431
- $ whirled_peas <config file> list_frames
432
- Frame 'start' displayed for 5 second(s)
433
- Frame 'move' displayed for 1 frame ({:direction=>'N'})
434
- ...
435
- EOF frame detected
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
- #### play_frame
760
+ #### `fonts`
439
761
 
440
- Displays a single frame for several seconds
762
+ List all installed title fonts with sample text.
441
763
 
442
764
  ```
443
- $ whirled_peas <config file> play_frame move '{"direction":"N"}'
765
+ # Usage: whirled_peas fonts
444
766
  ```
445
767
 
446
- Adding the `--debug` flag will result in just printing out the template's debug information, e.g.
768
+ #### `frames`
769
+
770
+ Print out list of frames generated by application.
447
771
 
448
772
  ```
449
- $ whirled_peas <config file> play_frame move '{"direction":"N"}' --debug
450
- + TEMPLATE [WhirledPeas::UI::Template]
451
- - Settings
452
- WhirledPeas::UI::TemplateSettings
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
- #### loading
780
+ #### `help`
460
781
 
461
- Displays the configured loading screen for several seconds
782
+ Print out command-specific help message
462
783
 
463
784
  ```
464
- $ whirled_peas <config file> loading
785
+ Usage: whirled_peas help <command>
465
786
  ```
466
787
 
467
- Adding the `--debug` flag will result in just printing out the loading template's debug information, e.g.
788
+ #### `play`
789
+
790
+ Play an animation from an application or prerecorded file
468
791
 
469
792
  ```
470
- $ whirled_peas <config file> loading --debug
471
- + TEMPLATE [WhirledPeas::UI::Template]
472
- - Settings
473
- WhirledPeas::UI::TemplateSettings
474
- <default>
475
- - Children
476
- + TitleContainer [WhirledPeas::UI::BoxElement]
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
+ ```