vedeu 0.1.18 → 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +5 -0
- data/Dockerfile +40 -0
- data/README.md +7 -30
- data/docs/api.md +79 -0
- data/docs/events.md +121 -0
- data/lib/vedeu.rb +61 -18
- data/lib/vedeu/api/api.rb +73 -53
- data/lib/vedeu/api/composition.rb +4 -1
- data/lib/vedeu/api/defined.rb +35 -0
- data/lib/vedeu/api/helpers.rb +20 -15
- data/lib/vedeu/api/interface.rb +17 -12
- data/lib/vedeu/api/line.rb +20 -12
- data/lib/vedeu/api/stream.rb +3 -0
- data/lib/vedeu/application.rb +34 -1
- data/lib/vedeu/configuration.rb +15 -3
- data/lib/vedeu/input/input.rb +77 -0
- data/lib/vedeu/launcher.rb +7 -0
- data/lib/vedeu/models/attributes/background.rb +15 -2
- data/lib/vedeu/models/attributes/coercions.rb +18 -3
- data/lib/vedeu/models/attributes/colour_translator.rb +23 -17
- data/lib/vedeu/models/attributes/foreground.rb +10 -2
- data/lib/vedeu/models/attributes/presentation.rb +62 -0
- data/lib/vedeu/models/colour.rb +7 -3
- data/lib/vedeu/models/composition.rb +17 -19
- data/lib/vedeu/models/geometry.rb +13 -5
- data/lib/vedeu/models/interface.rb +35 -19
- data/lib/vedeu/models/line.rb +24 -8
- data/lib/vedeu/models/stream.rb +13 -7
- data/lib/vedeu/models/style.rb +17 -7
- data/lib/vedeu/{support → output}/clear.rb +14 -0
- data/lib/vedeu/output/compositor.rb +77 -0
- data/lib/vedeu/output/refresh.rb +129 -0
- data/lib/vedeu/{support → output}/render.rb +49 -13
- data/lib/vedeu/{support → output}/view.rb +15 -8
- data/lib/vedeu/repositories/buffers.rb +181 -0
- data/lib/vedeu/{support → repositories}/events.rb +16 -6
- data/lib/vedeu/repositories/focus.rb +109 -0
- data/lib/vedeu/repositories/groups.rb +76 -0
- data/lib/vedeu/repositories/interfaces.rb +74 -0
- data/lib/vedeu/support/common.rb +20 -0
- data/lib/vedeu/support/cursor.rb +77 -0
- data/lib/vedeu/support/esc.rb +181 -46
- data/lib/vedeu/support/event.rb +22 -4
- data/lib/vedeu/support/grid.rb +10 -3
- data/lib/vedeu/support/log.rb +14 -1
- data/lib/vedeu/support/menu.rb +51 -12
- data/lib/vedeu/support/position.rb +9 -0
- data/lib/vedeu/support/terminal.rb +49 -15
- data/lib/vedeu/support/trace.rb +11 -4
- data/test/integration/defining_interfaces_test.rb +27 -0
- data/test/integration/views/basic_view_test.rb +767 -0
- data/test/lib/vedeu/api/api_test.rb +32 -37
- data/test/lib/vedeu/api/composition_test.rb +23 -61
- data/test/lib/vedeu/api/defined_test.rb +49 -0
- data/test/lib/vedeu/api/helpers_test.rb +91 -0
- data/test/lib/vedeu/api/interface_test.rb +136 -688
- data/test/lib/vedeu/api/line_test.rb +28 -32
- data/test/lib/vedeu/application_test.rb +6 -0
- data/test/lib/vedeu/configuration_test.rb +8 -4
- data/test/lib/vedeu/{support → input}/input_test.rb +9 -0
- data/test/lib/vedeu/launcher_test.rb +6 -0
- data/test/lib/vedeu/models/attributes/{coercer_test.rb → coercions_test.rb} +11 -10
- data/test/lib/vedeu/models/attributes/colour_translator_test.rb +13 -0
- data/test/lib/vedeu/models/attributes/presentation_test.rb +30 -0
- data/test/lib/vedeu/models/colour_test.rb +8 -0
- data/test/lib/vedeu/models/composition_test.rb +208 -200
- data/test/lib/vedeu/models/geometry_test.rb +39 -0
- data/test/lib/vedeu/models/interface_test.rb +11 -1
- data/test/lib/vedeu/models/line_test.rb +8 -1
- data/test/lib/vedeu/models/stream_test.rb +35 -0
- data/test/lib/vedeu/models/style_test.rb +8 -0
- data/test/lib/vedeu/{support → output}/clear_test.rb +1 -1
- data/test/lib/vedeu/output/compositor_test.rb +64 -0
- data/test/lib/vedeu/output/refresh_test.rb +48 -0
- data/test/lib/vedeu/{support → output}/render_test.rb +36 -0
- data/test/lib/vedeu/{support → output}/view_test.rb +0 -0
- data/test/lib/vedeu/repositories/buffers_test.rb +48 -0
- data/test/lib/vedeu/{support → repositories}/events_test.rb +0 -0
- data/test/lib/vedeu/repositories/focus_test.rb +74 -0
- data/test/lib/vedeu/repositories/groups_test.rb +66 -0
- data/test/lib/vedeu/repositories/interfaces_test.rb +6 -0
- data/test/lib/vedeu/support/common_test.rb +6 -0
- data/test/lib/vedeu/support/cursor_test.rb +79 -0
- data/test/lib/vedeu/support/log_test.rb +6 -0
- data/test/lib/vedeu/support/terminal_test.rb +6 -28
- data/test/lib/vedeu/support/trace_test.rb +6 -0
- data/test/test_helper.rb +37 -0
- data/vedeu.gemspec +1 -1
- metadata +65 -33
- data/bin/log +0 -13
- data/lib/vedeu/support/buffer.rb +0 -69
- data/lib/vedeu/support/buffers.rb +0 -106
- data/lib/vedeu/support/focus.rb +0 -83
- data/lib/vedeu/support/groups.rb +0 -61
- data/lib/vedeu/support/input.rb +0 -67
- data/test/lib/vedeu/support/buffer_test.rb +0 -83
- data/test/lib/vedeu/support/buffers_test.rb +0 -15
- data/test/lib/vedeu/support/focus_test.rb +0 -114
- data/test/lib/vedeu/support/groups_test.rb +0 -65
@@ -1,11 +1,14 @@
|
|
1
1
|
module Vedeu
|
2
2
|
module API
|
3
|
+
|
4
|
+
# @see Vedeu::Composition
|
3
5
|
class Composition < Vedeu::Composition
|
4
6
|
|
5
7
|
# @api public
|
6
8
|
# @see Vedeu::API#view
|
7
9
|
def view(name, &block)
|
8
|
-
attributes[:interfaces] << Interface
|
10
|
+
attributes[:interfaces] << API::Interface
|
11
|
+
.build({ name: name, parent: self.view_attributes }, &block)
|
9
12
|
end
|
10
13
|
|
11
14
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Vedeu
|
2
|
+
module API
|
3
|
+
|
4
|
+
# Provides a set of helpful API methods to return information about various
|
5
|
+
# registered subsystems.
|
6
|
+
#
|
7
|
+
# @api public
|
8
|
+
module Defined
|
9
|
+
|
10
|
+
extend self
|
11
|
+
|
12
|
+
# Returns all events currently registered with Vedeu.
|
13
|
+
#
|
14
|
+
# @return [Array]
|
15
|
+
def events
|
16
|
+
Vedeu.events.registered
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns all groups currently registered with Vedeu.
|
20
|
+
#
|
21
|
+
# @return [Array]
|
22
|
+
def groups
|
23
|
+
Vedeu::Groups.registered
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns all interfaces currently registered with Vedeu.
|
27
|
+
#
|
28
|
+
# @return [Array]
|
29
|
+
def interfaces
|
30
|
+
Vedeu::Interfaces.registered
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/vedeu/api/helpers.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Vedeu
|
2
2
|
module API
|
3
|
+
|
4
|
+
# Provides colour and style helpers for use in the {API::Interface},
|
5
|
+
# {API::Line} and {API::Stream} classes.
|
3
6
|
module Helpers
|
4
7
|
|
5
8
|
# Define either or both foreground and background colours for an
|
@@ -11,25 +14,27 @@ module Vedeu
|
|
11
14
|
# @example
|
12
15
|
# interface 'my_interface' do
|
13
16
|
# colour background: '#000000', foreground: '#ffffff'
|
14
|
-
# ...
|
17
|
+
# ...
|
15
18
|
#
|
16
19
|
# line do
|
17
20
|
# colour background: '#000000', foreground: '#ffffff'
|
18
|
-
# ...
|
21
|
+
# ...
|
19
22
|
#
|
20
23
|
# stream do
|
21
24
|
# colour background: '#000000', foreground: '#ffffff'
|
22
|
-
# ...
|
25
|
+
# ...
|
23
26
|
#
|
24
|
-
# @return []
|
25
|
-
def colour(values
|
26
|
-
|
27
|
-
|
27
|
+
# @return [Hash]
|
28
|
+
def colour(values)
|
29
|
+
unless values.key?(:foreground) || values.key?(:background)
|
30
|
+
fail InvalidSyntax, '#colour expects a Hash containing ' \
|
31
|
+
':foreground or :background or both.'
|
32
|
+
end
|
28
33
|
|
29
34
|
attributes[:colour] = values
|
30
35
|
end
|
31
36
|
|
32
|
-
# Define a style for an interface, line or a stream.
|
37
|
+
# Define a style or styles for an interface, line or a stream.
|
33
38
|
#
|
34
39
|
# @api public
|
35
40
|
# @param values [Array|String]
|
@@ -38,24 +43,24 @@ module Vedeu
|
|
38
43
|
# @example
|
39
44
|
# interface 'my_interface' do
|
40
45
|
# style 'normal'
|
41
|
-
# ...
|
42
|
-
# end
|
46
|
+
# ...
|
43
47
|
#
|
44
48
|
# line do
|
45
49
|
# style ['bold', 'underline']
|
46
|
-
# ...
|
50
|
+
# ...
|
47
51
|
#
|
48
52
|
# stream do
|
49
53
|
# style 'blink'
|
50
|
-
# ...
|
54
|
+
# ...
|
51
55
|
#
|
52
|
-
# @return []
|
56
|
+
# @return [Array]
|
53
57
|
def style(values = [], &block)
|
54
58
|
if block_given?
|
55
|
-
attributes[:streams] << API::Stream
|
59
|
+
attributes[:streams] << API::Stream
|
60
|
+
.build({ style: Array(values) }, &block)
|
56
61
|
|
57
62
|
else
|
58
|
-
|
63
|
+
Array(values).each { |value| attributes[:style] << value }
|
59
64
|
|
60
65
|
end
|
61
66
|
end
|
data/lib/vedeu/api/interface.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Vedeu
|
2
2
|
module API
|
3
|
+
|
4
|
+
# Provides methods to be used to define interfaces or views.
|
3
5
|
class Interface < Vedeu::Interface
|
6
|
+
|
4
7
|
include Helpers
|
5
8
|
|
6
9
|
# Define a single line in a view.
|
@@ -21,13 +24,15 @@ module Vedeu
|
|
21
24
|
# end
|
22
25
|
# end
|
23
26
|
#
|
24
|
-
# @return []
|
27
|
+
# @return [API::Interface]
|
25
28
|
def line(value = '', &block)
|
26
29
|
if block_given?
|
27
|
-
attributes[:lines] << Line
|
30
|
+
attributes[:lines] << API::Line
|
31
|
+
.build({ parent: self.view_attributes }, &block)
|
28
32
|
|
29
33
|
else
|
30
|
-
attributes[:lines] << Line
|
34
|
+
attributes[:lines] << API::Line
|
35
|
+
.build({ streams: { text: value }, parent: self.view_attributes })
|
31
36
|
|
32
37
|
end
|
33
38
|
end
|
@@ -53,7 +58,7 @@ module Vedeu
|
|
53
58
|
# cursor true
|
54
59
|
# ...
|
55
60
|
#
|
56
|
-
# @return []
|
61
|
+
# @return [API::Interface]
|
57
62
|
def cursor(value)
|
58
63
|
unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
59
64
|
fail InvalidSyntax, 'Argument must be `true` or `false` for cursor.'
|
@@ -69,7 +74,7 @@ module Vedeu
|
|
69
74
|
# @api public
|
70
75
|
# @param value [Fixnum|Float]
|
71
76
|
#
|
72
|
-
# @return []
|
77
|
+
# @return [API::Interface]
|
73
78
|
def delay(value)
|
74
79
|
attributes[:delay] = value
|
75
80
|
end
|
@@ -86,7 +91,7 @@ module Vedeu
|
|
86
91
|
# group 'main_screen'
|
87
92
|
# ...
|
88
93
|
#
|
89
|
-
# @return []
|
94
|
+
# @return [API::Interface]
|
90
95
|
def group(value)
|
91
96
|
attributes[:group] = value
|
92
97
|
end
|
@@ -102,7 +107,7 @@ module Vedeu
|
|
102
107
|
# name 'my_interface'
|
103
108
|
# ...
|
104
109
|
#
|
105
|
-
# @return []
|
110
|
+
# @return [API::Interface]
|
106
111
|
def name(value)
|
107
112
|
attributes[:name] = value
|
108
113
|
end
|
@@ -122,7 +127,7 @@ module Vedeu
|
|
122
127
|
# # `my_interface` changes position,
|
123
128
|
# # `other_interface` will too.
|
124
129
|
#
|
125
|
-
# @return []
|
130
|
+
# @return [API::Interface]
|
126
131
|
def x(value = 0, &block)
|
127
132
|
return attributes[:geometry][:x] = block if block_given?
|
128
133
|
|
@@ -147,7 +152,7 @@ module Vedeu
|
|
147
152
|
# ... # `my_interface` changes position,
|
148
153
|
# # `other_interface` will too.
|
149
154
|
#
|
150
|
-
# @return []
|
155
|
+
# @return [API::Interface]
|
151
156
|
def y(value = 0, &block)
|
152
157
|
return attributes[:geometry][:y] = block if block_given?
|
153
158
|
|
@@ -166,7 +171,7 @@ module Vedeu
|
|
166
171
|
# width 25
|
167
172
|
# ...
|
168
173
|
#
|
169
|
-
# @return []
|
174
|
+
# @return [API::Interface]
|
170
175
|
def width(value)
|
171
176
|
Vedeu.log(out_of_bounds('width')) if x_out_of_bounds?(value)
|
172
177
|
|
@@ -183,7 +188,7 @@ module Vedeu
|
|
183
188
|
# height 8
|
184
189
|
# ...
|
185
190
|
#
|
186
|
-
# @return []
|
191
|
+
# @return [API::Interface]
|
187
192
|
def height(value)
|
188
193
|
Vedeu.log(out_of_bounds('height')) if y_out_of_bounds?(value)
|
189
194
|
|
@@ -201,7 +206,7 @@ module Vedeu
|
|
201
206
|
# centred true
|
202
207
|
# ...
|
203
208
|
#
|
204
|
-
# @return []
|
209
|
+
# @return [API::Interface]
|
205
210
|
def centred(value)
|
206
211
|
unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
207
212
|
fail InvalidSyntax, 'Argument must be `true` or `false` for centred.'
|
data/lib/vedeu/api/line.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Vedeu
|
2
2
|
module API
|
3
|
+
|
4
|
+
# Provides methods to be used to define views.
|
3
5
|
class Line < Vedeu::Line
|
6
|
+
|
4
7
|
include Helpers
|
5
8
|
|
6
9
|
# Define a stream (a subset of a line).
|
@@ -12,16 +15,14 @@ module Vedeu
|
|
12
15
|
# ...
|
13
16
|
# line do
|
14
17
|
# stream do
|
15
|
-
# ...
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
# ...
|
18
|
+
# ...
|
19
19
|
#
|
20
20
|
# @return [Array]
|
21
21
|
def stream(&block)
|
22
22
|
fail InvalidSyntax, '`stream` requires a block.' unless block_given?
|
23
23
|
|
24
|
-
attributes[:streams] << API::Stream
|
24
|
+
attributes[:streams] << API::Stream
|
25
|
+
.build({ parent: self.view_attributes }, &block)
|
25
26
|
end
|
26
27
|
|
27
28
|
# Define text for a line. Using this directive will not allow stream
|
@@ -34,7 +35,11 @@ module Vedeu
|
|
34
35
|
# @example
|
35
36
|
# ...
|
36
37
|
# line do
|
37
|
-
# text 'Some text
|
38
|
+
# text 'Some text goes here...'
|
39
|
+
#
|
40
|
+
# ...
|
41
|
+
# stream do
|
42
|
+
# text 'Some text goes here...'
|
38
43
|
#
|
39
44
|
# @return [Array]
|
40
45
|
def text(value)
|
@@ -53,9 +58,10 @@ module Vedeu
|
|
53
58
|
#
|
54
59
|
# @return [Array]
|
55
60
|
def foreground(value = '', &block)
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
stream = API::Stream.build({ colour: { foreground: value },
|
62
|
+
parent: self.view_attributes }, &block)
|
63
|
+
|
64
|
+
attributes[:streams] << stream
|
59
65
|
end
|
60
66
|
|
61
67
|
# @api public
|
@@ -70,11 +76,13 @@ module Vedeu
|
|
70
76
|
#
|
71
77
|
# @return [Array]
|
72
78
|
def background(value = '', &block)
|
73
|
-
|
74
|
-
|
75
|
-
|
79
|
+
stream = API::Stream.build({ colour: { background: value },
|
80
|
+
parent: self.view_attributes }, &block)
|
81
|
+
|
82
|
+
attributes[:streams] << stream
|
76
83
|
end
|
77
84
|
|
78
85
|
end
|
86
|
+
|
79
87
|
end
|
80
88
|
end
|
data/lib/vedeu/api/stream.rb
CHANGED
data/lib/vedeu/application.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Vedeu
|
2
|
+
|
3
|
+
# Orchestrates the running of the main application loop.
|
4
|
+
#
|
5
|
+
# @api public
|
2
6
|
class Application
|
7
|
+
# :nocov:
|
3
8
|
class << self
|
4
9
|
|
5
10
|
# @return []
|
@@ -8,6 +13,21 @@ module Vedeu
|
|
8
13
|
end
|
9
14
|
alias_method :restart, :start
|
10
15
|
|
16
|
+
# Stops the application!
|
17
|
+
# - The `:_cleanup_` event is triggered. Vedeu does not handle this event;
|
18
|
+
# the client application may treat this event as Vedeu signalling that it
|
19
|
+
# is about to terminate. Client applications are encouraged to use this
|
20
|
+
# event to close any open buffers, save files, empty trash, etc.
|
21
|
+
# - A StopIteration exception is raised which will cause {#start} to exit
|
22
|
+
# its looop and terminate the application.
|
23
|
+
#
|
24
|
+
# @api private
|
25
|
+
# @return [Exception]
|
26
|
+
def stop
|
27
|
+
Vedeu.trigger(:_cleanup_)
|
28
|
+
|
29
|
+
fail StopIteration
|
30
|
+
end
|
11
31
|
end
|
12
32
|
|
13
33
|
# @return [Application]
|
@@ -29,7 +49,7 @@ module Vedeu
|
|
29
49
|
Terminal.open do
|
30
50
|
Terminal.set_cursor_mode
|
31
51
|
|
32
|
-
Vedeu.
|
52
|
+
Vedeu.trigger(:_initialize_)
|
33
53
|
|
34
54
|
runner { main_sequence }
|
35
55
|
end
|
@@ -37,6 +57,9 @@ module Vedeu
|
|
37
57
|
|
38
58
|
private
|
39
59
|
|
60
|
+
# Runs the application loop either once, or forever (exceptions and signals
|
61
|
+
# permitting).
|
62
|
+
#
|
40
63
|
# @api private
|
41
64
|
# @return []
|
42
65
|
def runner
|
@@ -49,6 +72,12 @@ module Vedeu
|
|
49
72
|
end
|
50
73
|
end
|
51
74
|
|
75
|
+
# For an interactive application we capture input, (usually from the user),
|
76
|
+
# and continue the main loop.
|
77
|
+
#
|
78
|
+
# TODO: It appears for non-interactive applications, we do nothing. Must
|
79
|
+
# investigate.
|
80
|
+
#
|
52
81
|
# @api private
|
53
82
|
# @return []
|
54
83
|
def main_sequence
|
@@ -61,6 +90,9 @@ module Vedeu
|
|
61
90
|
end
|
62
91
|
end
|
63
92
|
|
93
|
+
# Runs the application in a continuous loop. This loop is stopped elsewhere
|
94
|
+
# with the raising of the StopIteration exception.
|
95
|
+
#
|
64
96
|
# @api private
|
65
97
|
# @return []
|
66
98
|
def run_many
|
@@ -74,4 +106,5 @@ module Vedeu
|
|
74
106
|
end
|
75
107
|
|
76
108
|
end
|
109
|
+
# :nocov:
|
77
110
|
end
|
data/lib/vedeu/configuration.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
module Vedeu
|
2
|
+
|
3
|
+
# Allows the customisation of Vedeu's behaviour through command-line
|
4
|
+
# arguments.
|
5
|
+
#
|
6
|
+
# @api public
|
2
7
|
module Configuration
|
8
|
+
|
3
9
|
extend self
|
4
10
|
|
5
11
|
# Parses arguments passed on the command-line or via {Vedeu::Launcher} into
|
@@ -51,9 +57,9 @@ module Vedeu
|
|
51
57
|
end
|
52
58
|
|
53
59
|
opts.on('-C', '--colour-mode [COLOURS]', Integer,
|
54
|
-
'Run application in either `8`, `16` or `
|
55
|
-
'mode.') do |colours|
|
56
|
-
if [8, 16, 256].include?(colours)
|
60
|
+
'Run application in either `8`, `16`, `256` or `16777216` ' \
|
61
|
+
'colour mode.') do |colours|
|
62
|
+
if [8, 16, 256, 16777216].include?(colours)
|
57
63
|
options[:colour_mode] = colours
|
58
64
|
|
59
65
|
else
|
@@ -157,6 +163,7 @@ module Vedeu
|
|
157
163
|
#
|
158
164
|
# @api private
|
159
165
|
# @return [Fixnum]
|
166
|
+
# :nocov:
|
160
167
|
def detect_colour_mode
|
161
168
|
if ENV['VEDEU_TERM']
|
162
169
|
case ENV['VEDEU_TERM']
|
@@ -177,11 +184,13 @@ module Vedeu
|
|
177
184
|
|
178
185
|
end
|
179
186
|
end
|
187
|
+
# :nocov:
|
180
188
|
|
181
189
|
# Determine the debug mode via an enviroment variable.
|
182
190
|
#
|
183
191
|
# @api private
|
184
192
|
# @return [TrueClass|FalseClass]
|
193
|
+
# :nocov:
|
185
194
|
def detect_debug_mode
|
186
195
|
if ENV['VEDEU_DEBUG']
|
187
196
|
case ENV['VEDEU_DEBUG']
|
@@ -195,11 +204,13 @@ module Vedeu
|
|
195
204
|
|
196
205
|
end
|
197
206
|
end
|
207
|
+
# :nocov:
|
198
208
|
|
199
209
|
# Determine the trace mode via an environment variable.
|
200
210
|
#
|
201
211
|
# @api private
|
202
212
|
# @return [TrueClass|FalseClass]
|
213
|
+
# :nocov:
|
203
214
|
def detect_trace_mode
|
204
215
|
if ENV['VEDEU_TRACE']
|
205
216
|
case ENV['VEDEU_TRACE']
|
@@ -213,6 +224,7 @@ module Vedeu
|
|
213
224
|
|
214
225
|
end
|
215
226
|
end
|
227
|
+
# :nocov:
|
216
228
|
|
217
229
|
end
|
218
230
|
end
|