vedeu 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vedeu.rb +1 -1
- data/lib/vedeu/all.rb +2 -0
- data/lib/vedeu/buffers/buffer.rb +0 -11
- data/lib/vedeu/configuration/api.rb +4 -6
- data/lib/vedeu/configuration/cli.rb +1 -3
- data/lib/vedeu/configuration/configuration.rb +15 -0
- data/lib/vedeu/cursor/cursor.rb +2 -9
- data/lib/vedeu/cursor/move_cursor.rb +7 -9
- data/lib/vedeu/cursor/toggle_cursor.rb +2 -2
- data/lib/vedeu/debug.rb +3 -0
- data/lib/vedeu/distributed/test_application.rb +4 -8
- data/lib/vedeu/dsl/components/keymap.rb +1 -3
- data/lib/vedeu/dsl/composition.rb +2 -2
- data/lib/vedeu/dsl/interface.rb +2 -2
- data/lib/vedeu/dsl/shared/text.rb +2 -2
- data/lib/vedeu/events/event.rb +1 -1
- data/lib/vedeu/geometry/all.rb +10 -0
- data/lib/vedeu/{support → geometry}/bounding_area.rb +1 -0
- data/lib/vedeu/{support → geometry}/content_geometry.rb +0 -7
- data/lib/vedeu/{support → geometry}/coordinate.rb +0 -14
- data/lib/vedeu/{support → geometry}/grid.rb +0 -0
- data/lib/vedeu/{support → geometry}/limit.rb +0 -0
- data/lib/vedeu/{support → geometry}/position.rb +3 -5
- data/lib/vedeu/{support → geometry}/position_validator.rb +2 -0
- data/lib/vedeu/input/input.rb +1 -1
- data/lib/vedeu/input/key.rb +0 -13
- data/lib/vedeu/input/keymap.rb +1 -1
- data/lib/vedeu/models/focus.rb +2 -2
- data/lib/vedeu/models/geometry.rb +4 -51
- data/lib/vedeu/models/menu.rb +1 -1
- data/lib/vedeu/models/model.rb +1 -1
- data/lib/vedeu/models/view/char.rb +2 -9
- data/lib/vedeu/models/view/composition.rb +3 -10
- data/lib/vedeu/models/view/interface.rb +5 -13
- data/lib/vedeu/models/view/line.rb +3 -10
- data/lib/vedeu/models/view/stream.rb +18 -11
- data/lib/vedeu/output/background.rb +6 -21
- data/lib/vedeu/output/border.rb +26 -17
- data/lib/vedeu/output/colour.rb +1 -1
- data/lib/vedeu/output/foreground.rb +6 -21
- data/lib/vedeu/output/html_renderer.rb +3 -9
- data/lib/vedeu/output/output.rb +38 -11
- data/lib/vedeu/output/style.rb +1 -1
- data/lib/vedeu/output/translator.rb +45 -15
- data/lib/vedeu/output/viewport.rb +1 -1
- data/lib/vedeu/output/virtual_buffer.rb +2 -2
- data/lib/vedeu/output/wordwrap.rb +1 -1
- data/lib/vedeu/repositories/all.rb +9 -9
- data/lib/vedeu/repositories/repository.rb +0 -7
- data/lib/vedeu/support/all.rb +1 -7
- data/lib/vedeu/support/esc.rb +33 -11
- data/lib/vedeu/support/template.rb +39 -0
- data/lib/vedeu/support/terminal.rb +3 -3
- data/lib/vedeu/support/text.rb +1 -1
- data/lib/vedeu/support/trace.rb +4 -4
- data/lib/vedeu/support/visible.rb +2 -7
- data/test/lib/vedeu/buffers/buffer_test.rb +0 -6
- data/test/lib/vedeu/cursor/cursor_test.rb +0 -6
- data/test/lib/vedeu/{support → geometry}/bounding_area_test.rb +0 -0
- data/test/lib/vedeu/{support → geometry}/content_geometry_test.rb +0 -6
- data/test/lib/vedeu/{support → geometry}/coordinate_test.rb +0 -8
- data/test/lib/vedeu/{support → geometry}/grid_test.rb +0 -0
- data/test/lib/vedeu/{support → geometry}/limit_test.rb +0 -0
- data/test/lib/vedeu/{support → geometry}/position_test.rb +8 -6
- data/test/lib/vedeu/{support → geometry}/position_validator_test.rb +0 -0
- data/test/lib/vedeu/input/key_test.rb +0 -12
- data/test/lib/vedeu/models/geometry_test.rb +0 -47
- data/test/lib/vedeu/models/view/char_test.rb +5 -9
- data/test/lib/vedeu/models/view/composition_test.rb +2 -8
- data/test/lib/vedeu/models/view/interface_test.rb +2 -8
- data/test/lib/vedeu/models/view/line_test.rb +0 -6
- data/test/lib/vedeu/models/view/stream_test.rb +0 -6
- data/test/lib/vedeu/output/border_test.rb +2 -2
- data/test/lib/vedeu/output/html_renderer_test.rb +0 -1
- data/test/lib/vedeu/output/output_test.rb +39 -0
- data/test/lib/vedeu/repositories/repository_test.rb +0 -6
- data/test/lib/vedeu/support/template_test.rb +24 -0
- data/test/lib/vedeu/support/visible_test.rb +0 -6
- data/test/support/helpers/model_test_class.rb +1 -1
- data/vedeu.gemspec +1 -1
- metadata +27 -23
data/lib/vedeu/input/keymap.rb
CHANGED
@@ -22,7 +22,7 @@ module Vedeu
|
|
22
22
|
# @option attributes repository [Vedeu::Repository] This model's storage.
|
23
23
|
# @return [Vedeu::Keymap]
|
24
24
|
def initialize(attributes = {})
|
25
|
-
@attributes = defaults.merge(attributes)
|
25
|
+
@attributes = defaults.merge!(attributes)
|
26
26
|
|
27
27
|
@name = @attributes[:name]
|
28
28
|
@keys = @attributes[:keys]
|
data/lib/vedeu/models/focus.rb
CHANGED
@@ -128,7 +128,7 @@ module Vedeu
|
|
128
128
|
#
|
129
129
|
# @return [Array|Hash|Set]
|
130
130
|
def reset
|
131
|
-
@
|
131
|
+
@storage = in_memory
|
132
132
|
end
|
133
133
|
|
134
134
|
private
|
@@ -151,7 +151,7 @@ module Vedeu
|
|
151
151
|
#
|
152
152
|
# @return [Array]
|
153
153
|
def storage
|
154
|
-
@
|
154
|
+
@storage ||= in_memory
|
155
155
|
end
|
156
156
|
|
157
157
|
# Returns an empty collection ready for the storing of interface names.
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'vedeu/dsl/components/geometry'
|
2
2
|
require 'vedeu/models/model'
|
3
|
-
|
3
|
+
|
4
|
+
require 'vedeu/geometry/limit'
|
5
|
+
require 'vedeu/geometry/position'
|
4
6
|
require 'vedeu/support/terminal'
|
5
7
|
|
6
8
|
module Vedeu
|
@@ -48,7 +50,7 @@ module Vedeu
|
|
48
50
|
# @option attributes yn [Fixnum]
|
49
51
|
# @return [Geometry]
|
50
52
|
def initialize(attributes = {})
|
51
|
-
@attributes = defaults.merge(attributes)
|
53
|
+
@attributes = defaults.merge!(attributes)
|
52
54
|
|
53
55
|
@centred = @attributes[:centred]
|
54
56
|
@height = @attributes[:height]
|
@@ -61,21 +63,6 @@ module Vedeu
|
|
61
63
|
@repository = Vedeu.geometries
|
62
64
|
end
|
63
65
|
|
64
|
-
# Returns log friendly output.
|
65
|
-
#
|
66
|
-
# @note
|
67
|
-
# The attribute format is (specified/calculated).
|
68
|
-
#
|
69
|
-
# @return [String]
|
70
|
-
def inspect
|
71
|
-
"<#{self.class.name} (height:(#{@height}/#{height}) " \
|
72
|
-
"width:(#{@width}/#{width}) " \
|
73
|
-
"top:#{top} " \
|
74
|
-
"bottom:#{bottom} " \
|
75
|
-
"left:#{left} " \
|
76
|
-
"right:#{right})>"
|
77
|
-
end
|
78
|
-
|
79
66
|
# Returns the row/line start position for the interface.
|
80
67
|
#
|
81
68
|
# @return [Fixnum]
|
@@ -147,16 +134,6 @@ module Vedeu
|
|
147
134
|
Vedeu::Limit.apply(y, @height, Terminal.height, Terminal.origin)
|
148
135
|
end
|
149
136
|
|
150
|
-
# Returns the position of the cursor at the top-left coordinate, relative to
|
151
|
-
# the interface's position.
|
152
|
-
#
|
153
|
-
# @param y_index [Fixnum]
|
154
|
-
# @param x_index [Fixnum]
|
155
|
-
# @return [Vedeu::Position]
|
156
|
-
def origin(y_index = 0, x_index = 0)
|
157
|
-
Vedeu::Position.new(virtual_y[y_index], virtual_x[x_index])
|
158
|
-
end
|
159
|
-
|
160
137
|
# Returns the top coordinate of the interface, a fixed or dynamic value
|
161
138
|
# depending on whether the interface is centred or not.
|
162
139
|
#
|
@@ -263,30 +240,6 @@ module Vedeu
|
|
263
240
|
|
264
241
|
private
|
265
242
|
|
266
|
-
# Provides a virtual y position within the interface's dimensions.
|
267
|
-
#
|
268
|
-
# @example
|
269
|
-
# # top = 3
|
270
|
-
# # bottom = 6
|
271
|
-
# # virtual_y # => [3, 4, 5]
|
272
|
-
#
|
273
|
-
# @return [Array]
|
274
|
-
def virtual_y
|
275
|
-
(top...bottom).to_a
|
276
|
-
end
|
277
|
-
|
278
|
-
# Provides a virtual x position within the interface's dimensions.
|
279
|
-
#
|
280
|
-
# @example
|
281
|
-
# # left = 9
|
282
|
-
# # right = 13
|
283
|
-
# # virtual_x # => [9, 10, 11, 12]
|
284
|
-
#
|
285
|
-
# @return [Array]
|
286
|
-
def virtual_x
|
287
|
-
(left...right).to_a
|
288
|
-
end
|
289
|
-
|
290
243
|
# The default values for a new instance of this class.
|
291
244
|
#
|
292
245
|
# @return [Hash]
|
data/lib/vedeu/models/menu.rb
CHANGED
@@ -64,7 +64,7 @@ module Vedeu
|
|
64
64
|
# @option attributes selected [Fixnum|NilClass]
|
65
65
|
# @return [Menu]
|
66
66
|
def initialize(attributes = {})
|
67
|
-
@attributes = defaults.merge(attributes)
|
67
|
+
@attributes = defaults.merge!(attributes)
|
68
68
|
@collection = @attributes[:collection]
|
69
69
|
@current = @attributes[:current]
|
70
70
|
@name = @attributes[:name]
|
data/lib/vedeu/models/model.rb
CHANGED
@@ -22,7 +22,7 @@ module Vedeu
|
|
22
22
|
# @param block [Proc] The block passed to the build method.
|
23
23
|
# @return [Object] An instance of the model.
|
24
24
|
def build(attributes = {}, &block)
|
25
|
-
attributes = defaults.merge(attributes)
|
25
|
+
attributes = defaults.merge!(attributes)
|
26
26
|
|
27
27
|
model = new(attributes)
|
28
28
|
model.deputy(attributes[:client]).instance_eval(&block) if block_given?
|
@@ -30,23 +30,16 @@ module Vedeu
|
|
30
30
|
# @option attributes border [Boolean]
|
31
31
|
# @return [Char]
|
32
32
|
def initialize(attributes = {})
|
33
|
-
@attributes = defaults.merge(attributes)
|
33
|
+
@attributes = defaults.merge!(attributes)
|
34
34
|
|
35
35
|
@border = @attributes[:border]
|
36
|
-
@colour =
|
36
|
+
@colour = @attributes[:colour]
|
37
37
|
@parent = @attributes[:parent]
|
38
38
|
@position = Vedeu::Position.coerce(@attributes[:position])
|
39
39
|
@style = @attributes[:style]
|
40
40
|
@value = @attributes[:value]
|
41
41
|
end
|
42
42
|
|
43
|
-
# Returns log friendly output.
|
44
|
-
#
|
45
|
-
# @return [String]
|
46
|
-
def inspect
|
47
|
-
"<#{self.class.name} (value:'#{@value}')>"
|
48
|
-
end
|
49
|
-
|
50
43
|
# @param other []
|
51
44
|
# @return [Boolean]
|
52
45
|
def ==(other)
|
@@ -31,10 +31,10 @@ module Vedeu
|
|
31
31
|
# @option attributes style []
|
32
32
|
# @return [Composition]
|
33
33
|
def initialize(attributes = {})
|
34
|
-
@attributes = defaults.merge(attributes)
|
34
|
+
@attributes = defaults.merge!(attributes)
|
35
35
|
@interfaces = @attributes[:interfaces]
|
36
|
-
@colour =
|
37
|
-
@style =
|
36
|
+
@colour = @attributes[:colour]
|
37
|
+
@style = @attributes[:style]
|
38
38
|
end
|
39
39
|
|
40
40
|
# @param child [Vedeu::Interface]
|
@@ -43,13 +43,6 @@ module Vedeu
|
|
43
43
|
@interfaces = interfaces.add(child)
|
44
44
|
end
|
45
45
|
|
46
|
-
# Returns log friendly output.
|
47
|
-
#
|
48
|
-
# @return [String]
|
49
|
-
def inspect
|
50
|
-
"<#{self.class.name} (interfaces:#{interfaces.size})>"
|
51
|
-
end
|
52
|
-
|
53
46
|
# @return [Vedeu::Interfaces]
|
54
47
|
def interfaces
|
55
48
|
collection.coerce(@interfaces, self)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'vedeu/
|
1
|
+
require 'vedeu/geometry/content_geometry'
|
2
2
|
require 'vedeu/models/model'
|
3
3
|
require 'vedeu/output/presentation'
|
4
4
|
require 'vedeu/buffers/display_buffer'
|
@@ -44,8 +44,7 @@ module Vedeu
|
|
44
44
|
:bottom,
|
45
45
|
:left,
|
46
46
|
:width,
|
47
|
-
:height
|
48
|
-
:origin
|
47
|
+
:height
|
49
48
|
|
50
49
|
# Return a new instance of Interface.
|
51
50
|
#
|
@@ -59,16 +58,16 @@ module Vedeu
|
|
59
58
|
# @option attributes style [Vedeu::Style]
|
60
59
|
# @return [Vedeu::Interface]
|
61
60
|
def initialize(attributes = {})
|
62
|
-
@attributes = defaults.merge(attributes)
|
61
|
+
@attributes = defaults.merge!(attributes)
|
63
62
|
|
64
|
-
@colour =
|
63
|
+
@colour = @attributes[:colour]
|
65
64
|
@delay = @attributes[:delay]
|
66
65
|
@group = @attributes[:group]
|
67
66
|
@lines = @attributes[:lines]
|
68
67
|
@name = @attributes[:name]
|
69
68
|
@parent = @attributes[:parent]
|
70
69
|
@repository = Vedeu.interfaces
|
71
|
-
@style =
|
70
|
+
@style = @attributes[:style]
|
72
71
|
end
|
73
72
|
|
74
73
|
# @param child []
|
@@ -121,13 +120,6 @@ module Vedeu
|
|
121
120
|
Vedeu.geometries.find(name)
|
122
121
|
end
|
123
122
|
|
124
|
-
# Returns log friendly output.
|
125
|
-
#
|
126
|
-
# @return [String]
|
127
|
-
def inspect
|
128
|
-
"<#{self.class.name} (lines:#{lines.size})>"
|
129
|
-
end
|
130
|
-
|
131
123
|
# @return [Vedeu::Lines]
|
132
124
|
def lines
|
133
125
|
collection.coerce(@lines, self)
|
@@ -31,11 +31,11 @@ module Vedeu
|
|
31
31
|
# @option attributes style [Vedeu::Style]
|
32
32
|
# @return [Line]
|
33
33
|
def initialize(attributes = {})
|
34
|
-
@attributes = defaults.merge(attributes)
|
35
|
-
@colour =
|
34
|
+
@attributes = defaults.merge!(attributes)
|
35
|
+
@colour = @attributes[:colour]
|
36
36
|
@parent = @attributes[:parent]
|
37
37
|
@streams = @attributes[:streams]
|
38
|
-
@style =
|
38
|
+
@style = @attributes[:style]
|
39
39
|
end
|
40
40
|
|
41
41
|
# @param child []
|
@@ -61,13 +61,6 @@ module Vedeu
|
|
61
61
|
streams.empty?
|
62
62
|
end
|
63
63
|
|
64
|
-
# Returns log friendly output.
|
65
|
-
#
|
66
|
-
# @return [String]
|
67
|
-
def inspect
|
68
|
-
"<#{self.class.name} (streams:#{streams.size})>"
|
69
|
-
end
|
70
|
-
|
71
64
|
# Returns the size of the content in characters without formatting.
|
72
65
|
#
|
73
66
|
# @return [Fixnum]
|
@@ -34,10 +34,10 @@ module Vedeu
|
|
34
34
|
# @option attributes client [Object]
|
35
35
|
# @return [Vedeu::Stream]
|
36
36
|
def initialize(attributes = {})
|
37
|
-
@attributes = defaults.merge(attributes)
|
38
|
-
@colour =
|
37
|
+
@attributes = defaults.merge!(attributes)
|
38
|
+
@colour = @attributes[:colour]
|
39
39
|
@parent = @attributes[:parent]
|
40
|
-
@style =
|
40
|
+
@style = @attributes[:style]
|
41
41
|
@value = @attributes[:value]
|
42
42
|
end
|
43
43
|
|
@@ -57,7 +57,11 @@ module Vedeu
|
|
57
57
|
return [] if value.empty?
|
58
58
|
|
59
59
|
value.chars.map do |char|
|
60
|
-
member.new({ value:
|
60
|
+
member.new({ value: char,
|
61
|
+
parent: parent,
|
62
|
+
colour: colour,
|
63
|
+
style: style,
|
64
|
+
position: nil }).to_s
|
61
65
|
end
|
62
66
|
end
|
63
67
|
|
@@ -68,13 +72,6 @@ module Vedeu
|
|
68
72
|
value.empty?
|
69
73
|
end
|
70
74
|
|
71
|
-
# Returns log friendly output.
|
72
|
-
#
|
73
|
-
# @return [String]
|
74
|
-
def inspect
|
75
|
-
"<#{self.class.name} (value:#{value}, size:#{size})>"
|
76
|
-
end
|
77
|
-
|
78
75
|
# Returns the size of the content in characters without formatting.
|
79
76
|
#
|
80
77
|
# @return [Fixnum]
|
@@ -85,6 +82,16 @@ module Vedeu
|
|
85
82
|
# @return [String]
|
86
83
|
def value
|
87
84
|
# Vedeu::Char.coerce(@value, parent, colour, style)
|
85
|
+
# @value ||= if @value.size > 1
|
86
|
+
# @value.chars.map do |char|
|
87
|
+
# Vedeu::Char.new(char, parent, colour, style)
|
88
|
+
# end
|
89
|
+
# elsif @value.size == 1
|
90
|
+
# Vedeu::Char.new(@value, parent, colour, style)
|
91
|
+
# else
|
92
|
+
# # ???
|
93
|
+
# end
|
94
|
+
|
88
95
|
@value
|
89
96
|
end
|
90
97
|
|
@@ -9,34 +9,19 @@ module Vedeu
|
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
-
# Returns an escape sequence for a named background colour.
|
13
|
-
#
|
14
|
-
# Valid names are: `:black`, `:red`, `:green`, `:yellow`, `:blue`,
|
15
|
-
# `:magenta`, `:cyan`, `:white` and `:default`.
|
16
|
-
#
|
17
12
|
# @return [String]
|
18
|
-
def
|
19
|
-
|
13
|
+
def named_codes
|
14
|
+
Esc.background_codes[colour]
|
20
15
|
end
|
21
16
|
|
22
|
-
# Returns an escape sequence.
|
23
|
-
#
|
24
17
|
# @return [String]
|
25
|
-
def
|
26
|
-
|
18
|
+
def numbered_prefix
|
19
|
+
"\e[48;5;"
|
27
20
|
end
|
28
21
|
|
29
|
-
# Returns an escape sequence.
|
30
|
-
#
|
31
22
|
# @return [String]
|
32
|
-
def
|
33
|
-
|
34
|
-
sprintf("\e[48;2;%s;%s;%sm", *css_to_rgb)
|
35
|
-
|
36
|
-
else
|
37
|
-
numbered
|
38
|
-
|
39
|
-
end
|
23
|
+
def rgb_prefix
|
24
|
+
"\e[48;2;%s;%s;%sm"
|
40
25
|
end
|
41
26
|
|
42
27
|
end # Background
|
data/lib/vedeu/output/border.rb
CHANGED
@@ -62,23 +62,22 @@ module Vedeu
|
|
62
62
|
# @option attributes vertical [String] The vertical border character.
|
63
63
|
# @return [Border]
|
64
64
|
def initialize(attributes = {})
|
65
|
-
@attributes
|
66
|
-
|
67
|
-
@
|
68
|
-
@bottom_left = @attributes[:bottom_left]
|
65
|
+
@attributes = defaults.merge!(attributes)
|
66
|
+
@enabled = @attributes[:enabled]
|
67
|
+
@bottom_left = @attributes[:bottom_left]
|
69
68
|
@bottom_right = @attributes[:bottom_right]
|
70
|
-
@show_bottom
|
71
|
-
@show_left
|
72
|
-
@show_right
|
73
|
-
@show_top
|
74
|
-
@top_left
|
75
|
-
@top_right
|
76
|
-
@horizontal
|
77
|
-
@vertical
|
78
|
-
@name
|
79
|
-
@colour
|
80
|
-
@repository
|
81
|
-
@style
|
69
|
+
@show_bottom = @attributes[:show_bottom]
|
70
|
+
@show_left = @attributes[:show_left]
|
71
|
+
@show_right = @attributes[:show_right]
|
72
|
+
@show_top = @attributes[:show_top]
|
73
|
+
@top_left = @attributes[:top_left]
|
74
|
+
@top_right = @attributes[:top_right]
|
75
|
+
@horizontal = @attributes[:horizontal]
|
76
|
+
@vertical = @attributes[:vertical]
|
77
|
+
@name = @attributes[:name]
|
78
|
+
@colour = @attributes[:colour]
|
79
|
+
@repository = Vedeu.borders
|
80
|
+
@style = @attributes[:style]
|
82
81
|
end
|
83
82
|
|
84
83
|
# Returns the width of the interface determined by whether a left, right,
|
@@ -119,6 +118,11 @@ module Vedeu
|
|
119
118
|
end
|
120
119
|
end
|
121
120
|
|
121
|
+
# @return [Vedeu::Colour]
|
122
|
+
def colour
|
123
|
+
Colour.coerce(@colour)
|
124
|
+
end
|
125
|
+
|
122
126
|
# Set the border colour.
|
123
127
|
#
|
124
128
|
# @return [Vedeu::Colour]
|
@@ -126,6 +130,11 @@ module Vedeu
|
|
126
130
|
@colour = Colour.coerce(value)
|
127
131
|
end
|
128
132
|
|
133
|
+
# @return [Vedeu::Style]
|
134
|
+
def style
|
135
|
+
Style.coerce(@style)
|
136
|
+
end
|
137
|
+
|
129
138
|
# Set the border style.
|
130
139
|
#
|
131
140
|
# @return [Vedeu::Style]
|
@@ -209,7 +218,7 @@ module Vedeu
|
|
209
218
|
|
210
219
|
# @return [Vedeu::Interface]
|
211
220
|
def interface
|
212
|
-
@
|
221
|
+
@interface ||= Vedeu.interfaces.find(name)
|
213
222
|
end
|
214
223
|
|
215
224
|
# The default values for a new instance of this class.
|
data/lib/vedeu/output/colour.rb
CHANGED
@@ -23,7 +23,7 @@ module Vedeu
|
|
23
23
|
# @option attributes foreground [String]
|
24
24
|
# @return [Colour]
|
25
25
|
def initialize(attributes = {})
|
26
|
-
@attributes = defaults.merge(attributes)
|
26
|
+
@attributes = defaults.merge!(attributes)
|
27
27
|
|
28
28
|
@background = Background.coerce(@attributes[:background])
|
29
29
|
@foreground = Foreground.coerce(@attributes[:foreground])
|