vedeu 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +3 -9
- data/docs/api.md +70 -42
- data/elements.txt +118 -0
- data/lib/vedeu.rb +14 -4
- data/lib/vedeu/api/api.rb +67 -24
- data/lib/vedeu/api/composition.rb +19 -0
- data/lib/vedeu/api/defined.rb +7 -0
- data/lib/vedeu/api/interface.rb +103 -75
- data/lib/vedeu/api/keymap.rb +62 -0
- data/lib/vedeu/api/menu.rb +3 -1
- data/lib/vedeu/configuration.rb +24 -6
- data/lib/vedeu/models/attributes/coercions.rb +18 -26
- data/lib/vedeu/models/attributes/colour_translator.rb +7 -7
- data/lib/vedeu/models/attributes/presentation.rb +12 -1
- data/lib/vedeu/models/geometry.rb +5 -1
- data/lib/vedeu/models/interface.rb +6 -47
- data/lib/vedeu/models/keymap.rb +66 -0
- data/lib/vedeu/models/line.rb +3 -1
- data/lib/vedeu/models/stream.rb +10 -1
- data/lib/vedeu/models/style.rb +10 -1
- data/lib/vedeu/output/compositor.rb +3 -0
- data/lib/vedeu/output/refresh.rb +16 -74
- data/lib/vedeu/output/render.rb +44 -17
- data/lib/vedeu/output/view.rb +3 -0
- data/lib/vedeu/repositories/buffers.rb +32 -42
- data/lib/vedeu/repositories/events.rb +8 -11
- data/lib/vedeu/repositories/focus.rb +15 -13
- data/lib/vedeu/repositories/groups.rb +20 -2
- data/lib/vedeu/repositories/interfaces.rb +22 -2
- data/lib/vedeu/repositories/keymap_validator.rb +104 -0
- data/lib/vedeu/repositories/keymaps.rb +239 -0
- data/lib/vedeu/repositories/menus.rb +12 -3
- data/lib/vedeu/support/common.rb +2 -2
- data/lib/vedeu/support/cursor.rb +3 -0
- data/lib/vedeu/support/event.rb +48 -7
- data/lib/vedeu/support/grid.rb +1 -1
- data/lib/vedeu/support/registrar.rb +66 -0
- data/lib/vedeu/support/trace.rb +71 -12
- data/test/lib/vedeu/api/api_test.rb +27 -9
- data/test/lib/vedeu/api/composition_test.rb +10 -0
- data/test/lib/vedeu/api/defined_test.rb +14 -0
- data/test/lib/vedeu/api/interface_test.rb +86 -85
- data/test/lib/vedeu/api/keymap_test.rb +61 -0
- data/test/lib/vedeu/configuration_test.rb +12 -0
- data/test/lib/vedeu/models/attributes/coercions_test.rb +3 -4
- data/test/lib/vedeu/models/interface_test.rb +0 -43
- data/test/lib/vedeu/models/keymap_test.rb +19 -0
- data/test/lib/vedeu/models/style_test.rb +10 -0
- data/test/lib/vedeu/output/refresh_test.rb +0 -12
- data/test/lib/vedeu/output/render_test.rb +51 -0
- data/test/lib/vedeu/repositories/buffers_test.rb +39 -12
- data/test/lib/vedeu/repositories/events_test.rb +6 -0
- data/test/lib/vedeu/repositories/focus_test.rb +12 -0
- data/test/lib/vedeu/repositories/keymap_validator_test.rb +81 -0
- data/test/lib/vedeu/repositories/keymaps_test.rb +254 -0
- data/test/lib/vedeu/support/common_test.rb +26 -0
- data/test/lib/vedeu/support/registrar_test.rb +68 -0
- data/vedeu.gemspec +1 -1
- metadata +18 -2
@@ -4,6 +4,25 @@ module Vedeu
|
|
4
4
|
# @see Vedeu::Composition
|
5
5
|
class Composition < Vedeu::Composition
|
6
6
|
|
7
|
+
# Directly write a view buffer to the terminal.
|
8
|
+
#
|
9
|
+
# @api public
|
10
|
+
# @param block [Proc]
|
11
|
+
# @return [Array] A collection of strings, each defining containing the
|
12
|
+
# escape sequences and content. This data has already
|
13
|
+
# been sent to the terminal to be output.
|
14
|
+
def self.render(&block)
|
15
|
+
fail InvalidSyntax, '`render` requires a block.' unless block_given?
|
16
|
+
|
17
|
+
attributes = API::Composition.build({}, &block)
|
18
|
+
|
19
|
+
Vedeu::Composition.new(attributes).interfaces.map do |interface|
|
20
|
+
Buffers.add(interface.attributes)
|
21
|
+
|
22
|
+
interface.name
|
23
|
+
end.map { |name| Compositor.render(name) }
|
24
|
+
end
|
25
|
+
|
7
26
|
# @api public
|
8
27
|
# @see Vedeu::API#view
|
9
28
|
def view(name, &block)
|
data/lib/vedeu/api/defined.rb
CHANGED
data/lib/vedeu/api/interface.rb
CHANGED
@@ -6,45 +6,24 @@ module Vedeu
|
|
6
6
|
|
7
7
|
include Helpers
|
8
8
|
|
9
|
-
#
|
9
|
+
# Instructs Vedeu to calculate x and y geometry automatically based on the
|
10
|
+
# centre character of the terminal, the width and the height.
|
10
11
|
#
|
11
12
|
# @api public
|
12
|
-
# @param value [
|
13
|
-
# @param block [Proc]
|
13
|
+
# @param value [Boolean]
|
14
14
|
#
|
15
15
|
# @example
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# line 'and so is this...'
|
16
|
+
# interface 'my_interface' do
|
17
|
+
# centred true
|
19
18
|
# ...
|
20
19
|
#
|
21
|
-
# view 'my_interface' do
|
22
|
-
# line do
|
23
|
-
# ... some line attributes ...
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
#
|
27
20
|
# @return [API::Interface]
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
.build({ parent: self.view_attributes }, &block)
|
32
|
-
|
33
|
-
else
|
34
|
-
attributes[:lines] << API::Line
|
35
|
-
.build({ streams: { text: value }, parent: self.view_attributes })
|
36
|
-
|
21
|
+
def centred(value)
|
22
|
+
unless value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
23
|
+
fail InvalidSyntax, 'Argument must be `true` or `false` for centred.'
|
37
24
|
end
|
38
|
-
end
|
39
25
|
|
40
|
-
|
41
|
-
# interfaces.
|
42
|
-
#
|
43
|
-
# @api public
|
44
|
-
# @param value [String]
|
45
|
-
# @see Vedeu::API#use
|
46
|
-
def use(value)
|
47
|
-
Vedeu.use(value)
|
26
|
+
attributes[:geometry][:centred] = value
|
48
27
|
end
|
49
28
|
|
50
29
|
# Define the cursor visibility for an interface. A `true` value will show
|
@@ -96,6 +75,54 @@ module Vedeu
|
|
96
75
|
attributes[:group] = value
|
97
76
|
end
|
98
77
|
|
78
|
+
# Define the number of characters/rows/lines tall the interface will be.
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
# @param value [Fixnum]
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# interface 'my_interface' do
|
85
|
+
# height 8
|
86
|
+
# ...
|
87
|
+
#
|
88
|
+
# @return [API::Interface]
|
89
|
+
def height(value)
|
90
|
+
Vedeu.log(out_of_bounds('height')) if y_out_of_bounds?(value)
|
91
|
+
|
92
|
+
attributes[:geometry][:height] = value
|
93
|
+
end
|
94
|
+
|
95
|
+
# Define a single line in a view.
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
# @param value [String]
|
99
|
+
# @param block [Proc]
|
100
|
+
#
|
101
|
+
# @example
|
102
|
+
# view 'my_interface' do
|
103
|
+
# line 'This is a line of text...'
|
104
|
+
# line 'and so is this...'
|
105
|
+
# ...
|
106
|
+
#
|
107
|
+
# view 'my_interface' do
|
108
|
+
# line do
|
109
|
+
# ... some line attributes ...
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# @return [API::Interface]
|
114
|
+
def line(value = '', &block)
|
115
|
+
if block_given?
|
116
|
+
attributes[:lines] << API::Line
|
117
|
+
.build({ parent: self.view_attributes }, &block)
|
118
|
+
|
119
|
+
else
|
120
|
+
attributes[:lines] << API::Line
|
121
|
+
.build({ streams: { text: value }, parent: self.view_attributes })
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
99
126
|
# The name of the interface. Used to reference the interface throughout
|
100
127
|
# your application's execution lifetime.
|
101
128
|
#
|
@@ -112,6 +139,33 @@ module Vedeu
|
|
112
139
|
attributes[:name] = value
|
113
140
|
end
|
114
141
|
|
142
|
+
# Use the specified interface; useful for sharing attributes with other
|
143
|
+
# interfaces.
|
144
|
+
#
|
145
|
+
# @api public
|
146
|
+
# @param value [String]
|
147
|
+
# @see Vedeu::API#use
|
148
|
+
def use(value)
|
149
|
+
Vedeu.use(value)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Define the number of characters/columns wide the interface will be.
|
153
|
+
#
|
154
|
+
# @api public
|
155
|
+
# @param value [Fixnum]
|
156
|
+
#
|
157
|
+
# @example
|
158
|
+
# interface 'my_interface' do
|
159
|
+
# width 25
|
160
|
+
# ...
|
161
|
+
#
|
162
|
+
# @return [API::Interface]
|
163
|
+
def width(value)
|
164
|
+
Vedeu.log(out_of_bounds('width')) if x_out_of_bounds?(value)
|
165
|
+
|
166
|
+
attributes[:geometry][:width] = value
|
167
|
+
end
|
168
|
+
|
115
169
|
# Define the starting x position (column) of the interface.
|
116
170
|
#
|
117
171
|
# @api public
|
@@ -161,58 +215,32 @@ module Vedeu
|
|
161
215
|
attributes[:geometry][:y] = value
|
162
216
|
end
|
163
217
|
|
164
|
-
|
165
|
-
#
|
166
|
-
# @api public
|
167
|
-
# @param value [Fixnum]
|
168
|
-
#
|
169
|
-
# @example
|
170
|
-
# interface 'my_interface' do
|
171
|
-
# width 25
|
172
|
-
# ...
|
173
|
-
#
|
174
|
-
# @return [API::Interface]
|
175
|
-
def width(value)
|
176
|
-
Vedeu.log(out_of_bounds('width')) if x_out_of_bounds?(value)
|
218
|
+
private
|
177
219
|
|
178
|
-
|
220
|
+
# Returns the out of bounds error message for the given named attribute.
|
221
|
+
#
|
222
|
+
# @api private
|
223
|
+
# @param name [String]
|
224
|
+
# @return [String]
|
225
|
+
def out_of_bounds(name)
|
226
|
+
"Note: For this terminal, the value of '#{name}' may lead to content " \
|
227
|
+
"that is outside the viewable area."
|
179
228
|
end
|
180
229
|
|
181
|
-
#
|
230
|
+
# Checks the value is within the terminal's confines.
|
182
231
|
#
|
183
|
-
# @api
|
184
|
-
# @
|
185
|
-
|
186
|
-
|
187
|
-
# interface 'my_interface' do
|
188
|
-
# height 8
|
189
|
-
# ...
|
190
|
-
#
|
191
|
-
# @return [API::Interface]
|
192
|
-
def height(value)
|
193
|
-
Vedeu.log(out_of_bounds('height')) if y_out_of_bounds?(value)
|
194
|
-
|
195
|
-
attributes[:geometry][:height] = value
|
232
|
+
# @api private
|
233
|
+
# @return [Boolean]
|
234
|
+
def y_out_of_bounds?(value)
|
235
|
+
value < 1 || value > Terminal.height
|
196
236
|
end
|
197
237
|
|
198
|
-
#
|
199
|
-
# centre character of the terminal, the width and the height.
|
200
|
-
#
|
201
|
-
# @api public
|
202
|
-
# @param value [Boolean]
|
203
|
-
#
|
204
|
-
# @example
|
205
|
-
# interface 'my_interface' do
|
206
|
-
# centred true
|
207
|
-
# ...
|
238
|
+
# Checks the value is within the terminal's confines.
|
208
239
|
#
|
209
|
-
# @
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
end
|
214
|
-
|
215
|
-
attributes[:geometry][:centred] = value
|
240
|
+
# @api private
|
241
|
+
# @return [Boolean]
|
242
|
+
def x_out_of_bounds?(value)
|
243
|
+
value < 1 || value > Terminal.width
|
216
244
|
end
|
217
245
|
|
218
246
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Vedeu
|
2
|
+
module API
|
3
|
+
|
4
|
+
# Provides methods to be used to define keypress mapped to actions.
|
5
|
+
class Keymap < Vedeu::Keymap
|
6
|
+
|
7
|
+
# Define keypress(es) to perform an action.
|
8
|
+
#
|
9
|
+
# @param value_or_values [String|Symbol] The key(s) pressed. Special keys
|
10
|
+
# can be found in {Vedeu::Input#specials}. When more than one key is
|
11
|
+
# defined, then the extras are treated as aliases.
|
12
|
+
# @param block [Proc] The action to perform when this key is pressed. Can
|
13
|
+
# be a method call or event triggered.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# keys do
|
17
|
+
# key('s') { trigger(:save) }
|
18
|
+
# key('h', :left) { trigger(:left) }
|
19
|
+
# key('j', :down) { trigger(:down) }
|
20
|
+
# ...
|
21
|
+
#
|
22
|
+
# @return [Array] A collection containing the keypress(es).
|
23
|
+
def key(*value_or_values, &block)
|
24
|
+
fail InvalidSyntax,
|
25
|
+
'No action defined for `key`.' unless block_given?
|
26
|
+
fail InvalidSyntax, 'No keypress(es) defined for `key`.' unless
|
27
|
+
defined_value?(value_or_values)
|
28
|
+
|
29
|
+
value_or_values.each do |value|
|
30
|
+
fail InvalidSyntax, 'Key cannot be empty.' unless
|
31
|
+
defined_value?(value)
|
32
|
+
|
33
|
+
attributes[:keys] << { key: value, action: block }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# The interface(s) which will handle these keys.
|
38
|
+
#
|
39
|
+
# @param name_or_names [String] The name or names of the interface(s)
|
40
|
+
# which will handle these keys.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# keys do
|
44
|
+
# interface 'my_interface'
|
45
|
+
# key('s') { :something }
|
46
|
+
# name 'my_keymap'
|
47
|
+
# ...
|
48
|
+
#
|
49
|
+
# keys do
|
50
|
+
# interface('main', 'other')
|
51
|
+
# key('s') { :something }
|
52
|
+
# ...
|
53
|
+
#
|
54
|
+
# @return [Array]
|
55
|
+
def interface(*name_or_names)
|
56
|
+
attributes[:interfaces] = name_or_names
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/vedeu/api/menu.rb
CHANGED
@@ -92,8 +92,10 @@ module Vedeu
|
|
92
92
|
}
|
93
93
|
end
|
94
94
|
|
95
|
+
# At present, validates that a menu has a name attribute.
|
96
|
+
#
|
95
97
|
# @api private
|
96
|
-
# @return [
|
98
|
+
# @return [Boolean]
|
97
99
|
def validate_attributes!
|
98
100
|
unless defined_value?(attributes[:name])
|
99
101
|
fail InvalidSyntax, 'Menus must have a `name`.'
|
data/lib/vedeu/configuration.rb
CHANGED
@@ -83,7 +83,7 @@ module Vedeu
|
|
83
83
|
# Returns whether debugging is enabled or disabled. Default is false;
|
84
84
|
# meaning nothing apart from warnings are written to the log file.
|
85
85
|
#
|
86
|
-
# @return [
|
86
|
+
# @return [Boolean]
|
87
87
|
def debug?
|
88
88
|
options[:debug]
|
89
89
|
end
|
@@ -93,7 +93,7 @@ module Vedeu
|
|
93
93
|
# standalone (will run until terminates of natural causes.) Default is true;
|
94
94
|
# meaning the application will require user input.
|
95
95
|
#
|
96
|
-
# @return [
|
96
|
+
# @return [Boolean]
|
97
97
|
def interactive?
|
98
98
|
options[:interactive]
|
99
99
|
end
|
@@ -103,12 +103,19 @@ module Vedeu
|
|
103
103
|
# not. Default is false; meaning the application will loop forever or until
|
104
104
|
# terminated by the user.
|
105
105
|
#
|
106
|
-
# @return [
|
106
|
+
# @return [Boolean]
|
107
107
|
def once?
|
108
108
|
options[:once]
|
109
109
|
end
|
110
110
|
alias_method :once, :once?
|
111
111
|
|
112
|
+
# Returns
|
113
|
+
#
|
114
|
+
# @return [Hash]
|
115
|
+
def system_keys
|
116
|
+
options[:system_keys]
|
117
|
+
end
|
118
|
+
|
112
119
|
# Returns the terminal mode for the application. Default is `:raw`.
|
113
120
|
#
|
114
121
|
# @return [Symbol]
|
@@ -120,7 +127,7 @@ module Vedeu
|
|
120
127
|
# the log file (logging method calls and events trigger). Default is false;
|
121
128
|
# meaning tracing is disabled.
|
122
129
|
#
|
123
|
-
# @return [
|
130
|
+
# @return [Boolean]
|
124
131
|
def trace?
|
125
132
|
options[:trace]
|
126
133
|
end
|
@@ -153,11 +160,22 @@ module Vedeu
|
|
153
160
|
debug: detect_debug_mode,
|
154
161
|
interactive: true,
|
155
162
|
once: false,
|
163
|
+
system_keys: default_system_keys,
|
156
164
|
terminal_mode: :raw, #cooked
|
157
165
|
trace: detect_trace_mode,
|
158
166
|
}
|
159
167
|
end
|
160
168
|
|
169
|
+
# Vedeu's system keys.
|
170
|
+
def default_system_keys
|
171
|
+
{
|
172
|
+
exit: 'q',
|
173
|
+
focus_next: :tab,
|
174
|
+
focus_prev: :shift_tab,
|
175
|
+
mode_switch: :escape,
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
161
179
|
# Determine the terminal colour mode via enviroment variables, or be
|
162
180
|
# optimistic and settle for 256 colours.
|
163
181
|
#
|
@@ -189,7 +207,7 @@ module Vedeu
|
|
189
207
|
# Determine the debug mode via an enviroment variable.
|
190
208
|
#
|
191
209
|
# @api private
|
192
|
-
# @return [
|
210
|
+
# @return [Boolean]
|
193
211
|
# :nocov:
|
194
212
|
def detect_debug_mode
|
195
213
|
if ENV['VEDEU_DEBUG']
|
@@ -209,7 +227,7 @@ module Vedeu
|
|
209
227
|
# Determine the trace mode via an environment variable.
|
210
228
|
#
|
211
229
|
# @api private
|
212
|
-
# @return [
|
230
|
+
# @return [Boolean]
|
213
231
|
# :nocov:
|
214
232
|
def detect_trace_mode
|
215
233
|
if ENV['VEDEU_TRACE']
|
@@ -5,31 +5,23 @@ module Vedeu
|
|
5
5
|
# @api private
|
6
6
|
module Coercions
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
[values].flatten.map do |value|
|
26
|
-
if value.is_a?(self)
|
27
|
-
value
|
28
|
-
|
29
|
-
else
|
30
|
-
self.new(value.merge!({ parent: parent }))
|
31
|
-
|
32
|
-
end
|
8
|
+
include Vedeu::Common
|
9
|
+
|
10
|
+
# Produces new objects of the correct class from attributes hashes,
|
11
|
+
# ignores objects that have already been coerced.
|
12
|
+
#
|
13
|
+
# @param values [Array|Hash]
|
14
|
+
# @return [Array]
|
15
|
+
def coercer(values)
|
16
|
+
return [] unless defined_value?(values)
|
17
|
+
|
18
|
+
[values].flatten.map do |value|
|
19
|
+
if value.is_a?(self)
|
20
|
+
value
|
21
|
+
|
22
|
+
else
|
23
|
+
self.new(value)
|
24
|
+
|
33
25
|
end
|
34
26
|
end
|
35
27
|
end
|
@@ -38,7 +30,7 @@ module Vedeu
|
|
38
30
|
# module, make its methods into class methods, so they may be called
|
39
31
|
# directly.
|
40
32
|
def self.included(receiver)
|
41
|
-
receiver.extend(
|
33
|
+
receiver.extend(self)
|
42
34
|
end
|
43
35
|
|
44
36
|
end
|