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.
- 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
|