whirled_peas 0.5.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +31 -0
  5. data/README.md +748 -137
  6. data/Rakefile +4 -32
  7. data/bin/easing +33 -0
  8. data/bin/reset_cursor +11 -0
  9. data/bin/screen_test +68 -0
  10. data/examples/graph.rb +54 -0
  11. data/examples/intro.rb +52 -0
  12. data/examples/scrolling.rb +54 -0
  13. data/lib/whirled_peas.rb +4 -12
  14. data/lib/whirled_peas/animator.rb +5 -0
  15. data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
  16. data/lib/whirled_peas/animator/easing.rb +72 -0
  17. data/lib/whirled_peas/animator/frame.rb +5 -0
  18. data/lib/whirled_peas/animator/frameset.rb +33 -0
  19. data/lib/whirled_peas/animator/producer.rb +35 -0
  20. data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
  21. data/lib/whirled_peas/command.rb +5 -0
  22. data/lib/whirled_peas/command/base.rb +86 -0
  23. data/lib/whirled_peas/command/config_command.rb +44 -0
  24. data/lib/whirled_peas/command/debug.rb +21 -0
  25. data/lib/whirled_peas/command/fonts.rb +22 -0
  26. data/lib/whirled_peas/command/frame_command.rb +34 -0
  27. data/lib/whirled_peas/command/frames.rb +24 -0
  28. data/lib/whirled_peas/command/help.rb +38 -0
  29. data/lib/whirled_peas/command/play.rb +108 -0
  30. data/lib/whirled_peas/command/record.rb +57 -0
  31. data/lib/whirled_peas/command/still.rb +29 -0
  32. data/lib/whirled_peas/command_line.rb +22 -220
  33. data/lib/whirled_peas/config.rb +56 -6
  34. data/lib/whirled_peas/device.rb +5 -0
  35. data/lib/whirled_peas/device/null_device.rb +8 -0
  36. data/lib/whirled_peas/device/output_file.rb +19 -0
  37. data/lib/whirled_peas/device/screen.rb +26 -0
  38. data/lib/whirled_peas/graphics.rb +14 -0
  39. data/lib/whirled_peas/graphics/box_painter.rb +48 -47
  40. data/lib/whirled_peas/graphics/canvas.rb +22 -11
  41. data/lib/whirled_peas/graphics/composer.rb +98 -0
  42. data/lib/whirled_peas/graphics/container_coords.rb +24 -13
  43. data/lib/whirled_peas/graphics/container_dimensions.rb +37 -9
  44. data/lib/whirled_peas/graphics/container_painter.rb +283 -36
  45. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  46. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  47. data/lib/whirled_peas/graphics/debugger.rb +10 -1
  48. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  49. data/lib/whirled_peas/graphics/graph_painter.rb +95 -0
  50. data/lib/whirled_peas/graphics/grid_painter.rb +25 -15
  51. data/lib/whirled_peas/graphics/mock_screen.rb +1 -1
  52. data/lib/whirled_peas/graphics/painter.rb +15 -6
  53. data/lib/whirled_peas/graphics/renderer.rb +13 -30
  54. data/lib/whirled_peas/graphics/text_painter.rb +11 -13
  55. data/lib/whirled_peas/settings/alignment.rb +24 -0
  56. data/lib/whirled_peas/settings/bg_color.rb +2 -0
  57. data/lib/whirled_peas/settings/border.rb +16 -16
  58. data/lib/whirled_peas/settings/color.rb +13 -14
  59. data/lib/whirled_peas/settings/container_settings.rb +133 -40
  60. data/lib/whirled_peas/settings/debugger.rb +9 -0
  61. data/lib/whirled_peas/settings/display_flow.rb +13 -11
  62. data/lib/whirled_peas/settings/element_settings.rb +8 -3
  63. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  64. data/lib/whirled_peas/settings/grid_settings.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 +34 -0
  68. data/lib/whirled_peas/settings/text_color.rb +2 -0
  69. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  70. data/lib/whirled_peas/utils/ansi.rb +13 -0
  71. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  72. data/lib/whirled_peas/utils/title_font.rb +1 -1
  73. data/lib/whirled_peas/version.rb +1 -1
  74. data/screen_test/{rendered/elements → elements}/box.frame +1 -1
  75. data/screen_test/{rendered/elements → elements}/box.rb +0 -0
  76. data/screen_test/elements/graph.frame +1 -0
  77. data/screen_test/elements/graph.rb +12 -0
  78. data/screen_test/elements/grid.frame +1 -0
  79. data/screen_test/{rendered/elements → elements}/grid.rb +0 -0
  80. data/screen_test/elements/screen_overflow_x.frame +1 -0
  81. data/screen_test/{rendered/elements/screen_overflow.rb → elements/screen_overflow_x.rb} +0 -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/{rendered/elements → elements}/text.rb +0 -0
  86. data/screen_test/elements/text_multiline.frame +1 -0
  87. data/screen_test/{rendered/elements → elements}/text_multiline.rb +0 -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/{rendered/settings/align/box.rb → settings/align/box_center.rb} +5 -4
  94. data/screen_test/settings/align/box_default.frame +1 -0
  95. data/screen_test/{rendered/settings/align/grid.rb → settings/align/box_default.rb} +6 -6
  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/{rendered/settings/width/overflow_box_t2b.rb → settings/ansi/bold.rb} +4 -5
  118. data/screen_test/{rendered/settings → settings}/ansi/color.frame +1 -1
  119. data/screen_test/{rendered/settings → settings}/ansi/color.rb +0 -0
  120. data/screen_test/settings/ansi/underline.frame +1 -0
  121. data/screen_test/{rendered/settings → settings}/ansi/underline.rb +4 -5
  122. data/screen_test/{rendered/settings → settings}/border.frame +1 -1
  123. data/screen_test/{rendered/settings → settings}/border.rb +1 -1
  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/{rendered/settings/margin.rb → settings/flow/grid_l2r.rb} +4 -4
  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/{rendered/settings → settings}/height/box.rb +0 -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/{rendered/settings → settings}/height/grid.rb +0 -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/{rendered/settings → settings}/height/overflow_grid.rb +0 -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/{rendered/settings → settings}/position/box_left.rb +2 -2
  160. data/screen_test/settings/position/box_left_negative.frame +1 -0
  161. data/screen_test/{rendered/settings → settings}/position/box_left_negative.rb +2 -2
  162. data/screen_test/settings/position/box_top.frame +1 -0
  163. data/screen_test/{rendered/settings → settings}/position/box_top.rb +1 -1
  164. data/screen_test/settings/position/box_top_negative.frame +1 -0
  165. data/screen_test/{rendered/settings → settings}/position/box_top_negative.rb +2 -2
  166. data/screen_test/settings/position/grid_left.frame +1 -0
  167. data/screen_test/{rendered/settings → settings}/position/grid_left.rb +1 -1
  168. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  169. data/screen_test/{rendered/settings → settings}/position/grid_left_negative.rb +1 -1
  170. data/screen_test/settings/position/grid_top.frame +1 -0
  171. data/screen_test/{rendered/settings → settings}/position/grid_top.rb +1 -1
  172. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  173. data/screen_test/{rendered/settings → settings}/position/grid_top_negative.rb +1 -1
  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/{rendered/settings → settings}/title_font.rb +1 -1
  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/{rendered/settings/width/box.rb → settings/width/box_default.rb} +3 -2
  210. data/screen_test/settings/width/grid.frame +1 -0
  211. data/screen_test/{rendered/settings → settings}/width/grid.rb +2 -2
  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/{rendered/settings → settings}/width/overflow_grid.rb +0 -0
  224. data/tools/whirled_peas/tools/screen_tester.rb +285 -0
  225. metadata +192 -98
  226. data/bin/debug +0 -35
  227. data/lib/whirled_peas/debugger.rb +0 -80
  228. data/lib/whirled_peas/frame.rb +0 -6
  229. data/lib/whirled_peas/frame/consumer.rb +0 -30
  230. data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
  231. data/lib/whirled_peas/frame/event_loop.rb +0 -90
  232. data/lib/whirled_peas/frame/producer.rb +0 -67
  233. data/lib/whirled_peas/graphics/screen.rb +0 -65
  234. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
  235. data/lib/whirled_peas/settings/text_align.rb +0 -19
  236. data/lib/whirled_peas/template.rb +0 -5
  237. data/lib/whirled_peas/template/box_element.rb +0 -8
  238. data/lib/whirled_peas/template/composer.rb +0 -68
  239. data/lib/whirled_peas/template/container.rb +0 -28
  240. data/lib/whirled_peas/template/debugger.rb +0 -34
  241. data/lib/whirled_peas/template/element.rb +0 -13
  242. data/lib/whirled_peas/template/grid_element.rb +0 -8
  243. data/lib/whirled_peas/template/text_element.rb +0 -24
  244. data/screen_test/rendered/elements/grid.frame +0 -1
  245. data/screen_test/rendered/elements/text.frame +0 -1
  246. data/screen_test/rendered/elements/text_multiline.frame +0 -1
  247. data/screen_test/rendered/settings/align/box.frame +0 -1
  248. data/screen_test/rendered/settings/align/children_center.frame +0 -1
  249. data/screen_test/rendered/settings/align/children_center.rb +0 -13
  250. data/screen_test/rendered/settings/align/children_left.frame +0 -1
  251. data/screen_test/rendered/settings/align/children_left.rb +0 -13
  252. data/screen_test/rendered/settings/align/children_right.frame +0 -1
  253. data/screen_test/rendered/settings/align/children_right.rb +0 -13
  254. data/screen_test/rendered/settings/align/grid.frame +0 -1
  255. data/screen_test/rendered/settings/ansi/bold.frame +0 -1
  256. data/screen_test/rendered/settings/ansi/bold.rb +0 -15
  257. data/screen_test/rendered/settings/ansi/underline.frame +0 -1
  258. data/screen_test/rendered/settings/flow/l2r.frame +0 -1
  259. data/screen_test/rendered/settings/flow/l2r.rb +0 -24
  260. data/screen_test/rendered/settings/flow/t2b.frame +0 -1
  261. data/screen_test/rendered/settings/flow/t2b.rb +0 -24
  262. data/screen_test/rendered/settings/height/box.frame +0 -1
  263. data/screen_test/rendered/settings/height/grid.frame +0 -1
  264. data/screen_test/rendered/settings/height/overflow_box.frame +0 -1
  265. data/screen_test/rendered/settings/height/overflow_box.rb +0 -13
  266. data/screen_test/rendered/settings/height/overflow_box_l2r.frame +0 -1
  267. data/screen_test/rendered/settings/height/overflow_box_l2r.rb +0 -15
  268. data/screen_test/rendered/settings/height/overflow_box_t2b.frame +0 -1
  269. data/screen_test/rendered/settings/height/overflow_box_t2b.rb +0 -14
  270. data/screen_test/rendered/settings/height/overflow_grid.frame +0 -1
  271. data/screen_test/rendered/settings/margin.frame +0 -1
  272. data/screen_test/rendered/settings/padding.frame +0 -1
  273. data/screen_test/rendered/settings/padding.rb +0 -11
  274. data/screen_test/rendered/settings/position/box_left.frame +0 -1
  275. data/screen_test/rendered/settings/position/box_left_negative.frame +0 -1
  276. data/screen_test/rendered/settings/position/box_top.frame +0 -1
  277. data/screen_test/rendered/settings/position/box_top_negative.frame +0 -1
  278. data/screen_test/rendered/settings/position/grid_left.frame +0 -1
  279. data/screen_test/rendered/settings/position/grid_left_negative.frame +0 -1
  280. data/screen_test/rendered/settings/position/grid_top.frame +0 -1
  281. data/screen_test/rendered/settings/position/grid_top_negative.frame +0 -1
  282. data/screen_test/rendered/settings/title_font.frame +0 -1
  283. data/screen_test/rendered/settings/width/box.frame +0 -1
  284. data/screen_test/rendered/settings/width/grid.frame +0 -1
  285. data/screen_test/rendered/settings/width/overflow_box.frame +0 -1
  286. data/screen_test/rendered/settings/width/overflow_box.rb +0 -11
  287. data/screen_test/rendered/settings/width/overflow_box_l2r.frame +0 -1
  288. data/screen_test/rendered/settings/width/overflow_box_l2r.rb +0 -14
  289. data/screen_test/rendered/settings/width/overflow_box_t2b.frame +0 -1
  290. data/screen_test/rendered/settings/width/overflow_grid.frame +0 -1
  291. data/screen_test/screen_tester.rb +0 -191
@@ -0,0 +1,15 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box('Wide') do |_, settings|
7
+ settings.full_border
8
+ settings.set_padding(left: 3, right: 4)
9
+ settings.width = 15
10
+ settings.sizing = :border
11
+ '15/border'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━━━━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━━━━━━━━━━━━━┛15/content[?25h
@@ -0,0 +1,15 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box('Wide') do |_, settings|
7
+ settings.full_border
8
+ settings.set_padding(left: 3, right: 4)
9
+ settings.width = 15
10
+ settings.sizing = :content
11
+ '15/content'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━━━━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━━━━━━━━━━━━━┛15/default[?25h
@@ -5,8 +5,9 @@ class TemplateFactory
5
5
  WhirledPeas.template do |composer|
6
6
  composer.add_box('Wide') do |_, settings|
7
7
  settings.full_border
8
- settings.width = 50
9
- "How big is it?"
8
+ settings.set_padding(left: 3, right: 4)
9
+ settings.width = 15
10
+ '15/default'
10
11
  end
11
12
  end
12
13
  end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━┳━━━━━━┓┃ ┃ ┃┣━━━━━━╋━━━━━━┫┃ ┃ ┃┣━━━━━━╋━━━━━━┫┃ ┃ ┃┗━━━━━━┻━━━━━━┛666666[?25h
@@ -5,9 +5,9 @@ class TemplateFactory
5
5
  WhirledPeas.template do |composer|
6
6
  composer.add_grid('Wide') do |_, settings|
7
7
  settings.full_border
8
- settings.width = 30
8
+ settings.width = 6
9
9
  settings.num_cols = 2
10
- 6.times.map { "How big is it?" }
10
+ 6.times.map { '6' }
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1 @@
1
+ [?25l┏━━━┓┃ ┃┗━━━┛345[?25h
@@ -0,0 +1,14 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box('Container') do |composer, settings|
7
+ settings.width = 3
8
+ settings.align = :center
9
+ settings.full_border
10
+ '123456'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━┓┃ ┃┗━━━┛456[?25h
@@ -0,0 +1,14 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box do |composer, settings|
7
+ settings.width = 3
8
+ settings.align = :right
9
+ settings.full_border
10
+ '123456'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━┛ABCDEFGHIJ[?25h
@@ -0,0 +1,13 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box do |_, settings|
7
+ settings.width = 10
8
+ settings.full_border
9
+ "ABCDEFGHIJKLMNOPQRSTUVWZYZ"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━┛0|0|1|0|1|[?25h
@@ -0,0 +1,16 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box do |composer, settings|
7
+ settings.width = 10
8
+ settings.full_border
9
+ str = ''
10
+ 10.times do |i|
11
+ composer.add_text { str += "#{i}|" }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━┓┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┗━━━━━━━━━━┛XOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXOXO[?25h
@@ -0,0 +1,17 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_box do |composer, settings|
7
+ settings.width = 10
8
+ settings.flow = :t2b
9
+ settings.full_border
10
+ str = ''
11
+ 10.times do
12
+ composer.add_text { str += 'XO' }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━┛ABCDEFGHIJ[?25h
@@ -0,0 +1,285 @@
1
+ require 'bundler/setup'
2
+ require 'whirled_peas'
3
+ require 'whirled_peas/animator/producer'
4
+ require 'whirled_peas/animator/renderer_consumer'
5
+ require 'whirled_peas/device/screen'
6
+ require 'whirled_peas/graphics/debugger'
7
+ require 'whirled_peas/graphics/renderer'
8
+ require 'whirled_peas/settings/text_color'
9
+ require 'whirled_peas/utils/ansi'
10
+ require 'whirled_peas/utils/formatted_string'
11
+
12
+ module WhirledPeas
13
+ # Useful code for managing the repository that should not be distributed with the gem
14
+ module Tools
15
+ # Return the parent directory N-levels up from the current file. If levels_up = 0 return
16
+ # the directory of the current file. E.g.
17
+ #
18
+ # parent_directory("/path/to/file.rb")
19
+ # # => "/path/to"
20
+ #
21
+ # parent_directory("really/long/path/to/another/file.rb", 3)
22
+ # # => "really/long"
23
+ #
24
+ def self.parent_directory(file, levels_up=0)
25
+ return File.dirname(file) if levels_up == 0
26
+ parent_directory(File.dirname(file), levels_up - 1)
27
+ end
28
+
29
+ class ScreenTester
30
+ # The output of a rendered frame is depenend upon the width and height of the screen.
31
+ # Thus for the sake of reproduceability, the same width and height should be used for
32
+ # all runs of the test. The values should be relatively small to discourage testing
33
+ # complicated templates.
34
+ SCREEN_WIDTH = 32
35
+ SCREEN_HEIGHT = 24
36
+
37
+ # Path to screen tests relative to the base of this repository
38
+ SCREEN_TEST_DIR = 'screen_test'
39
+
40
+ # Return the base directory of this repository
41
+ def self.base_dir
42
+ Tools.parent_directory(__FILE__, 3)
43
+ end
44
+
45
+ # Return all screen test files
46
+ def self.test_files
47
+ Dir.glob(File.join(base_dir, SCREEN_TEST_DIR, '**', '*.rb'))
48
+ end
49
+
50
+ # Run all screen tests that exist in the screen test directory
51
+ def self.run_all
52
+ failures = {}
53
+ pendings = Set.new
54
+ puts "Running #{test_files.length} rendered screen test(s)"
55
+ puts
56
+ test_files.each do |file|
57
+ tester = new(file)
58
+ if tester.pending?
59
+ print Utils::FormattedString.new('.', Settings::TextColor::YELLOW)
60
+ pendings << file
61
+ elsif tester.failed?
62
+ print Utils::FormattedString.new('.', Settings::TextColor::RED)
63
+ failures[file] = tester.error
64
+ else
65
+ print Utils::FormattedString.new('.', Settings::TextColor::GREEN)
66
+ end
67
+ STDOUT.flush
68
+ end
69
+ puts
70
+ puts if pendings.count > 0
71
+ pendings.each do |file|
72
+ puts Utils::FormattedString.new(
73
+ "PENDING: #{file}",
74
+ Settings::TextColor::YELLOW
75
+ )
76
+ end
77
+ puts if failures.count > 0
78
+ failures.each do |file, error|
79
+ puts Utils::FormattedString.new(
80
+ "Failed: #{file}:\n\n #{error}\n",
81
+ Settings::TextColor::RED
82
+ )
83
+ end
84
+
85
+ if failures.count == 0
86
+ puts
87
+ puts Utils::FormattedString.new(
88
+ 'No failures',
89
+ Settings::TextColor::GREEN
90
+ )
91
+ exit(0)
92
+ else
93
+ exit(1)
94
+ end
95
+ end
96
+
97
+ # View rendered output for each pending test, giving the user the option to save the output
98
+ # as the expected output
99
+ def self.view_pending
100
+ num_attempted = 0
101
+ test_files.map do |file|
102
+ tester = new(file)
103
+ if tester.pending?
104
+ puts "File: #{tester.test_file}"
105
+ puts Utils::FormattedString.new(
106
+ 'Frame file does not exist', Settings::TextColor::YELLOW
107
+ )
108
+ print 'View rendered frame? [Y/n/q] '
109
+ STDOUT.flush
110
+ response = STDIN.gets.strip.downcase
111
+ case response
112
+ when 'q'
113
+ exit
114
+ when 'n'
115
+ return
116
+ end
117
+ tester.ask_pending
118
+ num_attempted += 1
119
+ end
120
+ end
121
+ if num_attempted == 0
122
+ puts 'No pending tests.'
123
+ end
124
+ end
125
+
126
+ # View expected and rendered output for each failed test, giving the user the option
127
+ # to overwrite the expected output with the rendered output
128
+ def self.view_failed
129
+ num_attempted = 0
130
+ test_files.map do |file|
131
+ tester = new(file)
132
+ if tester.failed?
133
+ puts "File: #{tester.test_file}"
134
+ puts Utils::FormattedString.new(
135
+ 'Output from test does not match saved output', Settings::TextColor::RED
136
+ )
137
+ print 'View expected output? [Y/q] '
138
+ STDOUT.flush
139
+ exit if 'q' == STDIN.gets.strip.downcase
140
+ tester.ask_failed
141
+ num_attempted += 1
142
+ end
143
+ end
144
+ if num_attempted == 0
145
+ puts 'All rendered output matched expected.'
146
+ end
147
+ end
148
+
149
+ attr_reader :error, :test_file
150
+
151
+ def initialize(test_file)
152
+ # Convert the input file path to an absolute path (if necessary)
153
+ @full_test_file = test_file[0] == '/' ? test_file : File.join(Dir.pwd, test_file)
154
+ raise ArgumentError, "File not found: #{test_file}" unless File.exist?(@full_test_file)
155
+
156
+ # Remove the base directory from the full file path for a more readable file name
157
+ @test_file = @full_test_file.sub(self.class.base_dir, '').sub(/^\//, '')
158
+
159
+ # The output file has the same base name as the test file, but ends in `.frame`
160
+ @full_output_file = @full_test_file.sub(/\.rb$/, '.frame')
161
+
162
+ # Remove the base directory from the full file path for a more readable file name
163
+ @output_file = @full_output_file.sub(self.class.base_dir, '').sub(/^\//, '')
164
+ end
165
+
166
+ # Display the rendered output of the test and
167
+ #
168
+ # * If the expected ouptput matches the rendered output, simply display that output
169
+ # * If the expected ouptput does not match the rendered output, show the expect, then
170
+ # show the actual and give the user the option to overwrite expected with actual
171
+ # * If no expected output is saved for the test, give the user the option to save the
172
+ # rendered output as the expected output
173
+ def view
174
+ if pending?
175
+ ask_pending
176
+ elsif failed?
177
+ ask_failed
178
+ else
179
+ puts rendered
180
+ puts "Rendered output for #{test_file} matches expected."
181
+ end
182
+ end
183
+
184
+ # Return true if no output file exists for the test
185
+ def pending?
186
+ !File.exist?(full_output_file)
187
+ end
188
+
189
+ # Return true if the rendered output does not match the expected outptu
190
+ def failed?
191
+ return false if pending?
192
+ if rendered != File.read(full_output_file)
193
+ @error = 'Rendered output does not match expected.'
194
+ end
195
+ !@error.nil?
196
+ end
197
+
198
+ # Enable the Graphics debugger to print out debug information. Also render the template,
199
+ # but do not display it as rendering will clear the screen of debug output before the user
200
+ # can read it.
201
+ def debug
202
+ with_template_factory do |template_factory|
203
+ orig_debug = Graphics.debug
204
+ Graphics.debug = true
205
+ render_screen(template_factory, StringIO.new)
206
+ Graphics.debug = orig_debug
207
+ end
208
+ end
209
+
210
+ # Print out the template tree
211
+ def template
212
+ with_template_factory do |template_factory|
213
+ template = template_factory.build('Test', {})
214
+ puts Graphics::Debugger.new(template).debug
215
+ end
216
+ end
217
+
218
+ def ask_pending
219
+ puts rendered
220
+ STDOUT.flush
221
+ ask_to_save
222
+ end
223
+
224
+ def ask_failed
225
+ puts File.read(full_output_file)
226
+ puts "File: #{test_file}"
227
+ print 'View actual output? [Y/q] '
228
+ STDOUT.flush
229
+ exit if 'q' == STDIN.gets.strip.downcase
230
+ puts rendered
231
+ STDOUT.flush
232
+ ask_to_save
233
+ end
234
+
235
+ private
236
+
237
+ attr_reader :full_test_file, :full_output_file, :output_file
238
+
239
+ def ask_to_save
240
+ puts "File: #{test_file}"
241
+ print 'Save actual as the expected test output? [y/N/q] '
242
+ STDOUT.flush
243
+ response = STDIN.gets.strip.downcase
244
+ if response == 'y'
245
+ File.open(full_output_file, 'w') { |file| file.print(rendered) }
246
+ puts "Saved to #{output_file}"
247
+ elsif response == 'q'
248
+ puts 'Exiting'
249
+ exit
250
+ else
251
+ puts 'Skipped'
252
+ end
253
+ end
254
+
255
+ def rendered
256
+ @rendered ||= begin
257
+ string_io = StringIO.new
258
+ with_template_factory do |template_factory|
259
+ render_screen(template_factory, string_io)
260
+ end
261
+ string_io.string
262
+ end
263
+ end
264
+
265
+ def with_template_factory(&block)
266
+ require full_test_file
267
+ raise 'TemplateFactory must be defined' unless defined?(TemplateFactory)
268
+ yield TemplateFactory.new
269
+ ensure
270
+ Object.send(:remove_const, :TemplateFactory)
271
+ end
272
+
273
+ def render_screen(template_factory, output)
274
+ Utils::Ansi.with_screen(output, width: SCREEN_WIDTH, height: SCREEN_HEIGHT) do
275
+ rendered = Graphics::Renderer.new(
276
+ template_factory.build('test', {}),
277
+ SCREEN_WIDTH,
278
+ SCREEN_HEIGHT
279
+ ).paint
280
+ Device::Screen.new(10000, output: output).handle_renders([rendered])
281
+ end
282
+ end
283
+ end
284
+ end
285
+ end