whirled_peas 0.4.0 → 0.7.1

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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +38 -0
  4. data/README.md +450 -103
  5. data/Rakefile +28 -3
  6. data/examples/intro.rb +52 -0
  7. data/examples/scrolling.rb +53 -0
  8. data/lib/whirled_peas.rb +4 -8
  9. data/lib/whirled_peas/command_line.rb +44 -55
  10. data/lib/whirled_peas/errors.rb +2 -0
  11. data/lib/whirled_peas/frame.rb +0 -1
  12. data/lib/whirled_peas/frame/consumer.rb +30 -0
  13. data/lib/whirled_peas/frame/debug_consumer.rb +30 -0
  14. data/lib/whirled_peas/frame/event_loop.rb +28 -29
  15. data/lib/whirled_peas/frame/producer.rb +11 -5
  16. data/lib/whirled_peas/graphics.rb +19 -0
  17. data/lib/whirled_peas/graphics/box_painter.rb +101 -0
  18. data/lib/whirled_peas/graphics/canvas.rb +118 -0
  19. data/lib/whirled_peas/graphics/composer.rb +80 -0
  20. data/lib/whirled_peas/graphics/container_coords.rb +72 -0
  21. data/lib/whirled_peas/graphics/container_dimensions.rb +93 -0
  22. data/lib/whirled_peas/graphics/container_painter.rb +272 -0
  23. data/lib/whirled_peas/graphics/debugger.rb +52 -0
  24. data/lib/whirled_peas/graphics/grid_painter.rb +69 -0
  25. data/lib/whirled_peas/graphics/mock_screen.rb +26 -0
  26. data/lib/whirled_peas/graphics/painter.rb +23 -0
  27. data/lib/whirled_peas/graphics/renderer.rb +26 -0
  28. data/lib/whirled_peas/graphics/screen.rb +70 -0
  29. data/lib/whirled_peas/graphics/text_dimensions.rb +15 -0
  30. data/lib/whirled_peas/graphics/text_painter.rb +40 -0
  31. data/lib/whirled_peas/settings.rb +5 -0
  32. data/lib/whirled_peas/settings/alignment.rb +24 -0
  33. data/lib/whirled_peas/settings/bg_color.rb +24 -0
  34. data/lib/whirled_peas/settings/border.rb +101 -0
  35. data/lib/whirled_peas/settings/box_settings.rb +8 -0
  36. data/lib/whirled_peas/settings/color.rb +68 -0
  37. data/lib/whirled_peas/settings/container_settings.rb +223 -0
  38. data/lib/whirled_peas/settings/debugger.rb +96 -0
  39. data/lib/whirled_peas/settings/display_flow.rb +27 -0
  40. data/lib/whirled_peas/settings/element_settings.rb +61 -0
  41. data/lib/whirled_peas/settings/grid_settings.rb +19 -0
  42. data/lib/whirled_peas/settings/margin.rb +8 -0
  43. data/lib/whirled_peas/settings/padding.rb +8 -0
  44. data/lib/whirled_peas/settings/position.rb +15 -0
  45. data/lib/whirled_peas/settings/scrollbar.rb +15 -0
  46. data/lib/whirled_peas/settings/sizing.rb +19 -0
  47. data/lib/whirled_peas/settings/spacing.rb +58 -0
  48. data/lib/whirled_peas/settings/text_color.rb +21 -0
  49. data/lib/whirled_peas/settings/text_settings.rb +15 -0
  50. data/lib/whirled_peas/settings/vert_alignment.rb +24 -0
  51. data/lib/whirled_peas/utils/ansi.rb +6 -56
  52. data/lib/whirled_peas/utils/formatted_string.rb +64 -0
  53. data/lib/whirled_peas/utils/title_font.rb +1 -1
  54. data/lib/whirled_peas/version.rb +1 -1
  55. data/screen_test/elements/box.frame +1 -0
  56. data/screen_test/elements/box.rb +20 -0
  57. data/screen_test/elements/grid.frame +1 -0
  58. data/screen_test/elements/grid.rb +13 -0
  59. data/screen_test/elements/screen_overflow_x.frame +1 -0
  60. data/screen_test/elements/screen_overflow_x.rb +9 -0
  61. data/screen_test/elements/screen_overflow_y.frame +1 -0
  62. data/screen_test/elements/screen_overflow_y.rb +9 -0
  63. data/screen_test/elements/text.frame +1 -0
  64. data/screen_test/elements/text.rb +9 -0
  65. data/screen_test/elements/text_multiline.frame +1 -0
  66. data/screen_test/elements/text_multiline.rb +9 -0
  67. data/screen_test/settings/align/box_around.frame +1 -0
  68. data/screen_test/settings/align/box_around.rb +16 -0
  69. data/screen_test/settings/align/box_between.frame +1 -0
  70. data/screen_test/settings/align/box_between.rb +16 -0
  71. data/screen_test/settings/align/box_center.frame +1 -0
  72. data/screen_test/settings/align/box_center.rb +21 -0
  73. data/screen_test/settings/align/box_default.frame +1 -0
  74. data/screen_test/settings/align/box_default.rb +20 -0
  75. data/screen_test/settings/align/box_evenly.frame +1 -0
  76. data/screen_test/settings/align/box_evenly.rb +16 -0
  77. data/screen_test/settings/align/box_left.frame +1 -0
  78. data/screen_test/settings/align/box_left.rb +21 -0
  79. data/screen_test/settings/align/box_right.frame +1 -0
  80. data/screen_test/settings/align/box_right.rb +21 -0
  81. data/screen_test/settings/align/children_center.frame +1 -0
  82. data/screen_test/settings/align/children_center.rb +15 -0
  83. data/screen_test/settings/align/children_left.frame +1 -0
  84. data/screen_test/settings/align/children_left.rb +15 -0
  85. data/screen_test/settings/align/children_right.frame +1 -0
  86. data/screen_test/settings/align/children_right.rb +15 -0
  87. data/screen_test/settings/align/grid_center.frame +1 -0
  88. data/screen_test/settings/align/grid_center.rb +18 -0
  89. data/screen_test/settings/align/grid_default.frame +1 -0
  90. data/screen_test/settings/align/grid_default.rb +17 -0
  91. data/screen_test/settings/align/grid_left.frame +1 -0
  92. data/screen_test/settings/align/grid_left.rb +18 -0
  93. data/screen_test/settings/align/grid_right.frame +1 -0
  94. data/screen_test/settings/align/grid_right.rb +18 -0
  95. data/screen_test/settings/ansi/bold.frame +1 -0
  96. data/screen_test/settings/ansi/bold.rb +14 -0
  97. data/screen_test/settings/ansi/color.frame +1 -0
  98. data/screen_test/settings/ansi/color.rb +37 -0
  99. data/screen_test/settings/ansi/underline.frame +1 -0
  100. data/screen_test/settings/ansi/underline.rb +14 -0
  101. data/screen_test/settings/border.frame +1 -0
  102. data/screen_test/settings/border.rb +13 -0
  103. data/screen_test/settings/flow/box_b2t.frame +1 -0
  104. data/screen_test/settings/flow/box_b2t.rb +26 -0
  105. data/screen_test/settings/flow/box_l2r.frame +1 -0
  106. data/screen_test/settings/flow/box_l2r.rb +26 -0
  107. data/screen_test/settings/flow/box_r2l.frame +1 -0
  108. data/screen_test/settings/flow/box_r2l.rb +26 -0
  109. data/screen_test/settings/flow/box_t2b.frame +1 -0
  110. data/screen_test/settings/flow/box_t2b.rb +26 -0
  111. data/screen_test/settings/flow/grid_b2t.frame +1 -0
  112. data/screen_test/settings/flow/grid_b2t.rb +14 -0
  113. data/screen_test/settings/flow/grid_l2r.frame +1 -0
  114. data/screen_test/settings/flow/grid_l2r.rb +14 -0
  115. data/screen_test/settings/flow/grid_r2l.frame +1 -0
  116. data/screen_test/settings/flow/grid_r2l.rb +14 -0
  117. data/screen_test/settings/flow/grid_t2b.frame +1 -0
  118. data/screen_test/settings/flow/grid_t2b.rb +14 -0
  119. data/screen_test/settings/height/box.frame +1 -0
  120. data/screen_test/settings/height/box.rb +13 -0
  121. data/screen_test/settings/height/box_border_sizing.frame +1 -0
  122. data/screen_test/settings/height/box_border_sizing.rb +15 -0
  123. data/screen_test/settings/height/grid.frame +1 -0
  124. data/screen_test/settings/height/grid.rb +14 -0
  125. data/screen_test/settings/height/overflow_box.frame +1 -0
  126. data/screen_test/settings/height/overflow_box.rb +13 -0
  127. data/screen_test/settings/height/overflow_box_l2r.frame +1 -0
  128. data/screen_test/settings/height/overflow_box_l2r.rb +17 -0
  129. data/screen_test/settings/height/overflow_box_t2b.frame +1 -0
  130. data/screen_test/settings/height/overflow_box_t2b.rb +16 -0
  131. data/screen_test/settings/height/overflow_grid.frame +1 -0
  132. data/screen_test/settings/height/overflow_grid.rb +16 -0
  133. data/screen_test/settings/margin.frame +1 -0
  134. data/screen_test/settings/margin.rb +16 -0
  135. data/screen_test/settings/padding.frame +1 -0
  136. data/screen_test/settings/padding.rb +13 -0
  137. data/screen_test/settings/position/box_left.frame +1 -0
  138. data/screen_test/settings/position/box_left.rb +17 -0
  139. data/screen_test/settings/position/box_left_negative.frame +1 -0
  140. data/screen_test/settings/position/box_left_negative.rb +17 -0
  141. data/screen_test/settings/position/box_top.frame +1 -0
  142. data/screen_test/settings/position/box_top.rb +17 -0
  143. data/screen_test/settings/position/box_top_negative.frame +1 -0
  144. data/screen_test/settings/position/box_top_negative.rb +17 -0
  145. data/screen_test/settings/position/grid_left.frame +1 -0
  146. data/screen_test/settings/position/grid_left.rb +18 -0
  147. data/screen_test/settings/position/grid_left_negative.frame +1 -0
  148. data/screen_test/settings/position/grid_left_negative.rb +18 -0
  149. data/screen_test/settings/position/grid_top.frame +1 -0
  150. data/screen_test/settings/position/grid_top.rb +18 -0
  151. data/screen_test/settings/position/grid_top_negative.frame +1 -0
  152. data/screen_test/settings/position/grid_top_negative.rb +18 -0
  153. data/screen_test/settings/scroll/horiz_box.frame +1 -0
  154. data/screen_test/settings/scroll/horiz_box.rb +17 -0
  155. data/screen_test/settings/scroll/horiz_box_align_center.rb +18 -0
  156. data/screen_test/settings/scroll/horiz_box_align_right.rb +18 -0
  157. data/screen_test/settings/scroll/vert_box.frame +1 -0
  158. data/screen_test/settings/scroll/vert_box.rb +20 -0
  159. data/screen_test/settings/title_font.frame +1 -0
  160. data/screen_test/settings/title_font.rb +12 -0
  161. data/screen_test/settings/valign/box_around.frame +1 -0
  162. data/screen_test/settings/valign/box_around.rb +17 -0
  163. data/screen_test/settings/valign/box_between.frame +1 -0
  164. data/screen_test/settings/valign/box_between.rb +17 -0
  165. data/screen_test/settings/valign/box_bottom.frame +1 -0
  166. data/screen_test/settings/valign/box_bottom.rb +17 -0
  167. data/screen_test/settings/valign/box_default.frame +1 -0
  168. data/screen_test/settings/valign/box_default.rb +16 -0
  169. data/screen_test/settings/valign/box_evenly.frame +1 -0
  170. data/screen_test/settings/valign/box_evenly.rb +17 -0
  171. data/screen_test/settings/valign/box_middle.frame +1 -0
  172. data/screen_test/settings/valign/box_middle.rb +17 -0
  173. data/screen_test/settings/valign/box_top.frame +1 -0
  174. data/screen_test/settings/valign/box_top.rb +17 -0
  175. data/screen_test/settings/valign/grid_bottom.frame +1 -0
  176. data/screen_test/settings/valign/grid_bottom.rb +15 -0
  177. data/screen_test/settings/valign/grid_default.frame +1 -0
  178. data/screen_test/settings/valign/grid_default.rb +14 -0
  179. data/screen_test/settings/valign/grid_middle.frame +1 -0
  180. data/screen_test/settings/valign/grid_middle.rb +15 -0
  181. data/screen_test/settings/valign/grid_top.frame +1 -0
  182. data/screen_test/settings/valign/grid_top.rb +15 -0
  183. data/screen_test/settings/width/box_border_sizing.frame +1 -0
  184. data/screen_test/settings/width/box_border_sizing.rb +15 -0
  185. data/screen_test/settings/width/box_content.frame +1 -0
  186. data/screen_test/settings/width/box_content.rb +15 -0
  187. data/screen_test/settings/width/box_default.frame +1 -0
  188. data/screen_test/settings/width/box_default.rb +14 -0
  189. data/screen_test/settings/width/grid.frame +1 -0
  190. data/screen_test/settings/width/grid.rb +14 -0
  191. data/screen_test/settings/width/overflow_align_center.frame +1 -0
  192. data/screen_test/settings/width/overflow_align_center.rb +14 -0
  193. data/screen_test/settings/width/overflow_align_right.frame +1 -0
  194. data/screen_test/settings/width/overflow_align_right.rb +14 -0
  195. data/screen_test/settings/width/overflow_box.frame +1 -0
  196. data/screen_test/settings/width/overflow_box.rb +13 -0
  197. data/screen_test/settings/width/overflow_box_l2r.frame +1 -0
  198. data/screen_test/settings/width/overflow_box_l2r.rb +16 -0
  199. data/screen_test/settings/width/overflow_box_t2b.frame +1 -0
  200. data/screen_test/settings/width/overflow_box_t2b.rb +17 -0
  201. data/screen_test/settings/width/overflow_grid.frame +1 -0
  202. data/screen_test/settings/width/overflow_grid.rb +14 -0
  203. data/tools/whirled_peas/tools/screen_tester.rb +233 -0
  204. metadata +191 -12
  205. data/bin/title_fonts +0 -6
  206. data/lib/whirled_peas/frame/print_consumer.rb +0 -33
  207. data/lib/whirled_peas/template.rb +0 -5
  208. data/lib/whirled_peas/template/element.rb +0 -230
  209. data/lib/whirled_peas/template/settings.rb +0 -530
  210. data/lib/whirled_peas/ui.rb +0 -5
  211. data/lib/whirled_peas/ui/canvas.rb +0 -68
  212. data/lib/whirled_peas/ui/painter.rb +0 -287
  213. data/lib/whirled_peas/ui/screen.rb +0 -63
  214. data/lib/whirled_peas/utils/color.rb +0 -101
@@ -0,0 +1,96 @@
1
+ require_relative 'border'
2
+ require_relative 'container_settings'
3
+ require_relative 'margin'
4
+ require_relative 'padding'
5
+ require_relative 'position'
6
+ require_relative 'scrollbar'
7
+
8
+ module WhirledPeas
9
+ module Settings
10
+ class Debugger
11
+ def initialize(settings)
12
+ @settings = settings
13
+ end
14
+
15
+ def debug(indent='')
16
+ values = non_default_values(indent + ' ')
17
+ details = values.length > 0 ? values.join("\n") : "#{indent} <default>"
18
+ "#{indent}#{settings.class}\n#{details}"
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :settings
24
+
25
+ def non_default_values(indent)
26
+ settings.instance_variables.map do |ivar, values|
27
+ value = settings.instance_variable_get(ivar)
28
+ next if value.nil?
29
+ printable_value = debug_value(value)
30
+ "#{indent}#{ivar.to_s.sub(/^@?_?/, '')}: #{printable_value}" unless printable_value.nil?
31
+ end.compact
32
+ end
33
+
34
+ def debug_value(value)
35
+ return if value.nil?
36
+ case value
37
+ when Position
38
+ position_value(value)
39
+ when Margin
40
+ margin_value(value)
41
+ when Border
42
+ border_value(value)
43
+ when Padding
44
+ padding_value(value)
45
+ when Scrollbar
46
+ scrollbar_value(value)
47
+ else
48
+ value.inspect
49
+ end
50
+ end
51
+
52
+ def non_defaults(object, default_object, keys)
53
+ values = keys.map.with_object({}) do |key, hash|
54
+ unless object.send(key) == default_object.send(key)
55
+ hash[key] = object.send(key)
56
+ end
57
+ end
58
+ values.keys.map { |k| "#{k}: #{values[k]}"}.join(', ')
59
+ end
60
+
61
+ def position_value(position)
62
+ values = non_defaults(position, Position.new, %i[left top])
63
+ return if values == ''
64
+ "Position(#{values})"
65
+ end
66
+
67
+ def margin_value(margin)
68
+ values = non_defaults(margin, Margin.new, %i[left top right bottom])
69
+ return if values == ''
70
+ "Margin(#{values})"
71
+ end
72
+
73
+ def border_value(border)
74
+ values = non_defaults(
75
+ border,
76
+ Border.new,
77
+ %i[left? top? right? bottom? inner_horiz? inner_vert? style color]
78
+ )
79
+ return if values == ''
80
+ "Border(#{values})"
81
+ end
82
+
83
+ def padding_value(padding)
84
+ values = non_defaults(padding, Padding.new, %i[left top right bottom])
85
+ return if values == ''
86
+ "Padding(#{values})"
87
+ end
88
+
89
+ def scrollbar_value(scrollbar)
90
+ values = non_defaults(scrollbar, Scrollbar.new, %i[horiz? vert?])
91
+ return if values == ''
92
+ "Scrollbar(#{values})"
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,27 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ module DisplayFlow
4
+ LEFT_TO_RIGHT = :l2r
5
+ RIGHT_TO_LEFT = :r2l
6
+ TOP_TO_BOTTOM = :t2b
7
+ BOTTOM_TO_TOP = :b2t
8
+
9
+ DEFAULT = LEFT_TO_RIGHT
10
+
11
+ VALID = [
12
+ DisplayFlow::LEFT_TO_RIGHT,
13
+ DisplayFlow::RIGHT_TO_LEFT,
14
+ DisplayFlow::TOP_TO_BOTTOM,
15
+ DisplayFlow::BOTTOM_TO_TOP
16
+ ]
17
+ private_constant :VALID
18
+
19
+ def self.validate!(flow)
20
+ return if flow.nil?
21
+ return flow if VALID.include?(flow)
22
+ raise ArgumentError, "Unsupported display flow: #{flow.inspect}"
23
+ end
24
+ end
25
+ private_constant :DisplayFlow
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ require 'json'
2
+
3
+ require_relative 'alignment'
4
+ require_relative 'bg_color'
5
+ require_relative 'text_color'
6
+
7
+ module WhirledPeas
8
+ module Settings
9
+ class ElementSettings
10
+ def self.inherit(parent)
11
+ child = self.new
12
+ child.inherit(parent)
13
+ child
14
+ end
15
+
16
+ def bg_color
17
+ @_bg_color || BgColor::DEFAULT
18
+ end
19
+
20
+ def bg_color=(color)
21
+ @_bg_color = BgColor.validate!(color)
22
+ end
23
+
24
+ def bold?
25
+ @_bold || false
26
+ end
27
+
28
+ def bold=(val)
29
+ @_bold = val
30
+ end
31
+
32
+ def color
33
+ @_color || TextColor::DEFAULT
34
+ end
35
+
36
+ def color=(color)
37
+ @_color = TextColor.validate!(color)
38
+ end
39
+
40
+ def underline?
41
+ @_underline || false
42
+ end
43
+
44
+ def underline=(val)
45
+ @_underline = val
46
+ end
47
+
48
+ def inherit(parent)
49
+ @_bg_color = parent._bg_color
50
+ @_bold = parent._bold
51
+ @_color = parent._color
52
+ @_underline = parent._underline
53
+ end
54
+
55
+ protected
56
+
57
+ attr_accessor :_bg_color, :_bold, :_color, :_underline
58
+ end
59
+ private_constant :ElementSettings
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ require 'whirled_peas/utils/title_font'
2
+
3
+ require_relative 'container_settings'
4
+
5
+ module WhirledPeas
6
+ module Settings
7
+ class GridSettings < ContainerSettings
8
+ attr_accessor :num_cols
9
+
10
+ def set_scrollbar(*)
11
+ raise NotImplementedError, 'Grids do not support scrollbars'
12
+ end
13
+
14
+ def sizing=(*)
15
+ raise NotImplementedError, 'Grids only support the default sizing model'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'spacing'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ class Margin < Spacing
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require_relative 'spacing'
2
+
3
+ module WhirledPeas
4
+ module Settings
5
+ class Padding < Spacing
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ class Position
4
+ attr_writer :left, :top
5
+
6
+ def left
7
+ @left || 0
8
+ end
9
+
10
+ def top
11
+ @top || 0
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ class Scrollbar
4
+ attr_writer :horiz, :vert
5
+
6
+ def horiz?
7
+ @horiz == true
8
+ end
9
+
10
+ def vert?
11
+ @vert == true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ class Sizing
4
+ CONTENT = :content
5
+ BORDER = :border
6
+
7
+ DEFAULT = CONTENT
8
+
9
+ VALID = [CONTENT, BORDER]
10
+ private_constant :VALID
11
+
12
+ def self.validate!(sizing)
13
+ return if sizing.nil?
14
+ return sizing if VALID.include?(sizing)
15
+ raise ArgumentError, "Unsupported sizing model: #{sizing.inspect}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ class Spacing
4
+ attr_writer :left, :top, :right, :bottom
5
+
6
+ def left=(value)
7
+ @left = validate!(value)
8
+ end
9
+
10
+ def left
11
+ @left || 0
12
+ end
13
+
14
+ def top=(value)
15
+ @top = validate!(value)
16
+ end
17
+
18
+ def top
19
+ @top || 0
20
+ end
21
+
22
+ def right=(value)
23
+ @right = validate!(value)
24
+ end
25
+
26
+ def right
27
+ @right || 0
28
+ end
29
+
30
+ def bottom=(value)
31
+ @bottom = validate!(value)
32
+ end
33
+
34
+ def bottom
35
+ @bottom || 0
36
+ end
37
+
38
+ def horiz=(value)
39
+ self.left = self.right = value
40
+ end
41
+
42
+ def vert=(value)
43
+ self.top = self.bottom = value
44
+ end
45
+
46
+ private
47
+
48
+ def validate!(value)
49
+ if value && value < 0
50
+ raise ArgumentError, "Negative values for #{self.class.name.split('::').last.downcase} are not allowed"
51
+ else
52
+ value
53
+ end
54
+ end
55
+ end
56
+ private_constant :Spacing
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ require 'whirled_peas/utils/ansi'
2
+
3
+ require_relative 'color'
4
+
5
+ module WhirledPeas
6
+ module Settings
7
+ class TextColor < Color
8
+ BLACK = new(Utils::Ansi::BLACK)
9
+ RED = new(Utils::Ansi::RED)
10
+ GREEN = new(Utils::Ansi::GREEN)
11
+ YELLOW = new(Utils::Ansi::YELLOW)
12
+ BLUE = new(Utils::Ansi::BLUE)
13
+ MAGENTA = new(Utils::Ansi::MAGENTA)
14
+ CYAN = new(Utils::Ansi::CYAN)
15
+ WHITE = new(Utils::Ansi::WHITE)
16
+ GRAY = BLACK.bright
17
+
18
+ DEFAULT = nil # Use system defined default
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'whirled_peas/utils/title_font'
2
+
3
+ require_relative 'element_settings'
4
+
5
+ module WhirledPeas
6
+ module Settings
7
+ class TextSettings < ElementSettings
8
+ attr_reader :title_font
9
+
10
+ def title_font=(font)
11
+ @title_font = Utils::TitleFont.validate!(font)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module WhirledPeas
2
+ module Settings
3
+ module VertAlignment
4
+ TOP = :top
5
+ MIDDLE = :middle
6
+ BOTTOM = :bottom
7
+ BETWEEN = :between
8
+ AROUND = :around
9
+ EVENLY = :evenly
10
+
11
+ DEFAULT = TOP
12
+
13
+ VALID = [TOP, MIDDLE, BOTTOM, BETWEEN, AROUND, EVENLY]
14
+ private_constant :VALID
15
+
16
+ def self.validate!(valign)
17
+ return if valign.nil?
18
+ return valign if VALID.include?(valign)
19
+ raise ArgumentError, "Unsupported vertical alignment: #{valign.inspect}"
20
+ end
21
+ end
22
+ private_constant :VertAlignment
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module WhirledPeas
2
- module UI
2
+ module Utils
3
3
  # Helper module for working with ANSI escape codes. The most useful ANSI escape codes
4
4
  # relate to text formatting.
5
5
  #
@@ -7,6 +7,9 @@ module WhirledPeas
7
7
  module Ansi
8
8
  ESC = "\033"
9
9
 
10
+ END_FORMATTING = 0
11
+ private_constant :END_FORMATTING
12
+
10
13
  # Text formatting constants
11
14
  BOLD = 1
12
15
  UNDERLINE = 4
@@ -21,8 +24,8 @@ module WhirledPeas
21
24
  CYAN = 36
22
25
  WHITE = 37
23
26
 
24
- END_FORMATTING = 0
25
- private_constant :END_FORMATTING
27
+ # Bright colors are offset by this much from their standard versions
28
+ BRIGHT_OFFSET = 60
26
29
 
27
30
  class << self
28
31
  def cursor_pos(top: 0, left: 0)
@@ -37,63 +40,10 @@ module WhirledPeas
37
40
  "#{ESC}[J"
38
41
  end
39
42
 
40
- # Format the string with the ANSI escapes codes for the given integer codes
41
- #
42
- # @param str [String] the string to format
43
- # @param codes [Array<Integer>] the integer part of the ANSI escape code (see
44
- # constants in this module for codes and meanings)
45
- def format(str, codes)
46
- if str.empty? || codes.length == 0
47
- str
48
- else
49
- start_formatting = codes.map(&method(:esc_seq)).join
50
- "#{start_formatting}#{str}#{esc_seq(END_FORMATTING)}"
51
- end
52
- end
53
-
54
43
  def clear
55
44
  esc_seq(END_FORMATTING)
56
45
  end
57
46
 
58
- # If the string has unclosed formatting, add the end formatting characters to
59
- # the end of the string
60
- def close_formatting(str)
61
- codes = str.scan(/#{ESC}\[(\d+)m/)
62
- if codes.length > 0 && codes.last[0] != END_FORMATTING.to_s
63
- "#{str}#{esc_seq(END_FORMATTING)}"
64
- else
65
- str
66
- end
67
- end
68
-
69
- # Return a substring of the input string that preservse the formatting
70
- #
71
- # @param str [String] the (possibly formatted) string
72
- # @param first_visible_character [Integer] the index of the first character to
73
- # include in the substring (ignoring all hidden formatting characters)
74
- # @param num_visible_chars [Integer] the maximum number of visible characters to
75
- # include in the substring (ignoring all hidden formatting characters)
76
- def substring(str, first_visible_character, num_visible_chars)
77
- substr = ''
78
- is_visible = true
79
- visible_index = 0
80
- substr_visible_len = 0
81
- str.chars.each do |char|
82
- in_substring = (visible_index >= first_visible_character)
83
- is_visible = false if is_visible && char == ESC
84
- visible_index += 1 if is_visible
85
- if !is_visible || in_substring
86
- substr += char
87
- substr_visible_len += 1 if is_visible
88
- end
89
- is_visible = true if !is_visible && char == 'm'
90
- break if substr_visible_len == num_visible_chars
91
- end
92
- close_formatting(substr)
93
- end
94
-
95
- private
96
-
97
47
  def esc_seq(code)
98
48
  "#{ESC}[#{code}m"
99
49
  end