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
@@ -0,0 +1,239 @@
|
|
1
|
+
module Vedeu
|
2
|
+
|
3
|
+
# Repository for storing, retrieving and using defined keymaps.
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
module Keymaps
|
7
|
+
|
8
|
+
include Vedeu::Common
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Stores the keymap attributes defined by the API.
|
12
|
+
#
|
13
|
+
# @param attributes [Hash]
|
14
|
+
# @return [TrueClass|KeyInUse|FalseClass]
|
15
|
+
def add(attributes)
|
16
|
+
return false unless defined_value?(attributes[:keys])
|
17
|
+
|
18
|
+
if defined_value?(attributes[:interfaces])
|
19
|
+
attributes[:interfaces].map do |interface|
|
20
|
+
storage.store(interface, {}) unless registered?(interface)
|
21
|
+
|
22
|
+
register(attributes, interface)
|
23
|
+
end
|
24
|
+
|
25
|
+
else
|
26
|
+
register(attributes)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return the whole repository of keymaps.
|
34
|
+
#
|
35
|
+
# @return [Hash]
|
36
|
+
def all
|
37
|
+
storage
|
38
|
+
end
|
39
|
+
|
40
|
+
# Find a keymap by interface name.
|
41
|
+
#
|
42
|
+
# @param name [String]
|
43
|
+
# @return [Hash]
|
44
|
+
def find(name)
|
45
|
+
storage.fetch(name, {})
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return a boolean indicating whether the key is registered as a global key.
|
49
|
+
#
|
50
|
+
# @param key [String|Symbol]
|
51
|
+
# @return [Boolean]
|
52
|
+
def global_key?(key)
|
53
|
+
global_keys.include?(key)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return the collection of global keys.
|
57
|
+
#
|
58
|
+
# @return [Array]
|
59
|
+
def global_keys
|
60
|
+
storage.fetch('_global_keymap_', {}).keys
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return a boolean indicating whether the key is registered as an interface
|
64
|
+
# key. When an interface argument is provided, only that interface is
|
65
|
+
# checked.
|
66
|
+
#
|
67
|
+
# @param key [String|Symbol]
|
68
|
+
# @param interface [String]
|
69
|
+
# @return [Boolean]
|
70
|
+
def interface_key?(key, interface = '')
|
71
|
+
if defined_value?(interface)
|
72
|
+
find(interface).keys.include?(key)
|
73
|
+
|
74
|
+
else
|
75
|
+
interface_keys.include?(key)
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Return a collection of interface keys.
|
81
|
+
#
|
82
|
+
# @return [Hash]
|
83
|
+
def interface_keys
|
84
|
+
storage.reject do |k, _|
|
85
|
+
k == '_global_keymap_'
|
86
|
+
end.map { |_, v| v.keys }.flatten.uniq
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a collection of the interface names of all the registered keymaps.
|
90
|
+
#
|
91
|
+
# @return [Array]
|
92
|
+
def registered
|
93
|
+
storage.keys
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns a boolean indicating whether the named interface has a keymap
|
97
|
+
# registered.
|
98
|
+
#
|
99
|
+
# @param name [String]
|
100
|
+
# @return [Boolean]
|
101
|
+
def registered?(name)
|
102
|
+
storage.key?(name)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Reset the keymaps repository; removing all registered keymaps. Only the
|
106
|
+
# system keymap will remain.
|
107
|
+
#
|
108
|
+
# @return [Hash]
|
109
|
+
def reset
|
110
|
+
@_storage = in_memory
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return a boolean indicating whether the key is registered as a system key.
|
114
|
+
#
|
115
|
+
# @param key [String|Symbol]
|
116
|
+
# @return [Boolean]
|
117
|
+
def system_key?(key)
|
118
|
+
system_keys.include?(key)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Return a collection of system keys.
|
122
|
+
#
|
123
|
+
# @return [Array]
|
124
|
+
def system_keys
|
125
|
+
Configuration.system_keys.invert.keys
|
126
|
+
end
|
127
|
+
|
128
|
+
# Handles the keypress in your application. Can also be used to simulate a
|
129
|
+
# keypress.
|
130
|
+
#
|
131
|
+
# 1) Log the keypress if debugging is enabled.
|
132
|
+
# 2) Trigger the client application's `:key` event (it may not exist).
|
133
|
+
# 3) Determine if the key pertains to the focussed interface and action it,
|
134
|
+
# or check both global, then system keys to action it. Returns false if
|
135
|
+
# nothing can deal with it.
|
136
|
+
#
|
137
|
+
# @param key [String|Symbol] The key which was pressed. Escape sequences
|
138
|
+
# are also supported. Special keys like the F-keys are named as symbols;
|
139
|
+
# i.e. `:f4`. A list of these translations can be found at {Vedeu::Input}.
|
140
|
+
#
|
141
|
+
# @example
|
142
|
+
# Vedeu.keypress('s')
|
143
|
+
#
|
144
|
+
# @return [|FalseClass]
|
145
|
+
def use(key)
|
146
|
+
Vedeu.log("Key pressed: '#{key}'")
|
147
|
+
|
148
|
+
Vedeu.trigger(:key, key)
|
149
|
+
|
150
|
+
focussed_interface = Vedeu::Focus.current
|
151
|
+
|
152
|
+
if interface_key?(key, focussed_interface)
|
153
|
+
find(focussed_interface).fetch(key, noop).call
|
154
|
+
|
155
|
+
elsif global_key?(key)
|
156
|
+
find('_global_keymap_').fetch(key, noop).call
|
157
|
+
|
158
|
+
elsif system_key?(key)
|
159
|
+
system_key(key)
|
160
|
+
|
161
|
+
else
|
162
|
+
false
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# Triggers the system event defined for this key.
|
170
|
+
#
|
171
|
+
# @param key [String|Symbol]
|
172
|
+
# @return []
|
173
|
+
def system_key(key)
|
174
|
+
action = Vedeu::Configuration.system_keys.key(key)
|
175
|
+
event = ['_', action, '_'].join.to_sym
|
176
|
+
|
177
|
+
Vedeu.trigger(event)
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param key [String|Symbol]
|
181
|
+
# @param interface [String]
|
182
|
+
# @return []
|
183
|
+
def validate(key, interface = '')
|
184
|
+
Vedeu::KeymapValidator.check(storage, key, interface)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Registers the key.
|
188
|
+
#
|
189
|
+
# @api private
|
190
|
+
# @param attributes [Hash]
|
191
|
+
# @param interface [String]
|
192
|
+
# @return []
|
193
|
+
def register(attributes, interface = '')
|
194
|
+
attributes[:keys].map do |keymap|
|
195
|
+
valid, message = validate(keymap[:key], interface)
|
196
|
+
|
197
|
+
fail KeyInUse, message unless valid
|
198
|
+
|
199
|
+
Vedeu.log("Registering key '#{keymap[:key]}' with " \
|
200
|
+
"'#{namespace(interface)}'")
|
201
|
+
|
202
|
+
storage[namespace(interface)]
|
203
|
+
.merge!({ keymap[:key] => keymap[:action] })
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Determine which interface to store the key with.
|
208
|
+
#
|
209
|
+
# @api private
|
210
|
+
# @param interface [String]
|
211
|
+
# @return [String]
|
212
|
+
def namespace(interface = '')
|
213
|
+
return defined_value?(interface) ? interface : '_global_keymap_'
|
214
|
+
end
|
215
|
+
|
216
|
+
# Returns a noop proc which when called returns :noop.
|
217
|
+
#
|
218
|
+
# @return [Proc]
|
219
|
+
def noop
|
220
|
+
proc { :noop }
|
221
|
+
end
|
222
|
+
|
223
|
+
# Access to the storage for this repository.
|
224
|
+
#
|
225
|
+
# @api private
|
226
|
+
# @return [Array]
|
227
|
+
def storage
|
228
|
+
@_storage ||= in_memory
|
229
|
+
end
|
230
|
+
|
231
|
+
# @api private
|
232
|
+
# @return [Array]
|
233
|
+
def in_memory
|
234
|
+
{ '_global_keymap_' => {} }
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
@@ -5,6 +5,7 @@ module Vedeu
|
|
5
5
|
# @api private
|
6
6
|
module Menus
|
7
7
|
|
8
|
+
include Common
|
8
9
|
extend self
|
9
10
|
|
10
11
|
# System events which when called with the appropriate menu name will
|
@@ -25,7 +26,9 @@ module Vedeu
|
|
25
26
|
# @param attributes [Hash]
|
26
27
|
# @return [Hash|FalseClass]
|
27
28
|
def add(attributes)
|
28
|
-
return false
|
29
|
+
return false unless defined_value?(attributes[:name])
|
30
|
+
|
31
|
+
Vedeu.log("Registering menu '#{attributes[:name]}'")
|
29
32
|
|
30
33
|
storage.store(attributes[:name], attributes)
|
31
34
|
end
|
@@ -57,7 +60,8 @@ module Vedeu
|
|
57
60
|
|
58
61
|
# Returns a boolean indicating whether the named menu is registered.
|
59
62
|
#
|
60
|
-
# @
|
63
|
+
# @param name [String]
|
64
|
+
# @return [Boolean]
|
61
65
|
def registered?(name)
|
62
66
|
storage.key?(name)
|
63
67
|
end
|
@@ -65,7 +69,7 @@ module Vedeu
|
|
65
69
|
# Removes the menu from the repository and associated events.
|
66
70
|
#
|
67
71
|
# @param name [String]
|
68
|
-
# @return [
|
72
|
+
# @return [Boolean]
|
69
73
|
def remove(name)
|
70
74
|
return false unless registered?(name)
|
71
75
|
|
@@ -95,12 +99,17 @@ module Vedeu
|
|
95
99
|
|
96
100
|
private
|
97
101
|
|
102
|
+
# Access to the storage for this repository.
|
103
|
+
#
|
98
104
|
# @api private
|
99
105
|
# @return [Hash]
|
100
106
|
def storage
|
101
107
|
@_storage ||= in_memory
|
102
108
|
end
|
103
109
|
|
110
|
+
# Returns an empty collection ready for the storing of menus by name with
|
111
|
+
# associated menu instance.
|
112
|
+
#
|
104
113
|
# @api private
|
105
114
|
# @return [Hash]
|
106
115
|
def in_memory
|
data/lib/vedeu/support/common.rb
CHANGED
@@ -7,8 +7,8 @@ module Vedeu
|
|
7
7
|
|
8
8
|
# Returns a boolean indicating whether a variable has a useful value.
|
9
9
|
#
|
10
|
-
# @param variable [String|Array] The variable to check.
|
11
|
-
# @return [
|
10
|
+
# @param variable [String|Symbol|Array] The variable to check.
|
11
|
+
# @return [Boolean]
|
12
12
|
def defined_value?(variable)
|
13
13
|
return true unless variable.nil? || variable.empty?
|
14
14
|
|
data/lib/vedeu/support/cursor.rb
CHANGED
data/lib/vedeu/support/event.rb
CHANGED
@@ -25,9 +25,9 @@ module Vedeu
|
|
25
25
|
def trigger(*args)
|
26
26
|
return execute(*args) unless debouncing? || throttling?
|
27
27
|
|
28
|
-
return execute(*args) if debouncing? &&
|
28
|
+
return execute(*args) if debouncing? && debounce_expired?
|
29
29
|
|
30
|
-
return execute(*args) if throttling? &&
|
30
|
+
return execute(*args) if throttling? && throttle_expired?
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
@@ -63,19 +63,36 @@ module Vedeu
|
|
63
63
|
# throttling.
|
64
64
|
#
|
65
65
|
# @api private
|
66
|
-
# @return [
|
66
|
+
# @return [Boolean]
|
67
67
|
def throttling?
|
68
68
|
set_time
|
69
69
|
|
70
70
|
options[:delay] > 0
|
71
71
|
end
|
72
72
|
|
73
|
+
# Returns a boolean indicating whether the throttle has expired.
|
74
|
+
#
|
75
|
+
# @api private
|
76
|
+
# @return [Boolean]
|
77
|
+
def throttle_expired?
|
78
|
+
if elapsed_time > delay
|
79
|
+
Vedeu.log("Event throttle has expired for '#{event_name}', executing " \
|
80
|
+
"event.")
|
81
|
+
true
|
82
|
+
|
83
|
+
else
|
84
|
+
Vedeu.log("Event throttle not yet expired for '#{event_name}'.")
|
85
|
+
false
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
73
90
|
# Returns a boolean indicating whether debouncing is required for this
|
74
91
|
# event. Setting the debounce option to any value greater than 0 will
|
75
92
|
# enable debouncing.
|
76
93
|
#
|
77
94
|
# @api private
|
78
|
-
# @return [
|
95
|
+
# @return [Boolean]
|
79
96
|
def debouncing?
|
80
97
|
set_time
|
81
98
|
|
@@ -84,6 +101,23 @@ module Vedeu
|
|
84
101
|
options[:debounce] > 0
|
85
102
|
end
|
86
103
|
|
104
|
+
# Returns a boolean indicating whether the debounce has expired.
|
105
|
+
#
|
106
|
+
# @api private
|
107
|
+
# @return [Boolean]
|
108
|
+
def debounce_expired?
|
109
|
+
if set_executed > deadline
|
110
|
+
Vedeu.log("Event debounce has expired for '#{event_name}', executing " \
|
111
|
+
"event.")
|
112
|
+
true
|
113
|
+
|
114
|
+
else
|
115
|
+
Vedeu.log("Event debounce not yet expired for '#{event_name}'.")
|
116
|
+
false
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
87
121
|
# @api private
|
88
122
|
# @return [Float]
|
89
123
|
def elapsed_time
|
@@ -109,7 +143,7 @@ module Vedeu
|
|
109
143
|
end
|
110
144
|
|
111
145
|
# @api private
|
112
|
-
# @return [
|
146
|
+
# @return [Boolean]
|
113
147
|
def has_deadline?
|
114
148
|
@deadline > 0
|
115
149
|
end
|
@@ -128,6 +162,12 @@ module Vedeu
|
|
128
162
|
nil
|
129
163
|
end
|
130
164
|
|
165
|
+
# @api private
|
166
|
+
# @return [String]
|
167
|
+
def event_name
|
168
|
+
options[:event_name].to_s
|
169
|
+
end
|
170
|
+
|
131
171
|
# @api private
|
132
172
|
# @return [Fixnum|Float]
|
133
173
|
def debounce
|
@@ -150,8 +190,9 @@ module Vedeu
|
|
150
190
|
# @return [Hash]
|
151
191
|
def defaults
|
152
192
|
{
|
153
|
-
delay:
|
154
|
-
debounce:
|
193
|
+
delay: 0.0,
|
194
|
+
debounce: 0.0,
|
195
|
+
event_name: '',
|
155
196
|
}
|
156
197
|
end
|
157
198
|
|
data/lib/vedeu/support/grid.rb
CHANGED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Vedeu
|
2
|
+
|
3
|
+
# When the client application has defined interfaces to be used, the Registrar
|
4
|
+
# stores these interfaces into various repositories for later use.
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
class Registrar
|
8
|
+
|
9
|
+
include Common
|
10
|
+
|
11
|
+
# @param attributes [Hash]
|
12
|
+
# @return [TrueClass|]
|
13
|
+
def self.record(attributes = {})
|
14
|
+
new(attributes).record
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param attributes [Hash]
|
18
|
+
# @return [Registrar]
|
19
|
+
def initialize(attributes = {})
|
20
|
+
@attributes = attributes
|
21
|
+
end
|
22
|
+
|
23
|
+
# Adds the attributes to a variety of repositories to use later.
|
24
|
+
#
|
25
|
+
# @return [TrueClass|MissingRequired]
|
26
|
+
def record
|
27
|
+
validate_attributes!
|
28
|
+
|
29
|
+
Vedeu::Buffers.add(attributes)
|
30
|
+
|
31
|
+
Vedeu::Interfaces.add(attributes)
|
32
|
+
|
33
|
+
Vedeu::Groups.add(attributes)
|
34
|
+
|
35
|
+
Vedeu::Focus.add(attributes)
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Client application defined settings for interfaces etc.
|
43
|
+
attr_reader :attributes
|
44
|
+
|
45
|
+
# At present, validates that attributes has a `:name` key that is not nil or
|
46
|
+
# empty.
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @return [TrueClass|MissingRequired]
|
50
|
+
def validate_attributes!
|
51
|
+
return exception unless attributes.key?(:name)
|
52
|
+
return exception unless defined_value?(attributes[:name])
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
# Raises the MissingRequired exception.
|
58
|
+
#
|
59
|
+
# @see Vedeu::MissingRequired
|
60
|
+
def exception
|
61
|
+
fail MissingRequired, 'Cannot store data without a name attribute.'
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|