whirled_peas 0.9.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/CHANGELOG.md +21 -0
  4. data/README.md +9 -1053
  5. data/doc/application.md +92 -0
  6. data/doc/cli.md +115 -0
  7. data/doc/components.md +51 -0
  8. data/doc/easing.md +257 -0
  9. data/doc/elements.md +69 -0
  10. data/doc/screen_test.md +23 -0
  11. data/doc/settings.md +466 -0
  12. data/doc/template_factory.md +53 -0
  13. data/doc/themes.md +50 -0
  14. data/examples/components.rb +33 -0
  15. data/examples/graph.rb +1 -1
  16. data/examples/scrolling.rb +8 -19
  17. data/lib/data/themes.yaml +17 -0
  18. data/lib/whirled_peas.rb +31 -9
  19. data/lib/whirled_peas/animator/debug_consumer.rb +2 -2
  20. data/lib/whirled_peas/animator/easing.rb +57 -0
  21. data/lib/whirled_peas/animator/frameset.rb +13 -8
  22. data/lib/whirled_peas/animator/producer.rb +7 -8
  23. data/lib/whirled_peas/animator/renderer_consumer.rb +7 -5
  24. data/lib/whirled_peas/command/config_command.rb +3 -3
  25. data/lib/whirled_peas/command/frames.rb +1 -3
  26. data/lib/whirled_peas/command/play.rb +9 -7
  27. data/lib/whirled_peas/command/record.rb +1 -3
  28. data/lib/whirled_peas/command/still.rb +6 -2
  29. data/lib/whirled_peas/command/themes.rb +78 -0
  30. data/lib/whirled_peas/command_line.rb +3 -1
  31. data/lib/whirled_peas/component.rb +35 -0
  32. data/lib/whirled_peas/component/list_with_active.rb +88 -0
  33. data/lib/whirled_peas/config.rb +1 -8
  34. data/lib/whirled_peas/device/null_device.rb +1 -1
  35. data/lib/whirled_peas/device/output_file.rb +2 -2
  36. data/lib/whirled_peas/device/rendered_frame.rb +12 -0
  37. data/lib/whirled_peas/device/screen.rb +12 -8
  38. data/lib/whirled_peas/graphics/box_painter.rb +4 -4
  39. data/lib/whirled_peas/graphics/composer.rb +9 -2
  40. data/lib/whirled_peas/graphics/container_coords.rb +23 -25
  41. data/lib/whirled_peas/graphics/container_dimensions.rb +24 -0
  42. data/lib/whirled_peas/graphics/container_painter.rb +27 -139
  43. data/lib/whirled_peas/graphics/debugger.rb +2 -7
  44. data/lib/whirled_peas/graphics/graph_painter.rb +31 -22
  45. data/lib/whirled_peas/graphics/pixel_grid.rb +44 -0
  46. data/lib/whirled_peas/graphics/renderer.rb +4 -5
  47. data/lib/whirled_peas/graphics/scrollbar_helper.rb +126 -0
  48. data/lib/whirled_peas/null_logger.rb +0 -1
  49. data/lib/whirled_peas/settings/bg_color.rb +5 -1
  50. data/lib/whirled_peas/settings/border.rb +25 -4
  51. data/lib/whirled_peas/settings/color.rb +8 -4
  52. data/lib/whirled_peas/settings/container_settings.rb +14 -7
  53. data/lib/whirled_peas/settings/debugger.rb +3 -1
  54. data/lib/whirled_peas/settings/element_settings.rb +18 -6
  55. data/lib/whirled_peas/settings/graph_settings.rb +1 -1
  56. data/lib/whirled_peas/settings/position.rb +17 -5
  57. data/lib/whirled_peas/settings/text_color.rb +5 -0
  58. data/lib/whirled_peas/settings/text_settings.rb +1 -0
  59. data/lib/whirled_peas/settings/theme.rb +61 -0
  60. data/lib/whirled_peas/settings/theme_library.rb +69 -0
  61. data/lib/whirled_peas/utils/ansi.rb +4 -2
  62. data/lib/whirled_peas/utils/file_handler.rb +14 -9
  63. data/lib/whirled_peas/utils/formatted_string.rb +5 -3
  64. data/lib/whirled_peas/version.rb +1 -1
  65. data/screen_test/components/list_with_active/l2r_position_end.frame +1 -0
  66. data/screen_test/components/list_with_active/l2r_position_end.rb +16 -0
  67. data/screen_test/components/list_with_active/l2r_position_middle.frame +1 -0
  68. data/screen_test/components/list_with_active/l2r_position_middle.rb +16 -0
  69. data/screen_test/components/list_with_active/l2r_position_start.frame +1 -0
  70. data/screen_test/components/list_with_active/l2r_position_start.rb +16 -0
  71. data/screen_test/components/list_with_active/l2r_separator.frame +1 -0
  72. data/screen_test/components/list_with_active/l2r_separator.rb +17 -0
  73. data/screen_test/components/list_with_active/t2b_position_end.frame +1 -0
  74. data/screen_test/components/list_with_active/t2b_position_end.rb +17 -0
  75. data/screen_test/components/list_with_active/t2b_position_middle.frame +1 -0
  76. data/screen_test/components/list_with_active/t2b_position_middle.rb +17 -0
  77. data/screen_test/components/list_with_active/t2b_position_start.frame +1 -0
  78. data/screen_test/components/list_with_active/t2b_position_start.rb +17 -0
  79. data/screen_test/components/list_with_active/t2b_separator.frame +1 -0
  80. data/screen_test/components/list_with_active/t2b_separator.rb +18 -0
  81. data/screen_test/elements/box.frame +1 -1
  82. data/screen_test/elements/box.rb +1 -1
  83. data/screen_test/elements/graph_asc.frame +1 -0
  84. data/screen_test/elements/{graph.rb → graph_asc.rb} +1 -1
  85. data/screen_test/elements/graph_desc.frame +1 -0
  86. data/screen_test/elements/graph_desc.rb +12 -0
  87. data/screen_test/elements/graph_horiz.frame +1 -0
  88. data/screen_test/elements/graph_horiz.rb +12 -0
  89. data/screen_test/elements/graph_sin.frame +1 -0
  90. data/screen_test/elements/graph_sin.rb +12 -0
  91. data/screen_test/elements/grid.frame +1 -1
  92. data/screen_test/elements/grid.rb +1 -1
  93. data/screen_test/elements/screen_overflow_x.frame +1 -1
  94. data/screen_test/elements/screen_overflow_x.rb +1 -1
  95. data/screen_test/elements/screen_overflow_y.frame +1 -1
  96. data/screen_test/elements/screen_overflow_y.rb +1 -1
  97. data/screen_test/elements/text.frame +1 -1
  98. data/screen_test/elements/text.rb +1 -1
  99. data/screen_test/elements/text_multiline.frame +1 -1
  100. data/screen_test/elements/text_multiline.rb +1 -1
  101. data/screen_test/elements/theme.frame +1 -0
  102. data/screen_test/elements/theme.rb +26 -0
  103. data/screen_test/settings/align/box_around.frame +1 -1
  104. data/screen_test/settings/align/box_around.rb +1 -1
  105. data/screen_test/settings/align/box_between.frame +1 -1
  106. data/screen_test/settings/align/box_between.rb +1 -1
  107. data/screen_test/settings/align/box_center.frame +1 -1
  108. data/screen_test/settings/align/box_center.rb +1 -1
  109. data/screen_test/settings/align/box_default.frame +1 -1
  110. data/screen_test/settings/align/box_default.rb +1 -1
  111. data/screen_test/settings/align/box_evenly.frame +1 -1
  112. data/screen_test/settings/align/box_evenly.rb +1 -1
  113. data/screen_test/settings/align/box_left.frame +1 -1
  114. data/screen_test/settings/align/box_left.rb +1 -1
  115. data/screen_test/settings/align/box_right.frame +1 -1
  116. data/screen_test/settings/align/box_right.rb +1 -1
  117. data/screen_test/settings/align/children_center.frame +1 -1
  118. data/screen_test/settings/align/children_center.rb +1 -1
  119. data/screen_test/settings/align/children_left.frame +1 -1
  120. data/screen_test/settings/align/children_left.rb +1 -1
  121. data/screen_test/settings/align/children_right.frame +1 -1
  122. data/screen_test/settings/align/children_right.rb +1 -1
  123. data/screen_test/settings/align/grid_center.frame +1 -1
  124. data/screen_test/settings/align/grid_center.rb +1 -1
  125. data/screen_test/settings/align/grid_default.frame +1 -1
  126. data/screen_test/settings/align/grid_default.rb +1 -1
  127. data/screen_test/settings/align/grid_left.frame +1 -1
  128. data/screen_test/settings/align/grid_left.rb +1 -1
  129. data/screen_test/settings/align/grid_right.frame +1 -1
  130. data/screen_test/settings/align/grid_right.rb +1 -1
  131. data/screen_test/settings/ansi/bold.frame +1 -1
  132. data/screen_test/settings/ansi/bold.rb +1 -1
  133. data/screen_test/settings/ansi/color.frame +1 -1
  134. data/screen_test/settings/ansi/color.rb +1 -1
  135. data/screen_test/settings/ansi/underline.frame +1 -1
  136. data/screen_test/settings/ansi/underline.rb +1 -1
  137. data/screen_test/settings/border.frame +1 -1
  138. data/screen_test/settings/border.rb +1 -1
  139. data/screen_test/settings/content_start/box_bottom.frame +1 -0
  140. data/screen_test/settings/content_start/box_bottom.rb +17 -0
  141. data/screen_test/settings/content_start/box_left.frame +1 -0
  142. data/screen_test/settings/{position → content_start}/box_left.rb +2 -2
  143. data/screen_test/settings/content_start/box_left_negative.frame +1 -0
  144. data/screen_test/settings/{position → content_start}/box_left_negative.rb +2 -2
  145. data/screen_test/settings/content_start/box_right.frame +1 -0
  146. data/screen_test/settings/content_start/box_right.rb +17 -0
  147. data/screen_test/settings/content_start/box_top.frame +1 -0
  148. data/screen_test/settings/{position → content_start}/box_top.rb +2 -2
  149. data/screen_test/settings/content_start/box_top_negative.frame +1 -0
  150. data/screen_test/settings/{position → content_start}/box_top_negative.rb +2 -2
  151. data/screen_test/settings/content_start/grid_left.frame +1 -0
  152. data/screen_test/settings/{position → content_start}/grid_left.rb +2 -2
  153. data/screen_test/settings/content_start/grid_left_negative.frame +1 -0
  154. data/screen_test/settings/{position → content_start}/grid_left_negative.rb +2 -2
  155. data/screen_test/settings/content_start/grid_top.frame +1 -0
  156. data/screen_test/settings/{position → content_start}/grid_top.rb +2 -2
  157. data/screen_test/settings/content_start/grid_top_negative.frame +1 -0
  158. data/screen_test/settings/{position → content_start}/grid_top_negative.rb +2 -2
  159. data/screen_test/settings/flow/box_b2t.frame +1 -1
  160. data/screen_test/settings/flow/box_b2t.rb +1 -1
  161. data/screen_test/settings/flow/box_l2r.frame +1 -1
  162. data/screen_test/settings/flow/box_l2r.rb +1 -1
  163. data/screen_test/settings/flow/box_r2l.frame +1 -1
  164. data/screen_test/settings/flow/box_r2l.rb +1 -1
  165. data/screen_test/settings/flow/box_t2b.frame +1 -1
  166. data/screen_test/settings/flow/box_t2b.rb +1 -1
  167. data/screen_test/settings/flow/grid_b2t.frame +1 -1
  168. data/screen_test/settings/flow/grid_b2t.rb +1 -1
  169. data/screen_test/settings/flow/grid_l2r.frame +1 -1
  170. data/screen_test/settings/flow/grid_l2r.rb +1 -1
  171. data/screen_test/settings/flow/grid_r2l.frame +1 -1
  172. data/screen_test/settings/flow/grid_r2l.rb +1 -1
  173. data/screen_test/settings/flow/grid_t2b.frame +1 -1
  174. data/screen_test/settings/flow/grid_t2b.rb +1 -1
  175. data/screen_test/settings/height/box.frame +1 -1
  176. data/screen_test/settings/height/box.rb +1 -1
  177. data/screen_test/settings/height/box_border_sizing.frame +1 -1
  178. data/screen_test/settings/height/box_border_sizing.rb +1 -1
  179. data/screen_test/settings/height/grid.frame +1 -1
  180. data/screen_test/settings/height/grid.rb +1 -1
  181. data/screen_test/settings/height/overflow_box.frame +1 -1
  182. data/screen_test/settings/height/overflow_box.rb +1 -1
  183. data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
  184. data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
  185. data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
  186. data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
  187. data/screen_test/settings/height/overflow_grid.frame +1 -1
  188. data/screen_test/settings/height/overflow_grid.rb +1 -1
  189. data/screen_test/settings/margin.frame +1 -1
  190. data/screen_test/settings/margin.rb +1 -1
  191. data/screen_test/settings/padding.frame +1 -1
  192. data/screen_test/settings/padding.rb +1 -1
  193. data/screen_test/settings/scroll/horiz_box.frame +1 -1
  194. data/screen_test/settings/scroll/horiz_box.rb +3 -5
  195. data/screen_test/settings/scroll/horiz_box_align_center.rb +3 -5
  196. data/screen_test/settings/scroll/horiz_box_align_right.rb +3 -5
  197. data/screen_test/settings/scroll/vert_box.frame +1 -1
  198. data/screen_test/settings/scroll/vert_box.rb +6 -8
  199. data/screen_test/settings/title_font.frame +1 -1
  200. data/screen_test/settings/title_font.rb +1 -1
  201. data/screen_test/settings/valign/box_around.frame +1 -1
  202. data/screen_test/settings/valign/box_around.rb +1 -1
  203. data/screen_test/settings/valign/box_between.frame +1 -1
  204. data/screen_test/settings/valign/box_between.rb +1 -1
  205. data/screen_test/settings/valign/box_bottom.frame +1 -1
  206. data/screen_test/settings/valign/box_bottom.rb +1 -1
  207. data/screen_test/settings/valign/box_default.frame +1 -1
  208. data/screen_test/settings/valign/box_default.rb +1 -1
  209. data/screen_test/settings/valign/box_evenly.frame +1 -1
  210. data/screen_test/settings/valign/box_evenly.rb +1 -1
  211. data/screen_test/settings/valign/box_middle.frame +1 -1
  212. data/screen_test/settings/valign/box_middle.rb +1 -1
  213. data/screen_test/settings/valign/box_top.frame +1 -1
  214. data/screen_test/settings/valign/box_top.rb +1 -1
  215. data/screen_test/settings/valign/grid_bottom.frame +1 -1
  216. data/screen_test/settings/valign/grid_bottom.rb +1 -1
  217. data/screen_test/settings/valign/grid_default.frame +1 -1
  218. data/screen_test/settings/valign/grid_default.rb +1 -1
  219. data/screen_test/settings/valign/grid_middle.frame +1 -1
  220. data/screen_test/settings/valign/grid_middle.rb +1 -1
  221. data/screen_test/settings/valign/grid_top.frame +1 -1
  222. data/screen_test/settings/valign/grid_top.rb +1 -1
  223. data/screen_test/settings/width/box_border_sizing.frame +1 -1
  224. data/screen_test/settings/width/box_border_sizing.rb +1 -1
  225. data/screen_test/settings/width/box_content.frame +1 -1
  226. data/screen_test/settings/width/box_content.rb +1 -1
  227. data/screen_test/settings/width/box_default.frame +1 -1
  228. data/screen_test/settings/width/box_default.rb +1 -1
  229. data/screen_test/settings/width/grid.frame +1 -1
  230. data/screen_test/settings/width/grid.rb +1 -1
  231. data/screen_test/settings/width/overflow_align_center.frame +1 -1
  232. data/screen_test/settings/width/overflow_align_center.rb +1 -1
  233. data/screen_test/settings/width/overflow_align_right.frame +1 -1
  234. data/screen_test/settings/width/overflow_align_right.rb +1 -1
  235. data/screen_test/settings/width/overflow_box.frame +1 -1
  236. data/screen_test/settings/width/overflow_box.rb +1 -1
  237. data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
  238. data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
  239. data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
  240. data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
  241. data/screen_test/settings/width/overflow_grid.frame +1 -1
  242. data/screen_test/settings/width/overflow_grid.rb +1 -1
  243. data/tools/whirled_peas/tools/screen_tester.rb +20 -3
  244. metadata +67 -22
  245. data/bin/easing +0 -33
  246. data/lib/whirled_peas/graphics/mock_screen.rb +0 -26
  247. data/screen_test/elements/graph.frame +0 -1
  248. data/screen_test/settings/position/box_left.frame +0 -1
  249. data/screen_test/settings/position/box_left_negative.frame +0 -1
  250. data/screen_test/settings/position/box_top.frame +0 -1
  251. data/screen_test/settings/position/box_top_negative.frame +0 -1
  252. data/screen_test/settings/position/grid_left.frame +0 -1
  253. data/screen_test/settings/position/grid_left_negative.frame +0 -1
  254. data/screen_test/settings/position/grid_top.frame +0 -1
  255. data/screen_test/settings/position/grid_top_negative.frame +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7553fd2ea78bf560098d8be8cd3987f1e8a686cb000cf6ea082a922512764069
4
- data.tar.gz: 8fa1e64c35b311ae9346badc0198f556528c53dad9bfa0b99b2805c901369b8f
3
+ metadata.gz: 1c57dd3e70f4d79c41731d220f9cb3f7fec0a3e554a715f7da556dec5e0a5cde
4
+ data.tar.gz: 736d62121796101237e9aaa4fc5f37b0fe59f6d8c7670b149e63e0faf0ff9f3e
5
5
  SHA512:
6
- metadata.gz: 531b93061429918f99dc5aa7de09a53a7fda218c97bac57b47d5a450ad22510207f71ba5a095f5a1939e4cce9d1f13d70a981e15b4e3209d0786ba12be048bd6
7
- data.tar.gz: ea7daec0ccd65894bec99bfff75219d55dfc2cd9fc7b80d1e593b60e7a15a3e8eb7cbfa49e8ef20e8da5acbce2738d054cf56a9b0231661e46a5c399c83b8906
6
+ metadata.gz: 1823dc0eba84af3a78992c349c1d922bfd7837452133a0e1b6e35de2fe1d94ad589b0eda8cf5c7a70ae41ec92345ef8dcde6c2e0eeb63193de806582a5d2578a
7
+ data.tar.gz: d10d355b30e2cc1a0cc15413c5681b04135ec7f53a2e20e9a4ea307a8ae9bd0b69fb04cacb494dcfee8b7a9d473ae852173d140a708d1bb04210084f824acd99
data/.gitignore CHANGED
@@ -2,7 +2,6 @@
2
2
  /.yardoc
3
3
  /_yardoc/
4
4
  /coverage/
5
- /doc/
6
5
  /pkg/
7
6
  /spec/reports/
8
7
  /tmp/
@@ -12,4 +11,3 @@ Gemfile.lock
12
11
  # rspec failure tracking
13
12
  .rspec_status
14
13
  *.wpz
15
-
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.12.0- 2021-01-31
4
+
5
+ - [f218ed5](https://github.com/tcollier/whirled_peas/tree/f218ed5a8bbc20fc332a42ad9720467784a916e2): Optimize rendered frames
6
+
7
+ ## v0.11.1 - 2021-01-31
8
+
9
+ - [36e48cf](https://github.com/tcollier/whirled_peas/tree/36e48cf6731706539c6c41ce0ef66e86c62380a5): Add highlight colors and border style to theme
10
+ - [93b1034](https://github.com/tcollier/whirled_peas/tree/93b1034b9401fe9e31cd3199a5e2426d7a893ed6): Better handling of non-ascending graphs
11
+
12
+ ## v0.11.0 - 2021-01-30
13
+
14
+ - [c1f3d94](https://github.com/tcollier/whirled_peas/tree/c1f3d944a35305c3032681db13ffd6142a7e19e4): Add component support
15
+
16
+ ## v0.10.0 - 2021-01-29
17
+
18
+ - [3063a2b](https://github.com/tcollier/whirled_peas/tree/3063a2becb7680b5e320a1733b3da933e6c65210): Add built-in and user-defined themes
19
+
20
+ ## v0.9.1 - 2021-01-29
21
+
22
+ - [c35b134](https://github.com/tcollier/whirled_peas/tree/c35b134e1340b8b5f1d1fb0e6e56dc2a99b52e94): Improve graph plots
23
+
3
24
  ## v0.9.0 - 2021-01-29
4
25
 
5
26
  BREAKING: `Frameset#add_frame` signature changed
data/README.md CHANGED
@@ -38,10 +38,10 @@ Or install it yourself as:
38
38
 
39
39
  ## Usage
40
40
 
41
- A Whirled Peas application consists of the following pieces
41
+ A Whirled Peas application consists of the following required pieces
42
42
 
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
43
+ - [The application](doc/application.md) - the code that is to be visualized, it dictates the frame contents and playback speed
44
+ - [The template factory](doc/template_factory.md) - builds templates to convert frame from the application into terminal graphics
45
45
 
46
46
  These pieces are configured as following
47
47
 
@@ -74,1063 +74,23 @@ WhirledPeas.configure do |config|
74
74
  end
75
75
  ```
76
76
 
77
- Then the visualizer is started on the command line with
77
+ Then the visualizer is started on the [command line](doc/cli.md) with
78
78
 
79
79
  ```
80
80
  $ whirled_peas play visualize.rb
81
81
  ```
82
82
 
83
- ### Application
84
-
85
- The application is code to be visualized that integrates with Whirled Peas by providing the signature below
86
-
87
- ```ruby
88
- # Start the application and pass frame events to the producer to be rendered by the UI
89
- #
90
- # @param producer [Producer] frame producer that sends events to the UI
91
- def start(producer)
92
- # application code here
93
- end
94
- ```
95
-
96
- The producer provides the following methods
97
-
98
- ```ruby
99
- # Add a frame to be displayed
100
- #
101
- # @param name [String] application defined name for the frame. The template factory will be provided this name
102
- # @param duration [Number] time in seconds this frame should be displayed for (defaults to 1 frame)
103
- # @param args [Hash<Symbol, Object>] key value pairs to send as arguments to the template factory
104
- def add_frame(name, duration:, args:)
105
- end
106
-
107
- # Create and yield a frameset instance that allows applications to add multiple frames to play over the
108
- # given duration. Adding frames to the yielded frameset will result in playback that is eased by the
109
- # gvien `easing` and `effect` arguments (default is `:linear` easing)
110
- def frameset(duration, easing:, effect:, &block)
111
- end
112
- ```
113
-
114
- A frameset instance provides one method
115
-
116
- ```ruby
117
- # Add a frame to be displayed, the duration will be determine by the number of frames in the frameset along
118
- # with the duration and easing of the frameset
119
- #
120
- # @param name [String] application defined name for the frame. The template factory will be provided this name
121
- # @param args [Hash<Symbol, Object>] key value pairs to send as arguments to the template factory
122
- def add_frame(name, args:)
123
- end
124
- ```
125
-
126
- **IMPORTANT**: the keys in the `args` hash must be symbols!
127
-
128
- #### Example
129
-
130
- Simple application that loads a set of numbers and looks for a pair that adds up to 1,000
131
-
132
- ```ruby
133
- class Application
134
- def start(producer)
135
- numbers = File.readlines('/path/to/numbers.txt').map(&:to_i)
136
- producer.add_frame('load-numbers', duration: 3, args: { numbers: numbers })
137
- numbers.sort!
138
- producer.add_frame('sort-numbers', duration: 3, args: { numbers: numbers })
139
- low = 0
140
- high = numbers.length - 1
141
- while low < high
142
- sum = numbers[low] + numbers[high]
143
- if sum == 1000
144
- producer.add_frame('found-pair', duration: 5, args: { low: low, high: high, sum: sum })
145
- return
146
- elsif sum < 1000
147
- producer.add_frame('too-low', args: { low: low, high: high, sum: sum })
148
- low += 1
149
- else
150
- producer.add_frame('too-high', args: { low: low, high: high, sum: sum })
151
- high -= 1
152
- end
153
- end
154
- producer.add_frame('no-solution', duration: 5)
155
- end
156
- end
157
- ```
158
-
159
- ### Template Factory
160
-
161
- 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.
162
-
163
- #### Building Blocks
164
-
165
- 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
166
-
167
- - `margin` - all margin will be set to 0
168
- - `width` - will be set to the screen's width
169
- - `height` - will be set to the screen's height
170
- - `sizing` - will be set `:border` to ensure the entire box fits on the screen and fills it entirely.
171
-
172
- 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).
173
-
174
- - `add_box` - yields a `Composer` for a `Box` and a `BoxSettings`, which will be added to the parent's children
175
- - `add_graph` - yields a `nil` and a `GraphSettings`, which will be added to the parent's children, the block should return an array of numbers
176
- - `add_grid` - yields a `Composer` for a `Grid` and a `GridSettings`, which will be added to the parent's children
177
- - `add_text` - yields `nil` and a `TextSettings`, which will be added to the parent's children
178
-
179
- E.g.
180
-
181
- ```ruby
182
- WhirledPeas.template do |composer, settings|
183
- settings.bg_color = :blue
184
- composer.add_grid do |composer, settings|
185
- settings.num_cols = 10
186
- 100.times do |i|
187
- composer.add_text { i }
188
- end
189
- end
190
- end
191
- ```
192
-
193
- The above template can also be broken down into more manageable methods, e.g.
194
-
195
- ```ruby
196
- def number_grid(_composer, settings)
197
- settings.num_cols = 10
198
- 100.times.map(&:itself)
199
- end
200
-
201
- WhirledPeas.template do |composer, settings|
202
- settings.bg_color = :blue
203
- composer.add_grid(&method(:number_grid))
204
- end
205
- ```
206
-
207
- 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
208
-
209
- ```ruby
210
- template.add_grid do |composer|
211
- 100.times do |i|
212
- composer.add_text { i }
213
- end
214
- end
215
-
216
- template.add_grid do
217
- 100.times.map(&:itself)
218
- end
219
- ```
220
-
221
- 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
222
-
223
- ```ruby
224
- template.add_box do |composer|
225
- composer.add_text { "Hello!" }
226
- end
227
-
228
- template.add_box do
229
- "Hello!"
230
- end
231
- ```
232
-
233
- #### Settings
234
-
235
- 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
236
- The available settigs are
237
-
238
- | Setting | Description | Default | Availability | Inherited |
239
- | ------------ | -------------------------------------------------------------------------------- | ---------- | ------------ | -------------------- |
240
- | `align` | Justifies the content in the horizontal direction | `:left` | `Container` | No |
241
- | `axis_color` | Color used to paint the axes of the graph (see [Colors](#colors)) | | `Graph` | No |
242
- | `bg_color` | Background color (see [Colors](#colors)) | | all | Yes |
243
- | `bold` | `true` makes the font bold | `false` | all | Yes |
244
- | `border` | Set the border for the lements | none | `Container`, | Only style and color |
245
- | `color` | Foreground text color (see [Colors](#colors)) | | all | Yes |
246
- | `flow` | Flow to display child elements (see [Display Flow](#display-flow)) | `:l2r` | `Container` | No |
247
- | `height` | Override the calculated height of an element's content area | | all | No |
248
- | `margin` | Set the (left, top, right, bottom) margin of the element | `0` | `Container` | No |
249
- | `num_cols` | Number of columns in the grid (must be set!) | | `Grid` | No |
250
- | `padding` | Set the (left, top, right, bottom) padding of the element | `0` | `Container` | No |
251
- | `position` | Set the (left, top) position of the element relative to parent content area | `0` | `Container` | No |
252
- | `scrollbar` | Display a scroll bar for vertical or horizontal scrolling | | `Box` | No |
253
- | `sizing` | Sizing model (`:content` or `:border`) used in conjunction with `width`/`height` | `:content` | `Box` | No |
254
- | `title_font` | Font used for "large" text (see [Large Text](#large-text), ignores `underline`) | | `Text` | No |
255
- | `underline` | `true` underlines the font | `false` | all | Yes |
256
- | `width` | Override the calculated width of an element's content area | | all | No |
257
- | `valign` | Justifies the content in the vertical direction | `:top` | `Container` | No |
258
-
259
- ##### Alignment
260
-
261
- The `align` setting takes one of several values
262
-
263
- - `:left` - align content starting at the leftmost edge of the container's content area
264
-
265
- ```
266
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
267
- ┃[child 1][child 2][child 3] ┃
268
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
269
- ```
270
-
271
- - `:right` - align content starting at the rightmost edge of the container's content area
272
-
273
- ```
274
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
275
- ┃ [child 1][child 2][child 3]┃
276
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
277
- ```
278
-
279
- - `:center` - align content starting in the horizontal center of the container's content area
280
-
281
- ```
282
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
283
- ┃ [child 1][child 2][child 3] ┃
284
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
285
- ```
286
-
287
- - `:between` - distribute children so there is equal space between children no space outside of the children
288
-
289
- ```
290
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
291
- ┃[child 1] [child 2] [child 3]┃
292
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
293
- ```
294
-
295
- - `: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.
296
-
297
- ```
298
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
299
- ┃ [child 1] [child 2] [child 3] ┃
300
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
301
- ```
302
-
303
- - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
304
-
305
- ```
306
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
307
- ┃ [child 1] [child 2] [child 3] ┃
308
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
309
- ```
310
-
311
- The `valign` setting takes one of several values
312
-
313
- - `:top` - align content starting at the top of the container's content area
314
-
315
- ```
316
- ┏━━━━━━━━━┓
317
- ┃[child 1]┃
318
- ┃[child 2]┃
319
- ┃[child 3]┃
320
- ┃ ┃
321
- ┃ ┃
322
- ┃ ┃
323
- ┃ ┃
324
- ┃ ┃
325
- ┃ ┃
326
- ┃ ┃
327
- ┃ ┃
328
- ┃ ┃
329
- ┃ ┃
330
- ┃ ┃
331
- ┃ ┃
332
- ┗━━━━━━━━━┛
333
- ```
334
-
335
- - `:bottom` - align content starting at the bottom of the container's content area
336
-
337
- ```
338
- ┏━━━━━━━━━┓
339
- ┃ ┃
340
- ┃ ┃
341
- ┃ ┃
342
- ┃ ┃
343
- ┃ ┃
344
- ┃ ┃
345
- ┃ ┃
346
- ┃ ┃
347
- ┃ ┃
348
- ┃ ┃
349
- ┃ ┃
350
- ┃ ┃
351
- ┃[child 1]┃
352
- ┃[child 2]┃
353
- ┃[child 3]┃
354
- ┗━━━━━━━━━┛
355
- ```
356
-
357
- - `:middle` - align content starting in the vertical middle of the container's content area
358
-
359
- ```
360
- ┏━━━━━━━━━┓
361
- ┃ ┃
362
- ┃ ┃
363
- ┃ ┃
364
- ┃ ┃
365
- ┃ ┃
366
- ┃ ┃
367
- ┃[child 1]┃
368
- ┃[child 2]┃
369
- ┃[child 3]┃
370
- ┃ ┃
371
- ┃ ┃
372
- ┃ ┃
373
- ┃ ┃
374
- ┃ ┃
375
- ┃ ┃
376
- ┗━━━━━━━━━┛
377
- ```
378
-
379
- - `:between` - distribute children so there is equal space between children no space outside of the children
380
-
381
- ```
382
- ┏━━━━━━━━━┓
383
- ┃[child 1]┃
384
- ┃ ┃
385
- ┃ ┃
386
- ┃ ┃
387
- ┃ ┃
388
- ┃ ┃
389
- ┃ ┃
390
- ┃[child 2]┃
391
- ┃ ┃
392
- ┃ ┃
393
- ┃ ┃
394
- ┃ ┃
395
- ┃ ┃
396
- ┃ ┃
397
- ┃[child 3]┃
398
- ┗━━━━━━━━━┛
399
- ```
400
-
401
- - `: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.
402
-
403
- ```
404
- ┏━━━━━━━━━┓
405
- ┃ ┃
406
- ┃ ┃
407
- ┃[child 1]┃
408
- ┃ ┃
409
- ┃ ┃
410
- ┃ ┃
411
- ┃ ┃
412
- ┃[child 2]┃
413
- ┃ ┃
414
- ┃ ┃
415
- ┃ ┃
416
- ┃ ┃
417
- ┃[child 3]┃
418
- ┃ ┃
419
- ┃ ┃
420
- ┗━━━━━━━━━┛
421
- ```
422
-
423
- - `:evenly` - distribute children so there is even spacing between any two children (or space to the edge)
424
-
425
- ```
426
- ┏━━━━━━━━━┓
427
- ┃ ┃
428
- ┃ ┃
429
- ┃ ┃
430
- ┃[child 1]┃
431
- ┃ ┃
432
- ┃ ┃
433
- ┃ ┃
434
- ┃[child 2]┃
435
- ┃ ┃
436
- ┃ ┃
437
- ┃ ┃
438
- ┃[child 3]┃
439
- ┃ ┃
440
- ┃ ┃
441
- ┃ ┃
442
- ┗━━━━━━━━━┛
443
- ```
444
-
445
- ##### Position
446
-
447
- 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
448
-
449
- - `set_position(left:, top:)`
450
-
451
- ##### Sizing Model
452
-
453
- 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.
454
-
455
- ###### Examples
456
-
457
- In the examples below, the `~` character represents padding and would not be displayed in the acutal rendered screen.
458
-
459
- ```ruby
460
- settings.width = 10
461
- settings.height = 3
462
- settings.set_padding(left: 3, top: 1, right: 3, bottom: 1)
463
- settings.full_border
464
-
465
- ## Content sizing
466
- settings.sizing = :content
467
-
468
- # Results in the box
469
- #
470
- # ┏━━━━━━━━━━━━━━━━┓
471
- # ┃~~~~~~~~~~~~~~~~┃
472
- # ┃~~~1234567890~~~┃
473
- # ┃~~~1234567890~~~┃
474
- # ┃~~~1234567890~~~┃
475
- # ┃~~~~~~~~~~~~~~~~┃
476
- # ┗━━━━━━━━━━━━━━━━┛
477
-
478
- ## Border sizing
479
- settings.sizing = :border
480
-
481
- # Results in the box
482
- #
483
- # ┏━━━━━━━━┓
484
- # ┃~~~12~~~┃
485
- # ┗━━━━━━━━┛
486
- ```
487
-
488
- 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.
489
-
490
- ##### Margin
491
-
492
- 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
493
-
494
- - `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)
495
- - `margin.left=(value)` - set left margin
496
- - `margin.top=(value)` - set top margin
497
- - `margin.right=(value)` - set right margin
498
- - `margin.bottom=(value)` - set bottom margin
499
- - `margin.horiz=(value)` - set left and right margin to the same value
500
- - `margin.vert=(value)` - set top and bottom margin to the same value
501
-
502
- Note: values cannot be negative
503
-
504
- ##### Padding
505
-
506
- 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
507
-
508
- - `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)
509
- - `padding.left=(value)` - set left padding
510
- - `padding.top=(value)` - set top padding
511
- - `padding.right=(value)` - set right padding
512
- - `padding.bottom=(value)` - set bottom padding
513
- - `padding.horiz=(value)` - set left and right padding to the same value
514
- - `padding.vert=(value)` - set top and bottom padding to the same value
515
-
516
- Note: values cannot be negative
517
-
518
- ##### Scrollbar
519
-
520
- 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)
521
-
522
- - `set_scrollbar(horiz:, vert:)` - set both scrollbar settings
523
- - `scrollbar.horiz=(flag)` - show/hide the horizontal scrollbar
524
- - `scrollbar.vert=(flag)` - show/hide the vertical scrollbar
525
-
526
- Note: there is a know bug with scrollbars and `center`/`right` alignments. Using `left` alignment is the supported workaround
527
-
528
- ##### Border
529
-
530
- 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
531
-
532
- - `set_border(left:, top:, right:, bottom:, inner_horiz:, inner_vert:, color:, style:)` - set any combination of border settings
533
- - `full_border(style:, color:)` - set all borders to true and optionally set the style or color
534
- - `border.left=(flag)` - show/hide left border
535
- - `border.top=(flag)` - show/hide top border
536
- - `border.right=(flag)` - show/hide right border
537
- - `border.bottom=(flag)` - show/hide bottom border
538
- - `border.inner_horiz=(flag)` - show/hide inner horizontal border (dividing grid rows)
539
- - `border.inner_vert=(flag)` - show/hide inner vertical border (dividing grid columns)
540
- - `border.color=(text_color)` - set the border color
541
- - `border.style=(style)` - set the border style
542
-
543
- Available border styles are
544
-
545
- - `:bold` (default)
546
-
547
- ```
548
- ┏━━┳━━┓
549
- ┃ ┃ ┃
550
- ┣━━╋━━┫
551
- ┃ ┃ ┃
552
- ┗━━┻━━┛
553
- ```
554
-
555
- - `:double`
556
-
557
- ```
558
- ╔══╦══╗
559
- ║ ║ ║
560
- ╠══╬══╣
561
- ║ ║ ║
562
- ╚══╩══╝
563
- ```
564
-
565
- - `:soft`
566
-
567
- ```
568
- ╭──┬──╮
569
- │ │ │
570
- ├──┼──┤
571
- │ │ │
572
- ╰──┴──╯
573
- ```
574
-
575
- ##### Display Flow
576
-
577
- Child elements can flow in one of 4 directions
578
-
579
- - `:l2r` left-to-right
580
-
581
- ```
582
- # In a Box
583
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
584
- ┃[child 1] [child 2] ... [child N]┃
585
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
586
-
587
- # In a Grid
588
- ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
589
- ┃[child 1]┃[child 2]┃[child 3]┃
590
- ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
591
- ┃[chiid 4]┃[child 5]┃ ┃
592
- ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
593
- ```
594
-
595
- - `:r2l` right-to-left
596
-
597
- ```
598
- # In a Box
599
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
600
- ┃[child N] [child N - 1] ... [child 1]┃
601
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
602
-
603
- # In a Grid
604
- ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
605
- ┃[child 3]┃[child 2]┃[child 1]┃
606
- ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
607
- ┃ ┃[chiid 5]┃[child 4]┃
608
- ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
609
- ```
610
-
611
- - `:t2b` top-to-bottom
612
-
613
- ```
614
- # In a Box
615
- ┏━━━━━━━━━┓
616
- ┃[child 1]┃
617
- ┃[child 2]┃
618
- ┃ ... ┃
619
- ┃[child N]┃
620
- ┗━━━━━━━━━┛
621
-
622
- # In a Grid
623
- ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
624
- ┃[child 1]┃[child 3]┃[child 5]┃
625
- ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
626
- ┃[child 2]┃[child 4]┃ ┃
627
- ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
628
- ```
629
-
630
- - `:b2t` bottom-to-top
631
-
632
- ```
633
- # In a Box
634
- ┏━━━━━━━━━━━━━┓
635
- ┃[child N] ┃
636
- ┃[child N - 1]┃
637
- ┃ ... ┃
638
- ┃[child 1] ┃
639
- ┗━━━━━━━━━━━━━┛
640
-
641
- # In a Grid
642
- ┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┓
643
- ┃[child 2]┃[child 4]┃ ┃
644
- ┣━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━┫
645
- ┃[child 1]┃[child 3]┃[child 5]┃
646
- ┗━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━┛
647
- ```
648
-
649
- ##### Colors
650
-
651
- Below is the list of available colors (for both foreground and background)
652
-
653
- - `:black`
654
- - `:blue`
655
- - `:cyan`
656
- - `:gray`
657
- - `:green`
658
- - `:magenta`
659
- - `:red`
660
- - `:white`
661
- - `:yellow`
662
-
663
- Many of these also have a "bright" option:
664
-
665
- - `:bright_blue`
666
- - `:bright_cyan`
667
- - `:bright_green`
668
- - `:bright_magenta`
669
- - `:bright_red`
670
- - `:bright_yellow`
671
-
672
- ##### Large Text
673
-
674
- 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
675
-
676
- ```
677
- ██████╗ ███████╗███████╗ █████╗ ██╗ ██╗██╗ ████████╗
678
- ██╔══██╗██╔════╝██╔════╝██╔══██╗██║ ██║██║ ╚══██╔══╝
679
- ██║ ██║█████╗ █████╗ ███████║██║ ██║██║ ██║
680
- ██║ ██║██╔══╝ ██╔══╝ ██╔══██║██║ ██║██║ ██║
681
- ██████╔╝███████╗██║ ██║ ██║╚██████╔╝███████╗ ██║
682
- ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝
683
- ```
684
-
685
- To print out a list of all available fonts as well as sample text in that font, run
686
-
687
- ```
688
- $ whirled_peas title_fonts
689
- ```
690
-
691
- Note: when using a title font with WhirledPeas for the first time on a system, the gem loads all fonts to check which ones are available. This can be a slow process and may cause a noticeable delay when running a visualization. Running the command above will cache the results and thus when a WhirledPeas visualization is run, there will be no lag from loading fonts.
692
-
693
- #### Easing
694
-
695
- The play duration of a frame within a frameset is determined by the easing function and effect along with the frames relative position within the frameset. The three effects are
696
-
697
- - `:in` - apply easing only to the start of the frameset
698
- - `:out` - apply easing only to the end of the frameset
699
- - `:in_out` - apply easing to the start and end of the frameset
700
-
701
- The available easing functions are
702
-
703
- - `:bezier`
704
-
705
- ```
706
- # bezier (in)
707
- ┃ ▄▀
708
- ┃ ▄▄▀
709
- ┃ ▄▀
710
- ┃ ▄▀▀
711
- ┃ ▄▄▀
712
- ┃ ▄▄▀
713
- ┃ ▄▄▀
714
- ┃ ▄▀
715
- ┃ ▄▄▀▀
716
- ┃ ▄▄▀
717
- ┃ ▄▀▀
718
- ┃ ▄▄▀▀
719
- ┃ ▄▄▀▀▀
720
- ┃ ▄▄▄▀▀▀
721
- ┃▄▄▄▄▄▄▄▄▄▄▀▀▀
722
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
723
- ```
724
-
725
- ```
726
- # bezier (out)
727
- ┃ ▄▄▄▀▀▀▀▀▀▀▀▀
728
- ┃ ▄▄▄▀▀▀
729
- ┃ ▄▄▄▀▀
730
- ┃ ▄▄▀▀
731
- ┃ ▄▄▀
732
- ┃ ▄▀▀
733
- ┃ ▄▄▀▀
734
- ┃ ▄▀
735
- ┃ ▄▀▀
736
- ┃ ▄▀▀
737
- ┃ ▄▀▀
738
- ┃ ▄▄▀
739
- ┃ ▄▀
740
- ┃ ▄▀▀
741
- ┃▄▄▀
742
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
743
- ```
744
-
745
- ```
746
- # bezier (in_out)
747
- ┃ ▄▄▄▀▀▀▀▀▀
748
- ┃ ▄▄▀▀
749
- ┃ ▄▀▀
750
- ┃ ▄▀▀
751
- ┃ ▄▀▀
752
- ┃ ▄▀▀
753
- ┃ ▄▄▀
754
- ┃ ▄▀
755
- ┃ ▄▀▀
756
- ┃ ▄▄▀
757
- ┃ ▄▄▀
758
- ┃ ▄▄▀
759
- ┃ ▄▄▀
760
- ┃ ▄▄▀▀
761
- ┃▄▄▄▄▄▄▄▀▀▀
762
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
763
- ```
764
-
765
- `:linear`
766
-
767
- ```
768
- # linear (in)
769
- ┃ ▄▄▀
770
- ┃ ▄▄▀▀
771
- ┃ ▄▄▀▀
772
- ┃ ▄▄▀▀
773
- ┃ ▄▄▀▀
774
- ┃ ▄▄▀▀
775
- ┃ ▄▄▀▀
776
- ┃ ▄▄▀▀
777
- ┃ ▄▄▀▀
778
- ┃ ▄▄▀▀
779
- ┃ ▄▄▀▀
780
- ┃ ▄▄▀▀
781
- ┃ ▄▄▀▀
782
- ┃ ▄▄▀▀
783
- ┃▄▄▀▀
784
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
785
- ```
786
-
787
- ```
788
- # linear (out)
789
- ┃ ▄▄▀
790
- ┃ ▄▄▀▀
791
- ┃ ▄▄▀▀
792
- ┃ ▄▄▀▀
793
- ┃ ▄▄▀▀
794
- ┃ ▄▄▀▀
795
- ┃ ▄▄▀▀
796
- ┃ ▄▄▀▀
797
- ┃ ▄▄▀▀
798
- ┃ ▄▄▀▀
799
- ┃ ▄▄▀▀
800
- ┃ ▄▄▀▀
801
- ┃ ▄▄▀▀
802
- ┃ ▄▄▀▀
803
- ┃▄▄▀▀
804
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
805
- ```
806
-
807
- ```
808
- # linear (in_out)
809
- ┃ ▄▄▀
810
- ┃ ▄▄▀▀
811
- ┃ ▄▄▀▀
812
- ┃ ▄▄▀▀
813
- ┃ ▄▄▀▀
814
- ┃ ▄▄▀▀
815
- ┃ ▄▄▀▀
816
- ┃ ▄▄▀▀
817
- ┃ ▄▄▀▀
818
- ┃ ▄▄▀▀
819
- ┃ ▄▄▀▀
820
- ┃ ▄▄▀▀
821
- ┃ ▄▄▀▀
822
- ┃ ▄▄▀▀
823
- ┃▄▄▀▀
824
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
825
- ```
826
-
827
- `:parametric`
828
-
829
- ```
830
- # parametric (in)
831
- ┃ ▄
832
- ┃ ▄▀
833
- ┃ ▄▀
834
- ┃ ▄▄▀
835
- ┃ ▄▀
836
- ┃ ▄▀
837
- ┃ ▄▀
838
- ┃ ▄▄▀
839
- ┃ ▄▀
840
- ┃ ▄▀▀
841
- ┃ ▄▀▀
842
- ┃ ▄▄▀▀
843
- ┃ ▄▄▄▀▀
844
- ┃ ▄▄▄▄▀▀
845
- ┃▄▄▄▄▄▄▄▄▄▄▄▄▄▄▀▀▀▀▀
846
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
847
- ```
848
-
849
- ```
850
- # parametric (out)
851
- ┃ ▄▄▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀
852
- ┃ ▄▄▀▀▀▀
853
- ┃ ▄▄▀▀▀
854
- ┃ ▄▄▀▀
855
- ┃ ▄▄▀
856
- ┃ ▄▄▀
857
- ┃ ▄▀
858
- ┃ ▄▀▀
859
- ┃ ▄▀
860
- ┃ ▄▀
861
- ┃ ▄▀
862
- ┃ ▄▀▀
863
- ┃ ▄▀
864
- ┃ ▄▀
865
- ┃▄▀
866
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
867
- ```
868
-
869
- ```
870
- # parametric (in_out)
871
- ┃ ▄▄▄▀▀▀▀▀▀▀▀▀
872
- ┃ ▄▄▀▀
873
- ┃ ▄▀▀
874
- ┃ ▄▄▀
875
- ┃ ▄▀
876
- ┃ ▄▀
877
- ┃ ▄▀
878
- ┃ ▄▀
879
- ┃ ▄▀
880
- ┃ ▄▀
881
- ┃ ▄▀
882
- ┃ ▄▀▀
883
- ┃ ▄▄▀
884
- ┃ ▄▄▀▀
885
- ┃▄▄▄▄▄▄▄▄▄▄▀▀▀
886
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
887
- ```
888
-
889
- `:quadratic`
890
-
891
- ```
892
- # quadratic (in)
893
- ┃ ▄▄
894
- ┃ ▄▀
895
- ┃ ▄▀
896
- ┃ ▄▀
897
- ┃ ▄▀
898
- ┃ ▄▀▀
899
- ┃ ▄▀
900
- ┃ ▄▀▀
901
- ┃ ▄▀▀
902
- ┃ ▄▀▀
903
- ┃ ▄▄▀▀
904
- ┃ ▄▄▀▀
905
- ┃ ▄▄▄▀▀
906
- ┃ ▄▄▄▀▀▀
907
- ┃▄▄▄▄▄▄▄▄▄▄▄▀▀▀▀▀
908
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
909
- ```
910
-
911
- ```
912
- # quadratic (out)
913
- ┃ ▄▄▄▄▄▀▀▀▀▀▀▀▀▀▀
914
- ┃ ▄▄▄▀▀▀
915
- ┃ ▄▄▀▀▀
916
- ┃ ▄▄▀▀
917
- ┃ ▄▄▀▀
918
- ┃ ▄▄▀
919
- ┃ ▄▄▀
920
- ┃ ▄▄▀
921
- ┃ ▄▀
922
- ┃ ▄▄▀
923
- ┃ ▄▀
924
- ┃ ▄▀
925
- ┃ ▄▀
926
- ┃ ▄▀
927
- ┃▄▀▀
928
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
929
- ```
930
-
931
- ```
932
- # quadratic (in_out)
933
- ┃ ▄▄▄▀▀▀▀▀▀▀
934
- ┃ ▄▄▀▀▀
935
- ┃ ▄▀▀
936
- ┃ ▄▀▀
937
- ┃ ▄▄▀
938
- ┃ ▄▀
939
- ┃ ▄▀
940
- ┃ ▄▀
941
- ┃ ▄▀
942
- ┃ ▄▀
943
- ┃ ▄▀▀
944
- ┃ ▄▄▀
945
- ┃ ▄▄▀
946
- ┃ ▄▄▄▀▀
947
- ┃▄▄▄▄▄▄▄▄▀▀▀
948
- ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
949
- ```
950
-
951
- ### Full template example
952
-
953
- ```ruby
954
- class TemplateFactory
955
- def build(frame, args)
956
- set_state(frame, args)
957
- WhirledPeas.template do |composer, settings|
958
- settings.flow = :l2r
959
- settings.align = :center
960
-
961
- composer.add_box('Title', &method(:title))
962
- composer.add_box('Sum', &method(:sum))
963
- composer.add_grid('NumberGrid', &method(:number_grid))
964
- end
965
- end
966
-
967
- private
968
-
969
- def set_state(frame, args)
970
- @frame = frame
971
- @numbers = args.key?(:numbers) ? args[:numbers] || []
972
- @sum = args[:sum] if args.key?(:sum)
973
- @low = args[:low] if args.key?(:low)
974
- @high = args[:high] if args.key?(:high)
975
- end
976
-
977
- def title(_composer, settings)
978
- settings.underline = true
979
- "Pair Finder"
980
- end
981
-
982
- def sum(_composer, settings)
983
- settings.color = @frame == 'found-pair' ? :green : :red
984
- @sum ? "Sum: #{@sum}" : 'N/A'
985
- end
986
-
987
- def number_grid(composer, settings)
988
- settings.full_border
989
- @numbers.each.with_index do |num, index|
990
- composer.add_text do |_, settings|
991
- settings.bg_color = (@low == index || @high == index) ? :cyan : :white
992
- num
993
- end
994
- end
995
- end
996
- end
997
- ```
998
-
999
- ### Full usage
1000
-
1001
- ```
1002
- Usage: whirled_peas <command> [command options]
1003
-
1004
- Available commands:
1005
-
1006
- debug Print template tree for specified frame
1007
- fonts List installed title fonts with sample text
1008
- frames Print out list of frames generated by application
1009
- help Show detailed help for a command
1010
- play Play an animation from an application or prerecorded file
1011
- record Record animation to a file
1012
- still Show the specified still frame
1013
- ```
1014
-
1015
- #### `debug`
1016
-
1017
- Print the template tree for specified frame.
1018
-
1019
- ```
1020
- # Usage: whirled_peas debug <config file> <frame> [args as a JSON string]
1021
- % whirled_peas debug my_app.rb greeting '{"name":"World"}'
1022
- * WhirledPeas::Graphics::BoxPainter(TEMPLATE)
1023
- - Dimensions(outer=140x27, content=120x15, grid=1x1)
1024
- - Settings
1025
- WhirledPeas::Settings::BoxSettings
1026
- padding: Padding(left: 10, top: 6, right: 10, bottom: 6)
1027
- align: :center
1028
- width: 120
1029
- flow: :t2b
1030
- bold: true
1031
- bg_color: BgColor(code=107, bright=true)
1032
- - Children
1033
- * WhirledPeas::Graphics::BoxPainter(Element-1)
1034
- - Dimensions(outer=64x6, content=64x6, grid=1x1)
1035
- ```
1036
-
1037
- #### `fonts`
1038
-
1039
- List all installed title fonts with sample text.
1040
-
1041
- ```
1042
- # Usage: whirled_peas fonts
1043
- ```
1044
-
1045
- #### `frames`
1046
-
1047
- Print out list of frames generated by application.
1048
-
1049
- ```
1050
- # Usage: whirled_peas frames <config file>
1051
- % whirled_peas frames my_app.rb
1052
- Frame 'intro' displayed for 3 second(s) '{"title":"Foo"}'
1053
- Frame 'greet' displayed for 0.3 second(s)
1054
- ...
1055
- ```
1056
-
1057
- #### `help`
1058
-
1059
- Print out command-specific help message
1060
-
1061
- ```
1062
- Usage: whirled_peas help <command>
1063
- ```
1064
-
1065
- #### `play`
1066
-
1067
- Play an animation from an application or prerecorded file
1068
-
1069
- ```
1070
- # Usage: whirled_peas play <config/wpz file>
1071
-
1072
- # Play animation directly from app
1073
- % whirled_peas play my_app.rb
1074
- # Animation plays
1075
-
1076
- # Play animation from previously recorded file
1077
- % whirled_peas play my_animation.wpz
1078
- # Animation plays
1079
- ```
1080
-
1081
- #### `record`
1082
-
1083
- Record animation to a file
1084
-
1085
- ```
1086
- # Usage: whirled_peas record <config file> <output file>
1087
- % whirled_peas record my_app.rb my_animation.wpz
1088
- # Record animation to my_animation.wpz
1089
- ```
1090
-
1091
- #### `still`
1092
-
1093
- Show the specified still frame
1094
-
1095
- ```
1096
- # Usage: whirled_peas still <config file> <frame> [args as a JSON string]
1097
- % whirled_peas still my_app.rb greeting '{"name":"World"}'
1098
- # Still frame is displayed
1099
- ```
1100
-
1101
83
  ## Development
1102
84
 
1103
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
1104
-
1105
- 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).
1106
-
1107
- ### Testing
1108
-
1109
- 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.
1110
-
1111
- Note: viewing `.frame` files with `cat` works better than most other text editors.
85
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
1112
86
 
1113
- ```
1114
-
1115
- Usage: screen_test [file] [options]
1116
-
1117
- If not file or options are provide, all tests are run
87
+ Tests inclued standard RSpec tests for application logic as well as custom [screen tests](doc/screen_test.md) to validate the rendered graphics.
1118
88
 
1119
- If no file is provided, the supported options are
1120
- --help print this usage statement and exit
1121
- --view-pending interactively display and optionally save rendered output for each pending test
1122
- --view-failed interactively display and optionally save rendered output for each faiing test
1123
-
1124
- If a screen test file is provided as the first argument, the supported options are
1125
- --run run screen test for given file
1126
- --view interactively display and optionally save the file's test output
1127
- --template print out template tree for the test template
1128
- --debug render the test template without displying it, printing out debug information
1129
- ```
89
+ 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).
1130
90
 
1131
91
  ## Contributing
1132
92
 
1133
- 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).
93
+ Bug reports and pull requests are welcome on GitHub at https://github.com/tcollier/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/tcollier/whirled_peas/blob/master/CODE_OF_CONDUCT.md).
1134
94
 
1135
95
  ## License
1136
96
 
@@ -1138,8 +98,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
1138
98
 
1139
99
  ## Code of Conduct
1140
100
 
1141
- 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).
1142
-
1143
- ```
1144
-
1145
- ```
101
+ 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/tcollier/whirled_peas/blob/master/CODE_OF_CONDUCT.md).