whirled_peas 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +125 -6
- data/bin/title_fonts +6 -0
- data/exe/whirled_peas +7 -0
- data/lib/whirled_peas.rb +12 -32
- data/lib/whirled_peas/command_line.rb +266 -0
- data/lib/whirled_peas/config.rb +21 -0
- data/lib/whirled_peas/errors.rb +5 -0
- data/lib/whirled_peas/frame.rb +0 -4
- data/lib/whirled_peas/frame/event_loop.rb +60 -28
- data/lib/whirled_peas/frame/print_consumer.rb +33 -0
- data/lib/whirled_peas/frame/producer.rb +29 -18
- data/lib/whirled_peas/template.rb +5 -0
- data/lib/whirled_peas/{ui → template}/element.rb +12 -6
- data/lib/whirled_peas/{ui → template}/settings.rb +8 -1
- data/lib/whirled_peas/ui.rb +1 -3
- data/lib/whirled_peas/ui/canvas.rb +1 -1
- data/lib/whirled_peas/ui/painter.rb +20 -16
- data/lib/whirled_peas/ui/screen.rb +21 -18
- data/lib/whirled_peas/utils.rb +5 -0
- data/lib/whirled_peas/{ui → utils}/ansi.rb +0 -0
- data/lib/whirled_peas/{ui → utils}/color.rb +0 -0
- data/lib/whirled_peas/utils/title_font.rb +75 -0
- data/lib/whirled_peas/version.rb +1 -1
- data/whirled_peas.gemspec +4 -1
- metadata +32 -13
- data/sandbox/auto.rb +0 -13
- data/sandbox/box.rb +0 -19
- data/sandbox/grid.rb +0 -13
- data/sandbox/sandbox.rb +0 -17
- data/sandbox/text.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 740b5ae88bfdd0f6dfbf4b1ef9e220a4298ddd8f4d8b01d62e904e3bfb4e109b
|
4
|
+
data.tar.gz: 1e78f0bf1664187825441258909a750c74455017266d01b4b64d5cdd7c609572
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0960008e3b09aae39cf0655ff57d6dde8859bd3437844b68b37fd72b49bc04199dae2fa5544ba219f795d87f5b5ada80d56f0e96f005eaffddbd74de67d4037c'
|
7
|
+
data.tar.gz: ce998b69ac1db491577cdfaaaa4b35fb79a0bd07d24c622f426e38b1ff3eb0851ff10c90d24b8b7f48dc1b97dd01c11f93960a011c2611df201f3d86c45ce65a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v0.3.0 - 2021-01-21
|
4
|
+
|
5
|
+
- [617f802](https://github.com/tcollier/whirled_peas/tree/617f8027d6688a2ec81a3e594e529c94485cee85): BREAKING: send frames directly to EventLoop (`Producer#send` renamed to `Producer#send_frame`)
|
6
|
+
|
3
7
|
## v0.2.0 - 2021-01-20
|
4
8
|
|
5
9
|
- [73eb326](https://github.com/tcollier/whirled_peas/tree/73eb326426f9814e91e3bc7a60dfd87be3d69f7e): Convert "primitive" data types to strings
|
data/README.md
CHANGED
@@ -22,13 +22,22 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
+
A Whirled Peas application consists of the following pieces
|
26
|
+
|
27
|
+
1. [REQUIRED] The driver, which emits lightweight frame events
|
28
|
+
1. [REQUIRED] The main template factory, which builds templates to convert frame events from the driver into terminal graphics
|
29
|
+
1. [OPTIONAL] A loading screen template factory, which is used while content is loading
|
30
|
+
|
31
|
+
These pieces are configured as following
|
32
|
+
|
25
33
|
```ruby
|
34
|
+
# visualize.rb
|
26
35
|
require 'whirled_peas'
|
27
36
|
|
28
37
|
class TemplateFactory
|
29
38
|
def build(frame, args)
|
30
39
|
WhirledPeas.template do |body|
|
31
|
-
body.add_box do |_, settings|
|
40
|
+
body.add_box('Title') do |_, settings|
|
32
41
|
settings.underline = true
|
33
42
|
"Hello #{args['name']}"
|
34
43
|
end
|
@@ -44,13 +53,39 @@ class Driver
|
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
47
|
-
WhirledPeas.
|
56
|
+
WhirledPeas.configure do |config|
|
57
|
+
config.driver = Driver.new
|
58
|
+
config.template_factory = TemplateFactory.new
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Then the visualizer is started on the command line with
|
63
|
+
|
64
|
+
```
|
65
|
+
$ whirled_peas start visualize.rb
|
48
66
|
```
|
49
67
|
|
50
|
-
|
68
|
+
The optional loading screen can be configured like
|
51
69
|
|
52
|
-
|
53
|
-
|
70
|
+
````ruby
|
71
|
+
class LoadingTemplateFactory
|
72
|
+
def build
|
73
|
+
WhirledPeas.template do |t|
|
74
|
+
t.add_box('Loading') do |box, settings|
|
75
|
+
settings.set_margin(top: 15)
|
76
|
+
settings.auto_margin = true
|
77
|
+
settings.full_border(color: :blue, style: :double)
|
78
|
+
"Loading..."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
WhirledPeas.configure do |config|
|
85
|
+
# ...
|
86
|
+
config.loading_template_factory = LoadingTemplateFactory.new
|
87
|
+
end
|
88
|
+
```
|
54
89
|
|
55
90
|
### Driver
|
56
91
|
|
@@ -63,7 +98,7 @@ The driver is the application code to be visualized. This is typically a lightwe
|
|
63
98
|
def start(producer)
|
64
99
|
# application code here
|
65
100
|
end
|
66
|
-
|
101
|
+
````
|
67
102
|
|
68
103
|
The producer provides a single method
|
69
104
|
|
@@ -113,6 +148,10 @@ end
|
|
113
148
|
|
114
149
|
To render the frame events sent by the driver, the application requires a template factory. This factory will be called for each frame event, with the frame name and the arguments supplied by the driver. A template factory can be a simple ruby class and thus can maintain state. Whirled Peas provides a few basic building blocks to make simple, yet elegant terminal-based UIs.
|
115
150
|
|
151
|
+
#### Loading Template Factory
|
152
|
+
|
153
|
+
`WhirledPeas.start` takes an optional template facotry to build a loading screen. This instance must implement `#build` (taking no arguments). The template returned by that method will be painted while the event loop is waiting for frames. The factory method will be called once per refresh cycle, so it's possible to implement animation.
|
154
|
+
|
116
155
|
#### Building Blocks
|
117
156
|
|
118
157
|
A template is created with `WhirledPeas.template`, which yields a `Template` object and `TemplateSettings`. This template object is a `ComposableElement`, which allows for attaching child elements and setting layout options. `GridElement` and `BoxElement` are two other composable elements and `TextElement` is a simple element that can hold a text/number value and has layout options, but cannot have any child elements.
|
@@ -195,6 +234,7 @@ The available settigs are
|
|
195
234
|
| `flow` | Flow to display child elements (see [Display Flow](#display-flow)) | `:l2r` | `Box` | Yes |
|
196
235
|
| `margin` | Set the (left, top, right, bottom) margin of the element | `0` | `Box`, `Grid` | Yes |
|
197
236
|
| `padding` | Set the (left, top, right, bottom) padding of the element | `0` | `Box`, `Grid` | Yes |
|
237
|
+
| `title_font` | Font used to create "large" text (see [Large Text](#large-text)) | | `Text` |
|
198
238
|
| `transpose` | Display grid elements top-to-bottom, then left-to-right | `false` | `Grid` | No |
|
199
239
|
| `underline` | `true` underlines the font | `false` | `Box`, `Grid`, `Template`, `Text` | Yes |
|
200
240
|
| `width` | Override the calculated with of an element | | `Box`, `Grid`, `Text` | No |
|
@@ -304,6 +344,27 @@ Many of these also have a "bright" option:
|
|
304
344
|
- `:bright_red`
|
305
345
|
- `:bright_yellow`
|
306
346
|
|
347
|
+
##### Large Text
|
348
|
+
|
349
|
+
The `title_font` setting for `TextElement`s converts the standard terminal font into a large block font. The available fonts vary from system to system. Every system will have a `:default` font available, this font could look like
|
350
|
+
|
351
|
+
```
|
352
|
+
██████╗ ███████╗███████╗ █████╗ ██╗ ██╗██╗ ████████╗
|
353
|
+
██╔══██╗██╔════╝██╔════╝██╔══██╗██║ ██║██║ ╚══██╔══╝
|
354
|
+
██║ ██║█████╗ █████╗ ███████║██║ ██║██║ ██║
|
355
|
+
██║ ██║██╔══╝ ██╔══╝ ██╔══██║██║ ██║██║ ██║
|
356
|
+
██████╔╝███████╗██║ ██║ ██║╚██████╔╝███████╗ ██║
|
357
|
+
╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝
|
358
|
+
```
|
359
|
+
|
360
|
+
To print out a list of all available fonts as well as sample text in that font, run
|
361
|
+
|
362
|
+
```
|
363
|
+
$ whirled_peas title_fonts
|
364
|
+
```
|
365
|
+
|
366
|
+
Note: when using a title font with WhirledPeas for the first time on a system, the gem loads all fonts to check which ones are available. This can be a slow process and may cause a noticeable delay when running a visualization. Running the command above will cache the results and thus when a WhirledPeas visualization is run, there will be no lag from loading fonts.
|
367
|
+
|
307
368
|
### Example
|
308
369
|
|
309
370
|
```ruby
|
@@ -356,6 +417,64 @@ class TemplateFactory
|
|
356
417
|
end
|
357
418
|
```
|
358
419
|
|
420
|
+
### Debugging
|
421
|
+
|
422
|
+
The `whirled_peas` executable provides some commands that are helpful for debugging.
|
423
|
+
|
424
|
+
#### list_frames
|
425
|
+
|
426
|
+
List the frames sent by the driver
|
427
|
+
|
428
|
+
```
|
429
|
+
$ whirled_peas <config file> list_frames
|
430
|
+
Frame 'start' displayed for 5 second(s)
|
431
|
+
Frame 'move' displayed for 1 frame ({:direction=>'N'})
|
432
|
+
...
|
433
|
+
EOF frame detected
|
434
|
+
```
|
435
|
+
|
436
|
+
#### play_frame
|
437
|
+
|
438
|
+
Displays a single frame for several seconds
|
439
|
+
|
440
|
+
```
|
441
|
+
$ whirled_peas <config file> play_frame move '{"direction":"N"}'
|
442
|
+
```
|
443
|
+
|
444
|
+
Adding the `--debug` flag will result in just printing out the template's debug information, e.g.
|
445
|
+
|
446
|
+
```
|
447
|
+
$ whirled_peas <config file> play_frame move '{"direction":"N"}' --debug
|
448
|
+
+ TEMPLATE [WhirledPeas::UI::Template]
|
449
|
+
- Settings
|
450
|
+
WhirledPeas::UI::TemplateSettings
|
451
|
+
<default>
|
452
|
+
- Children
|
453
|
+
+ TitleContainer [WhirledPeas::UI::BoxElement]
|
454
|
+
...
|
455
|
+
```
|
456
|
+
|
457
|
+
#### loading
|
458
|
+
|
459
|
+
Displays the configured loading screen for several seconds
|
460
|
+
|
461
|
+
```
|
462
|
+
$ whirled_peas <config file> loading
|
463
|
+
```
|
464
|
+
|
465
|
+
Adding the `--debug` flag will result in just printing out the loading template's debug information, e.g.
|
466
|
+
|
467
|
+
```
|
468
|
+
$ whirled_peas <config file> loading --debug
|
469
|
+
+ TEMPLATE [WhirledPeas::UI::Template]
|
470
|
+
- Settings
|
471
|
+
WhirledPeas::UI::TemplateSettings
|
472
|
+
<default>
|
473
|
+
- Children
|
474
|
+
+ TitleContainer [WhirledPeas::UI::BoxElement]
|
475
|
+
...
|
476
|
+
```
|
477
|
+
|
359
478
|
## Development
|
360
479
|
|
361
480
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/bin/title_fonts
ADDED
data/exe/whirled_peas
ADDED
data/lib/whirled_peas.rb
CHANGED
@@ -1,46 +1,26 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
|
+
require 'whirled_peas/errors'
|
4
|
+
|
5
|
+
require 'whirled_peas/config'
|
3
6
|
require 'whirled_peas/frame'
|
7
|
+
require 'whirled_peas/template'
|
4
8
|
require 'whirled_peas/ui'
|
9
|
+
require 'whirled_peas/utils'
|
5
10
|
require 'whirled_peas/version'
|
6
11
|
|
7
12
|
module WhirledPeas
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
LOGGER_ID = 'MAIN'
|
13
|
-
|
14
|
-
def self.start(driver, template_factory, log_level: Logger::INFO, refresh_rate: DEFAULT_REFRESH_RATE)
|
15
|
-
logger = Logger.new(File.open('whirled_peas.log', 'a'))
|
16
|
-
logger.level = log_level
|
17
|
-
logger.formatter = proc do |severity, datetime, progname, msg|
|
18
|
-
if msg.is_a?(Exception)
|
19
|
-
msg = %Q(#{msg.class}: #{msg.to_s}\n #{msg.backtrace.join("\n ")})
|
20
|
-
end
|
21
|
-
"[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
|
22
|
-
end
|
23
|
-
|
24
|
-
event_loop = Frame::EventLoop.new(template_factory, refresh_rate, logger)
|
25
|
-
event_loop_thread = Thread.new do
|
26
|
-
Thread.current.report_on_exception = false
|
27
|
-
event_loop.start
|
28
|
-
end
|
29
|
-
|
30
|
-
Frame::Producer.produce(event_loop: event_loop, logger: logger) do |producer|
|
31
|
-
begin
|
32
|
-
driver.start(producer)
|
33
|
-
rescue => e
|
34
|
-
logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
|
35
|
-
logger.error(LOGGER_ID) { e }
|
36
|
-
raise
|
37
|
-
end
|
38
|
-
end
|
13
|
+
def self.config
|
14
|
+
@config ||= Config.new
|
15
|
+
end
|
39
16
|
|
40
|
-
|
17
|
+
def self.configure(&block)
|
18
|
+
yield config
|
41
19
|
end
|
42
20
|
|
43
21
|
def self.template(&block)
|
22
|
+
require 'whirled_peas/template/element'
|
23
|
+
|
44
24
|
template = UI::Template.new
|
45
25
|
yield template, template.settings
|
46
26
|
template
|
@@ -0,0 +1,266 @@
|
|
1
|
+
module WhirledPeas
|
2
|
+
class Command
|
3
|
+
DEFAULT_REFRESH_RATE = 30
|
4
|
+
|
5
|
+
DEFAULT_LOG_LEVEL = Logger::INFO
|
6
|
+
DEFAULT_FORMATTER = proc do |severity, datetime, progname, msg|
|
7
|
+
if msg.is_a?(Exception)
|
8
|
+
msg = %Q(#{msg.class}: #{msg.to_s}\n #{msg.backtrace.join("\n ")})
|
9
|
+
end
|
10
|
+
"[#{severity}] #{datetime.strftime('%Y-%m-%dT%H:%M:%S.%L')} (#{progname}) - #{msg}\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.command_name
|
14
|
+
self.name.split('::').last.sub(/Command$/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.build_logger(output, level=DEFAULT_LOG_LEVEL, formatter=DEFAULT_FORMATTER)
|
18
|
+
logger = Logger.new(output)
|
19
|
+
logger.level = level
|
20
|
+
logger.formatter = formatter
|
21
|
+
logger
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :args
|
25
|
+
|
26
|
+
def initialize(args)
|
27
|
+
@args = args
|
28
|
+
end
|
29
|
+
|
30
|
+
def valid?
|
31
|
+
@error_text = nil
|
32
|
+
validate!
|
33
|
+
@error_text.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
def print_error
|
37
|
+
puts @error_text if @error_text
|
38
|
+
print_usage
|
39
|
+
end
|
40
|
+
|
41
|
+
def start
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def print_usage
|
47
|
+
puts "Usage: #{$0} #{self.class.command_name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate!
|
51
|
+
# Set @error_text if the options are not valid
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class TitleFontsCommand < Command
|
56
|
+
def start
|
57
|
+
require 'whirled_peas/utils/title_font'
|
58
|
+
|
59
|
+
Utils::TitleFont.fonts.keys.each do |key|
|
60
|
+
puts Utils::TitleFont.to_s(key.to_s, key)
|
61
|
+
puts key.inspect
|
62
|
+
puts
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class ConfigCommand < Command
|
68
|
+
def start
|
69
|
+
require args[0]
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def validate!
|
75
|
+
if args.length == 0
|
76
|
+
@error_text = "#{self.class.command_name} requires a config file"
|
77
|
+
elsif !File.exist?(args[0])
|
78
|
+
@error_text = "File not found: #{args[0]}"
|
79
|
+
elsif args[0][-3..-1] != '.rb'
|
80
|
+
@error_text = 'Config file should be a .rb file'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def print_usage
|
85
|
+
puts "Usage: #{$0} #{self.class.command_name} <config file>"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class StartCommand < ConfigCommand
|
90
|
+
LOGGER_ID = 'MAIN'
|
91
|
+
|
92
|
+
def start
|
93
|
+
super
|
94
|
+
require 'whirled_peas/frame/event_loop'
|
95
|
+
require 'whirled_peas/frame/producer'
|
96
|
+
|
97
|
+
logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
|
98
|
+
|
99
|
+
consumer = Frame::EventLoop.new(
|
100
|
+
WhirledPeas.config.template_factory,
|
101
|
+
WhirledPeas.config.loading_template_factory,
|
102
|
+
DEFAULT_REFRESH_RATE,
|
103
|
+
logger
|
104
|
+
)
|
105
|
+
Frame::Producer.produce(consumer, logger) do |producer|
|
106
|
+
begin
|
107
|
+
WhirledPeas.config.driver.start(producer)
|
108
|
+
rescue => e
|
109
|
+
logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
|
110
|
+
logger.error(LOGGER_ID) { e }
|
111
|
+
raise
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class ListFramesCommand < ConfigCommand
|
118
|
+
def start
|
119
|
+
super
|
120
|
+
require 'whirled_peas/frame/print_consumer'
|
121
|
+
require 'whirled_peas/frame/producer'
|
122
|
+
|
123
|
+
logger = self.class.build_logger(STDOUT)
|
124
|
+
Frame::Producer.produce(Frame::PrintConsumer.new, logger) do |producer|
|
125
|
+
begin
|
126
|
+
WhirledPeas.config.driver.start(producer)
|
127
|
+
rescue => e
|
128
|
+
logger.warn(LOGGER_ID) { 'Driver exited with error, terminating producer...' }
|
129
|
+
logger.error(LOGGER_ID) { e }
|
130
|
+
raise
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
class PlayFrameCommand < ConfigCommand
|
137
|
+
def start
|
138
|
+
super
|
139
|
+
|
140
|
+
if args.last == '--debug'
|
141
|
+
puts WhirledPeas.config.template_factory.build(frame, frame_args).inspect
|
142
|
+
exit
|
143
|
+
end
|
144
|
+
|
145
|
+
require 'whirled_peas/frame/event_loop'
|
146
|
+
require 'whirled_peas/frame/producer'
|
147
|
+
|
148
|
+
logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
|
149
|
+
|
150
|
+
consumer = Frame::EventLoop.new(
|
151
|
+
WhirledPeas.config.template_factory,
|
152
|
+
WhirledPeas.config.loading_template_factory,
|
153
|
+
DEFAULT_REFRESH_RATE,
|
154
|
+
logger
|
155
|
+
)
|
156
|
+
Frame::Producer.produce(consumer, logger) do |producer|
|
157
|
+
producer.send_frame(args[1], duration: 5, args: frame_args)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
attr_reader :frame, :frame_args
|
164
|
+
|
165
|
+
def validate!
|
166
|
+
super
|
167
|
+
if !@error_text.nil?
|
168
|
+
return
|
169
|
+
elsif args.length < 2
|
170
|
+
@error_text = "#{self.class.command_name} requires a frame name"
|
171
|
+
else
|
172
|
+
require 'json'
|
173
|
+
@frame = args[1]
|
174
|
+
@frame_args = {}
|
175
|
+
JSON.parse(args[2] || '{}').each do |key, value|
|
176
|
+
@frame_args[key.to_sym] = value
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def print_usage
|
182
|
+
puts "Usage: #{$0} #{self.class.command_name} <config file> <frame> [args as a JSON string] [--debug]"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class LoadingCommand < ConfigCommand
|
187
|
+
def start
|
188
|
+
super
|
189
|
+
unless WhirledPeas.config.loading_template_factory
|
190
|
+
puts 'No loading screen configured'
|
191
|
+
exit
|
192
|
+
end
|
193
|
+
|
194
|
+
if args.last == '--debug'
|
195
|
+
puts WhirledPeas.config.loading_template_factory.build.inspect
|
196
|
+
exit
|
197
|
+
end
|
198
|
+
|
199
|
+
require 'whirled_peas/frame/event_loop'
|
200
|
+
require 'whirled_peas/frame/producer'
|
201
|
+
|
202
|
+
logger = self.class.build_logger(File.open('whirled_peas.log', 'a'))
|
203
|
+
consumer = Frame::EventLoop.new(
|
204
|
+
WhirledPeas.config.template_factory,
|
205
|
+
WhirledPeas.config.loading_template_factory,
|
206
|
+
DEFAULT_REFRESH_RATE,
|
207
|
+
logger
|
208
|
+
)
|
209
|
+
Frame::Producer.produce(consumer, logger) { sleep(5) }
|
210
|
+
end
|
211
|
+
|
212
|
+
private
|
213
|
+
|
214
|
+
def print_usage
|
215
|
+
puts "Usage: #{$0} #{self.class.command_name} [--debug]"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class CommandLine
|
220
|
+
COMMANDS = [
|
221
|
+
StartCommand,
|
222
|
+
ListFramesCommand,
|
223
|
+
PlayFrameCommand,
|
224
|
+
LoadingCommand,
|
225
|
+
TitleFontsCommand
|
226
|
+
].map.with_object({}) { |c, h| h[c.command_name] = c }
|
227
|
+
|
228
|
+
def initialize(args)
|
229
|
+
@args = args
|
230
|
+
end
|
231
|
+
|
232
|
+
def start
|
233
|
+
if args.length < 1
|
234
|
+
print_usage
|
235
|
+
exit(1)
|
236
|
+
end
|
237
|
+
|
238
|
+
command = args.shift
|
239
|
+
|
240
|
+
unless COMMANDS.key?(command)
|
241
|
+
puts "Unrecognized command: #{command}"
|
242
|
+
print_usage
|
243
|
+
exit(1)
|
244
|
+
end
|
245
|
+
|
246
|
+
cmd = COMMANDS[command].new(args)
|
247
|
+
|
248
|
+
unless cmd.valid?
|
249
|
+
cmd.print_error
|
250
|
+
exit(1)
|
251
|
+
end
|
252
|
+
|
253
|
+
cmd.start
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
|
258
|
+
attr_reader :args
|
259
|
+
|
260
|
+
def print_usage
|
261
|
+
puts "Usage: #{$0} <command> [command options]"
|
262
|
+
puts
|
263
|
+
puts "Available commands: #{COMMANDS.keys.join(', ')}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|