whirled_peas 0.1.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/CHANGELOG.md +32 -0
  4. data/Gemfile +1 -0
  5. data/README.md +240 -79
  6. data/Rakefile +37 -3
  7. data/bin/debug +35 -0
  8. data/exe/whirled_peas +7 -0
  9. data/lib/whirled_peas.rb +17 -37
  10. data/lib/whirled_peas/command_line.rb +263 -0
  11. data/lib/whirled_peas/config.rb +21 -0
  12. data/lib/whirled_peas/debugger.rb +80 -0
  13. data/lib/whirled_peas/errors.rb +7 -0
  14. data/lib/whirled_peas/frame.rb +0 -8
  15. data/lib/whirled_peas/frame/consumer.rb +14 -51
  16. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  17. data/lib/whirled_peas/frame/event_loop.rb +68 -38
  18. data/lib/whirled_peas/frame/producer.rb +37 -34
  19. data/lib/whirled_peas/graphics.rb +5 -0
  20. data/lib/whirled_peas/graphics/box_painter.rb +100 -0
  21. data/lib/whirled_peas/graphics/canvas.rb +107 -0
  22. data/lib/whirled_peas/graphics/container_coords.rb +61 -0
  23. data/lib/whirled_peas/graphics/container_dimensions.rb +65 -0
  24. data/lib/whirled_peas/graphics/container_painter.rb +116 -0
  25. data/lib/whirled_peas/graphics/debugger.rb +43 -0
  26. data/lib/whirled_peas/graphics/grid_painter.rb +56 -0
  27. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  28. data/lib/whirled_peas/graphics/painter.rb +24 -0
  29. data/lib/whirled_peas/graphics/renderer.rb +49 -0
  30. data/lib/whirled_peas/graphics/screen.rb +65 -0
  31. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  32. data/lib/whirled_peas/graphics/text_painter.rb +38 -0
  33. data/lib/whirled_peas/settings.rb +5 -0
  34. data/lib/whirled_peas/settings/bg_color.rb +22 -0
  35. data/lib/whirled_peas/settings/border.rb +101 -0
  36. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  37. data/lib/whirled_peas/settings/color.rb +69 -0
  38. data/lib/whirled_peas/settings/container_settings.rb +128 -0
  39. data/lib/whirled_peas/settings/debugger.rb +87 -0
  40. data/lib/whirled_peas/settings/display_flow.rb +25 -0
  41. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  42. data/lib/whirled_peas/settings/grid_settings.rb +11 -0
  43. data/lib/whirled_peas/settings/margin.rb +8 -0
  44. data/lib/whirled_peas/settings/padding.rb +8 -0
  45. data/lib/whirled_peas/settings/position.rb +15 -0
  46. data/lib/whirled_peas/settings/spacing.rb +24 -0
  47. data/lib/whirled_peas/settings/text_align.rb +19 -0
  48. data/lib/whirled_peas/settings/text_color.rb +19 -0
  49. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  50. data/lib/whirled_peas/template.rb +5 -0
  51. data/lib/whirled_peas/template/box_element.rb +8 -0
  52. data/lib/whirled_peas/template/composer.rb +68 -0
  53. data/lib/whirled_peas/template/container.rb +28 -0
  54. data/lib/whirled_peas/template/debugger.rb +34 -0
  55. data/lib/whirled_peas/template/element.rb +13 -0
  56. data/lib/whirled_peas/template/grid_element.rb +8 -0
  57. data/lib/whirled_peas/template/text_element.rb +24 -0
  58. data/lib/whirled_peas/utils.rb +5 -0
  59. data/lib/whirled_peas/utils/ansi.rb +53 -0
  60. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  61. data/lib/whirled_peas/utils/title_font.rb +75 -0
  62. data/lib/whirled_peas/version.rb +1 -1
  63. data/screen_test/rendered/elements/box.frame +1 -0
  64. data/screen_test/rendered/elements/box.rb +20 -0
  65. data/screen_test/rendered/elements/grid.frame +1 -0
  66. data/screen_test/rendered/elements/grid.rb +13 -0
  67. data/screen_test/rendered/elements/screen_overflow.rb +9 -0
  68. data/screen_test/rendered/elements/text.frame +1 -0
  69. data/screen_test/rendered/elements/text.rb +9 -0
  70. data/screen_test/rendered/elements/text_multiline.frame +1 -0
  71. data/screen_test/rendered/elements/text_multiline.rb +9 -0
  72. data/screen_test/rendered/settings/align/box.frame +1 -0
  73. data/screen_test/rendered/settings/align/box.rb +20 -0
  74. data/screen_test/rendered/settings/align/children_center.frame +1 -0
  75. data/screen_test/rendered/settings/align/children_center.rb +13 -0
  76. data/screen_test/rendered/settings/align/children_left.frame +1 -0
  77. data/screen_test/rendered/settings/align/children_left.rb +13 -0
  78. data/screen_test/rendered/settings/align/children_right.frame +1 -0
  79. data/screen_test/rendered/settings/align/children_right.rb +13 -0
  80. data/screen_test/rendered/settings/align/grid.frame +1 -0
  81. data/screen_test/rendered/settings/align/grid.rb +20 -0
  82. data/screen_test/rendered/settings/ansi/bold.frame +1 -0
  83. data/screen_test/rendered/settings/ansi/bold.rb +15 -0
  84. data/screen_test/rendered/settings/ansi/color.frame +1 -0
  85. data/screen_test/rendered/settings/ansi/color.rb +37 -0
  86. data/screen_test/rendered/settings/ansi/underline.frame +1 -0
  87. data/screen_test/rendered/settings/ansi/underline.rb +15 -0
  88. data/screen_test/rendered/settings/border.frame +1 -0
  89. data/screen_test/rendered/settings/border.rb +13 -0
  90. data/screen_test/rendered/settings/flow/l2r.frame +1 -0
  91. data/screen_test/rendered/settings/flow/l2r.rb +24 -0
  92. data/screen_test/rendered/settings/flow/t2b.frame +1 -0
  93. data/screen_test/rendered/settings/flow/t2b.rb +24 -0
  94. data/screen_test/rendered/settings/height/box.frame +1 -0
  95. data/screen_test/rendered/settings/height/box.rb +13 -0
  96. data/screen_test/rendered/settings/height/grid.frame +1 -0
  97. data/screen_test/rendered/settings/height/grid.rb +14 -0
  98. data/screen_test/rendered/settings/height/overflow_box.frame +1 -0
  99. data/screen_test/rendered/settings/height/overflow_box.rb +13 -0
  100. data/screen_test/rendered/settings/height/overflow_box_l2r.frame +1 -0
  101. data/screen_test/rendered/settings/height/overflow_box_l2r.rb +15 -0
  102. data/screen_test/rendered/settings/height/overflow_box_t2b.frame +1 -0
  103. data/screen_test/rendered/settings/height/overflow_box_t2b.rb +14 -0
  104. data/screen_test/rendered/settings/height/overflow_grid.frame +1 -0
  105. data/screen_test/rendered/settings/height/overflow_grid.rb +16 -0
  106. data/screen_test/rendered/settings/margin.frame +1 -0
  107. data/screen_test/rendered/settings/margin.rb +14 -0
  108. data/screen_test/rendered/settings/padding.frame +1 -0
  109. data/screen_test/rendered/settings/padding.rb +11 -0
  110. data/screen_test/rendered/settings/position/box_left.frame +1 -0
  111. data/screen_test/rendered/settings/position/box_left.rb +17 -0
  112. data/screen_test/rendered/settings/position/box_left_negative.frame +1 -0
  113. data/screen_test/rendered/settings/position/box_left_negative.rb +17 -0
  114. data/screen_test/rendered/settings/position/box_top.frame +1 -0
  115. data/screen_test/rendered/settings/position/box_top.rb +17 -0
  116. data/screen_test/rendered/settings/position/box_top_negative.frame +1 -0
  117. data/screen_test/rendered/settings/position/box_top_negative.rb +17 -0
  118. data/screen_test/rendered/settings/position/grid_left.frame +1 -0
  119. data/screen_test/rendered/settings/position/grid_left.rb +18 -0
  120. data/screen_test/rendered/settings/position/grid_left_negative.frame +1 -0
  121. data/screen_test/rendered/settings/position/grid_left_negative.rb +18 -0
  122. data/screen_test/rendered/settings/position/grid_top.frame +1 -0
  123. data/screen_test/rendered/settings/position/grid_top.rb +18 -0
  124. data/screen_test/rendered/settings/position/grid_top_negative.frame +1 -0
  125. data/screen_test/rendered/settings/position/grid_top_negative.rb +18 -0
  126. data/screen_test/rendered/settings/title_font.frame +1 -0
  127. data/screen_test/rendered/settings/title_font.rb +12 -0
  128. data/screen_test/rendered/settings/width/box.frame +1 -0
  129. data/screen_test/rendered/settings/width/box.rb +13 -0
  130. data/screen_test/rendered/settings/width/grid.frame +1 -0
  131. data/screen_test/rendered/settings/width/grid.rb +14 -0
  132. data/screen_test/rendered/settings/width/overflow_box.frame +1 -0
  133. data/screen_test/rendered/settings/width/overflow_box.rb +11 -0
  134. data/screen_test/rendered/settings/width/overflow_box_l2r.frame +1 -0
  135. data/screen_test/rendered/settings/width/overflow_box_l2r.rb +14 -0
  136. data/screen_test/rendered/settings/width/overflow_box_t2b.frame +1 -0
  137. data/screen_test/rendered/settings/width/overflow_box_t2b.rb +15 -0
  138. data/screen_test/rendered/settings/width/overflow_grid.frame +1 -0
  139. data/screen_test/rendered/settings/width/overflow_grid.rb +14 -0
  140. data/screen_test/screen_tester.rb +191 -0
  141. data/whirled_peas.gemspec +4 -2
  142. metadata +136 -20
  143. data/lib/whirled_peas/ui.rb +0 -7
  144. data/lib/whirled_peas/ui/ansi.rb +0 -154
  145. data/lib/whirled_peas/ui/canvas.rb +0 -35
  146. data/lib/whirled_peas/ui/element.rb +0 -199
  147. data/lib/whirled_peas/ui/painter.rb +0 -283
  148. data/lib/whirled_peas/ui/screen.rb +0 -62
  149. data/lib/whirled_peas/ui/settings.rb +0 -512
  150. data/lib/whirled_peas/ui/stroke.rb +0 -29
  151. data/sandbox/auto.rb +0 -13
  152. data/sandbox/box.rb +0 -19
  153. data/sandbox/grid.rb +0 -13
  154. data/sandbox/sandbox.rb +0 -17
  155. data/sandbox/text.rb +0 -33
data/Rakefile CHANGED
@@ -1,6 +1,40 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ def screen_test(file, method)
7
+ raise ArgumentError, 'Missing argument: file' unless file
8
+
9
+ require 'bundler/setup'
10
+ require 'whirled_peas'
11
+ require_relative 'screen_test/screen_tester'
12
+
13
+ WhirledPeas::ScreenTester.new(file).send(method)
14
+ end
15
+
16
+ namespace :screen_test do
17
+ %i[debug run save view].each do |t|
18
+ task t, [:file] do |_, args|
19
+ screen_test(args[:file], t)
20
+ end
21
+ end
22
+
23
+ task :update_all do
24
+ require 'bundler/setup'
25
+ require 'whirled_peas'
26
+ require_relative 'screen_test/screen_tester'
27
+
28
+ WhirledPeas::ScreenTester.update_all
29
+ end
30
+ end
31
+
32
+ task :screen_test do
33
+ require 'bundler/setup'
34
+ require 'whirled_peas'
35
+ require_relative 'screen_test/screen_tester'
36
+
37
+ WhirledPeas::ScreenTester.run_all
38
+ end
39
+
40
+ task default: [:screen_test, :spec]
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ def print_usage
4
+ puts "Usage: #{$0} <config file> [options]"
5
+ puts
6
+ puts 'options include'
7
+ puts ' --disable-screen Disable the screen (useful when printing debug statements)'
8
+ puts ' --painter Print the painter debug tree and exit'
9
+ puts ' --template Print the template debug tree and exit'
10
+ end
11
+
12
+ if !(1..2).include?(ARGV.length)
13
+ print_usage
14
+ exit(1)
15
+ elsif !File.exist?(ARGV.first)
16
+ puts "File not found: #{ARGV.first}"
17
+ print_usage
18
+ exit(1)
19
+ elsif ARGV.length == 2 && !%w[--disable-screen --template --painter].include?(ARGV[1])
20
+ puts "Unrecognized option: #{ARGV[1]}"
21
+ print_usage
22
+ exit(1)
23
+ end
24
+
25
+ require 'bundler/setup'
26
+ require 'whirled_peas'
27
+
28
+ if ARGV.length == 1
29
+ option = nil
30
+ else
31
+ option = ARGV[1].sub(/^--/, '').gsub(/-/, '_').to_sym
32
+ end
33
+
34
+ template_file = ARGV.first[0] == '/' ? ARGV.first : File.join(Dir.pwd, ARGV.first)
35
+ WhirledPeas.debug(template_file, option)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'whirled_peas'
5
+ require 'whirled_peas/command_line'
6
+
7
+ WhirledPeas::CommandLine.new(ARGV).start
@@ -1,50 +1,30 @@
1
1
  require 'logger'
2
2
 
3
+ require 'whirled_peas/errors'
4
+ require 'whirled_peas/config'
5
+ require 'whirled_peas/debugger'
3
6
  require 'whirled_peas/frame'
4
- require 'whirled_peas/ui'
7
+ require 'whirled_peas/graphics'
8
+ require 'whirled_peas/settings'
9
+ require 'whirled_peas/template'
10
+ require 'whirled_peas/utils'
5
11
  require 'whirled_peas/version'
6
12
 
7
13
  module WhirledPeas
8
- class Error < StandardError; end
9
-
10
- DEFAULT_HOST = 'localhost'
11
- DEFAULT_PORT = 8765
12
- DEFAULT_REFRESH_RATE = 30
13
-
14
- LOGGER_ID = 'MAIN'
15
-
16
- def self.start(driver, template_factory, log_level: Logger::INFO, refresh_rate: DEFAULT_REFRESH_RATE, host: DEFAULT_HOST, port: DEFAULT_PORT)
17
- logger = Logger.new(File.open('whirled_peas.log', 'a'))
18
- logger.level = log_level
19
- logger.formatter = proc do |severity, datetime, progname, msg|
20
- "[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
21
- end
22
-
23
- consumer = Frame::Consumer.new(template_factory, refresh_rate, logger)
24
- consumer_thread = Thread.new do
25
- Thread.current.report_on_exception = false
26
- consumer.start(host: host, port: port)
27
- end
14
+ def self.config
15
+ @config ||= Config.new
16
+ end
28
17
 
29
- Frame::Producer.start(logger: logger, host: host, port: port) do |producer|
30
- begin
31
- driver.start(producer)
32
- producer.stop
33
- rescue => e
34
- logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
35
- logger.error(LOGGER_ID) { e }
36
- logger.error(LOGGER_ID) { e.backtrace.join("\n") }
37
- producer.terminate
38
- raise
39
- end
40
- end
18
+ def self.configure(&block)
19
+ yield config
20
+ end
41
21
 
42
- consumer_thread.join
22
+ def self.debug(config_file, option=nil)
23
+ Debugger.new(config_file, option).debug
43
24
  end
44
25
 
45
26
  def self.template(&block)
46
- template = UI::Template.new
47
- yield template, template.settings
48
- template
27
+ require 'whirled_peas/template/composer'
28
+ Template::Composer.build(&block)
49
29
  end
50
30
  end
@@ -0,0 +1,263 @@
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'
10
+
11
+ 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
+ class CommandLine
217
+ COMMANDS = [
218
+ StartCommand,
219
+ ListFramesCommand,
220
+ PlayFrameCommand,
221
+ LoadingCommand,
222
+ TitleFontsCommand
223
+ ].map.with_object({}) { |c, h| h[c.command_name] = c }
224
+
225
+ def initialize(args)
226
+ @args = args
227
+ end
228
+
229
+ def start
230
+ if args.length < 1
231
+ print_usage
232
+ exit(1)
233
+ end
234
+
235
+ command = args.shift
236
+
237
+ unless COMMANDS.key?(command)
238
+ puts "Unrecognized command: #{command}"
239
+ print_usage
240
+ exit(1)
241
+ end
242
+
243
+ cmd = COMMANDS[command].new(args)
244
+
245
+ unless cmd.valid?
246
+ cmd.print_error
247
+ exit(1)
248
+ end
249
+
250
+ cmd.start
251
+ end
252
+
253
+ private
254
+
255
+ attr_reader :args
256
+
257
+ def print_usage
258
+ puts "Usage: #{$0} <command> [command options]"
259
+ puts
260
+ puts "Available commands: #{COMMANDS.keys.join(', ')}"
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,21 @@
1
+ module WhirledPeas
2
+ class Config
3
+ attr_writer :driver, :template_factory
4
+ attr_accessor :loading_template_factory
5
+
6
+ def driver
7
+ unless @driver
8
+ raise ConfigurationError, 'driver must be configured'
9
+ end
10
+ @driver
11
+ end
12
+
13
+ def template_factory
14
+ unless @template_factory
15
+ raise ConfigurationError, 'template_factory must be configured'
16
+ end
17
+ @template_factory
18
+ end
19
+ end
20
+ private_constant :Config
21
+ end
@@ -0,0 +1,80 @@
1
+ require 'whirled_peas/frame/event_loop'
2
+ require 'whirled_peas/frame/producer'
3
+ require 'whirled_peas/graphics/debugger'
4
+ require 'whirled_peas/graphics/mock_screen'
5
+ require 'whirled_peas/graphics/renderer'
6
+ require 'whirled_peas/graphics/screen'
7
+ require 'whirled_peas/template/debugger'
8
+
9
+ module WhirledPeas
10
+ class Debugger
11
+ module Option
12
+ DISABLE_SCREEN = :disable_screen
13
+ PAINTER = :painter
14
+ TEMPLATE = :template
15
+
16
+ VALID = [DISABLE_SCREEN, PAINTER, TEMPLATE]
17
+ end
18
+ private_constant :Option
19
+
20
+ FRAME = 'debug'
21
+ private_constant :FRAME
22
+
23
+ def initialize(template_file, option=nil)
24
+ unless option.nil? || Option::VALID.include?(option)
25
+ message =
26
+ "Invalid option: #{option}, expecting one of #{Option::VALID.join(', ')}"
27
+ raise ArgumentError, message
28
+ end
29
+ @template_file = template_file
30
+ @option = option
31
+ end
32
+
33
+ def debug
34
+ require template_file
35
+ template_factory = TemplateFactory.new
36
+ if play_frame?
37
+ screen = if disable_screen?
38
+ Graphics::MockScreen.new(80, 40)
39
+ else
40
+ Graphics::Screen.new
41
+ end
42
+ consumer = Frame::EventLoop.new(template_factory, screen: screen)
43
+ Frame::Producer.produce(consumer) do |producer|
44
+ producer.send_frame(FRAME, args: {})
45
+ end
46
+ return
47
+ end
48
+
49
+ template = template_factory.build(FRAME, {})
50
+ if print_painter?
51
+ painter = Graphics::Renderer.new(template, *Graphics::Screen.current_dimensions).painter
52
+ puts Graphics::Debugger.new(painter).debug
53
+ elsif print_template?
54
+ puts Template::Debugger.new(template).debug
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ attr_reader :template_file, :option
61
+
62
+ def play_frame?
63
+ option.nil? || option == Option::DISABLE_SCREEN
64
+ end
65
+
66
+ def disable_screen?
67
+ !option.nil? && option == Option::DISABLE_SCREEN
68
+ end
69
+
70
+ def print_painter?
71
+ !option.nil? && option == Option::PAINTER
72
+ end
73
+
74
+ def print_template?
75
+ !option.nil? && option == Option::TEMPLATE
76
+ end
77
+ end
78
+
79
+ private_constant :Debugger
80
+ end