whirled_peas 0.3.0 → 0.7.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +549 -85
  5. data/Rakefile +28 -3
  6. data/examples/intro.rb +52 -0
  7. data/examples/scrolling.rb +53 -0
  8. data/exe/whirled_peas +7 -0
  9. data/lib/whirled_peas.rb +12 -36
  10. data/lib/whirled_peas/command_line.rb +255 -0
  11. data/lib/whirled_peas/config.rb +21 -0
  12. data/lib/whirled_peas/errors.rb +7 -0
  13. data/lib/whirled_peas/frame.rb +0 -5
  14. data/lib/whirled_peas/frame/consumer.rb +30 -0
  15. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  16. data/lib/whirled_peas/frame/event_loop.rb +69 -38
  17. data/lib/whirled_peas/frame/producer.rb +36 -19
  18. data/lib/whirled_peas/graphics.rb +19 -0
  19. data/lib/whirled_peas/graphics/box_painter.rb +101 -0
  20. data/lib/whirled_peas/graphics/canvas.rb +118 -0
  21. data/lib/whirled_peas/graphics/composer.rb +80 -0
  22. data/lib/whirled_peas/graphics/container_coords.rb +72 -0
  23. data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
  24. data/lib/whirled_peas/graphics/container_painter.rb +272 -0
  25. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  26. data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
  27. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  28. data/lib/whirled_peas/graphics/painter.rb +23 -0
  29. data/lib/whirled_peas/graphics/renderer.rb +26 -0
  30. data/lib/whirled_peas/graphics/screen.rb +70 -0
  31. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  32. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  33. data/lib/whirled_peas/settings.rb +5 -0
  34. data/lib/whirled_peas/settings/alignment.rb +24 -0
  35. data/lib/whirled_peas/settings/bg_color.rb +24 -0
  36. data/lib/whirled_peas/settings/border.rb +101 -0
  37. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  38. data/lib/whirled_peas/settings/color.rb +68 -0
  39. data/lib/whirled_peas/settings/container_settings.rb +223 -0
  40. data/lib/whirled_peas/settings/debugger.rb +96 -0
  41. data/lib/whirled_peas/settings/display_flow.rb +27 -0
  42. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  43. data/lib/whirled_peas/settings/grid_settings.rb +19 -0
  44. data/lib/whirled_peas/settings/margin.rb +8 -0
  45. data/lib/whirled_peas/settings/padding.rb +8 -0
  46. data/lib/whirled_peas/settings/position.rb +15 -0
  47. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  48. data/lib/whirled_peas/settings/sizing.rb +19 -0
  49. data/lib/whirled_peas/settings/spacing.rb +58 -0
  50. data/lib/whirled_peas/settings/text_color.rb +21 -0
  51. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  52. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  53. data/lib/whirled_peas/utils.rb +5 -0
  54. data/lib/whirled_peas/utils/ansi.rb +53 -0
  55. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  56. data/lib/whirled_peas/utils/title_font.rb +75 -0
  57. data/lib/whirled_peas/version.rb +1 -1
  58. data/screen_test/elements/box.frame +1 -0
  59. data/screen_test/elements/box.rb +20 -0
  60. data/screen_test/elements/grid.frame +1 -0
  61. data/screen_test/elements/grid.rb +13 -0
  62. data/screen_test/elements/screen_overflow_x.frame +1 -0
  63. data/screen_test/elements/screen_overflow_x.rb +9 -0
  64. data/screen_test/elements/screen_overflow_y.frame +1 -0
  65. data/screen_test/elements/screen_overflow_y.rb +9 -0
  66. data/screen_test/elements/text.frame +1 -0
  67. data/screen_test/elements/text.rb +9 -0
  68. data/screen_test/elements/text_multiline.frame +1 -0
  69. data/screen_test/elements/text_multiline.rb +9 -0
  70. data/screen_test/settings/align/box_around.frame +1 -0
  71. data/screen_test/settings/align/box_around.rb +16 -0
  72. data/screen_test/settings/align/box_between.frame +1 -0
  73. data/screen_test/settings/align/box_between.rb +16 -0
  74. data/screen_test/settings/align/box_center.frame +1 -0
  75. data/screen_test/settings/align/box_center.rb +21 -0
  76. data/screen_test/settings/align/box_default.frame +1 -0
  77. data/screen_test/settings/align/box_default.rb +20 -0
  78. data/screen_test/settings/align/box_evenly.frame +1 -0
  79. data/screen_test/settings/align/box_evenly.rb +16 -0
  80. data/screen_test/settings/align/box_left.frame +1 -0
  81. data/screen_test/settings/align/box_left.rb +21 -0
  82. data/screen_test/settings/align/box_right.frame +1 -0
  83. data/screen_test/settings/align/box_right.rb +21 -0
  84. data/screen_test/settings/align/children_center.frame +1 -0
  85. data/screen_test/settings/align/children_center.rb +15 -0
  86. data/screen_test/settings/align/children_left.frame +1 -0
  87. data/screen_test/settings/align/children_left.rb +15 -0
  88. data/screen_test/settings/align/children_right.frame +1 -0
  89. data/screen_test/settings/align/children_right.rb +15 -0
  90. data/screen_test/settings/align/grid_center.frame +1 -0
  91. data/screen_test/settings/align/grid_center.rb +18 -0
  92. data/screen_test/settings/align/grid_default.frame +1 -0
  93. data/screen_test/settings/align/grid_default.rb +17 -0
  94. data/screen_test/settings/align/grid_left.frame +1 -0
  95. data/screen_test/settings/align/grid_left.rb +18 -0
  96. data/screen_test/settings/align/grid_right.frame +1 -0
  97. data/screen_test/settings/align/grid_right.rb +18 -0
  98. data/screen_test/settings/ansi/bold.frame +1 -0
  99. data/screen_test/settings/ansi/bold.rb +14 -0
  100. data/screen_test/settings/ansi/color.frame +1 -0
  101. data/screen_test/settings/ansi/color.rb +37 -0
  102. data/screen_test/settings/ansi/underline.frame +1 -0
  103. data/screen_test/settings/ansi/underline.rb +14 -0
  104. data/screen_test/settings/border.frame +1 -0
  105. data/screen_test/settings/border.rb +13 -0
  106. data/screen_test/settings/flow/box_b2t.frame +1 -0
  107. data/screen_test/settings/flow/box_b2t.rb +26 -0
  108. data/screen_test/settings/flow/box_l2r.frame +1 -0
  109. data/screen_test/settings/flow/box_l2r.rb +26 -0
  110. data/screen_test/settings/flow/box_r2l.frame +1 -0
  111. data/screen_test/settings/flow/box_r2l.rb +26 -0
  112. data/screen_test/settings/flow/box_t2b.frame +1 -0
  113. data/screen_test/settings/flow/box_t2b.rb +26 -0
  114. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  115. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  116. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  117. data/screen_test/settings/flow/grid_l2r.rb +14 -0
  118. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  119. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  120. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  121. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  122. data/screen_test/settings/height/box.frame +1 -0
  123. data/screen_test/settings/height/box.rb +13 -0
  124. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  125. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  126. data/screen_test/settings/height/grid.frame +1 -0
  127. data/screen_test/settings/height/grid.rb +14 -0
  128. data/screen_test/settings/height/overflow_box.frame +1 -0
  129. data/screen_test/settings/height/overflow_box.rb +13 -0
  130. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  131. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  132. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  133. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  134. data/screen_test/settings/height/overflow_grid.frame +1 -0
  135. data/screen_test/settings/height/overflow_grid.rb +16 -0
  136. data/screen_test/settings/margin.frame +1 -0
  137. data/screen_test/settings/margin.rb +16 -0
  138. data/screen_test/settings/padding.frame +1 -0
  139. data/screen_test/settings/padding.rb +13 -0
  140. data/screen_test/settings/position/box_left.frame +1 -0
  141. data/screen_test/settings/position/box_left.rb +17 -0
  142. data/screen_test/settings/position/box_left_negative.frame +1 -0
  143. data/screen_test/settings/position/box_left_negative.rb +17 -0
  144. data/screen_test/settings/position/box_top.frame +1 -0
  145. data/screen_test/settings/position/box_top.rb +17 -0
  146. data/screen_test/settings/position/box_top_negative.frame +1 -0
  147. data/screen_test/settings/position/box_top_negative.rb +17 -0
  148. data/screen_test/settings/position/grid_left.frame +1 -0
  149. data/screen_test/settings/position/grid_left.rb +18 -0
  150. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  151. data/screen_test/settings/position/grid_left_negative.rb +18 -0
  152. data/screen_test/settings/position/grid_top.frame +1 -0
  153. data/screen_test/settings/position/grid_top.rb +18 -0
  154. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  155. data/screen_test/settings/position/grid_top_negative.rb +18 -0
  156. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  157. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  158. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  159. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  160. data/screen_test/settings/scroll/vert_box.frame +1 -0
  161. data/screen_test/settings/scroll/vert_box.rb +20 -0
  162. data/screen_test/settings/title_font.frame +1 -0
  163. data/screen_test/settings/title_font.rb +12 -0
  164. data/screen_test/settings/valign/box_around.frame +1 -0
  165. data/screen_test/settings/valign/box_around.rb +17 -0
  166. data/screen_test/settings/valign/box_between.frame +1 -0
  167. data/screen_test/settings/valign/box_between.rb +17 -0
  168. data/screen_test/settings/valign/box_bottom.frame +1 -0
  169. data/screen_test/settings/valign/box_bottom.rb +17 -0
  170. data/screen_test/settings/valign/box_default.frame +1 -0
  171. data/screen_test/settings/valign/box_default.rb +16 -0
  172. data/screen_test/settings/valign/box_evenly.frame +1 -0
  173. data/screen_test/settings/valign/box_evenly.rb +17 -0
  174. data/screen_test/settings/valign/box_middle.frame +1 -0
  175. data/screen_test/settings/valign/box_middle.rb +17 -0
  176. data/screen_test/settings/valign/box_top.frame +1 -0
  177. data/screen_test/settings/valign/box_top.rb +17 -0
  178. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  179. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  180. data/screen_test/settings/valign/grid_default.frame +1 -0
  181. data/screen_test/settings/valign/grid_default.rb +14 -0
  182. data/screen_test/settings/valign/grid_middle.frame +1 -0
  183. data/screen_test/settings/valign/grid_middle.rb +15 -0
  184. data/screen_test/settings/valign/grid_top.frame +1 -0
  185. data/screen_test/settings/valign/grid_top.rb +15 -0
  186. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  187. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  188. data/screen_test/settings/width/box_content.frame +1 -0
  189. data/screen_test/settings/width/box_content.rb +15 -0
  190. data/screen_test/settings/width/box_default.frame +1 -0
  191. data/screen_test/settings/width/box_default.rb +14 -0
  192. data/screen_test/settings/width/grid.frame +1 -0
  193. data/screen_test/settings/width/grid.rb +14 -0
  194. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  195. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  196. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  197. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  198. data/screen_test/settings/width/overflow_box.frame +1 -0
  199. data/screen_test/settings/width/overflow_box.rb +13 -0
  200. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  201. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  202. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  203. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  204. data/screen_test/settings/width/overflow_grid.frame +1 -0
  205. data/screen_test/settings/width/overflow_grid.rb +14 -0
  206. data/tools/whirled_peas/tools/screen_tester.rb +233 -0
  207. data/whirled_peas.gemspec +4 -1
  208. metadata +215 -17
  209. data/lib/whirled_peas/ui.rb +0 -7
  210. data/lib/whirled_peas/ui/ansi.rb +0 -103
  211. data/lib/whirled_peas/ui/canvas.rb +0 -68
  212. data/lib/whirled_peas/ui/color.rb +0 -101
  213. data/lib/whirled_peas/ui/element.rb +0 -224
  214. data/lib/whirled_peas/ui/painter.rb +0 -283
  215. data/lib/whirled_peas/ui/screen.rb +0 -60
  216. data/lib/whirled_peas/ui/settings.rb +0 -523
  217. data/sandbox/auto.rb +0 -13
  218. data/sandbox/box.rb +0 -19
  219. data/sandbox/grid.rb +0 -13
  220. data/sandbox/sandbox.rb +0 -17
  221. data/sandbox/text.rb +0 -33
@@ -0,0 +1 @@
1
+ [?25l┏━┓┃ ┃┃ ┃┃ ┃┗━┛A[?25h
@@ -0,0 +1,15 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_grid('Alignment') do |composer, settings|
7
+ settings.num_cols = 1
8
+ settings.full_border
9
+ settings.height = 3
10
+ settings.valign = :top
11
+ composer.add_text { 'A' }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━━━━━━━━┓┃ ┃┗━━━━━━━━━━━━━┛15/bor[?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 = :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
@@ -0,0 +1,14 @@
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
+ '15/default'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ [?25l┏━━━━━━┳━━━━━━┓┃ ┃ ┃┣━━━━━━╋━━━━━━┫┃ ┃ ┃┣━━━━━━╋━━━━━━┫┃ ┃ ┃┗━━━━━━┻━━━━━━┛666666[?25h
@@ -0,0 +1,14 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer|
6
+ composer.add_grid('Wide') do |_, settings|
7
+ settings.full_border
8
+ settings.width = 6
9
+ settings.num_cols = 2
10
+ 6.times.map { '6' }
11
+ end
12
+ end
13
+ end
14
+ 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,14 @@
1
+ require 'whirled_peas'
2
+
3
+ class TemplateFactory
4
+ def build(*)
5
+ WhirledPeas.template do |composer, settings|
6
+ composer.add_grid('grid') do |_, settings|
7
+ settings.width = 10
8
+ settings.full_border
9
+ settings.num_cols = 1
10
+ ["ABCDEFGHIJKLMNOPQRSTUVWZYZ"]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,233 @@
1
+ require 'bundler/setup'
2
+ require 'whirled_peas'
3
+ require 'whirled_peas/frame/event_loop'
4
+ require 'whirled_peas/frame/producer'
5
+ require 'whirled_peas/graphics/debugger'
6
+ require 'whirled_peas/graphics/renderer'
7
+ require 'whirled_peas/graphics/screen'
8
+ require 'whirled_peas/settings/text_color'
9
+ require 'whirled_peas/utils/formatted_string'
10
+
11
+ module WhirledPeas
12
+ module Tools
13
+ # levels_up = 0 returns the directory of the current file. If the current file is a
14
+ # directory, then it will return a parent directory
15
+ def self.parent_directory(file, levels_up=0)
16
+ return File.dirname(file) if levels_up == 0
17
+ parent_directory(File.dirname(file), levels_up - 1)
18
+ end
19
+
20
+ class ScreenTester
21
+ SCREEN_WIDTH = 32
22
+ SCREEN_HEIGHT = 24
23
+
24
+ def self.base_dir
25
+ Tools.parent_directory(__FILE__, 3)
26
+ end
27
+
28
+ def self.test_files
29
+ Dir.glob(File.join(base_dir, 'screen_test', '**', '*.rb'))
30
+ end
31
+
32
+ def self.run_all
33
+ failures = {}
34
+ pendings = Set.new
35
+ puts "Running #{test_files.length} rendered screen test(s)"
36
+ puts
37
+ test_files.each do |file|
38
+ tester = new(file)
39
+ if tester.pending?
40
+ print Utils::FormattedString.new('.', Settings::TextColor::YELLOW)
41
+ pendings << file
42
+ elsif tester.failed?
43
+ print Utils::FormattedString.new('.', Settings::TextColor::RED)
44
+ failures[file] = tester.error
45
+ else
46
+ print Utils::FormattedString.new('.', Settings::TextColor::GREEN)
47
+ end
48
+ STDOUT.flush
49
+ end
50
+ puts
51
+ puts if pendings.count > 0
52
+ pendings.each do |file|
53
+ puts Utils::FormattedString.new("PENDING: #{file}", Settings::TextColor::YELLOW)
54
+ end
55
+ puts if failures.count > 0
56
+ failures.each do |file, error|
57
+ puts Utils::FormattedString.new("Failed: #{file}:\n\n #{error}\n", Settings::TextColor::RED)
58
+ end
59
+
60
+ if failures.count == 0
61
+ puts
62
+ puts Utils::FormattedString.new('No failures', Settings::TextColor::GREEN)
63
+ else
64
+ exit(1)
65
+ end
66
+ end
67
+
68
+ def self.update_all
69
+ num_attempted = 0
70
+ test_files.map do |file|
71
+ num_attempted += 1 if new(file).update(false)
72
+ end
73
+ if num_attempted == 0
74
+ puts 'All rendered output matched expected.'
75
+ end
76
+ end
77
+
78
+ attr_reader :error
79
+
80
+ def initialize(test_file)
81
+ @full_test_file = test_file[0] == '/' ? test_file : File.join(Dir.pwd, test_file)
82
+ raise ArgumentError, "File not found: #{test_file}" unless File.exist?(@full_test_file)
83
+ @test_file = @full_test_file.sub(self.class.base_dir, '').sub(/^\//, '')
84
+ @full_output_file = @full_test_file.sub(/\.rb$/, '.frame')
85
+ @output_file = @full_output_file.sub(self.class.base_dir, '').sub(/^\//, '')
86
+ end
87
+
88
+ def update(report_passing=true)
89
+ if pending?
90
+ ask_pending
91
+ return true
92
+ elsif failed?
93
+ ask_failed
94
+ return true
95
+ elsif report_passing
96
+ puts "Actual rendered output for #{test_file} matches expected."
97
+ end
98
+ false
99
+ end
100
+
101
+ def pending?
102
+ !File.exist?(full_output_file)
103
+ end
104
+
105
+ def failed?
106
+ if rendered != File.read(full_output_file)
107
+ @error = 'Rendered output does not match saved output'
108
+ end
109
+ !@error.nil?
110
+ end
111
+
112
+ def view
113
+ with_template_factory do |template_factory|
114
+ render_screen(template_factory, STDOUT)
115
+ end
116
+ end
117
+
118
+ def debug
119
+ with_template_factory do |template_factory|
120
+ orig_debug = Graphics.debug
121
+ Graphics.debug = true
122
+ render_screen(template_factory, StringIO.new)
123
+ Graphics.debug = orig_debug
124
+ end
125
+ end
126
+
127
+ def template
128
+ with_template_factory do |template_factory|
129
+ template = template_factory.build('Test', {})
130
+ puts Graphics::Debugger.new(template).debug
131
+ end
132
+ end
133
+
134
+ def save
135
+ if File.exist?(full_output_file)
136
+ puts "Existing output file found: #{full_output_file}"
137
+ puts "overwriting..."
138
+ else
139
+ puts "Writing output to file: #{full_output_file}"
140
+ end
141
+
142
+ with_template_factory do |template_factory|
143
+ File.open(full_output_file, 'w') do |file|
144
+ render_screen(template_factory, file)
145
+ end
146
+ end
147
+ end
148
+
149
+ def ask_pending
150
+ puts "File: #{test_file}"
151
+ puts Utils::FormattedString.new('Frame file does not exist', Settings::TextColor::YELLOW)
152
+ print 'View rendered frame? [Y/n/q] '
153
+ STDOUT.flush
154
+ response = STDIN.gets.strip.downcase
155
+ case response
156
+ when 'q'
157
+ exit
158
+ when 'n'
159
+ return
160
+ end
161
+ puts rendered
162
+ STDOUT.flush
163
+ ask_to_save
164
+ end
165
+
166
+ def ask_failed
167
+ puts "File: #{test_file}"
168
+ puts Utils::FormattedString.new('Output from test does not match saved output', Settings::TextColor::RED)
169
+ print 'View expected output? [Y/q] '
170
+ STDOUT.flush
171
+ exit if 'q' == STDIN.gets.strip.downcase
172
+ puts File.read(full_output_file)
173
+ puts "File: #{test_file}"
174
+ print 'View actual output? [Y/q] '
175
+ STDOUT.flush
176
+ exit if 'q' == STDIN.gets.strip.downcase
177
+ puts rendered
178
+ STDOUT.flush
179
+ ask_to_save
180
+ end
181
+
182
+ private
183
+
184
+ attr_reader :full_test_file, :test_file, :full_output_file, :output_file
185
+
186
+ def ask_to_save
187
+ puts "File: #{test_file}"
188
+ print 'Save actual as the expected test output? [y/N/q] '
189
+ STDOUT.flush
190
+ response = STDIN.gets.strip.downcase
191
+ print Utils::Ansi.cursor_pos(left: 0, top: 0)
192
+ print Utils::Ansi.clear_down
193
+ if response == 'y'
194
+ File.open(full_output_file, 'w') { |file| file.print(rendered) }
195
+ puts "Saved to #{output_file}"
196
+ elsif response == 'q'
197
+ puts 'Exiting'
198
+ exit
199
+ else
200
+ puts 'Skipped'
201
+ end
202
+ end
203
+
204
+ def rendered
205
+ @rendered ||= begin
206
+ string_io = StringIO.new
207
+ with_template_factory do |template_factory|
208
+ render_screen(template_factory, string_io)
209
+ end
210
+ string_io.string
211
+ end
212
+ end
213
+
214
+ def with_template_factory(&block)
215
+ require full_test_file
216
+ raise 'TemplateFactory must be defined' unless defined?(TemplateFactory)
217
+ yield TemplateFactory.new
218
+ ensure
219
+ Object.send(:remove_const, :TemplateFactory)
220
+ end
221
+
222
+ def render_screen(template_factory, output)
223
+ screen = Graphics::Screen.new(output: output, width: SCREEN_WIDTH, height: SCREEN_HEIGHT)
224
+ consumer = Frame::EventLoop.new(
225
+ template_factory, screen: screen, refresh_rate: 100000
226
+ )
227
+ Frame::Producer.produce(consumer) do |producer|
228
+ producer.send_frame('test', args: {})
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
@@ -18,10 +18,13 @@ Gem::Specification.new do |spec|
18
18
  # Specify which files should be added to the gem when it is released.
19
19
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
20
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|sandbox)/}) }
22
22
  end
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
25
  spec.require_paths = ['lib']
24
26
 
25
27
  spec.add_runtime_dependency 'highline', '~> 2.0'
26
28
  spec.add_runtime_dependency 'json', '~> 2.5'
29
+ spec.add_runtime_dependency 'ruby_figlet', '~> 0.6'
27
30
  end