whirled_peas 0.5.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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,57 @@
1
+ require_relative 'config_command'
2
+
3
+ module WhirledPeas
4
+ module Command
5
+ class Record < ConfigCommand
6
+ def self.description
7
+ 'Record animation to a file'
8
+ end
9
+
10
+ def start
11
+ super
12
+ require 'highline'
13
+ require 'whirled_peas/animator/renderer_consumer'
14
+ require 'whirled_peas/animator/producer'
15
+ require 'whirled_peas/device/output_file'
16
+
17
+ width, height = HighLine.new.terminal.terminal_size
18
+ consumer = Animator::RendererConsumer.new(
19
+ WhirledPeas.config.template_factory,
20
+ Device::OutputFile.new(out_file),
21
+ width,
22
+ height
23
+ )
24
+ Animator::Producer.produce(
25
+ consumer, WhirledPeas.config.refresh_rate
26
+ ) do |producer|
27
+ config.application.start(producer)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :out_file
34
+
35
+ def validate!
36
+ super
37
+ return unless @error_text.nil?
38
+
39
+ out_file = args.shift
40
+ if out_file.nil?
41
+ @error_text = "#{command_name} requires an output file"
42
+ elsif !out_file.end_with?('.wpz')
43
+ if out_file.split('/').last =~ /\./
44
+ extra = ", found: .#{out_file.split('.').last}"
45
+ end
46
+ @error_text = "Expecting output file with .wpz extension#{extra}"
47
+ else
48
+ @out_file = out_file[0] == '/' ? out_file : File.join(Dir.pwd, out_file)
49
+ end
50
+ end
51
+
52
+ def options_usage
53
+ [*super, '<output file>'].join(' ')
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'frame_command'
2
+
3
+ module WhirledPeas
4
+ module Command
5
+ # Display a still frame with the specified arguments.
6
+ class Still < FrameCommand
7
+ def self.description
8
+ 'Show the specified still frame'
9
+ end
10
+
11
+ def start
12
+ super
13
+
14
+ require 'whirled_peas/device/screen'
15
+ require 'whirled_peas/graphics/renderer'
16
+ require 'whirled_peas/utils/ansi'
17
+
18
+ Utils::Ansi.with_screen do |width, height|
19
+ rendered = Graphics::Renderer.new(
20
+ WhirledPeas.config.template_factory.build(frame, frame_args),
21
+ width,
22
+ height
23
+ ).paint
24
+ Device::Screen.new(10000).handle_renders([rendered])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,225 +1,21 @@
1
- require 'json'
2
-
3
- require 'whirled_peas/graphics/debugger'
4
- require 'whirled_peas/graphics/renderer'
5
- require 'whirled_peas/graphics/screen'
6
- require 'whirled_peas/frame/debug_consumer'
7
- require 'whirled_peas/frame/event_loop'
8
- require 'whirled_peas/frame/producer'
9
- require 'whirled_peas/template/debugger'
1
+ require 'whirled_peas/command/debug'
2
+ require 'whirled_peas/command/fonts'
3
+ require 'whirled_peas/command/frames'
4
+ require 'whirled_peas/command/help'
5
+ require 'whirled_peas/command/play'
6
+ require 'whirled_peas/command/record'
7
+ require 'whirled_peas/command/still'
10
8
 
11
9
  module WhirledPeas
12
- class Command
13
- DEFAULT_LOG_LEVEL = Logger::INFO
14
- DEFAULT_FORMATTER = proc do |severity, datetime, progname, msg|
15
- if msg.is_a?(Exception)
16
- msg = %Q(#{msg.class}: #{msg.to_s}\n #{msg.backtrace.join("\n ")})
17
- end
18
- "[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
19
- end
20
-
21
- def self.command_name
22
- self.name.split('::').last.sub(/Command$/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
23
- end
24
-
25
- def self.build_logger(output, level=DEFAULT_LOG_LEVEL, formatter=DEFAULT_FORMATTER)
26
- logger = Logger.new(output)
27
- logger.level = level
28
- logger.formatter = formatter
29
- logger
30
- end
31
-
32
- attr_reader :args
33
-
34
- def initialize(args)
35
- @args = args
36
- end
37
-
38
- def valid?
39
- @error_text = nil
40
- validate!
41
- @error_text.nil?
42
- end
43
-
44
- def print_error
45
- puts @error_text if @error_text
46
- print_usage
47
- end
48
-
49
- def start
50
- end
51
-
52
- private
53
-
54
- def print_usage
55
- puts "Usage: #{$0} #{self.class.command_name}"
56
- end
57
-
58
- def validate!
59
- # Set @error_text if the options are not valid
60
- end
61
- end
62
-
63
- class TitleFontsCommand < Command
64
- def start
65
- require 'whirled_peas/utils/title_font'
66
-
67
- Utils::TitleFont.fonts.keys.each do |key|
68
- puts Utils::TitleFont.to_s(key.to_s, key)
69
- puts key.inspect
70
- puts
71
- end
72
- end
73
- end
74
-
75
- class ConfigCommand < Command
76
- def start
77
- require config
78
- end
79
-
80
- private
81
-
82
- attr_reader :config
83
-
84
- def validate!
85
- if args.length == 0
86
- @error_text = "#{self.class.command_name} requires a config file"
87
- elsif !File.exist?(args[0])
88
- @error_text = "File not found: #{args[0]}"
89
- elsif args[0][-3..-1] != '.rb'
90
- @error_text = 'Config file should be a .rb file'
91
- else
92
- @config = args[0][0] == '/' ? args[0] : File.join(Dir.pwd, args[0])
93
- end
94
- end
95
-
96
- def print_usage
97
- puts "Usage: #{$0} #{self.class.command_name} <config file>"
98
- end
99
- end
100
-
101
- class StartCommand < ConfigCommand
102
- LOGGER_ID = 'MAIN'
103
-
104
- def start
105
- super
106
-
107
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
108
-
109
- consumer = Frame::EventLoop.new(
110
- WhirledPeas.config.template_factory,
111
- WhirledPeas.config.loading_template_factory,
112
- logger: logger
113
- )
114
- Frame::Producer.produce(consumer, logger) do |producer|
115
- begin
116
- WhirledPeas.config.driver.start(producer)
117
- rescue => e
118
- logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
119
- logger.error(LOGGER_ID) { e }
120
- raise
121
- end
122
- end
123
- end
124
- end
125
-
126
- class ListFramesCommand < ConfigCommand
127
- def start
128
- super
129
-
130
- Frame::Producer.produce(Frame::DebugConsumer.new) do |producer|
131
- WhirledPeas.config.driver.start(producer)
132
- end
133
- end
134
- end
135
-
136
- class PlayFrameCommand < ConfigCommand
137
- def start
138
- super
139
-
140
- if args.last == '--template'
141
- element = WhirledPeas.config.template_factory.build(frame, frame_args)
142
- puts Template::Debugger.new(element).debug
143
- exit
144
- elsif args.last == '--painter'
145
- element = WhirledPeas.config.template_factory.build(frame, frame_args)
146
- painter = Graphics::Renderer.new(element, *Graphics::Screen.current_dimensions).painter
147
- puts Graphics::Debugger.new(painter).debug
148
- exit
149
- end
150
-
151
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
152
-
153
- consumer = Frame::EventLoop.new(
154
- WhirledPeas.config.template_factory,
155
- logger: logger
156
- )
157
- Frame::Producer.produce(consumer, logger) do |producer|
158
- producer.send_frame(frame, args: frame_args)
159
- end
160
- end
161
-
162
- private
163
-
164
- attr_reader :frame, :frame_args
165
-
166
- def validate!
167
- super
168
- if !@error_text.nil?
169
- return
170
- elsif args.length < 2
171
- @error_text = "#{self.class.command_name} requires a frame name"
172
- else
173
- @frame = args[1]
174
- @frame_args = {}
175
- return if args.length < 3 || args[2][0..1] == '--'
176
- JSON.parse(args[2] || '{}').each do |key, value|
177
- @frame_args[key.to_sym] = value
178
- end
179
- end
180
- end
181
-
182
- def print_usage
183
- puts "Usage: #{$0} #{self.class.command_name} <config file> <frame> [args as a JSON string] [--debug]"
184
- end
185
- end
186
-
187
- class LoadingCommand < ConfigCommand
188
- def start
189
- super
190
- unless WhirledPeas.config.loading_template_factory
191
- puts 'No loading screen configured'
192
- exit
193
- end
194
-
195
- if args.last == '--debug'
196
- puts WhirledPeas.config.loading_template_factory.build.inspect
197
- exit
198
- end
199
-
200
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
201
- consumer = Frame::EventLoop.new(
202
- WhirledPeas.config.template_factory,
203
- WhirledPeas.config.loading_template_factory,
204
- logger: logger
205
- )
206
- Frame::Producer.produce(consumer, logger) { sleep(5) }
207
- end
208
-
209
- private
210
-
211
- def print_usage
212
- puts "Usage: #{$0} #{self.class.command_name} [--debug]"
213
- end
214
- end
215
-
216
10
  class CommandLine
217
11
  COMMANDS = [
218
- StartCommand,
219
- ListFramesCommand,
220
- PlayFrameCommand,
221
- LoadingCommand,
222
- TitleFontsCommand
12
+ Command::Debug,
13
+ Command::Fonts,
14
+ Command::Frames,
15
+ Command::Help,
16
+ Command::Play,
17
+ Command::Record,
18
+ Command::Still
223
19
  ].map.with_object({}) { |c, h| h[c.command_name] = c }
224
20
 
225
21
  def initialize(args)
@@ -240,7 +36,7 @@ module WhirledPeas
240
36
  exit(1)
241
37
  end
242
38
 
243
- cmd = COMMANDS[command].new(args)
39
+ cmd = COMMANDS[command].new(args, WhirledPeas.config)
244
40
 
245
41
  unless cmd.valid?
246
42
  cmd.print_error
@@ -257,7 +53,13 @@ module WhirledPeas
257
53
  def print_usage
258
54
  puts "Usage: #{$0} <command> [command options]"
259
55
  puts
260
- puts "Available commands: #{COMMANDS.keys.join(', ')}"
56
+ puts 'Available commands:'
57
+ puts
58
+ max_name_length = 0
59
+ COMMANDS.keys.each { |c| max_name_length = c.length if c.length > max_name_length }
60
+ COMMANDS.each do |name, klass|
61
+ puts " #{name.ljust(max_name_length, ' ')} #{klass.description}"
62
+ end
261
63
  end
262
64
  end
263
65
  end
@@ -1,13 +1,47 @@
1
+ require 'logger'
2
+
1
3
  module WhirledPeas
2
4
  class Config
3
- attr_writer :driver, :template_factory
4
- attr_accessor :loading_template_factory
5
+ # Refreshed rate measured in frames per second
6
+ DEFAULT_REFRESH_RATE = 30
7
+
8
+ DEFAULT_LOG_LEVEL = Logger::INFO
9
+ DEFAULT_LOG_FILE = 'whirled_peas.log'
5
10
 
6
- def driver
7
- unless @driver
8
- raise ConfigurationError, 'driver must be configured'
11
+ # This formatter expects a loggers to send `progname` in each log call. This value
12
+ # should be an all uppercase version of the module or class that is invoking the
13
+ # logger. Ruby's logger supports setting this value on a per-log statement basis
14
+ # when the log message is passed in through a block:
15
+ #
16
+ # logger.<level>(progname, &block)
17
+ #
18
+ # E.g.
19
+ #
20
+ # class Foo
21
+ # def bar
22
+ # logger.warn('FOO') { 'Something fishy happened in #bar' }
23
+ # end
24
+ # end
25
+ #
26
+ # The block format also has the advantage that the evaluation of the block only
27
+ # occurs if the message gets logged. So expensive to calculate debug statements
28
+ # will not impact the performance of the application if the log level is INFO or
29
+ # higher.
30
+ DEFAULT_FORMATTER = proc do |severity, datetime, progname, msg|
31
+ # Convert an instance of an exception into a nicely formatted message string
32
+ if msg.is_a?(Exception)
33
+ msg = %Q(#{msg.class}: #{msg.to_s}\n #{msg.backtrace.join("\n ")})
9
34
  end
10
- @driver
35
+ "[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
36
+ end
37
+
38
+ attr_writer :application, :template_factory, :refresh_rate, :log_level, :log_formatter, :log_file
39
+
40
+ def application
41
+ unless @application
42
+ raise ConfigurationError, 'application must be configured'
43
+ end
44
+ @application
11
45
  end
12
46
 
13
47
  def template_factory
@@ -16,6 +50,22 @@ module WhirledPeas
16
50
  end
17
51
  @template_factory
18
52
  end
53
+
54
+ def refresh_rate
55
+ @refresh_rate || DEFAULT_REFRESH_RATE
56
+ end
57
+
58
+ def log_level
59
+ @log_level || DEFAULT_LOG_LEVEL
60
+ end
61
+
62
+ def log_formatter
63
+ @log_formatter || DEFAULT_FORMATTER
64
+ end
65
+
66
+ def log_file
67
+ @log_file || DEFAULT_LOG_FILE
68
+ end
19
69
  end
20
70
  private_constant :Config
21
71
  end
@@ -0,0 +1,5 @@
1
+ module WhirledPeas
2
+ module Device
3
+ end
4
+ private_constant :Device
5
+ end
@@ -0,0 +1,8 @@
1
+ module WhirledPeas
2
+ module Device
3
+ class NullDevice
4
+ def handle_renders(*)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,19 @@
1
+ require 'whirled_peas/utils/file_handler'
2
+
3
+ module WhirledPeas
4
+ module Device
5
+ class OutputFile
6
+ def initialize(file)
7
+ @file = file
8
+ end
9
+
10
+ def handle_renders(renders)
11
+ Utils::FileHandler.write(file, renders)
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :file
17
+ end
18
+ end
19
+ end