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
@@ -28,9 +28,6 @@ module WhirledPeas
|
|
28
28
|
|
29
29
|
def dimensions
|
30
30
|
@dimensions ||= begin
|
31
|
-
if settings.num_cols.nil? || settings.num_cols == 0
|
32
|
-
raise SettingsError, "`num_cols` must be set for GridSettings(#{name})"
|
33
|
-
end
|
34
31
|
num_cols = settings.num_cols
|
35
32
|
num_rows = (num_children.to_f / num_cols).ceil
|
36
33
|
content_width = 0
|
@@ -58,7 +55,7 @@ module WhirledPeas
|
|
58
55
|
col_index, row_index = [index % dimensions.num_cols, index / dimensions.num_cols]
|
59
56
|
col_index = dimensions.num_cols - col_index - 1 if settings.reverse_flow?
|
60
57
|
else
|
61
|
-
col_index, row_index = [index / dimensions.
|
58
|
+
col_index, row_index = [index / dimensions.num_rows, index % dimensions.num_rows]
|
62
59
|
row_index = dimensions.num_rows - row_index - 1 if settings.reverse_flow?
|
63
60
|
end
|
64
61
|
[col_index, row_index]
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module WhirledPeas
|
2
2
|
module Graphics
|
3
|
+
# Abstract base Painter class. Given a canvas and start coordinates (left, top), a painter
|
4
|
+
# is responsible for generating the "strokes" that display the element.
|
3
5
|
class Painter
|
4
6
|
attr_reader :name, :settings
|
5
7
|
|
@@ -8,9 +10,17 @@ module WhirledPeas
|
|
8
10
|
@name = name
|
9
11
|
end
|
10
12
|
|
13
|
+
# Paint the element onto the canvas by yielding strokes to the block. A stroke is composed
|
14
|
+
# of a left, top, and chars. E.g.
|
15
|
+
#
|
16
|
+
# yield 10, 3, 'Hello World!'
|
17
|
+
#
|
18
|
+
# paints the string "Hello World!" in the 10th column from the left, 3rd row down.
|
11
19
|
def paint(canvas, left, top, &block)
|
12
20
|
end
|
13
21
|
|
22
|
+
# Return a dimension object that provider the `outer_width` and `outer_height` of the
|
23
|
+
# element being painted.
|
14
24
|
def dimensions
|
15
25
|
end
|
16
26
|
|
@@ -9,13 +9,19 @@ module WhirledPeas
|
|
9
9
|
@height = height
|
10
10
|
end
|
11
11
|
|
12
|
-
def paint
|
12
|
+
def paint
|
13
13
|
# Modify the template's settings so that it fills the entire screen
|
14
14
|
template.settings.width = width
|
15
15
|
template.settings.height = height
|
16
16
|
template.settings.sizing = :border
|
17
17
|
template.settings.set_margin(left: 0, top: 0, right: 0, bottom: 0)
|
18
|
-
|
18
|
+
strokes = [Utils::Ansi.cursor_visible(false), Utils::Ansi.cursor_pos, Utils::Ansi.clear_down]
|
19
|
+
template.paint(Canvas.new(0, 0, width, height), 0, 0) do |left, top, fstring|
|
20
|
+
next unless fstring.length > 0
|
21
|
+
strokes << Utils::Ansi.cursor_pos(left: left, top: top)
|
22
|
+
strokes << fstring
|
23
|
+
end
|
24
|
+
strokes.join
|
19
25
|
end
|
20
26
|
|
21
27
|
private
|
@@ -1,14 +1,12 @@
|
|
1
1
|
require 'whirled_peas/utils/formatted_string'
|
2
2
|
require 'whirled_peas/utils/title_font'
|
3
3
|
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
4
|
+
require_relative 'content_dimensions'
|
5
|
+
require_relative 'content_painter'
|
6
6
|
|
7
7
|
module WhirledPeas
|
8
8
|
module Graphics
|
9
|
-
class TextPainter <
|
10
|
-
attr_reader :content
|
11
|
-
|
9
|
+
class TextPainter < ContentPainter
|
12
10
|
def paint(canvas, left, top, &block)
|
13
11
|
return unless canvas.writable?
|
14
12
|
formatting = [*settings.color, *settings.bg_color]
|
@@ -16,17 +14,15 @@ module WhirledPeas
|
|
16
14
|
if settings.underline? && settings.title_font.nil?
|
17
15
|
formatting << Utils::Ansi::UNDERLINE
|
18
16
|
end
|
19
|
-
|
17
|
+
content_lines.each.with_index do |line, index|
|
20
18
|
canvas.stroke(left, top + index, line, formatting, &block)
|
21
19
|
end
|
22
20
|
end
|
23
21
|
|
24
|
-
|
25
|
-
TextDimensions.new(content)
|
26
|
-
end
|
22
|
+
private
|
27
23
|
|
28
|
-
def
|
29
|
-
@
|
24
|
+
def content_lines
|
25
|
+
@content_lines = if settings.title_font
|
30
26
|
Utils::TitleFont.to_s(
|
31
27
|
content, settings.title_font
|
32
28
|
).split("\n")
|
@@ -51,8 +51,20 @@ module WhirledPeas
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
+
def self.inherit(parent)
|
55
|
+
border = new(parent.theme)
|
56
|
+
border.inherit(parent)
|
57
|
+
border
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :theme
|
61
|
+
|
54
62
|
attr_writer :left, :top, :right, :bottom, :inner_horiz, :inner_vert
|
55
63
|
|
64
|
+
def initialize(theme)
|
65
|
+
@theme = theme
|
66
|
+
end
|
67
|
+
|
56
68
|
def left?
|
57
69
|
@left == true
|
58
70
|
end
|
@@ -82,20 +94,29 @@ module WhirledPeas
|
|
82
94
|
end
|
83
95
|
|
84
96
|
def style
|
85
|
-
@
|
97
|
+
@_style || Styles::DEFAULT
|
86
98
|
end
|
87
99
|
|
88
100
|
def style=(val)
|
89
|
-
@
|
101
|
+
@_style = Styles.validate!(val)
|
90
102
|
end
|
91
103
|
|
92
104
|
def color=(val)
|
93
|
-
@
|
105
|
+
@_color = TextColor.validate!(val)
|
94
106
|
end
|
95
107
|
|
96
108
|
def color
|
97
|
-
@
|
109
|
+
@_color || theme.border_color
|
98
110
|
end
|
111
|
+
|
112
|
+
def inherit(parent)
|
113
|
+
@_style = parent._style
|
114
|
+
@_color = parent._color
|
115
|
+
end
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
attr_reader :_style, :_color
|
99
120
|
end
|
100
121
|
end
|
101
122
|
end
|
@@ -12,8 +12,6 @@ require_relative 'vert_alignment'
|
|
12
12
|
module WhirledPeas
|
13
13
|
module Settings
|
14
14
|
class ContainerSettings < ElementSettings
|
15
|
-
attr_accessor :width, :height
|
16
|
-
|
17
15
|
def align
|
18
16
|
@_align || Alignment::DEFAULT
|
19
17
|
end
|
@@ -98,7 +96,7 @@ module WhirledPeas
|
|
98
96
|
end
|
99
97
|
|
100
98
|
def border
|
101
|
-
@_border ||= Border.new
|
99
|
+
@_border ||= Border.new(theme)
|
102
100
|
end
|
103
101
|
|
104
102
|
def flow=(flow)
|
@@ -214,7 +212,7 @@ module WhirledPeas
|
|
214
212
|
def inherit(parent)
|
215
213
|
super
|
216
214
|
return unless parent.is_a?(ContainerSettings)
|
217
|
-
|
215
|
+
@_border = Border.inherit(parent.border)
|
218
216
|
end
|
219
217
|
|
220
218
|
protected
|
@@ -8,13 +8,22 @@ module WhirledPeas
|
|
8
8
|
module Settings
|
9
9
|
class ElementSettings
|
10
10
|
def self.inherit(parent)
|
11
|
-
child = self.new
|
11
|
+
child = self.new(parent.theme)
|
12
12
|
child.inherit(parent)
|
13
13
|
child
|
14
14
|
end
|
15
15
|
|
16
|
+
attr_accessor :theme, :width, :height
|
17
|
+
|
18
|
+
def initialize(theme)
|
19
|
+
@theme = theme
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate!
|
23
|
+
end
|
24
|
+
|
16
25
|
def bg_color
|
17
|
-
@_bg_color ||
|
26
|
+
@_bg_color || theme.bg_color
|
18
27
|
end
|
19
28
|
|
20
29
|
def bg_color=(color)
|
@@ -30,7 +39,7 @@ module WhirledPeas
|
|
30
39
|
end
|
31
40
|
|
32
41
|
def color
|
33
|
-
@_color ||
|
42
|
+
@_color || theme.color
|
34
43
|
end
|
35
44
|
|
36
45
|
def color=(color)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'text_color'
|
2
|
+
require_relative 'element_settings'
|
3
|
+
|
4
|
+
module WhirledPeas
|
5
|
+
module Settings
|
6
|
+
class GraphSettings < ElementSettings
|
7
|
+
def axis_color
|
8
|
+
@_axis_color || theme.axis_color
|
9
|
+
end
|
10
|
+
|
11
|
+
def axis_color=(color)
|
12
|
+
@_axis_color = TextColor.validate!(color)
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
super
|
17
|
+
raise SettingsError, "`height` must be set for GraphSettings" if height.nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -7,6 +7,13 @@ module WhirledPeas
|
|
7
7
|
class GridSettings < ContainerSettings
|
8
8
|
attr_accessor :num_cols
|
9
9
|
|
10
|
+
def validate!
|
11
|
+
super
|
12
|
+
if num_cols.nil? || num_cols <= 0
|
13
|
+
raise SettingsError, "`num_cols` must be set to a positive number for GridSettings"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
10
17
|
def set_scrollbar(*)
|
11
18
|
raise NotImplementedError, 'Grids do not support scrollbars'
|
12
19
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'whirled_peas/utils/title_font'
|
2
|
+
|
3
|
+
require_relative 'bg_color'
|
4
|
+
require_relative 'text_color'
|
5
|
+
|
6
|
+
module WhirledPeas
|
7
|
+
module Settings
|
8
|
+
class Theme
|
9
|
+
attr_reader :color, :bg_color, :title_font
|
10
|
+
|
11
|
+
def color=(value)
|
12
|
+
@color = TextColor.validate!(value)
|
13
|
+
end
|
14
|
+
|
15
|
+
def bg_color=(value)
|
16
|
+
@bg_color = BgColor.validate!(value)
|
17
|
+
end
|
18
|
+
|
19
|
+
def border_color=(value)
|
20
|
+
@border_color = TextColor.validate!(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def border_color
|
24
|
+
@border_color || color
|
25
|
+
end
|
26
|
+
|
27
|
+
def axis_color=(value)
|
28
|
+
@axis_color = TextColor.validate!(value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def axis_color
|
32
|
+
@axis_color || border_color
|
33
|
+
end
|
34
|
+
|
35
|
+
def title_font=(value)
|
36
|
+
@title_font = Utils::TitleFont.validate!(value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
require_relative 'theme'
|
4
|
+
|
5
|
+
module WhirledPeas
|
6
|
+
module Settings
|
7
|
+
module ThemeLibrary
|
8
|
+
CONFIG_FILE = File.join(File.dirname(File.dirname(File.dirname(__FILE__))), 'data', 'themes.yaml')
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def theme_names
|
12
|
+
themes.keys
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(name, theme)
|
16
|
+
themes[name] = theme
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(name)
|
20
|
+
unless themes.key?(name)
|
21
|
+
expected = themes.keys.map(&:inspect).join(', ')
|
22
|
+
raise ArgumentError, "Unknown theme: #{name.inspect}, expecting one of #{expected}"
|
23
|
+
end
|
24
|
+
themes[name]
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_name
|
28
|
+
themes.keys.first
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def themes
|
34
|
+
return @themes if @themes
|
35
|
+
@themes = {}
|
36
|
+
config = YAML.load_file(CONFIG_FILE)
|
37
|
+
config.each do |name, settings|
|
38
|
+
name = name.to_sym
|
39
|
+
theme = Theme.new
|
40
|
+
settings.each do |key, value|
|
41
|
+
case key
|
42
|
+
when 'color'
|
43
|
+
theme.color = value
|
44
|
+
when 'bg_color'
|
45
|
+
theme.bg_color = value
|
46
|
+
when 'border_color'
|
47
|
+
theme.border_color = value
|
48
|
+
when 'axis_color'
|
49
|
+
theme.axis_color = value
|
50
|
+
when 'title_font'
|
51
|
+
theme.title_font = value
|
52
|
+
else
|
53
|
+
raise ArgumentError, "Unexpected theme setting: #{key} in #{CONFIG_FILE}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@themes[name] = theme
|
57
|
+
end
|
58
|
+
@themes
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -28,6 +28,19 @@ module WhirledPeas
|
|
28
28
|
BRIGHT_OFFSET = 60
|
29
29
|
|
30
30
|
class << self
|
31
|
+
def with_screen(output=STDOUT, width: nil, height: nil, &block)
|
32
|
+
require 'highline'
|
33
|
+
unless width && height
|
34
|
+
width, height = HighLine.new.terminal.terminal_size
|
35
|
+
end
|
36
|
+
yield width, height
|
37
|
+
ensure
|
38
|
+
output.print clear
|
39
|
+
output.print cursor_pos(top: height - 1)
|
40
|
+
output.print cursor_visible(true)
|
41
|
+
output.flush
|
42
|
+
end
|
43
|
+
|
31
44
|
def cursor_pos(top: 0, left: 0)
|
32
45
|
"#{ESC}[#{top + 1};#{left + 1}H"
|
33
46
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
module WhirledPeas
|
5
|
+
module Utils
|
6
|
+
module FileHandler
|
7
|
+
module FileWriter
|
8
|
+
VERSION = '1'
|
9
|
+
|
10
|
+
def self.write(fp, renders)
|
11
|
+
fp.puts renders.count
|
12
|
+
renders.each do |strokes|
|
13
|
+
encoded = Base64.encode64(strokes)
|
14
|
+
fp.puts encoded.count("\n")
|
15
|
+
fp.puts encoded
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
private_constant :FileWriter
|
20
|
+
|
21
|
+
class FileReaderV1
|
22
|
+
def self.read(fp)
|
23
|
+
num_renders = Integer(fp.readline.chomp, 10)
|
24
|
+
num_renders.times.map do
|
25
|
+
num_strokes = Integer(fp.readline.chomp, 10)
|
26
|
+
Base64.decode64(num_strokes.times.map { fp.readline }.join)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :file
|
33
|
+
end
|
34
|
+
private_constant :FileReaderV1
|
35
|
+
|
36
|
+
READERS = {
|
37
|
+
'1' => FileReaderV1
|
38
|
+
}
|
39
|
+
private_constant :READERS
|
40
|
+
|
41
|
+
def self.write(file, renders)
|
42
|
+
Zlib::GzipWriter.open(file, Zlib::BEST_COMPRESSION) do |gz|
|
43
|
+
gz.puts FileWriter::VERSION
|
44
|
+
FileWriter.write(gz, renders)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.read(file)
|
49
|
+
Zlib::GzipReader.open(file) do |gz|
|
50
|
+
version = gz.gets.chomp
|
51
|
+
raise ArgumentError, "Invalid file: #{file}" unless READERS.key?(version)
|
52
|
+
READERS[version].read(gz)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|