whirled_peas 0.7.1 → 0.11.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.
Files changed (262) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +25 -0
  4. data/README.md +530 -121
  5. data/Rakefile +1 -20
  6. data/bin/easing +33 -0
  7. data/bin/reset_cursor +11 -0
  8. data/bin/screen_test +68 -0
  9. data/examples/components.rb +35 -0
  10. data/examples/graph.rb +54 -0
  11. data/examples/intro.rb +3 -3
  12. data/examples/scrolling.rb +13 -23
  13. data/lib/data/themes.yaml +13 -0
  14. data/lib/whirled_peas.rb +33 -13
  15. data/lib/whirled_peas/animator.rb +5 -0
  16. data/lib/whirled_peas/animator/debug_consumer.rb +17 -0
  17. data/lib/whirled_peas/animator/easing.rb +72 -0
  18. data/lib/whirled_peas/animator/frame.rb +5 -0
  19. data/lib/whirled_peas/animator/frameset.rb +33 -0
  20. data/lib/whirled_peas/animator/producer.rb +35 -0
  21. data/lib/whirled_peas/animator/renderer_consumer.rb +31 -0
  22. data/lib/whirled_peas/command.rb +5 -0
  23. data/lib/whirled_peas/command/base.rb +86 -0
  24. data/lib/whirled_peas/command/config_command.rb +44 -0
  25. data/lib/whirled_peas/command/debug.rb +21 -0
  26. data/lib/whirled_peas/command/fonts.rb +22 -0
  27. data/lib/whirled_peas/command/frame_command.rb +34 -0
  28. data/lib/whirled_peas/command/frames.rb +24 -0
  29. data/lib/whirled_peas/command/help.rb +38 -0
  30. data/lib/whirled_peas/command/play.rb +112 -0
  31. data/lib/whirled_peas/command/record.rb +57 -0
  32. data/lib/whirled_peas/command/still.rb +29 -0
  33. data/lib/whirled_peas/command/themes.rb +77 -0
  34. data/lib/whirled_peas/command_line.rb +24 -212
  35. data/lib/whirled_peas/component.rb +35 -0
  36. data/lib/whirled_peas/component/list_with_active.rb +88 -0
  37. data/lib/whirled_peas/config.rb +56 -6
  38. data/lib/whirled_peas/device.rb +5 -0
  39. data/lib/whirled_peas/device/null_device.rb +8 -0
  40. data/lib/whirled_peas/device/output_file.rb +19 -0
  41. data/lib/whirled_peas/device/screen.rb +26 -0
  42. data/lib/whirled_peas/graphics/box_painter.rb +4 -4
  43. data/lib/whirled_peas/graphics/composer.rb +27 -2
  44. data/lib/whirled_peas/graphics/container_coords.rb +24 -2
  45. data/lib/whirled_peas/graphics/container_painter.rb +63 -82
  46. data/lib/whirled_peas/graphics/content_dimensions.rb +19 -0
  47. data/lib/whirled_peas/graphics/content_painter.rb +20 -0
  48. data/lib/whirled_peas/graphics/debugger.rb +1 -7
  49. data/lib/whirled_peas/graphics/graph_dimensions.rb +12 -0
  50. data/lib/whirled_peas/graphics/graph_painter.rb +97 -0
  51. data/lib/whirled_peas/graphics/grid_painter.rb +0 -3
  52. data/lib/whirled_peas/graphics/painter.rb +10 -0
  53. data/lib/whirled_peas/graphics/renderer.rb +8 -2
  54. data/lib/whirled_peas/graphics/scrollbar_helper.rb +124 -0
  55. data/lib/whirled_peas/graphics/text_painter.rb +7 -11
  56. data/lib/whirled_peas/null_logger.rb +0 -1
  57. data/lib/whirled_peas/settings/border.rb +25 -4
  58. data/lib/whirled_peas/settings/container_settings.rb +14 -9
  59. data/lib/whirled_peas/settings/debugger.rb +1 -1
  60. data/lib/whirled_peas/settings/element_settings.rb +12 -3
  61. data/lib/whirled_peas/settings/graph_settings.rb +21 -0
  62. data/lib/whirled_peas/settings/grid_settings.rb +7 -0
  63. data/lib/whirled_peas/settings/position.rb +17 -5
  64. data/lib/whirled_peas/settings/text_settings.rb +1 -0
  65. data/lib/whirled_peas/settings/theme.rb +40 -0
  66. data/lib/whirled_peas/settings/theme_library.rb +63 -0
  67. data/lib/whirled_peas/utils/ansi.rb +13 -0
  68. data/lib/whirled_peas/utils/file_handler.rb +57 -0
  69. data/lib/whirled_peas/version.rb +1 -1
  70. data/screen_test/components/list_with_active/l2r_active_color.frame +1 -0
  71. data/screen_test/components/list_with_active/l2r_active_color.rb +18 -0
  72. data/screen_test/components/list_with_active/l2r_position_end.frame +1 -0
  73. data/screen_test/components/list_with_active/l2r_position_end.rb +16 -0
  74. data/screen_test/components/list_with_active/l2r_position_middle.frame +1 -0
  75. data/screen_test/components/list_with_active/l2r_position_middle.rb +16 -0
  76. data/screen_test/components/list_with_active/l2r_position_start.frame +1 -0
  77. data/screen_test/components/list_with_active/l2r_position_start.rb +16 -0
  78. data/screen_test/components/list_with_active/l2r_separator.frame +1 -0
  79. data/screen_test/components/list_with_active/l2r_separator.rb +17 -0
  80. data/screen_test/components/list_with_active/t2b_active_color.frame +1 -0
  81. data/screen_test/components/list_with_active/t2b_active_color.rb +19 -0
  82. data/screen_test/components/list_with_active/t2b_position_end.frame +1 -0
  83. data/screen_test/components/list_with_active/t2b_position_end.rb +17 -0
  84. data/screen_test/components/list_with_active/t2b_position_middle.frame +1 -0
  85. data/screen_test/components/list_with_active/t2b_position_middle.rb +17 -0
  86. data/screen_test/components/list_with_active/t2b_position_start.frame +1 -0
  87. data/screen_test/components/list_with_active/t2b_position_start.rb +17 -0
  88. data/screen_test/components/list_with_active/t2b_separator.frame +1 -0
  89. data/screen_test/components/list_with_active/t2b_separator.rb +18 -0
  90. data/screen_test/elements/box.frame +1 -1
  91. data/screen_test/elements/box.rb +1 -1
  92. data/screen_test/elements/graph.frame +1 -0
  93. data/screen_test/elements/graph.rb +12 -0
  94. data/screen_test/elements/grid.frame +1 -1
  95. data/screen_test/elements/grid.rb +1 -1
  96. data/screen_test/elements/screen_overflow_x.frame +1 -1
  97. data/screen_test/elements/screen_overflow_x.rb +1 -1
  98. data/screen_test/elements/screen_overflow_y.frame +1 -1
  99. data/screen_test/elements/screen_overflow_y.rb +1 -1
  100. data/screen_test/elements/text.frame +1 -1
  101. data/screen_test/elements/text.rb +1 -1
  102. data/screen_test/elements/text_multiline.frame +1 -1
  103. data/screen_test/elements/text_multiline.rb +1 -1
  104. data/screen_test/elements/theme.frame +1 -0
  105. data/screen_test/elements/theme.rb +26 -0
  106. data/screen_test/settings/align/box_around.frame +1 -1
  107. data/screen_test/settings/align/box_around.rb +1 -1
  108. data/screen_test/settings/align/box_between.frame +1 -1
  109. data/screen_test/settings/align/box_between.rb +1 -1
  110. data/screen_test/settings/align/box_center.frame +1 -1
  111. data/screen_test/settings/align/box_center.rb +1 -1
  112. data/screen_test/settings/align/box_default.frame +1 -1
  113. data/screen_test/settings/align/box_default.rb +1 -1
  114. data/screen_test/settings/align/box_evenly.frame +1 -1
  115. data/screen_test/settings/align/box_evenly.rb +1 -1
  116. data/screen_test/settings/align/box_left.frame +1 -1
  117. data/screen_test/settings/align/box_left.rb +1 -1
  118. data/screen_test/settings/align/box_right.frame +1 -1
  119. data/screen_test/settings/align/box_right.rb +1 -1
  120. data/screen_test/settings/align/children_center.frame +1 -1
  121. data/screen_test/settings/align/children_center.rb +1 -1
  122. data/screen_test/settings/align/children_left.frame +1 -1
  123. data/screen_test/settings/align/children_left.rb +1 -1
  124. data/screen_test/settings/align/children_right.frame +1 -1
  125. data/screen_test/settings/align/children_right.rb +1 -1
  126. data/screen_test/settings/align/grid_center.frame +1 -1
  127. data/screen_test/settings/align/grid_center.rb +1 -1
  128. data/screen_test/settings/align/grid_default.frame +1 -1
  129. data/screen_test/settings/align/grid_default.rb +1 -1
  130. data/screen_test/settings/align/grid_left.frame +1 -1
  131. data/screen_test/settings/align/grid_left.rb +1 -1
  132. data/screen_test/settings/align/grid_right.frame +1 -1
  133. data/screen_test/settings/align/grid_right.rb +1 -1
  134. data/screen_test/settings/ansi/bold.frame +1 -1
  135. data/screen_test/settings/ansi/bold.rb +1 -1
  136. data/screen_test/settings/ansi/color.frame +1 -1
  137. data/screen_test/settings/ansi/color.rb +1 -1
  138. data/screen_test/settings/ansi/underline.frame +1 -1
  139. data/screen_test/settings/ansi/underline.rb +1 -1
  140. data/screen_test/settings/border.frame +1 -1
  141. data/screen_test/settings/border.rb +1 -1
  142. data/screen_test/settings/content_start/box_bottom.frame +1 -0
  143. data/screen_test/settings/content_start/box_bottom.rb +17 -0
  144. data/screen_test/settings/content_start/box_left.frame +1 -0
  145. data/screen_test/settings/{position → content_start}/box_left.rb +2 -2
  146. data/screen_test/settings/content_start/box_left_negative.frame +1 -0
  147. data/screen_test/settings/{position → content_start}/box_left_negative.rb +2 -2
  148. data/screen_test/settings/content_start/box_right.frame +1 -0
  149. data/screen_test/settings/content_start/box_right.rb +17 -0
  150. data/screen_test/settings/content_start/box_top.frame +1 -0
  151. data/screen_test/settings/{position → content_start}/box_top.rb +2 -2
  152. data/screen_test/settings/content_start/box_top_negative.frame +1 -0
  153. data/screen_test/settings/{position → content_start}/box_top_negative.rb +2 -2
  154. data/screen_test/settings/content_start/grid_left.frame +1 -0
  155. data/screen_test/settings/{position → content_start}/grid_left.rb +2 -2
  156. data/screen_test/settings/content_start/grid_left_negative.frame +1 -0
  157. data/screen_test/settings/{position → content_start}/grid_left_negative.rb +2 -2
  158. data/screen_test/settings/content_start/grid_top.frame +1 -0
  159. data/screen_test/settings/{position → content_start}/grid_top.rb +2 -2
  160. data/screen_test/settings/content_start/grid_top_negative.frame +1 -0
  161. data/screen_test/settings/{position → content_start}/grid_top_negative.rb +2 -2
  162. data/screen_test/settings/flow/box_b2t.frame +1 -1
  163. data/screen_test/settings/flow/box_b2t.rb +1 -1
  164. data/screen_test/settings/flow/box_l2r.frame +1 -1
  165. data/screen_test/settings/flow/box_l2r.rb +1 -1
  166. data/screen_test/settings/flow/box_r2l.frame +1 -1
  167. data/screen_test/settings/flow/box_r2l.rb +1 -1
  168. data/screen_test/settings/flow/box_t2b.frame +1 -1
  169. data/screen_test/settings/flow/box_t2b.rb +1 -1
  170. data/screen_test/settings/flow/grid_b2t.frame +1 -1
  171. data/screen_test/settings/flow/grid_b2t.rb +1 -1
  172. data/screen_test/settings/flow/grid_l2r.frame +1 -1
  173. data/screen_test/settings/flow/grid_l2r.rb +1 -1
  174. data/screen_test/settings/flow/grid_r2l.frame +1 -1
  175. data/screen_test/settings/flow/grid_r2l.rb +1 -1
  176. data/screen_test/settings/flow/grid_t2b.frame +1 -1
  177. data/screen_test/settings/flow/grid_t2b.rb +1 -1
  178. data/screen_test/settings/height/box.frame +1 -1
  179. data/screen_test/settings/height/box.rb +1 -1
  180. data/screen_test/settings/height/box_border_sizing.frame +1 -1
  181. data/screen_test/settings/height/box_border_sizing.rb +1 -1
  182. data/screen_test/settings/height/grid.frame +1 -1
  183. data/screen_test/settings/height/grid.rb +1 -1
  184. data/screen_test/settings/height/overflow_box.frame +1 -1
  185. data/screen_test/settings/height/overflow_box.rb +1 -1
  186. data/screen_test/settings/height/overflow_box_l2r.frame +1 -1
  187. data/screen_test/settings/height/overflow_box_l2r.rb +1 -1
  188. data/screen_test/settings/height/overflow_box_t2b.frame +1 -1
  189. data/screen_test/settings/height/overflow_box_t2b.rb +1 -1
  190. data/screen_test/settings/height/overflow_grid.frame +1 -1
  191. data/screen_test/settings/height/overflow_grid.rb +1 -1
  192. data/screen_test/settings/margin.frame +1 -1
  193. data/screen_test/settings/margin.rb +1 -1
  194. data/screen_test/settings/padding.frame +1 -1
  195. data/screen_test/settings/padding.rb +1 -1
  196. data/screen_test/settings/scroll/horiz_box.frame +1 -1
  197. data/screen_test/settings/scroll/horiz_box.rb +3 -5
  198. data/screen_test/settings/scroll/horiz_box_align_center.rb +3 -5
  199. data/screen_test/settings/scroll/horiz_box_align_right.rb +3 -5
  200. data/screen_test/settings/scroll/vert_box.frame +1 -1
  201. data/screen_test/settings/scroll/vert_box.rb +6 -8
  202. data/screen_test/settings/title_font.frame +1 -1
  203. data/screen_test/settings/title_font.rb +1 -1
  204. data/screen_test/settings/valign/box_around.frame +1 -1
  205. data/screen_test/settings/valign/box_around.rb +1 -1
  206. data/screen_test/settings/valign/box_between.frame +1 -1
  207. data/screen_test/settings/valign/box_between.rb +1 -1
  208. data/screen_test/settings/valign/box_bottom.frame +1 -1
  209. data/screen_test/settings/valign/box_bottom.rb +1 -1
  210. data/screen_test/settings/valign/box_default.frame +1 -1
  211. data/screen_test/settings/valign/box_default.rb +1 -1
  212. data/screen_test/settings/valign/box_evenly.frame +1 -1
  213. data/screen_test/settings/valign/box_evenly.rb +1 -1
  214. data/screen_test/settings/valign/box_middle.frame +1 -1
  215. data/screen_test/settings/valign/box_middle.rb +1 -1
  216. data/screen_test/settings/valign/box_top.frame +1 -1
  217. data/screen_test/settings/valign/box_top.rb +1 -1
  218. data/screen_test/settings/valign/grid_bottom.frame +1 -1
  219. data/screen_test/settings/valign/grid_bottom.rb +1 -1
  220. data/screen_test/settings/valign/grid_default.frame +1 -1
  221. data/screen_test/settings/valign/grid_default.rb +1 -1
  222. data/screen_test/settings/valign/grid_middle.frame +1 -1
  223. data/screen_test/settings/valign/grid_middle.rb +1 -1
  224. data/screen_test/settings/valign/grid_top.frame +1 -1
  225. data/screen_test/settings/valign/grid_top.rb +1 -1
  226. data/screen_test/settings/width/box_border_sizing.frame +1 -1
  227. data/screen_test/settings/width/box_border_sizing.rb +1 -1
  228. data/screen_test/settings/width/box_content.frame +1 -1
  229. data/screen_test/settings/width/box_content.rb +1 -1
  230. data/screen_test/settings/width/box_default.frame +1 -1
  231. data/screen_test/settings/width/box_default.rb +1 -1
  232. data/screen_test/settings/width/grid.frame +1 -1
  233. data/screen_test/settings/width/grid.rb +1 -1
  234. data/screen_test/settings/width/overflow_align_center.frame +1 -1
  235. data/screen_test/settings/width/overflow_align_center.rb +1 -1
  236. data/screen_test/settings/width/overflow_align_right.frame +1 -1
  237. data/screen_test/settings/width/overflow_align_right.rb +1 -1
  238. data/screen_test/settings/width/overflow_box.frame +1 -1
  239. data/screen_test/settings/width/overflow_box.rb +1 -1
  240. data/screen_test/settings/width/overflow_box_l2r.frame +1 -1
  241. data/screen_test/settings/width/overflow_box_l2r.rb +1 -1
  242. data/screen_test/settings/width/overflow_box_t2b.frame +1 -1
  243. data/screen_test/settings/width/overflow_box_t2b.rb +1 -1
  244. data/screen_test/settings/width/overflow_grid.frame +1 -1
  245. data/screen_test/settings/width/overflow_grid.rb +1 -1
  246. data/tools/whirled_peas/tools/screen_tester.rb +131 -65
  247. metadata +86 -25
  248. data/lib/whirled_peas/frame.rb +0 -6
  249. data/lib/whirled_peas/frame/consumer.rb +0 -30
  250. data/lib/whirled_peas/frame/debug_consumer.rb +0 -30
  251. data/lib/whirled_peas/frame/event_loop.rb +0 -90
  252. data/lib/whirled_peas/frame/producer.rb +0 -67
  253. data/lib/whirled_peas/graphics/screen.rb +0 -70
  254. data/lib/whirled_peas/graphics/text_dimensions.rb +0 -15
  255. data/screen_test/settings/position/box_left.frame +0 -1
  256. data/screen_test/settings/position/box_left_negative.frame +0 -1
  257. data/screen_test/settings/position/box_top.frame +0 -1
  258. data/screen_test/settings/position/box_top_negative.frame +0 -1
  259. data/screen_test/settings/position/grid_left.frame +0 -1
  260. data/screen_test/settings/position/grid_left_negative.frame +0 -1
  261. data/screen_test/settings/position/grid_top.frame +0 -1
  262. data/screen_test/settings/position/grid_top_negative.frame +0 -1
@@ -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)
@@ -177,13 +175,20 @@ module WhirledPeas
177
175
  @_padding ||= Padding.new
178
176
  end
179
177
 
180
- def set_position(left: nil, top: nil)
181
- position.left = left if left
182
- position.top = top if top
178
+ def set_content_start(left: nil, top: nil, right: nil, bottom: nil)
179
+ if left && right
180
+ raise ArgumentError, 'Setting left and right content_start is not supported'
181
+ elsif top && bottom
182
+ raise ArgumentError, 'Setting top and bottom content_start is not supported'
183
+ end
184
+ content_start.left = left if left
185
+ content_start.top = top if top
186
+ content_start.right = right if right
187
+ content_start.bottom = bottom if bottom
183
188
  end
184
189
 
185
- def position
186
- @_position ||= Position.new
190
+ def content_start
191
+ @_content_start ||= Position.new
187
192
  end
188
193
 
189
194
  def set_scrollbar(horiz: nil, vert: nil)
@@ -214,7 +219,7 @@ module WhirledPeas
214
219
  def inherit(parent)
215
220
  super
216
221
  return unless parent.is_a?(ContainerSettings)
217
- set_border(color: parent.border.color, style: parent.border.style)
222
+ @_border = Border.inherit(parent.border)
218
223
  end
219
224
 
220
225
  protected
@@ -73,7 +73,7 @@ module WhirledPeas
73
73
  def border_value(border)
74
74
  values = non_defaults(
75
75
  border,
76
- Border.new,
76
+ Border.new(settings.theme),
77
77
  %i[left? top? right? bottom? inner_horiz? inner_vert? style color]
78
78
  )
79
79
  return if values == ''
@@ -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 || BgColor::DEFAULT
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 || TextColor::DEFAULT
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
@@ -1,14 +1,26 @@
1
1
  module WhirledPeas
2
2
  module Settings
3
3
  class Position
4
- attr_writer :left, :top
4
+ attr_reader :left, :top, :right, :bottom
5
5
 
6
- def left
7
- @left || 0
6
+ def left=(value)
7
+ @right = nil
8
+ @left = value
8
9
  end
9
10
 
10
- def top
11
- @top || 0
11
+ def top=(value)
12
+ @bottom = nil
13
+ @top = value
14
+ end
15
+
16
+ def right=(value)
17
+ @left = nil
18
+ @right = value
19
+ end
20
+
21
+ def bottom=(value)
22
+ @top = nil
23
+ @bottom = value
12
24
  end
13
25
  end
14
26
  end
@@ -8,6 +8,7 @@ module WhirledPeas
8
8
  attr_reader :title_font
9
9
 
10
10
  def title_font=(font)
11
+ font = theme.title_font if font == :theme
11
12
  @title_font = Utils::TitleFont.validate!(font)
12
13
  end
13
14
  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
@@ -1,3 +1,3 @@
1
1
  module WhirledPeas
2
- VERSION = '0.7.1'
2
+ VERSION = '0.11.0'
3
3
  end
@@ -0,0 +1 @@
1
+ [?25l                        ┏━━━━━━━━━━┓┃ ┃┃ ▗▄▄▄▖ ┃┗━━━━━━━━━━┛HIJKLMNOPQ[?25h
@@ -0,0 +1,18 @@
1
+ require 'whirled_peas'
2
+ require 'whirled_peas/component/list_with_active'
3
+
4
+ class TemplateFactory
5
+ ITEMS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars
6
+
7
+ def build(*)
8
+ WhirledPeas.template(:test) do |composer, settings|
9
+ WhirledPeas.component(composer, settings, :list_with_active) do |component|
10
+ component.items = ITEMS
11
+ component.active_index = ITEMS.length / 2
12
+ component.viewport_size = 10
13
+ component.active_color = :gray
14
+ component.active_bg_color = :bright_white
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ [?25l                        ┏━━━━━━━━━━┓┃ ┃┃ ▄▄▄▄┃┗━━━━━━━━━━┛QRSTUVWXYZ[?25h
@@ -0,0 +1,16 @@
1
+ require 'whirled_peas'
2
+ require 'whirled_peas/component/list_with_active'
3
+
4
+ class TemplateFactory
5
+ ITEMS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars
6
+
7
+ def build(*)
8
+ WhirledPeas.template(:test) do |composer, settings|
9
+ WhirledPeas.component(composer, settings, :list_with_active) do |component|
10
+ component.items = ITEMS
11
+ component.active_index = ITEMS.size - 1
12
+ component.viewport_size = 10
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ [?25l                        ┏━━━━━━━━━━┓┃ ┃┃ ▗▄▄▄▖ ┃┗━━━━━━━━━━┛HIJKLMNOPQ[?25h
@@ -0,0 +1,16 @@
1
+ require 'whirled_peas'
2
+ require 'whirled_peas/component/list_with_active'
3
+
4
+ class TemplateFactory
5
+ ITEMS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars
6
+
7
+ def build(*)
8
+ WhirledPeas.template(:test) do |composer, settings|
9
+ WhirledPeas.component(composer, settings, :list_with_active) do |component|
10
+ component.items = ITEMS
11
+ component.active_index = ITEMS.length / 2
12
+ component.viewport_size = 10
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ [?25l                        ┏━━━━━━━━━━┓┃ ┃┃▄▄▄▖ ┃┗━━━━━━━━━━┛ABCDEFGHIJ[?25h
@@ -0,0 +1,16 @@
1
+ require 'whirled_peas'
2
+ require 'whirled_peas/component/list_with_active'
3
+
4
+ class TemplateFactory
5
+ ITEMS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.chars
6
+
7
+ def build(*)
8
+ WhirledPeas.template(:test) do |composer, settings|
9
+ WhirledPeas.component(composer, settings, :list_with_active) do |component|
10
+ component.items = ITEMS
11
+ component.active_index = 0
12
+ component.viewport_size = 10
13
+ end
14
+ end
15
+ end
16
+ end