whirled_peas 0.7.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +25 -0
- data/README.md +467 -120
- data/Rakefile +1 -20
- data/bin/easing +33 -0
- data/bin/reset_cursor +11 -0
- data/bin/screen_test +68 -0
- data/examples/graph.rb +54 -0
- data/examples/intro.rb +3 -3
- data/examples/scrolling.rb +5 -4
- data/lib/data/themes.yaml +13 -0
- data/lib/whirled_peas.rb +12 -6
- data/lib/whirled_peas/animator.rb +5 -0
- data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
- data/lib/whirled_peas/animator/easing.rb +72 -0
- data/lib/whirled_peas/animator/frame.rb +5 -0
- data/lib/whirled_peas/animator/frameset.rb +33 -0
- data/lib/whirled_peas/animator/producer.rb +35 -0
- data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
- data/lib/whirled_peas/command.rb +5 -0
- data/lib/whirled_peas/command/base.rb +86 -0
- data/lib/whirled_peas/command/config_command.rb +43 -0
- data/lib/whirled_peas/command/debug.rb +21 -0
- data/lib/whirled_peas/command/fonts.rb +22 -0
- data/lib/whirled_peas/command/frame_command.rb +34 -0
- data/lib/whirled_peas/command/frames.rb +24 -0
- data/lib/whirled_peas/command/help.rb +38 -0
- data/lib/whirled_peas/command/play.rb +111 -0
- data/lib/whirled_peas/command/record.rb +57 -0
- data/lib/whirled_peas/command/still.rb +29 -0
- data/lib/whirled_peas/command/themes.rb +76 -0
- data/lib/whirled_peas/command_line.rb +24 -212
- data/lib/whirled_peas/config.rb +56 -6
- data/lib/whirled_peas/device.rb +5 -0
- data/lib/whirled_peas/device/null_device.rb +8 -0
- data/lib/whirled_peas/device/output_file.rb +19 -0
- data/lib/whirled_peas/device/screen.rb +26 -0
- data/lib/whirled_peas/graphics/composer.rb +23 -2
- data/lib/whirled_peas/graphics/container_painter.rb +91 -0
- data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
- data/lib/whirled_peas/graphics/content_painter.rb +20 -0
- data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
- data/lib/whirled_peas/graphics/graph_painter.rb +97 -0
- data/lib/whirled_peas/graphics/grid_painter.rb +1 -4
- data/lib/whirled_peas/graphics/painter.rb +10 -0
- data/lib/whirled_peas/graphics/renderer.rb +8 -2
- data/lib/whirled_peas/graphics/text_painter.rb +7 -11
- data/lib/whirled_peas/settings/border.rb +25 -4
- data/lib/whirled_peas/settings/container_settings.rb +2 -4
- data/lib/whirled_peas/settings/element_settings.rb +12 -3
- data/lib/whirled_peas/settings/graph_settings.rb +21 -0
- data/lib/whirled_peas/settings/grid_settings.rb +7 -0
- data/lib/whirled_peas/settings/text_settings.rb +1 -0
- data/lib/whirled_peas/settings/theme.rb +40 -0
- data/lib/whirled_peas/settings/theme_library.rb +63 -0
- data/lib/whirled_peas/utils/ansi.rb +13 -0
- data/lib/whirled_peas/utils/file_handler.rb +57 -0
- data/lib/whirled_peas/version.rb +1 -1
- data/screen_test/elements/box.frame +1 -1
- data/screen_test/elements/box.rb +1 -1
- data/screen_test/elements/graph.frame +1 -0
- data/screen_test/elements/graph.rb +12 -0
- data/screen_test/elements/grid.frame +1 -1
- data/screen_test/elements/grid.rb +1 -1
- data/screen_test/elements/screen_overflow_x.frame +1 -1
- data/screen_test/elements/screen_overflow_x.rb +1 -1
- data/screen_test/elements/screen_overflow_y.frame +1 -1
- data/screen_test/elements/screen_overflow_y.rb +1 -1
- data/screen_test/elements/text.frame +1 -1
- data/screen_test/elements/text.rb +1 -1
- data/screen_test/elements/text_multiline.frame +1 -1
- data/screen_test/elements/text_multiline.rb +1 -1
- data/screen_test/elements/theme.frame +1 -0
- data/screen_test/elements/theme.rb +26 -0
- data/screen_test/settings/align/box_around.frame +1 -1
- data/screen_test/settings/align/box_around.rb +1 -1
- data/screen_test/settings/align/box_between.frame +1 -1
- data/screen_test/settings/align/box_between.rb +1 -1
- data/screen_test/settings/align/box_center.frame +1 -1
- data/screen_test/settings/align/box_center.rb +1 -1
- data/screen_test/settings/align/box_default.frame +1 -1
- data/screen_test/settings/align/box_default.rb +1 -1
- data/screen_test/settings/align/box_evenly.frame +1 -1
- data/screen_test/settings/align/box_evenly.rb +1 -1
- data/screen_test/settings/align/box_left.frame +1 -1
- data/screen_test/settings/align/box_left.rb +1 -1
- data/screen_test/settings/align/box_right.frame +1 -1
- data/screen_test/settings/align/box_right.rb +1 -1
- data/screen_test/settings/align/children_center.frame +1 -1
- data/screen_test/settings/align/children_center.rb +1 -1
- data/screen_test/settings/align/children_left.frame +1 -1
- data/screen_test/settings/align/children_left.rb +1 -1
- data/screen_test/settings/align/children_right.frame +1 -1
- data/screen_test/settings/align/children_right.rb +1 -1
- data/screen_test/settings/align/grid_center.frame +1 -1
- data/screen_test/settings/align/grid_center.rb +1 -1
- data/screen_test/settings/align/grid_default.frame +1 -1
- data/screen_test/settings/align/grid_default.rb +1 -1
- data/screen_test/settings/align/grid_left.frame +1 -1
- data/screen_test/settings/align/grid_left.rb +1 -1
- data/screen_test/settings/align/grid_right.frame +1 -1
- data/screen_test/settings/align/grid_right.rb +1 -1
- data/screen_test/settings/ansi/bold.frame +1 -1
- data/screen_test/settings/ansi/bold.rb +1 -1
- data/screen_test/settings/ansi/color.frame +1 -1
- data/screen_test/settings/ansi/color.rb +1 -1
- data/screen_test/settings/ansi/underline.frame +1 -1
- data/screen_test/settings/ansi/underline.rb +1 -1
- data/screen_test/settings/border.frame +1 -1
- data/screen_test/settings/border.rb +1 -1
- data/screen_test/settings/flow/box_b2t.frame +1 -1
- data/screen_test/settings/flow/box_b2t.rb +1 -1
- data/screen_test/settings/flow/box_l2r.frame +1 -1
- data/screen_test/settings/flow/box_l2r.rb +1 -1
- data/screen_test/settings/flow/box_r2l.frame +1 -1
- data/screen_test/settings/flow/box_r2l.rb +1 -1
- data/screen_test/settings/flow/box_t2b.frame +1 -1
- data/screen_test/settings/flow/box_t2b.rb +1 -1
- data/screen_test/settings/flow/grid_b2t.frame +1 -1
- data/screen_test/settings/flow/grid_b2t.rb +2 -2
- data/screen_test/settings/flow/grid_l2r.frame +1 -1
- data/screen_test/settings/flow/grid_l2r.rb +2 -2
- data/screen_test/settings/flow/grid_r2l.frame +1 -1
- data/screen_test/settings/flow/grid_r2l.rb +2 -2
- data/screen_test/settings/flow/grid_t2b.frame +1 -1
- data/screen_test/settings/flow/grid_t2b.rb +2 -2
- data/screen_test/settings/height/box.frame +1 -1
- data/screen_test/settings/height/box.rb +1 -1
- data/screen_test/settings/height/box_border_sizing.frame +1 -1
- data/screen_test/settings/height/box_border_sizing.rb +1 -1
- data/screen_test/settings/height/grid.frame +1 -1
- data/screen_test/settings/height/grid.rb +1 -1
- data/screen_test/settings/height/overflow_box.frame +1 -1
- data/screen_test/settings/height/overflow_box.rb +1 -1
- data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
- data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
- data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
- data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
- data/screen_test/settings/height/overflow_grid.frame +1 -1
- data/screen_test/settings/height/overflow_grid.rb +1 -1
- data/screen_test/settings/margin.frame +1 -1
- data/screen_test/settings/margin.rb +1 -1
- data/screen_test/settings/padding.frame +1 -1
- data/screen_test/settings/padding.rb +1 -1
- data/screen_test/settings/position/box_left.frame +1 -1
- data/screen_test/settings/position/box_left.rb +1 -1
- data/screen_test/settings/position/box_left_negative.frame +1 -1
- data/screen_test/settings/position/box_left_negative.rb +1 -1
- data/screen_test/settings/position/box_top.frame +1 -1
- data/screen_test/settings/position/box_top.rb +1 -1
- data/screen_test/settings/position/box_top_negative.frame +1 -1
- data/screen_test/settings/position/box_top_negative.rb +1 -1
- data/screen_test/settings/position/grid_left.frame +1 -1
- data/screen_test/settings/position/grid_left.rb +1 -1
- data/screen_test/settings/position/grid_left_negative.frame +1 -1
- data/screen_test/settings/position/grid_left_negative.rb +1 -1
- data/screen_test/settings/position/grid_top.frame +1 -1
- data/screen_test/settings/position/grid_top.rb +1 -1
- data/screen_test/settings/position/grid_top_negative.frame +1 -1
- data/screen_test/settings/position/grid_top_negative.rb +1 -1
- data/screen_test/settings/scroll/horiz_box.frame +1 -1
- data/screen_test/settings/scroll/horiz_box.rb +1 -1
- data/screen_test/settings/scroll/horiz_box_align_center.rb +1 -1
- data/screen_test/settings/scroll/horiz_box_align_right.rb +1 -1
- data/screen_test/settings/scroll/vert_box.frame +1 -1
- data/screen_test/settings/scroll/vert_box.rb +1 -1
- data/screen_test/settings/title_font.frame +1 -1
- data/screen_test/settings/title_font.rb +1 -1
- data/screen_test/settings/valign/box_around.frame +1 -1
- data/screen_test/settings/valign/box_around.rb +1 -1
- data/screen_test/settings/valign/box_between.frame +1 -1
- data/screen_test/settings/valign/box_between.rb +1 -1
- data/screen_test/settings/valign/box_bottom.frame +1 -1
- data/screen_test/settings/valign/box_bottom.rb +1 -1
- data/screen_test/settings/valign/box_default.frame +1 -1
- data/screen_test/settings/valign/box_default.rb +1 -1
- data/screen_test/settings/valign/box_evenly.frame +1 -1
- data/screen_test/settings/valign/box_evenly.rb +1 -1
- data/screen_test/settings/valign/box_middle.frame +1 -1
- data/screen_test/settings/valign/box_middle.rb +1 -1
- data/screen_test/settings/valign/box_top.frame +1 -1
- data/screen_test/settings/valign/box_top.rb +1 -1
- data/screen_test/settings/valign/grid_bottom.frame +1 -1
- data/screen_test/settings/valign/grid_bottom.rb +1 -1
- data/screen_test/settings/valign/grid_default.frame +1 -1
- data/screen_test/settings/valign/grid_default.rb +1 -1
- data/screen_test/settings/valign/grid_middle.frame +1 -1
- data/screen_test/settings/valign/grid_middle.rb +1 -1
- data/screen_test/settings/valign/grid_top.frame +1 -1
- data/screen_test/settings/valign/grid_top.rb +1 -1
- data/screen_test/settings/width/box_border_sizing.frame +1 -1
- data/screen_test/settings/width/box_border_sizing.rb +1 -1
- data/screen_test/settings/width/box_content.frame +1 -1
- data/screen_test/settings/width/box_content.rb +1 -1
- data/screen_test/settings/width/box_default.frame +1 -1
- data/screen_test/settings/width/box_default.rb +1 -1
- data/screen_test/settings/width/grid.frame +1 -1
- data/screen_test/settings/width/grid.rb +1 -1
- data/screen_test/settings/width/overflow_align_center.frame +1 -1
- data/screen_test/settings/width/overflow_align_center.rb +1 -1
- data/screen_test/settings/width/overflow_align_right.frame +1 -1
- data/screen_test/settings/width/overflow_align_right.rb +1 -1
- data/screen_test/settings/width/overflow_box.frame +1 -1
- data/screen_test/settings/width/overflow_box.rb +1 -1
- data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
- data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
- data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
- data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
- data/screen_test/settings/width/overflow_grid.frame +1 -1
- data/screen_test/settings/width/overflow_grid.rb +1 -1
- data/tools/whirled_peas/tools/screen_tester.rb +131 -65
- metadata +42 -9
- data/lib/whirled_peas/frame.rb +0 -6
- data/lib/whirled_peas/frame/consumer.rb +0 -30
- data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
- data/lib/whirled_peas/frame/event_loop.rb +0 -90
- data/lib/whirled_peas/frame/producer.rb +0 -67
- data/lib/whirled_peas/graphics/screen.rb +0 -70
- data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'whirled_peas/graphics/renderer'
|
2
|
+
require 'whirled_peas/utils/ansi'
|
3
|
+
|
4
|
+
module WhirledPeas
|
5
|
+
module Animator
|
6
|
+
class RendererConsumer
|
7
|
+
def initialize(template_factory, device, width, height)
|
8
|
+
@template_factory = template_factory
|
9
|
+
@device = device
|
10
|
+
@width = width
|
11
|
+
@height = height
|
12
|
+
@renders = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_frameset(frameset)
|
16
|
+
frameset.each_frame do |frame, args|
|
17
|
+
template = template_factory.build(frame, args)
|
18
|
+
renders << Graphics::Renderer.new(template, width, height).paint
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def process
|
23
|
+
device.handle_renders(renders)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :template_factory, :device, :width, :height, :renders
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module WhirledPeas
|
2
|
+
module Command
|
3
|
+
# Abstract base class for all commands
|
4
|
+
class Base
|
5
|
+
# Returns the name of the command as expected by the command line script. By convention,
|
6
|
+
# this name is snake case version of the class name, e.g. the command `do_something`
|
7
|
+
# would be implemented by `WhirledPeas::Command::DoSomething`, which needs to inherit
|
8
|
+
# from this class.
|
9
|
+
def self.command_name
|
10
|
+
name.split('::').last.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.description
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.print_usage
|
17
|
+
puts description
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :args
|
21
|
+
|
22
|
+
def initialize(args, config)
|
23
|
+
@args = args
|
24
|
+
@config = config
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the name of the command as expected by the command line script. By convention,
|
28
|
+
# this name is snake case version of the class name, e.g. the command `do_something`
|
29
|
+
# would be implemented by `WhirledPeas::Command::DoSomething`, which needs to inherit
|
30
|
+
# from this class.
|
31
|
+
def command_name
|
32
|
+
self.class.command_name
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_logger
|
36
|
+
require 'logger'
|
37
|
+
|
38
|
+
if config.log_file.is_a?(IO)
|
39
|
+
output = config.log_file
|
40
|
+
else
|
41
|
+
File.open(config.log_file, 'a')
|
42
|
+
end
|
43
|
+
|
44
|
+
logger = Logger.new(output)
|
45
|
+
logger.level = config.log_level
|
46
|
+
logger.formatter = config.log_formatter
|
47
|
+
logger
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [true|false] true if all of the required options were provided
|
51
|
+
def valid?
|
52
|
+
@error_text = nil
|
53
|
+
validate!
|
54
|
+
@error_text.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Display the validation error and print a usage statement
|
58
|
+
def print_error
|
59
|
+
puts @error_text if @error_text
|
60
|
+
print_usage
|
61
|
+
end
|
62
|
+
|
63
|
+
# Commands that inherit from this class must override this method
|
64
|
+
def start
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
attr_reader :config
|
70
|
+
|
71
|
+
def print_usage
|
72
|
+
puts ["Usage: #{$0} #{command_name}", *options_usage].join(' ')
|
73
|
+
end
|
74
|
+
|
75
|
+
# Commands that inherit from this class can override this method to validate
|
76
|
+
# command line options
|
77
|
+
def validate!
|
78
|
+
# Set @error_text if the options are not valid
|
79
|
+
end
|
80
|
+
|
81
|
+
def options_usage
|
82
|
+
end
|
83
|
+
end
|
84
|
+
private_constant :Base
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
# Abstract command that expects a config file as an argument and then requires the
|
6
|
+
# specified file. All implementing classes must call `super` if they override `start`
|
7
|
+
# or `validate!`
|
8
|
+
class ConfigCommand < Base
|
9
|
+
def start
|
10
|
+
require config_file
|
11
|
+
rescue LoadError
|
12
|
+
puts "Error loading #{config_file}"
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :config_file
|
19
|
+
|
20
|
+
def validate!
|
21
|
+
super
|
22
|
+
# Note that the main script consumes the <command> argument from ARGV, so we
|
23
|
+
# expect the config file to be at index 0.
|
24
|
+
config_file = args.shift
|
25
|
+
if config_file.nil?
|
26
|
+
@error_text = "#{command_name} requires a config file"
|
27
|
+
elsif !File.exist?(config_file)
|
28
|
+
@error_text = "File not found: #{config_file}"
|
29
|
+
elsif config_file[-3..-1] != '.rb'
|
30
|
+
@error_text = 'Config file should be a .rb file'
|
31
|
+
else
|
32
|
+
# We think we have a valid ruby config file, set the absolute path to @config
|
33
|
+
@config_file = config_file[0] == '/' ? config_file : File.join(Dir.pwd, config_file)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def options_usage
|
38
|
+
'<config file>'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
private_constant :ConfigCommand
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'frame_command'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
# Display the template tree for a single frame with the specified arguments.
|
6
|
+
class Debug < FrameCommand
|
7
|
+
def self.description
|
8
|
+
'Print template tree for specified frame'
|
9
|
+
end
|
10
|
+
|
11
|
+
def start
|
12
|
+
super
|
13
|
+
|
14
|
+
require 'whirled_peas/graphics/debugger'
|
15
|
+
|
16
|
+
template = config.template_factory.build(frame, frame_args)
|
17
|
+
puts Graphics::Debugger.new(template).debug
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
# List title fonts installed on the user's system and print sample text in each.
|
6
|
+
class Fonts < Base
|
7
|
+
def self.description
|
8
|
+
'List installed title fonts with sample text'
|
9
|
+
end
|
10
|
+
|
11
|
+
def start
|
12
|
+
require 'whirled_peas/utils/title_font'
|
13
|
+
|
14
|
+
Utils::TitleFont.fonts.keys.each do |key|
|
15
|
+
puts Utils::TitleFont.to_s(key.to_s, key)
|
16
|
+
puts key.inspect
|
17
|
+
puts
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'config_command'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
class FrameCommand < ConfigCommand
|
6
|
+
private
|
7
|
+
|
8
|
+
attr_reader :frame, :frame_args
|
9
|
+
|
10
|
+
def validate!
|
11
|
+
super
|
12
|
+
frame = args.shift
|
13
|
+
raw_args = args.shift
|
14
|
+
if frame.nil?
|
15
|
+
@error_text = "#{command_name} requires a frame name"
|
16
|
+
else
|
17
|
+
@frame = frame
|
18
|
+
@frame_args = {}
|
19
|
+
return if raw_args.nil?
|
20
|
+
|
21
|
+
require 'json'
|
22
|
+
|
23
|
+
JSON.parse(raw_args || '{}').each do |key, value|
|
24
|
+
@frame_args[key.to_sym] = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def options_usage
|
30
|
+
"#{super} <frame> [args as a JSON string]"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'config_command'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
class Frames < ConfigCommand
|
6
|
+
def self.description
|
7
|
+
'Print out list of frames generated by application'
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
super
|
12
|
+
|
13
|
+
require 'whirled_peas/animator/debug_consumer'
|
14
|
+
require 'whirled_peas/animator/producer'
|
15
|
+
|
16
|
+
Animator::Producer.produce(
|
17
|
+
Animator::DebugConsumer.new, WhirledPeas.config.refresh_rate
|
18
|
+
) do |producer|
|
19
|
+
config.application.start(producer)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module WhirledPeas
|
4
|
+
module Command
|
5
|
+
class Help < Base
|
6
|
+
def self.description
|
7
|
+
'Show detailed help for a command'
|
8
|
+
end
|
9
|
+
|
10
|
+
def start
|
11
|
+
class_name = cmd.split('_').map(&:capitalize).join
|
12
|
+
klass = Command.const_get(class_name)
|
13
|
+
klass.print_usage
|
14
|
+
rescue NameError
|
15
|
+
puts "Unrecognized command: #{cmd}"
|
16
|
+
exit(1)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :cmd
|
22
|
+
|
23
|
+
def validate!
|
24
|
+
super
|
25
|
+
cmd = args.shift
|
26
|
+
if cmd.nil?
|
27
|
+
@error_text = "#{command_name} requires a command"
|
28
|
+
else
|
29
|
+
@cmd = cmd
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def options_usage
|
34
|
+
[*super, '<command>'].join(' ')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
|
2
|
+
require_relative 'base'
|
3
|
+
|
4
|
+
module WhirledPeas
|
5
|
+
module Command
|
6
|
+
# Start the animation
|
7
|
+
class Play < Base
|
8
|
+
class NullPlayer
|
9
|
+
def play
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ApplicationPlayer
|
14
|
+
def initialize(app_config_file, config, logger)
|
15
|
+
@app_config_file = app_config_file
|
16
|
+
@config = config
|
17
|
+
@logger = logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def play
|
21
|
+
require app_config_file
|
22
|
+
|
23
|
+
require 'whirled_peas/animator/renderer_consumer'
|
24
|
+
require 'whirled_peas/animator/producer'
|
25
|
+
require 'whirled_peas/device/screen'
|
26
|
+
require 'whirled_peas/utils/ansi'
|
27
|
+
|
28
|
+
Utils::Ansi.with_screen do |width, height|
|
29
|
+
consumer = Animator::RendererConsumer.new(
|
30
|
+
WhirledPeas.config.template_factory,
|
31
|
+
Device::Screen.new(WhirledPeas.config.refresh_rate),
|
32
|
+
width,
|
33
|
+
height
|
34
|
+
)
|
35
|
+
Animator::Producer.produce(
|
36
|
+
consumer, WhirledPeas.config.refresh_rate
|
37
|
+
) do |producer|
|
38
|
+
config.application.start(producer)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
rescue LoadError
|
42
|
+
puts "Error loading #{config_file}"
|
43
|
+
exit(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :app_config_file, :config, :logger
|
49
|
+
end
|
50
|
+
|
51
|
+
class FilePlayer
|
52
|
+
def initialize(wpz_file)
|
53
|
+
@wpz_file = wpz_file
|
54
|
+
end
|
55
|
+
|
56
|
+
def play
|
57
|
+
require 'whirled_peas/device/screen'
|
58
|
+
require 'whirled_peas/utils/ansi'
|
59
|
+
require 'whirled_peas/utils/file_handler'
|
60
|
+
|
61
|
+
Utils::Ansi.with_screen do
|
62
|
+
screen = Device::Screen.new(WhirledPeas.config.refresh_rate)
|
63
|
+
renders = Utils::FileHandler.read(wpz_file)
|
64
|
+
screen.handle_renders(renders)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
attr_reader :wpz_file
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.description
|
74
|
+
'Play an animation from an application or prerecorded file'
|
75
|
+
end
|
76
|
+
|
77
|
+
def start
|
78
|
+
super
|
79
|
+
player.play
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
attr_reader :player
|
85
|
+
|
86
|
+
def validate!
|
87
|
+
super
|
88
|
+
@player = NullPlayer
|
89
|
+
file = args.shift
|
90
|
+
if file.nil?
|
91
|
+
@error_text = "#{command_name} requires an config file or frames file file"
|
92
|
+
elsif !File.exist?(file)
|
93
|
+
@error_text = "File not found: #{file}"
|
94
|
+
else
|
95
|
+
full_path_file = file[0] == '/' ? file : File.join(Dir.pwd, file)
|
96
|
+
if full_path_file.end_with?('.wpz')
|
97
|
+
@player = FilePlayer.new(full_path_file)
|
98
|
+
elsif full_path_file.end_with?('.rb')
|
99
|
+
@player = ApplicationPlayer.new(full_path_file, config, build_logger)
|
100
|
+
else
|
101
|
+
@error_text = "Unsupported file type: .#{file.split('.').last}, epxecting .rb or .wpz"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def options_usage
|
107
|
+
'<config/wpz file>'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -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
|