whirled_peas 0.4.1 → 0.8.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/.travis.yml +1 -0
- data/CHANGELOG.md +37 -0
- data/README.md +529 -156
- data/Rakefile +9 -3
- data/bin/reset_cursor +11 -0
- data/bin/screen_test +68 -0
- data/examples/intro.rb +52 -0
- data/examples/scrolling.rb +54 -0
- data/lib/whirled_peas.rb +6 -12
- 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 +44 -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 +108 -0
- data/lib/whirled_peas/command/record.rb +57 -0
- data/lib/whirled_peas/command/still.rb +29 -0
- data/lib/whirled_peas/command_line.rb +23 -228
- 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/errors.rb +2 -0
- data/lib/whirled_peas/graphics.rb +19 -0
- data/lib/whirled_peas/graphics/box_painter.rb +101 -0
- data/lib/whirled_peas/graphics/canvas.rb +118 -0
- data/lib/whirled_peas/graphics/composer.rb +80 -0
- data/lib/whirled_peas/graphics/container_coords.rb +72 -0
- data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
- data/lib/whirled_peas/graphics/container_painter.rb +363 -0
- data/lib/whirled_peas/graphics/debugger.rb +52 -0
- data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
- data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
- data/lib/whirled_peas/graphics/painter.rb +33 -0
- data/lib/whirled_peas/graphics/renderer.rb +32 -0
- data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
- data/lib/whirled_peas/graphics/text_painter.rb +40 -0
- data/lib/whirled_peas/settings.rb +5 -0
- data/lib/whirled_peas/settings/alignment.rb +24 -0
- data/lib/whirled_peas/settings/bg_color.rb +24 -0
- data/lib/whirled_peas/settings/border.rb +101 -0
- data/lib/whirled_peas/settings/box_settings.rb +8 -0
- data/lib/whirled_peas/settings/color.rb +68 -0
- data/lib/whirled_peas/settings/container_settings.rb +223 -0
- data/lib/whirled_peas/settings/debugger.rb +96 -0
- data/lib/whirled_peas/settings/display_flow.rb +27 -0
- data/lib/whirled_peas/settings/element_settings.rb +61 -0
- data/lib/whirled_peas/settings/grid_settings.rb +19 -0
- data/lib/whirled_peas/settings/margin.rb +8 -0
- data/lib/whirled_peas/settings/padding.rb +8 -0
- data/lib/whirled_peas/settings/position.rb +15 -0
- data/lib/whirled_peas/settings/scrollbar.rb +15 -0
- data/lib/whirled_peas/settings/sizing.rb +19 -0
- data/lib/whirled_peas/settings/spacing.rb +58 -0
- data/lib/whirled_peas/settings/text_color.rb +21 -0
- data/lib/whirled_peas/settings/text_settings.rb +15 -0
- data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
- data/lib/whirled_peas/utils/ansi.rb +19 -56
- data/lib/whirled_peas/utils/file_handler.rb +57 -0
- data/lib/whirled_peas/utils/formatted_string.rb +64 -0
- data/lib/whirled_peas/utils/title_font.rb +1 -1
- data/lib/whirled_peas/version.rb +1 -1
- data/screen_test/elements/box.frame +1 -0
- data/screen_test/elements/box.rb +20 -0
- data/screen_test/elements/grid.frame +1 -0
- data/screen_test/elements/grid.rb +13 -0
- data/screen_test/elements/screen_overflow_x.frame +1 -0
- data/screen_test/elements/screen_overflow_x.rb +9 -0
- data/screen_test/elements/screen_overflow_y.frame +1 -0
- data/screen_test/elements/screen_overflow_y.rb +9 -0
- data/screen_test/elements/text.frame +1 -0
- data/screen_test/elements/text.rb +9 -0
- data/screen_test/elements/text_multiline.frame +1 -0
- data/screen_test/elements/text_multiline.rb +9 -0
- data/screen_test/settings/align/box_around.frame +1 -0
- data/screen_test/settings/align/box_around.rb +16 -0
- data/screen_test/settings/align/box_between.frame +1 -0
- data/screen_test/settings/align/box_between.rb +16 -0
- data/screen_test/settings/align/box_center.frame +1 -0
- data/screen_test/settings/align/box_center.rb +21 -0
- data/screen_test/settings/align/box_default.frame +1 -0
- data/screen_test/settings/align/box_default.rb +20 -0
- data/screen_test/settings/align/box_evenly.frame +1 -0
- data/screen_test/settings/align/box_evenly.rb +16 -0
- data/screen_test/settings/align/box_left.frame +1 -0
- data/screen_test/settings/align/box_left.rb +21 -0
- data/screen_test/settings/align/box_right.frame +1 -0
- data/screen_test/settings/align/box_right.rb +21 -0
- data/screen_test/settings/align/children_center.frame +1 -0
- data/screen_test/settings/align/children_center.rb +15 -0
- data/screen_test/settings/align/children_left.frame +1 -0
- data/screen_test/settings/align/children_left.rb +15 -0
- data/screen_test/settings/align/children_right.frame +1 -0
- data/screen_test/settings/align/children_right.rb +15 -0
- data/screen_test/settings/align/grid_center.frame +1 -0
- data/screen_test/settings/align/grid_center.rb +18 -0
- data/screen_test/settings/align/grid_default.frame +1 -0
- data/screen_test/settings/align/grid_default.rb +17 -0
- data/screen_test/settings/align/grid_left.frame +1 -0
- data/screen_test/settings/align/grid_left.rb +18 -0
- data/screen_test/settings/align/grid_right.frame +1 -0
- data/screen_test/settings/align/grid_right.rb +18 -0
- data/screen_test/settings/ansi/bold.frame +1 -0
- data/screen_test/settings/ansi/bold.rb +14 -0
- data/screen_test/settings/ansi/color.frame +1 -0
- data/screen_test/settings/ansi/color.rb +37 -0
- data/screen_test/settings/ansi/underline.frame +1 -0
- data/screen_test/settings/ansi/underline.rb +14 -0
- data/screen_test/settings/border.frame +1 -0
- data/screen_test/settings/border.rb +13 -0
- data/screen_test/settings/flow/box_b2t.frame +1 -0
- data/screen_test/settings/flow/box_b2t.rb +26 -0
- data/screen_test/settings/flow/box_l2r.frame +1 -0
- data/screen_test/settings/flow/box_l2r.rb +26 -0
- data/screen_test/settings/flow/box_r2l.frame +1 -0
- data/screen_test/settings/flow/box_r2l.rb +26 -0
- data/screen_test/settings/flow/box_t2b.frame +1 -0
- data/screen_test/settings/flow/box_t2b.rb +26 -0
- data/screen_test/settings/flow/grid_b2t.frame +1 -0
- data/screen_test/settings/flow/grid_b2t.rb +14 -0
- data/screen_test/settings/flow/grid_l2r.frame +1 -0
- data/screen_test/settings/flow/grid_l2r.rb +14 -0
- data/screen_test/settings/flow/grid_r2l.frame +1 -0
- data/screen_test/settings/flow/grid_r2l.rb +14 -0
- data/screen_test/settings/flow/grid_t2b.frame +1 -0
- data/screen_test/settings/flow/grid_t2b.rb +14 -0
- data/screen_test/settings/height/box.frame +1 -0
- data/screen_test/settings/height/box.rb +13 -0
- data/screen_test/settings/height/box_border_sizing.frame +1 -0
- data/screen_test/settings/height/box_border_sizing.rb +15 -0
- data/screen_test/settings/height/grid.frame +1 -0
- data/screen_test/settings/height/grid.rb +14 -0
- data/screen_test/settings/height/overflow_box.frame +1 -0
- data/screen_test/settings/height/overflow_box.rb +13 -0
- data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
- data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
- data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
- data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
- data/screen_test/settings/height/overflow_grid.frame +1 -0
- data/screen_test/settings/height/overflow_grid.rb +16 -0
- data/screen_test/settings/margin.frame +1 -0
- data/screen_test/settings/margin.rb +16 -0
- data/screen_test/settings/padding.frame +1 -0
- data/screen_test/settings/padding.rb +13 -0
- data/screen_test/settings/position/box_left.frame +1 -0
- data/screen_test/settings/position/box_left.rb +17 -0
- data/screen_test/settings/position/box_left_negative.frame +1 -0
- data/screen_test/settings/position/box_left_negative.rb +17 -0
- data/screen_test/settings/position/box_top.frame +1 -0
- data/screen_test/settings/position/box_top.rb +17 -0
- data/screen_test/settings/position/box_top_negative.frame +1 -0
- data/screen_test/settings/position/box_top_negative.rb +17 -0
- data/screen_test/settings/position/grid_left.frame +1 -0
- data/screen_test/settings/position/grid_left.rb +18 -0
- data/screen_test/settings/position/grid_left_negative.frame +1 -0
- data/screen_test/settings/position/grid_left_negative.rb +18 -0
- data/screen_test/settings/position/grid_top.frame +1 -0
- data/screen_test/settings/position/grid_top.rb +18 -0
- data/screen_test/settings/position/grid_top_negative.frame +1 -0
- data/screen_test/settings/position/grid_top_negative.rb +18 -0
- data/screen_test/settings/scroll/horiz_box.frame +1 -0
- data/screen_test/settings/scroll/horiz_box.rb +17 -0
- data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
- data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
- data/screen_test/settings/scroll/vert_box.frame +1 -0
- data/screen_test/settings/scroll/vert_box.rb +20 -0
- data/screen_test/settings/title_font.frame +1 -0
- data/screen_test/settings/title_font.rb +12 -0
- data/screen_test/settings/valign/box_around.frame +1 -0
- data/screen_test/settings/valign/box_around.rb +17 -0
- data/screen_test/settings/valign/box_between.frame +1 -0
- data/screen_test/settings/valign/box_between.rb +17 -0
- data/screen_test/settings/valign/box_bottom.frame +1 -0
- data/screen_test/settings/valign/box_bottom.rb +17 -0
- data/screen_test/settings/valign/box_default.frame +1 -0
- data/screen_test/settings/valign/box_default.rb +16 -0
- data/screen_test/settings/valign/box_evenly.frame +1 -0
- data/screen_test/settings/valign/box_evenly.rb +17 -0
- data/screen_test/settings/valign/box_middle.frame +1 -0
- data/screen_test/settings/valign/box_middle.rb +17 -0
- data/screen_test/settings/valign/box_top.frame +1 -0
- data/screen_test/settings/valign/box_top.rb +17 -0
- data/screen_test/settings/valign/grid_bottom.frame +1 -0
- data/screen_test/settings/valign/grid_bottom.rb +15 -0
- data/screen_test/settings/valign/grid_default.frame +1 -0
- data/screen_test/settings/valign/grid_default.rb +14 -0
- data/screen_test/settings/valign/grid_middle.frame +1 -0
- data/screen_test/settings/valign/grid_middle.rb +15 -0
- data/screen_test/settings/valign/grid_top.frame +1 -0
- data/screen_test/settings/valign/grid_top.rb +15 -0
- data/screen_test/settings/width/box_border_sizing.frame +1 -0
- data/screen_test/settings/width/box_border_sizing.rb +15 -0
- data/screen_test/settings/width/box_content.frame +1 -0
- data/screen_test/settings/width/box_content.rb +15 -0
- data/screen_test/settings/width/box_default.frame +1 -0
- data/screen_test/settings/width/box_default.rb +14 -0
- data/screen_test/settings/width/grid.frame +1 -0
- data/screen_test/settings/width/grid.rb +14 -0
- data/screen_test/settings/width/overflow_align_center.frame +1 -0
- data/screen_test/settings/width/overflow_align_center.rb +14 -0
- data/screen_test/settings/width/overflow_align_right.frame +1 -0
- data/screen_test/settings/width/overflow_align_right.rb +14 -0
- data/screen_test/settings/width/overflow_box.frame +1 -0
- data/screen_test/settings/width/overflow_box.rb +13 -0
- data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
- data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
- data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
- data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
- data/screen_test/settings/width/overflow_grid.frame +1 -0
- data/screen_test/settings/width/overflow_grid.rb +14 -0
- data/tools/whirled_peas/tools/screen_tester.rb +285 -0
- metadata +213 -15
- data/bin/title_fonts +0 -6
- data/lib/whirled_peas/frame.rb +0 -7
- data/lib/whirled_peas/frame/event_loop.rb +0 -91
- data/lib/whirled_peas/frame/print_consumer.rb +0 -33
- data/lib/whirled_peas/frame/producer.rb +0 -61
- data/lib/whirled_peas/template.rb +0 -5
- data/lib/whirled_peas/template/element.rb +0 -230
- data/lib/whirled_peas/template/settings.rb +0 -530
- data/lib/whirled_peas/ui.rb +0 -5
- data/lib/whirled_peas/ui/canvas.rb +0 -68
- data/lib/whirled_peas/ui/painter.rb +0 -287
- data/lib/whirled_peas/ui/screen.rb +0 -63
- data/lib/whirled_peas/utils/color.rb +0 -101
| @@ -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,44 @@ | |
| 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 => e
         | 
| 12 | 
            +
                    puts "Error loading #{config_file}"
         | 
| 13 | 
            +
                    puts e.message
         | 
| 14 | 
            +
                    exit(1)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  attr_reader :config_file
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def validate!
         | 
| 22 | 
            +
                    super
         | 
| 23 | 
            +
                    # Note that the main script consumes the <command> argument from ARGV, so we
         | 
| 24 | 
            +
                    # expect the config file to be at index 0.
         | 
| 25 | 
            +
                    config_file = args.shift
         | 
| 26 | 
            +
                    if config_file.nil?
         | 
| 27 | 
            +
                      @error_text = "#{command_name} requires a config file"
         | 
| 28 | 
            +
                    elsif !File.exist?(config_file)
         | 
| 29 | 
            +
                      @error_text = "File not found: #{config_file}"
         | 
| 30 | 
            +
                    elsif config_file[-3..-1] != '.rb'
         | 
| 31 | 
            +
                      @error_text = 'Config file should be a .rb file'
         | 
| 32 | 
            +
                    else
         | 
| 33 | 
            +
                      # We think we have a valid ruby config file, set the absolute path to @config
         | 
| 34 | 
            +
                      @config_file = config_file[0] == '/' ? config_file : File.join(Dir.pwd, config_file)
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def options_usage
         | 
| 39 | 
            +
                    '<config file>'
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                private_constant :ConfigCommand
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            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,108 @@ | |
| 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 | 
            +
                    end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    private
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    attr_reader :app_config_file, :config, :logger
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  class FilePlayer
         | 
| 49 | 
            +
                    def initialize(wpz_file)
         | 
| 50 | 
            +
                      @wpz_file = wpz_file
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    def play
         | 
| 54 | 
            +
                      require 'whirled_peas/device/screen'
         | 
| 55 | 
            +
                      require 'whirled_peas/utils/ansi'
         | 
| 56 | 
            +
                      require 'whirled_peas/utils/file_handler'
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                      Utils::Ansi.with_screen do
         | 
| 59 | 
            +
                        screen = Device::Screen.new(WhirledPeas.config.refresh_rate)
         | 
| 60 | 
            +
                        renders = Utils::FileHandler.read(wpz_file)
         | 
| 61 | 
            +
                        screen.handle_renders(renders)
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    private
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    attr_reader :wpz_file
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def self.description
         | 
| 71 | 
            +
                    'Play an animation from an application or prerecorded file'
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  def start
         | 
| 75 | 
            +
                    super
         | 
| 76 | 
            +
                    player.play
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  private
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  attr_reader :player
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  def validate!
         | 
| 84 | 
            +
                    super
         | 
| 85 | 
            +
                    @player = NullPlayer
         | 
| 86 | 
            +
                    file = args.shift
         | 
| 87 | 
            +
                    if file.nil?
         | 
| 88 | 
            +
                      @error_text = "#{command_name} requires an config file or frames file file"
         | 
| 89 | 
            +
                    elsif !File.exist?(file)
         | 
| 90 | 
            +
                      @error_text = "File not found: #{file}"
         | 
| 91 | 
            +
                    else
         | 
| 92 | 
            +
                      full_path_file = file[0] == '/' ? file : File.join(Dir.pwd, file)
         | 
| 93 | 
            +
                      if full_path_file.end_with?('.wpz')
         | 
| 94 | 
            +
                        @player = FilePlayer.new(full_path_file)
         | 
| 95 | 
            +
                      elsif full_path_file.end_with?('.rb')
         | 
| 96 | 
            +
                        @player = ApplicationPlayer.new(full_path_file, config, build_logger)
         | 
| 97 | 
            +
                      else
         | 
| 98 | 
            +
                        @error_text = "Unsupported file type: .#{file.split('.').last}, epxecting .rb or .wpz"
         | 
| 99 | 
            +
                      end
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  def options_usage
         | 
| 104 | 
            +
                    '<config/wpz file>'
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
            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
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require_relative 'frame_command'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module WhirledPeas
         | 
| 4 | 
            +
              module Command
         | 
| 5 | 
            +
                # Display a still frame with the specified arguments.
         | 
| 6 | 
            +
                class Still < FrameCommand
         | 
| 7 | 
            +
                  def self.description
         | 
| 8 | 
            +
                    'Show the specified still frame'
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def start
         | 
| 12 | 
            +
                    super
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    require 'whirled_peas/device/screen'
         | 
| 15 | 
            +
                    require 'whirled_peas/graphics/renderer'
         | 
| 16 | 
            +
                    require 'whirled_peas/utils/ansi'
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    Utils::Ansi.with_screen do |width, height|
         | 
| 19 | 
            +
                      rendered = Graphics::Renderer.new(
         | 
| 20 | 
            +
                        WhirledPeas.config.template_factory.build(frame, frame_args),
         | 
| 21 | 
            +
                        width,
         | 
| 22 | 
            +
                        height
         | 
| 23 | 
            +
                      ).paint
         | 
| 24 | 
            +
                      Device::Screen.new(10000).handle_renders([rendered])
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         |