whirled_peas 0.7.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (220) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +25 -0
  4. data/README.md +467 -120
  5. data/Rakefile +1 -20
  6. data/bin/easing +33 -0
  7. data/bin/reset_cursor +11 -0
  8. data/bin/screen_test +68 -0
  9. data/examples/graph.rb +54 -0
  10. data/examples/intro.rb +3 -3
  11. data/examples/scrolling.rb +5 -4
  12. data/lib/data/themes.yaml +13 -0
  13. data/lib/whirled_peas.rb +12 -6
  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 +43 -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 +111 -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/themes.rb +76 -0
  33. data/lib/whirled_peas/command_line.rb +24 -212
  34. data/lib/whirled_peas/config.rb +56 -6
  35. data/lib/whirled_peas/device.rb +5 -0
  36. data/lib/whirled_peas/device/null_device.rb +8 -0
  37. data/lib/whirled_peas/device/output_file.rb +19 -0
  38. data/lib/whirled_peas/device/screen.rb +26 -0
  39. data/lib/whirled_peas/graphics/composer.rb +23 -2
  40. data/lib/whirled_peas/graphics/container_painter.rb +91 -0
  41. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  42. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  43. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  44. data/lib/whirled_peas/graphics/graph_painter.rb +97 -0
  45. data/lib/whirled_peas/graphics/grid_painter.rb +1 -4
  46. data/lib/whirled_peas/graphics/painter.rb +10 -0
  47. data/lib/whirled_peas/graphics/renderer.rb +8 -2
  48. data/lib/whirled_peas/graphics/text_painter.rb +7 -11
  49. data/lib/whirled_peas/settings/border.rb +25 -4
  50. data/lib/whirled_peas/settings/container_settings.rb +2 -4
  51. data/lib/whirled_peas/settings/element_settings.rb +12 -3
  52. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  53. data/lib/whirled_peas/settings/grid_settings.rb +7 -0
  54. data/lib/whirled_peas/settings/text_settings.rb +1 -0
  55. data/lib/whirled_peas/settings/theme.rb +40 -0
  56. data/lib/whirled_peas/settings/theme_library.rb +63 -0
  57. data/lib/whirled_peas/utils/ansi.rb +13 -0
  58. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  59. data/lib/whirled_peas/version.rb +1 -1
  60. data/screen_test/elements/box.frame +1 -1
  61. data/screen_test/elements/box.rb +1 -1
  62. data/screen_test/elements/graph.frame +1 -0
  63. data/screen_test/elements/graph.rb +12 -0
  64. data/screen_test/elements/grid.frame +1 -1
  65. data/screen_test/elements/grid.rb +1 -1
  66. data/screen_test/elements/screen_overflow_x.frame +1 -1
  67. data/screen_test/elements/screen_overflow_x.rb +1 -1
  68. data/screen_test/elements/screen_overflow_y.frame +1 -1
  69. data/screen_test/elements/screen_overflow_y.rb +1 -1
  70. data/screen_test/elements/text.frame +1 -1
  71. data/screen_test/elements/text.rb +1 -1
  72. data/screen_test/elements/text_multiline.frame +1 -1
  73. data/screen_test/elements/text_multiline.rb +1 -1
  74. data/screen_test/elements/theme.frame +1 -0
  75. data/screen_test/elements/theme.rb +26 -0
  76. data/screen_test/settings/align/box_around.frame +1 -1
  77. data/screen_test/settings/align/box_around.rb +1 -1
  78. data/screen_test/settings/align/box_between.frame +1 -1
  79. data/screen_test/settings/align/box_between.rb +1 -1
  80. data/screen_test/settings/align/box_center.frame +1 -1
  81. data/screen_test/settings/align/box_center.rb +1 -1
  82. data/screen_test/settings/align/box_default.frame +1 -1
  83. data/screen_test/settings/align/box_default.rb +1 -1
  84. data/screen_test/settings/align/box_evenly.frame +1 -1
  85. data/screen_test/settings/align/box_evenly.rb +1 -1
  86. data/screen_test/settings/align/box_left.frame +1 -1
  87. data/screen_test/settings/align/box_left.rb +1 -1
  88. data/screen_test/settings/align/box_right.frame +1 -1
  89. data/screen_test/settings/align/box_right.rb +1 -1
  90. data/screen_test/settings/align/children_center.frame +1 -1
  91. data/screen_test/settings/align/children_center.rb +1 -1
  92. data/screen_test/settings/align/children_left.frame +1 -1
  93. data/screen_test/settings/align/children_left.rb +1 -1
  94. data/screen_test/settings/align/children_right.frame +1 -1
  95. data/screen_test/settings/align/children_right.rb +1 -1
  96. data/screen_test/settings/align/grid_center.frame +1 -1
  97. data/screen_test/settings/align/grid_center.rb +1 -1
  98. data/screen_test/settings/align/grid_default.frame +1 -1
  99. data/screen_test/settings/align/grid_default.rb +1 -1
  100. data/screen_test/settings/align/grid_left.frame +1 -1
  101. data/screen_test/settings/align/grid_left.rb +1 -1
  102. data/screen_test/settings/align/grid_right.frame +1 -1
  103. data/screen_test/settings/align/grid_right.rb +1 -1
  104. data/screen_test/settings/ansi/bold.frame +1 -1
  105. data/screen_test/settings/ansi/bold.rb +1 -1
  106. data/screen_test/settings/ansi/color.frame +1 -1
  107. data/screen_test/settings/ansi/color.rb +1 -1
  108. data/screen_test/settings/ansi/underline.frame +1 -1
  109. data/screen_test/settings/ansi/underline.rb +1 -1
  110. data/screen_test/settings/border.frame +1 -1
  111. data/screen_test/settings/border.rb +1 -1
  112. data/screen_test/settings/flow/box_b2t.frame +1 -1
  113. data/screen_test/settings/flow/box_b2t.rb +1 -1
  114. data/screen_test/settings/flow/box_l2r.frame +1 -1
  115. data/screen_test/settings/flow/box_l2r.rb +1 -1
  116. data/screen_test/settings/flow/box_r2l.frame +1 -1
  117. data/screen_test/settings/flow/box_r2l.rb +1 -1
  118. data/screen_test/settings/flow/box_t2b.frame +1 -1
  119. data/screen_test/settings/flow/box_t2b.rb +1 -1
  120. data/screen_test/settings/flow/grid_b2t.frame +1 -1
  121. data/screen_test/settings/flow/grid_b2t.rb +2 -2
  122. data/screen_test/settings/flow/grid_l2r.frame +1 -1
  123. data/screen_test/settings/flow/grid_l2r.rb +2 -2
  124. data/screen_test/settings/flow/grid_r2l.frame +1 -1
  125. data/screen_test/settings/flow/grid_r2l.rb +2 -2
  126. data/screen_test/settings/flow/grid_t2b.frame +1 -1
  127. data/screen_test/settings/flow/grid_t2b.rb +2 -2
  128. data/screen_test/settings/height/box.frame +1 -1
  129. data/screen_test/settings/height/box.rb +1 -1
  130. data/screen_test/settings/height/box_border_sizing.frame +1 -1
  131. data/screen_test/settings/height/box_border_sizing.rb +1 -1
  132. data/screen_test/settings/height/grid.frame +1 -1
  133. data/screen_test/settings/height/grid.rb +1 -1
  134. data/screen_test/settings/height/overflow_box.frame +1 -1
  135. data/screen_test/settings/height/overflow_box.rb +1 -1
  136. data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
  137. data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
  138. data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
  139. data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
  140. data/screen_test/settings/height/overflow_grid.frame +1 -1
  141. data/screen_test/settings/height/overflow_grid.rb +1 -1
  142. data/screen_test/settings/margin.frame +1 -1
  143. data/screen_test/settings/margin.rb +1 -1
  144. data/screen_test/settings/padding.frame +1 -1
  145. data/screen_test/settings/padding.rb +1 -1
  146. data/screen_test/settings/position/box_left.frame +1 -1
  147. data/screen_test/settings/position/box_left.rb +1 -1
  148. data/screen_test/settings/position/box_left_negative.frame +1 -1
  149. data/screen_test/settings/position/box_left_negative.rb +1 -1
  150. data/screen_test/settings/position/box_top.frame +1 -1
  151. data/screen_test/settings/position/box_top.rb +1 -1
  152. data/screen_test/settings/position/box_top_negative.frame +1 -1
  153. data/screen_test/settings/position/box_top_negative.rb +1 -1
  154. data/screen_test/settings/position/grid_left.frame +1 -1
  155. data/screen_test/settings/position/grid_left.rb +1 -1
  156. data/screen_test/settings/position/grid_left_negative.frame +1 -1
  157. data/screen_test/settings/position/grid_left_negative.rb +1 -1
  158. data/screen_test/settings/position/grid_top.frame +1 -1
  159. data/screen_test/settings/position/grid_top.rb +1 -1
  160. data/screen_test/settings/position/grid_top_negative.frame +1 -1
  161. data/screen_test/settings/position/grid_top_negative.rb +1 -1
  162. data/screen_test/settings/scroll/horiz_box.frame +1 -1
  163. data/screen_test/settings/scroll/horiz_box.rb +1 -1
  164. data/screen_test/settings/scroll/horiz_box_align_center.rb +1 -1
  165. data/screen_test/settings/scroll/horiz_box_align_right.rb +1 -1
  166. data/screen_test/settings/scroll/vert_box.frame +1 -1
  167. data/screen_test/settings/scroll/vert_box.rb +1 -1
  168. data/screen_test/settings/title_font.frame +1 -1
  169. data/screen_test/settings/title_font.rb +1 -1
  170. data/screen_test/settings/valign/box_around.frame +1 -1
  171. data/screen_test/settings/valign/box_around.rb +1 -1
  172. data/screen_test/settings/valign/box_between.frame +1 -1
  173. data/screen_test/settings/valign/box_between.rb +1 -1
  174. data/screen_test/settings/valign/box_bottom.frame +1 -1
  175. data/screen_test/settings/valign/box_bottom.rb +1 -1
  176. data/screen_test/settings/valign/box_default.frame +1 -1
  177. data/screen_test/settings/valign/box_default.rb +1 -1
  178. data/screen_test/settings/valign/box_evenly.frame +1 -1
  179. data/screen_test/settings/valign/box_evenly.rb +1 -1
  180. data/screen_test/settings/valign/box_middle.frame +1 -1
  181. data/screen_test/settings/valign/box_middle.rb +1 -1
  182. data/screen_test/settings/valign/box_top.frame +1 -1
  183. data/screen_test/settings/valign/box_top.rb +1 -1
  184. data/screen_test/settings/valign/grid_bottom.frame +1 -1
  185. data/screen_test/settings/valign/grid_bottom.rb +1 -1
  186. data/screen_test/settings/valign/grid_default.frame +1 -1
  187. data/screen_test/settings/valign/grid_default.rb +1 -1
  188. data/screen_test/settings/valign/grid_middle.frame +1 -1
  189. data/screen_test/settings/valign/grid_middle.rb +1 -1
  190. data/screen_test/settings/valign/grid_top.frame +1 -1
  191. data/screen_test/settings/valign/grid_top.rb +1 -1
  192. data/screen_test/settings/width/box_border_sizing.frame +1 -1
  193. data/screen_test/settings/width/box_border_sizing.rb +1 -1
  194. data/screen_test/settings/width/box_content.frame +1 -1
  195. data/screen_test/settings/width/box_content.rb +1 -1
  196. data/screen_test/settings/width/box_default.frame +1 -1
  197. data/screen_test/settings/width/box_default.rb +1 -1
  198. data/screen_test/settings/width/grid.frame +1 -1
  199. data/screen_test/settings/width/grid.rb +1 -1
  200. data/screen_test/settings/width/overflow_align_center.frame +1 -1
  201. data/screen_test/settings/width/overflow_align_center.rb +1 -1
  202. data/screen_test/settings/width/overflow_align_right.frame +1 -1
  203. data/screen_test/settings/width/overflow_align_right.rb +1 -1
  204. data/screen_test/settings/width/overflow_box.frame +1 -1
  205. data/screen_test/settings/width/overflow_box.rb +1 -1
  206. data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
  207. data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
  208. data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
  209. data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
  210. data/screen_test/settings/width/overflow_grid.frame +1 -1
  211. data/screen_test/settings/width/overflow_grid.rb +1 -1
  212. data/tools/whirled_peas/tools/screen_tester.rb +131 -65
  213. metadata +42 -9
  214. data/lib/whirled_peas/frame.rb +0 -6
  215. data/lib/whirled_peas/frame/consumer.rb +0 -30
  216. data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
  217. data/lib/whirled_peas/frame/event_loop.rb +0 -90
  218. data/lib/whirled_peas/frame/producer.rb +0 -67
  219. data/lib/whirled_peas/graphics/screen.rb +0 -70
  220. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
@@ -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
@@ -0,0 +1,76 @@
1
+ require 'whirled_peas/device/screen'
2
+ require 'whirled_peas/graphics/renderer'
3
+ require 'whirled_peas/settings/theme_library'
4
+
5
+ require_relative 'base'
6
+
7
+ module WhirledPeas
8
+ module Command
9
+ # Display a still frame with the specified arguments.
10
+ class Themes < Base
11
+ def self.description
12
+ 'List all themes with sample template rendered in the theme'
13
+ end
14
+
15
+ def start
16
+ super
17
+
18
+ require config_file unless config_file.nil?
19
+
20
+ theme_names = Settings::ThemeLibrary.theme_names
21
+ theme_names.each.with_index do |name, index|
22
+ template = WhirledPeas.template(name) do |composer, settings|
23
+ settings.full_border
24
+ settings.flow = :t2b
25
+ composer.add_text do |_, settings|
26
+ settings.title_font = :theme
27
+ name
28
+ end
29
+ composer.add_text do
30
+ name == Settings::ThemeLibrary.default_name ? ' (default)' : ''
31
+ end
32
+ composer.add_graph do |_, settings|
33
+ settings.height = 12
34
+ 20.times.map { |i| Math.sqrt(i) }
35
+ end
36
+ end
37
+ Utils::Ansi.with_screen do |width, height|
38
+ rendered = Graphics::Renderer.new(
39
+ template,
40
+ 80,
41
+ 30
42
+ ).paint
43
+ Device::Screen.new(10000).handle_renders([rendered])
44
+ end
45
+
46
+ if index < theme_names.length - 1
47
+ print 'See next theme? [Y/q] '
48
+ STDOUT.flush
49
+ break if gets.chomp == 'q'
50
+ end
51
+ end
52
+ rescue LoadError
53
+ puts "Error loading #{config_file}"
54
+ exit(1)
55
+ end
56
+
57
+ private
58
+
59
+ attr_reader :config_file
60
+
61
+ def validate!
62
+ super
63
+ config_file = args.shift
64
+ @error_text = 'hi'
65
+ unless config_file.nil?
66
+ # We think we have a valid ruby config file, set the absolute path to @config
67
+ @config_file = config_file[0] == '/' ? config_file : File.join(Dir.pwd, config_file)
68
+ end
69
+ end
70
+
71
+ def options_usage
72
+ '[config file]'
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,217 +1,23 @@
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'
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'
8
+ require 'whirled_peas/command/themes'
9
9
 
10
10
  module WhirledPeas
11
- class Command
12
- DEFAULT_LOG_LEVEL = Logger::INFO
13
- DEFAULT_FORMATTER = proc do |severity, datetime, progname, msg|
14
- if msg.is_a?(Exception)
15
- msg = %Q(#{msg.class}: #{msg.to_s}\n #{msg.backtrace.join("\n ")})
16
- end
17
- "[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
18
- end
19
-
20
- def self.command_name
21
- self.name.split('::').last.sub(/Command$/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
22
- end
23
-
24
- def self.build_logger(output, level=DEFAULT_LOG_LEVEL, formatter=DEFAULT_FORMATTER)
25
- logger = Logger.new(output)
26
- logger.level = level
27
- logger.formatter = formatter
28
- logger
29
- end
30
-
31
- attr_reader :args
32
-
33
- def initialize(args)
34
- @args = args
35
- end
36
-
37
- def valid?
38
- @error_text = nil
39
- validate!
40
- @error_text.nil?
41
- end
42
-
43
- def print_error
44
- puts @error_text if @error_text
45
- print_usage
46
- end
47
-
48
- def start
49
- end
50
-
51
- private
52
-
53
- def print_usage
54
- puts "Usage: #{$0} #{self.class.command_name}"
55
- end
56
-
57
- def validate!
58
- # Set @error_text if the options are not valid
59
- end
60
- end
61
-
62
- class TitleFontsCommand < Command
63
- def start
64
- require 'whirled_peas/utils/title_font'
65
-
66
- Utils::TitleFont.fonts.keys.each do |key|
67
- puts Utils::TitleFont.to_s(key.to_s, key)
68
- puts key.inspect
69
- puts
70
- end
71
- end
72
- end
73
-
74
- class ConfigCommand < Command
75
- def start
76
- require config
77
- end
78
-
79
- private
80
-
81
- attr_reader :config
82
-
83
- def validate!
84
- if args.length == 0
85
- @error_text = "#{self.class.command_name} requires a config file"
86
- elsif !File.exist?(args[0])
87
- @error_text = "File not found: #{args[0]}"
88
- elsif args[0][-3..-1] != '.rb'
89
- @error_text = 'Config file should be a .rb file'
90
- else
91
- @config = args[0][0] == '/' ? args[0] : File.join(Dir.pwd, args[0])
92
- end
93
- end
94
-
95
- def print_usage
96
- puts "Usage: #{$0} #{self.class.command_name} <config file>"
97
- end
98
- end
99
-
100
- class StartCommand < ConfigCommand
101
- LOGGER_ID = 'MAIN'
102
-
103
- def start
104
- super
105
-
106
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
107
-
108
- consumer = Frame::EventLoop.new(
109
- WhirledPeas.config.template_factory,
110
- WhirledPeas.config.loading_template_factory,
111
- logger: logger
112
- )
113
- Frame::Producer.produce(consumer, logger) do |producer|
114
- begin
115
- WhirledPeas.config.driver.start(producer)
116
- rescue => e
117
- logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
118
- logger.error(LOGGER_ID) { e }
119
- raise
120
- end
121
- end
122
- end
123
- end
124
-
125
- class ListFramesCommand < ConfigCommand
126
- def start
127
- super
128
-
129
- Frame::Producer.produce(Frame::DebugConsumer.new) do |producer|
130
- WhirledPeas.config.driver.start(producer)
131
- end
132
- end
133
- end
134
-
135
- class PlayFrameCommand < ConfigCommand
136
- def start
137
- super
138
-
139
- if args.last == '--template'
140
- template = WhirledPeas.config.template_factory.build(frame, frame_args)
141
- puts Graphics::Debugger.new(template).debug
142
- else
143
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
144
- consumer = Frame::EventLoop.new(
145
- WhirledPeas.config.template_factory,
146
- logger: logger
147
- )
148
- Frame::Producer.produce(consumer, logger) do |producer|
149
- producer.send_frame(frame, args: frame_args)
150
- end
151
- end
152
- end
153
-
154
- private
155
-
156
- attr_reader :frame, :frame_args
157
-
158
- def validate!
159
- super
160
- if !@error_text.nil?
161
- return
162
- elsif args.length < 2
163
- @error_text = "#{self.class.command_name} requires a frame name"
164
- else
165
- @frame = args[1]
166
- @frame_args = {}
167
- return if args.length < 3 || args[2][0..1] == '--'
168
- JSON.parse(args[2] || '{}').each do |key, value|
169
- @frame_args[key.to_sym] = value
170
- end
171
- end
172
- end
173
-
174
- def print_usage
175
- puts "Usage: #{$0} #{self.class.command_name} <config file> <frame> [args as a JSON string] [--template]"
176
- end
177
- end
178
-
179
- class LoadingCommand < ConfigCommand
180
- def start
181
- super
182
- unless WhirledPeas.config.loading_template_factory
183
- puts 'No loading screen configured'
184
- exit(1)
185
- end
186
-
187
- if args.last == '--template'
188
- template = WhirledPeas.config.loading_template_factory.build
189
- puts Graphics::Debugger.new(template).debug
190
- else
191
- logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
192
- consumer = Frame::EventLoop.new(
193
- WhirledPeas.config.template_factory,
194
- WhirledPeas.config.loading_template_factory,
195
- logger: logger
196
- )
197
- Frame::Producer.produce(consumer, logger) { sleep(5) }
198
- end
199
- end
200
-
201
- private
202
-
203
- def print_usage
204
- puts "Usage: #{$0} #{self.class.command_name} [--template]"
205
- end
206
- end
207
-
208
11
  class CommandLine
209
12
  COMMANDS = [
210
- StartCommand,
211
- ListFramesCommand,
212
- PlayFrameCommand,
213
- LoadingCommand,
214
- TitleFontsCommand
13
+ Command::Debug,
14
+ Command::Fonts,
15
+ Command::Frames,
16
+ Command::Help,
17
+ Command::Play,
18
+ Command::Record,
19
+ Command::Still,
20
+ Command::Themes
215
21
  ].map.with_object({}) { |c, h| h[c.command_name] = c }
216
22
 
217
23
  def initialize(args)
@@ -232,7 +38,7 @@ module WhirledPeas
232
38
  exit(1)
233
39
  end
234
40
 
235
- cmd = COMMANDS[command].new(args)
41
+ cmd = COMMANDS[command].new(args, WhirledPeas.config)
236
42
 
237
43
  unless cmd.valid?
238
44
  cmd.print_error
@@ -249,7 +55,13 @@ module WhirledPeas
249
55
  def print_usage
250
56
  puts "Usage: #{$0} <command> [command options]"
251
57
  puts
252
- puts "Available commands: #{COMMANDS.keys.join(', ')}"
58
+ puts 'Available commands:'
59
+ puts
60
+ max_name_length = 0
61
+ COMMANDS.keys.each { |c| max_name_length = c.length if c.length > max_name_length }
62
+ COMMANDS.each do |name, klass|
63
+ puts " #{name.ljust(max_name_length, ' ')} #{klass.description}"
64
+ end
253
65
  end
254
66
  end
255
67
  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