vedeu 0.6.37 → 0.6.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/events/system.md +28 -12
- data/examples/dsl_editor.rb +81 -0
- data/examples/dsl_hello_worlds.rb +16 -14
- data/lib/vedeu/editor/document.rb +8 -0
- data/lib/vedeu/error.rb +3 -2
- data/lib/vedeu/input/capture.rb +28 -4
- data/lib/vedeu/input/mapper.rb +55 -37
- data/lib/vedeu/interfaces/dsl.rb +61 -5
- data/lib/vedeu/interfaces/interface.rb +6 -0
- data/lib/vedeu/null/generic.rb +1 -0
- data/lib/vedeu/output/text.rb +30 -1
- data/lib/vedeu/output/wordwrap.rb +33 -3
- data/lib/vedeu/repositories/collection.rb +8 -2
- data/lib/vedeu/version.rb +1 -1
- data/test/lib/vedeu/editor/document_test.rb +16 -0
- data/test/lib/vedeu/input/capture_test.rb +53 -3
- data/test/lib/vedeu/input/mapper_test.rb +40 -7
- data/test/lib/vedeu/interfaces/dsl_test.rb +28 -0
- data/test/lib/vedeu/interfaces/interface_test.rb +15 -9
- data/test/lib/vedeu/null/generic_test.rb +2 -0
- data/test/lib/vedeu/output/wordwrap_test.rb +4 -2
- data/test/lib/vedeu/repositories/collection_test.rb +1 -9
- metadata +2 -3
- data/test/support/examples/editor_app.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3b9204a33456f344d0f99492f9b00b544036b23
|
4
|
+
data.tar.gz: 80f15efc5738f5fcaacd6065e53235f61e5e5b0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd3541b906d8894c766f680ce02d5e49f9ad323302a8476ac2105a75aac5413c8956de137acb26a725be1a6e9bfee7b4493d16cc6398ec5bb280308c4d79881f
|
7
|
+
data.tar.gz: 11373347106344fd1617785d3367920f18d5ef6cd404e9f778833b812180fa1945013efa9ef557688e2cb399e89244885883c4f0e41447d10408a3ecf6d095d2
|
data/docs/events/system.md
CHANGED
@@ -41,14 +41,31 @@ action(s), like render the first screen, interface or make a sound.
|
|
41
41
|
Vedeu.trigger(:_initialize_)
|
42
42
|
|
43
43
|
### `:\_keypress\_`
|
44
|
-
|
45
|
-
to 'do things'. If the `escape` key is pressed, then `key` is
|
46
|
-
triggered with the argument `:escape`, also an internal event
|
47
|
-
`_mode_switch_` is triggered. Vedeu recognises most key presses and
|
48
|
-
some 'extended' keypress (eg. Ctrl+J), a list of supported keypresses
|
49
|
-
can be found here: {Vedeu::Input::Capture}.
|
44
|
+
When the name is given:
|
50
45
|
|
51
|
-
|
46
|
+
- The given key is passed to the named keymap. If the keymap is
|
47
|
+
registered, and the key has an associated action assigned, then
|
48
|
+
the action will be called/triggered.
|
49
|
+
- If the keymap is not registered, the key will be passed to the
|
50
|
+
global keymap to be actioned, or ignored if the global keymap does
|
51
|
+
not have an action assigned for the key pressed.
|
52
|
+
|
53
|
+
When the name is not given:
|
54
|
+
|
55
|
+
- The given key is passed to the named keymap associated with the
|
56
|
+
interface/view currently in focus. If the key has an associated
|
57
|
+
action assigned, then the action will be called or triggered,
|
58
|
+
otherwise, the key is (as above) passed to the global keymap to be
|
59
|
+
processed.
|
60
|
+
|
61
|
+
It is also to be noted, that a `:key` event will be triggered
|
62
|
+
irrespective of the conditions above, you can bind to this event
|
63
|
+
separately to 'do things'.
|
64
|
+
|
65
|
+
A list of supported keypresses can be found here:
|
66
|
+
{Vedeu::Input::Capture}.
|
67
|
+
|
68
|
+
Vedeu.trigger(:_keypress_, key, optional_name)
|
52
69
|
|
53
70
|
### `:\_log\_`
|
54
71
|
When triggered with a message will cause Vedeu to log the message if
|
@@ -59,10 +76,9 @@ Note: 'message' is a String.
|
|
59
76
|
Vedeu.trigger(:_log_, message)
|
60
77
|
|
61
78
|
### `:\_mode_switch\_`
|
62
|
-
When triggered
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
commands with arguments.
|
79
|
+
When triggered, Vedeu switches between modes of the terminal. The idea
|
80
|
+
here being that the raw mode is for single keypress actions, whilst
|
81
|
+
fake and cooked modes allow the user to enter more elaborate commands-
|
82
|
+
such as commands with arguments.
|
67
83
|
|
68
84
|
Vedeu.trigger(:_mode_switch_)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'vedeu'
|
5
|
+
|
6
|
+
class EditorApp
|
7
|
+
|
8
|
+
Vedeu.bind(:_initialize_) { Vedeu.trigger(:_refresh_) }
|
9
|
+
|
10
|
+
Vedeu.configure do
|
11
|
+
log './tmp/editor.log'
|
12
|
+
renderers Vedeu::Renderers::File.new(filename: './tmp/editor.out')
|
13
|
+
fake!
|
14
|
+
end
|
15
|
+
|
16
|
+
Vedeu.interface :editor_view do
|
17
|
+
border do
|
18
|
+
title 'Editor'
|
19
|
+
end
|
20
|
+
editable!
|
21
|
+
geometry do
|
22
|
+
align(:top, :left, 40, 8)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Vedeu.interface :help_view do
|
27
|
+
geometry do
|
28
|
+
height use(:editor_view).height
|
29
|
+
width use(:editor_view).width
|
30
|
+
x use(:editor_view).left
|
31
|
+
y use(:editor_view).south
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# When pressing Return/Enter in the editor view, the :_command_
|
36
|
+
# event will be triggered with any typed content you have provided.
|
37
|
+
#
|
38
|
+
# Bind to this event to retrieve the content entered, and then
|
39
|
+
# process yourself in whatever way appropriate.
|
40
|
+
#
|
41
|
+
# Vedeu.bind(:_command_) do |data|
|
42
|
+
# # ... do something with 'data'
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
Vedeu.keymap :editor_view do
|
46
|
+
key(:enter) { Vedeu.trigger(:_editor_execute_, :editor_view) }
|
47
|
+
end
|
48
|
+
|
49
|
+
Vedeu.keymap '_global_' do
|
50
|
+
key('q') { Vedeu.exit }
|
51
|
+
end
|
52
|
+
|
53
|
+
Vedeu.render do
|
54
|
+
view(:editor_view) do
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Vedeu.render do
|
59
|
+
view(:help_view) do
|
60
|
+
lines do
|
61
|
+
line 'Type into the editor dialog above,'
|
62
|
+
line 'and press Return. This will trigger the'
|
63
|
+
line ':_command_ event with the contents of '
|
64
|
+
line 'the view.'
|
65
|
+
|
66
|
+
# @todo Not implemented yet:
|
67
|
+
#
|
68
|
+
# text 'Type into the editor dialog above, and press Return. This will ' \
|
69
|
+
# 'trigger the :_command_ event with the contents of the view.',
|
70
|
+
# name: :help_view, mode: :wrap
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.start(argv = ARGV)
|
76
|
+
Vedeu::Launcher.execute!(argv)
|
77
|
+
end
|
78
|
+
|
79
|
+
end # EditorApp
|
80
|
+
|
81
|
+
EditorApp.start
|
@@ -18,9 +18,11 @@ class HelloWorldsApp
|
|
18
18
|
Vedeu.trigger(:_refresh_)
|
19
19
|
}
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# Add specific configuration for the client application.
|
22
|
+
#
|
23
|
+
# Vedeu.configure do
|
24
|
+
# log './tmp/hello_worlds.log'
|
25
|
+
# end
|
24
26
|
|
25
27
|
Vedeu.interface :hello do
|
26
28
|
# Define all of the interface in one place.
|
@@ -29,23 +31,23 @@ class HelloWorldsApp
|
|
29
31
|
geometry do
|
30
32
|
align(:middle, :centre, 24, 5)
|
31
33
|
end
|
32
|
-
# (You usually specify the views outside the interface block).
|
33
|
-
Vedeu.views do
|
34
|
-
view :hello do
|
35
|
-
lines do
|
36
|
-
line { centre 'Hello Worlds!', width: 24 }
|
37
|
-
line
|
38
|
-
line { centre "Press 'q' to exit,", width: 24 }
|
39
|
-
line { centre " 'w' to switch worlds.", width: 24 }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
34
|
keymap do
|
44
35
|
key('q') { Vedeu.exit }
|
45
36
|
key('w') { HelloWorldsApp.render_world }
|
46
37
|
end
|
47
38
|
end
|
48
39
|
|
40
|
+
Vedeu.renders do
|
41
|
+
view :hello do
|
42
|
+
lines do
|
43
|
+
line { centre 'Hello Worlds!', width: 24 }
|
44
|
+
line
|
45
|
+
line { centre "Press 'q' to exit,", width: 24 }
|
46
|
+
line { centre " 'w' to switch worlds.", width: 24 }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
49
51
|
def self.start(argv = ARGV)
|
50
52
|
Vedeu::Launcher.execute!(argv)
|
51
53
|
end
|
@@ -27,6 +27,14 @@ module Vedeu
|
|
27
27
|
# @return [String|Symbol]
|
28
28
|
attr_accessor :name
|
29
29
|
|
30
|
+
# Store an instance of this class with its repository.
|
31
|
+
#
|
32
|
+
# @param (see #initialize)
|
33
|
+
# @return (see #initialize)
|
34
|
+
def self.store(attributes = {})
|
35
|
+
new(attributes).store
|
36
|
+
end
|
37
|
+
|
30
38
|
# Returns a new instance of Vedeu::Editor::Document.
|
31
39
|
#
|
32
40
|
# @param attributes [Hash]
|
data/lib/vedeu/error.rb
CHANGED
@@ -45,8 +45,9 @@ module Vedeu
|
|
45
45
|
|
46
46
|
end # InvalidSyntax
|
47
47
|
|
48
|
-
# Raised when
|
49
|
-
#
|
48
|
+
# Raised when value required by Vedeu to proceed is not given.
|
49
|
+
# For example, when a name is not provided for a model when
|
50
|
+
# attempting to store it in a repository.
|
50
51
|
#
|
51
52
|
class MissingRequired < StandardError
|
52
53
|
|
data/lib/vedeu/input/capture.rb
CHANGED
@@ -24,9 +24,21 @@ module Vedeu
|
|
24
24
|
@reader = reader
|
25
25
|
end
|
26
26
|
|
27
|
-
# Triggers
|
28
|
-
#
|
29
|
-
#
|
27
|
+
# Triggers various events dependent on the terminal mode.
|
28
|
+
#
|
29
|
+
# - When in raw mode, the :_keypress_ event is triggered with
|
30
|
+
# the key(s) pressed.
|
31
|
+
# - When in fake mode, the keypress will be checked against the
|
32
|
+
# keymap relating to the interface/view currently in focus.
|
33
|
+
# - If registered, the :_keypress_ event is triggered with the
|
34
|
+
# key(s) pressed.
|
35
|
+
# - If the keypress is not registered, we check whether the
|
36
|
+
# interface in focus is editable, if so, the :_editor_
|
37
|
+
# event is triggered.
|
38
|
+
# - Otherwise, the :key event is triggered for the client
|
39
|
+
# application to handle.
|
40
|
+
# - When in cooked mode, the :_command_ event is triggered with
|
41
|
+
# the input given.
|
30
42
|
#
|
31
43
|
# @return [Array|String|Symbol]
|
32
44
|
def read
|
@@ -34,8 +46,20 @@ module Vedeu
|
|
34
46
|
Vedeu.trigger(:_keypress_, keypress)
|
35
47
|
|
36
48
|
elsif reader.fake_mode?
|
37
|
-
Vedeu.
|
49
|
+
name = Vedeu.focus
|
50
|
+
interface = Vedeu.interfaces.by_name(name)
|
51
|
+
key = keypress
|
52
|
+
|
53
|
+
if Vedeu::Input::Mapper.registered?(key, name)
|
54
|
+
Vedeu.trigger(:_keypress_, key, name)
|
55
|
+
|
56
|
+
elsif interface.editable?
|
57
|
+
Vedeu.trigger(:_editor_, key)
|
58
|
+
|
59
|
+
else
|
60
|
+
Vedeu.trigger(:key, key)
|
38
61
|
|
62
|
+
end
|
39
63
|
else
|
40
64
|
Vedeu.trigger(:_command_, command)
|
41
65
|
|
data/lib/vedeu/input/mapper.rb
CHANGED
@@ -6,34 +6,51 @@ module Vedeu
|
|
6
6
|
#
|
7
7
|
class Mapper
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
return
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
9
|
+
class << self
|
10
|
+
|
11
|
+
include Vedeu::Common
|
12
|
+
|
13
|
+
# Takes a key as a keypress and sends it to registered
|
14
|
+
# keymaps. If found, the associated action is fired,
|
15
|
+
# otherwise, we move to the next keymap or return false.
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# Vedeu.keypress(key_name, keymap_name)
|
19
|
+
#
|
20
|
+
# @param (see #initialize)
|
21
|
+
# @return [Boolean]
|
22
|
+
def keypress(key = nil, name = nil)
|
23
|
+
Vedeu.trigger(:key, key)
|
24
|
+
|
25
|
+
return false unless key
|
26
|
+
|
27
|
+
new(key, name).keypress
|
28
|
+
end
|
29
|
+
|
30
|
+
def registered?(key = nil, name = nil)
|
31
|
+
fail Vedeu::Error::MissingRequired,
|
32
|
+
'Cannot check whether a key is registered to a keymap without ' \
|
33
|
+
'the key.' if absent?(key)
|
34
|
+
fail Vedeu::Error::MissingRequired,
|
35
|
+
'Cannot check whether a key is registered to a keymap without ' \
|
36
|
+
'the keymap name.' if absent?(name)
|
37
|
+
|
38
|
+
new(key, name).registered?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Checks a key is valid; i.e. not already registered to a
|
42
|
+
# keymap. When the key is registered, then the key is invalid
|
43
|
+
# and cannot be used again.
|
44
|
+
#
|
45
|
+
# @param (see #initialize)
|
46
|
+
# @return [Boolean]
|
47
|
+
def valid?(key = nil, name = nil)
|
48
|
+
return false unless key
|
49
|
+
|
50
|
+
new(key, name).valid?
|
51
|
+
end
|
52
|
+
|
53
|
+
end # Eigenclass
|
37
54
|
|
38
55
|
# Returns a new instance of Vedeu::Input::Mapper.
|
39
56
|
#
|
@@ -63,6 +80,15 @@ module Vedeu
|
|
63
80
|
false
|
64
81
|
end
|
65
82
|
|
83
|
+
# Is the key defined in the named keymap?
|
84
|
+
#
|
85
|
+
# @param named [NilClass|String]
|
86
|
+
# @return [Boolean]
|
87
|
+
def key_defined?(named = name)
|
88
|
+
keymap?(named) && keymap(named).key_defined?(key)
|
89
|
+
end
|
90
|
+
alias_method :registered?, :key_defined?
|
91
|
+
|
66
92
|
# Returns a boolean indicating that the key is not registered to
|
67
93
|
# the current keymap, or the global keymap.
|
68
94
|
#
|
@@ -92,14 +118,6 @@ module Vedeu
|
|
92
118
|
key_defined?('_global_')
|
93
119
|
end
|
94
120
|
|
95
|
-
# Is the key defined in the named keymap?
|
96
|
-
#
|
97
|
-
# @param named [NilClass|String]
|
98
|
-
# @return [Boolean]
|
99
|
-
def key_defined?(named = name)
|
100
|
-
keymap?(named) && keymap(named).key_defined?(key)
|
101
|
-
end
|
102
|
-
|
103
121
|
# Fetch the named keymap from the repository.
|
104
122
|
#
|
105
123
|
# @param named [NilClass|String]
|
@@ -137,7 +155,7 @@ module Vedeu
|
|
137
155
|
# :nocov:
|
138
156
|
|
139
157
|
# See {file:docs/events/system.md#\_keypress_}
|
140
|
-
Vedeu.bind(:_keypress_) { |key| Vedeu.keypress(key) }
|
158
|
+
Vedeu.bind(:_keypress_) { |key, name| Vedeu.keypress(key, name) }
|
141
159
|
|
142
160
|
# See {file:docs/events/drb.md#\_drb_input_}
|
143
161
|
Vedeu.bind(:_drb_input_) do |data, type|
|
data/lib/vedeu/interfaces/dsl.rb
CHANGED
@@ -39,13 +39,18 @@ module Vedeu
|
|
39
39
|
fail Vedeu::Error::MissingRequired,
|
40
40
|
'name not given'.freeze unless present?(name)
|
41
41
|
|
42
|
+
attributes = { client: client(&block), name: name }
|
43
|
+
|
44
|
+
interface = Vedeu::Interfaces::Interface
|
45
|
+
.build(attributes, &block)
|
46
|
+
.store
|
47
|
+
|
42
48
|
add_buffers!(name)
|
43
49
|
add_cursor!(name)
|
50
|
+
add_editor!(name) if interface.editable?
|
44
51
|
add_focusable!(name)
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
Vedeu::Interfaces::Interface.build(attributes, &block).store
|
53
|
+
interface
|
49
54
|
end
|
50
55
|
|
51
56
|
private
|
@@ -70,6 +75,13 @@ module Vedeu
|
|
70
75
|
Vedeu::Cursors::Cursor.store(name: name)
|
71
76
|
end
|
72
77
|
|
78
|
+
# Registers a new document with the interface.
|
79
|
+
#
|
80
|
+
# @param name [String|Symbol]
|
81
|
+
def add_editor!(name)
|
82
|
+
Vedeu::Editor::Document.store(name: name)
|
83
|
+
end
|
84
|
+
|
73
85
|
# Registers interface name in focus list unless already
|
74
86
|
# registered.
|
75
87
|
#
|
@@ -92,8 +104,7 @@ module Vedeu
|
|
92
104
|
# Set the cursor visibility on an interface.
|
93
105
|
#
|
94
106
|
# @param value [Boolean] Any value other than nil or false will
|
95
|
-
# evaluate
|
96
|
-
# to true.
|
107
|
+
# evaluate to true.
|
97
108
|
#
|
98
109
|
# @example
|
99
110
|
# Vedeu.interface :my_interface do
|
@@ -151,6 +162,51 @@ module Vedeu
|
|
151
162
|
model.delay = value
|
152
163
|
end
|
153
164
|
|
165
|
+
# Set whether the interface is editable.
|
166
|
+
#
|
167
|
+
# @note
|
168
|
+
# When an interface is made editable, then the cursor
|
169
|
+
# visibility will be set to visible.
|
170
|
+
#
|
171
|
+
# @param value [Boolean] Any value other than nil or false will
|
172
|
+
# evaluate to true.
|
173
|
+
#
|
174
|
+
# @example
|
175
|
+
# Vedeu.interface :my_interface do
|
176
|
+
# editable true # => The interface/view can be edited.
|
177
|
+
#
|
178
|
+
# # or...
|
179
|
+
#
|
180
|
+
# editable! # => Convenience method for above.
|
181
|
+
#
|
182
|
+
# # ...
|
183
|
+
# end
|
184
|
+
#
|
185
|
+
# Vedeu.interface :my_interface do
|
186
|
+
# editable false # => The interface/view cannot be edited.
|
187
|
+
#
|
188
|
+
# # or...
|
189
|
+
#
|
190
|
+
# editable # => as above
|
191
|
+
# # ...
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# @return [Boolean]
|
195
|
+
def editable(value = true)
|
196
|
+
boolean = value ? true : false
|
197
|
+
|
198
|
+
cursor(true) if boolean
|
199
|
+
|
200
|
+
model.editable = boolean
|
201
|
+
end
|
202
|
+
|
203
|
+
# Set the interface to be editable.
|
204
|
+
#
|
205
|
+
# @return [Boolean]
|
206
|
+
def editable!
|
207
|
+
editable(true)
|
208
|
+
end
|
209
|
+
|
154
210
|
# Specify this interface as being in focus when the application
|
155
211
|
# starts.
|
156
212
|
#
|
@@ -23,6 +23,11 @@ module Vedeu
|
|
23
23
|
# @return [Fixnum|Float]
|
24
24
|
attr_accessor :delay
|
25
25
|
|
26
|
+
# @!attribute [rw] editable
|
27
|
+
# @return [Boolean]
|
28
|
+
attr_accessor :editable
|
29
|
+
alias_method :editable?, :editable
|
30
|
+
|
26
31
|
# @!attribute [rw] group
|
27
32
|
# @return [Symbol|String]
|
28
33
|
attr_accessor :group
|
@@ -111,6 +116,7 @@ module Vedeu
|
|
111
116
|
colour: Vedeu::Colours::Colour.coerce(background: :default,
|
112
117
|
foreground: :default),
|
113
118
|
delay: 0.0,
|
119
|
+
editable: false,
|
114
120
|
group: '',
|
115
121
|
name: '',
|
116
122
|
parent: nil,
|
data/lib/vedeu/null/generic.rb
CHANGED
data/lib/vedeu/output/text.rb
CHANGED
@@ -26,6 +26,7 @@ module Vedeu
|
|
26
26
|
# @option options foreground [String]
|
27
27
|
# @option options model
|
28
28
|
# [Vedeu::Views::View|Vedeu::Views::Line|Vedeu::Views::Stream]
|
29
|
+
# @option options mode (see Vedeu::Output::Wordwrap#mode)
|
29
30
|
# @option options pad [String]
|
30
31
|
# @option options width [Integer]
|
31
32
|
# @return [Vedeu::Output::Text]
|
@@ -55,7 +56,13 @@ module Vedeu
|
|
55
56
|
#
|
56
57
|
# @return [void]
|
57
58
|
def add
|
58
|
-
|
59
|
+
if wrap?
|
60
|
+
model.add(wrapped)
|
61
|
+
|
62
|
+
else
|
63
|
+
model.add(content)
|
64
|
+
|
65
|
+
end
|
59
66
|
end
|
60
67
|
|
61
68
|
protected
|
@@ -123,6 +130,7 @@ module Vedeu
|
|
123
130
|
anchor: :left,
|
124
131
|
colour: nil,
|
125
132
|
model: nil,
|
133
|
+
mode: :default,
|
126
134
|
pad: ' ',
|
127
135
|
width: nil,
|
128
136
|
}
|
@@ -150,6 +158,12 @@ module Vedeu
|
|
150
158
|
@model ||= options[:model] || Vedeu::Null::Generic.new
|
151
159
|
end
|
152
160
|
|
161
|
+
# @see Vedeu::Output::Wordwrap#mode
|
162
|
+
# @return [Symbol]
|
163
|
+
def mode
|
164
|
+
options[:mode]
|
165
|
+
end
|
166
|
+
|
153
167
|
# The character to use for padding the string.
|
154
168
|
#
|
155
169
|
# @return [String]
|
@@ -218,6 +232,21 @@ module Vedeu
|
|
218
232
|
options[:width]
|
219
233
|
end
|
220
234
|
|
235
|
+
# Return a boolean indicating whether the string should be
|
236
|
+
# wrapped.
|
237
|
+
#
|
238
|
+
# @return [Boolean]
|
239
|
+
def wrap?
|
240
|
+
options[:mode] == :wrap
|
241
|
+
end
|
242
|
+
|
243
|
+
# Return the content as wrapped lines.
|
244
|
+
#
|
245
|
+
# @return [Vedeu::Views::Lines]
|
246
|
+
def wrapped
|
247
|
+
Vedeu::Output::Wordwrap.for(string, options)
|
248
|
+
end
|
249
|
+
|
221
250
|
end # Text
|
222
251
|
|
223
252
|
end # Output
|
@@ -6,6 +6,8 @@ module Vedeu
|
|
6
6
|
#
|
7
7
|
class Wordwrap
|
8
8
|
|
9
|
+
include Vedeu::Common
|
10
|
+
|
9
11
|
# @see Vedeu::Output::Wordwrap#initialize
|
10
12
|
def self.for(text, options = {})
|
11
13
|
new(text, options).content
|
@@ -17,6 +19,7 @@ module Vedeu
|
|
17
19
|
# @param options [Hash]
|
18
20
|
# @option options ellipsis [String] See {#ellipsis}.
|
19
21
|
# @option options mode [Symbol] See {#mode}.
|
22
|
+
# @option options name [String|Symbol] See {#name}.
|
20
23
|
# @option options width [Fixnum] See {#width}.
|
21
24
|
# @return [Vedeu::Output::Wordwrap]
|
22
25
|
def initialize(text, options = {})
|
@@ -136,31 +139,58 @@ module Vedeu
|
|
136
139
|
|
137
140
|
# Returns the word wrapping mode. One of :default, :prune or
|
138
141
|
# :wrap;
|
142
|
+
#
|
139
143
|
# :default = Renders the content as is.
|
140
144
|
# :prune = Discards the remainder of the content line
|
141
145
|
# after width.
|
142
146
|
# :wrap = Forces the content on to a new line after
|
143
147
|
# width.
|
148
|
+
#
|
144
149
|
# @return [Symbol]
|
145
150
|
def mode
|
146
151
|
options[:mode]
|
147
152
|
end
|
148
153
|
|
154
|
+
# Returns the value of the :name option. When given, and a
|
155
|
+
# geometry is registered with this name, the width of the
|
156
|
+
# geometry is used if the :width option was not given.
|
157
|
+
#
|
158
|
+
# @return [String|Symbol]
|
159
|
+
def name
|
160
|
+
options[:name]
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns a boolean indicating the :name option was given and
|
164
|
+
# a geometry is registered with that name.
|
165
|
+
#
|
166
|
+
# @return [Boolean]
|
167
|
+
def registered?
|
168
|
+
present?(name) && Vedeu.geometries.registered?(name)
|
169
|
+
end
|
170
|
+
|
149
171
|
# Returns the width to prune or wrap to.
|
150
172
|
#
|
173
|
+
# @raise [Vedeu::Error::MissingRequired]
|
151
174
|
# @return [Fixnum]
|
152
175
|
def width
|
153
|
-
options[:width]
|
176
|
+
return options[:width] if present?(options[:width])
|
177
|
+
return Vedeu.geometries.by_name(name).width if registered?
|
178
|
+
|
179
|
+
fail Vedeu::Error::MissingRequired,
|
180
|
+
'The text provided cannot be wrapped or pruned because a :width ' \
|
181
|
+
'option was not given, or a :name option was either not given ' \
|
182
|
+
'or there is no geometry registered with that name.'
|
154
183
|
end
|
155
184
|
|
156
185
|
# Returns the default options/attributes for this class.
|
157
186
|
#
|
158
|
-
# @return [Hash<Symbol =>
|
187
|
+
# @return [Hash<Symbol => NilClass, String, Symbol>]
|
159
188
|
def defaults
|
160
189
|
{
|
161
190
|
ellipsis: '...',
|
162
191
|
mode: :default,
|
163
|
-
|
192
|
+
name: nil,
|
193
|
+
width: nil,
|
164
194
|
}
|
165
195
|
end
|
166
196
|
|
@@ -60,8 +60,14 @@ module Vedeu
|
|
60
60
|
#
|
61
61
|
# @param other [Vedeu::Repositories::Collection]
|
62
62
|
# @return [Vedeu::Repositories::Collection]
|
63
|
-
def add(
|
64
|
-
|
63
|
+
def add(other)
|
64
|
+
if other.is_a?(Vedeu::Repositories::Collection)
|
65
|
+
return self.class.coerce(other, parent, name) if empty?
|
66
|
+
|
67
|
+
else
|
68
|
+
self.class.new(@collection += Array(other), parent, name)
|
69
|
+
|
70
|
+
end
|
65
71
|
end
|
66
72
|
alias_method :<<, :add
|
67
73
|
|
data/lib/vedeu/version.rb
CHANGED
@@ -48,6 +48,22 @@ module Vedeu
|
|
48
48
|
}
|
49
49
|
end
|
50
50
|
|
51
|
+
describe '.store' do
|
52
|
+
before { Vedeu.documents.reset! }
|
53
|
+
|
54
|
+
subject { described.store(attributes) }
|
55
|
+
|
56
|
+
it { subject.must_be_instance_of(described) }
|
57
|
+
|
58
|
+
it 'registers the instance with the repository' do
|
59
|
+
Vedeu.documents.registered?(_name).must_equal(false)
|
60
|
+
|
61
|
+
subject
|
62
|
+
|
63
|
+
Vedeu.documents.registered?(_name).must_equal(true)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
51
67
|
describe 'accessors' do
|
52
68
|
it {
|
53
69
|
instance.must_respond_to(:attributes)
|
@@ -46,10 +46,60 @@ module Vedeu
|
|
46
46
|
|
47
47
|
before { reader.stubs(:read).returns(keypress) }
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
context 'when an interface or view has been registered' do
|
50
|
+
let(:interface_name) { :fake_interface }
|
51
|
+
let(:interface) {
|
52
|
+
Vedeu::Interfaces::Interface.new(name: interface_name, editable: editable)
|
53
|
+
}
|
54
|
+
let(:editable) { false }
|
55
|
+
let(:registered) { false }
|
56
|
+
|
57
|
+
before do
|
58
|
+
Vedeu.stubs(:focus).returns(interface_name)
|
59
|
+
Vedeu.interfaces.stubs(:by_name).with(interface_name).returns(interface)
|
60
|
+
Vedeu::Input::Mapper.expects(:registered?).with(keypress, interface_name).returns(registered)
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when the keypress is registered with the keymap' do
|
64
|
+
let(:registered) { true }
|
65
|
+
|
66
|
+
it 'triggers an event with the keypress' do
|
67
|
+
Vedeu.expects(:trigger).with(:_keypress_, keypress, interface_name)
|
68
|
+
subject
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when the keypress is not registered with the keymap' do
|
73
|
+
let(:registered) { false }
|
74
|
+
|
75
|
+
context 'when the interface or view is editable' do
|
76
|
+
let(:editable) { true }
|
77
|
+
|
78
|
+
it 'triggers an event with the keypress' do
|
79
|
+
Vedeu.expects(:trigger).with(:_editor_, keypress)
|
80
|
+
subject
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when the interface or view is not editable' do
|
85
|
+
let(:editable) { false }
|
86
|
+
|
87
|
+
it 'triggers an event with the keypress' do
|
88
|
+
Vedeu.expects(:trigger).with(:key, keypress)
|
89
|
+
subject
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
52
93
|
end
|
94
|
+
|
95
|
+
# context 'when no interfaces or views have been registered' do
|
96
|
+
# before {
|
97
|
+
# Vedeu.focus.reset
|
98
|
+
# Vedeu.interfaces.reset
|
99
|
+
# }
|
100
|
+
|
101
|
+
# it { proc { subject }.must_raise(Vedeu::Error::Fatal) }
|
102
|
+
# end
|
53
103
|
end
|
54
104
|
|
55
105
|
context 'when in raw mode' do
|
@@ -13,9 +13,9 @@ module Vedeu
|
|
13
13
|
describe Mapper do
|
14
14
|
|
15
15
|
let(:described) { Vedeu::Input::Mapper }
|
16
|
-
let(:instance) { described.new(key,
|
16
|
+
let(:instance) { described.new(key, _name, repository) }
|
17
17
|
let(:key) {}
|
18
|
-
let(:
|
18
|
+
let(:_name) {}
|
19
19
|
let(:repository) {}
|
20
20
|
|
21
21
|
before { Vedeu.keymaps.reset }
|
@@ -23,7 +23,7 @@ module Vedeu
|
|
23
23
|
describe '#initialize' do
|
24
24
|
it { instance.must_be_instance_of(described) }
|
25
25
|
it { instance.instance_variable_get('@key').must_equal(key) }
|
26
|
-
it { instance.instance_variable_get('@name').must_equal(
|
26
|
+
it { instance.instance_variable_get('@name').must_equal(_name) }
|
27
27
|
it do
|
28
28
|
instance.instance_variable_get('@repository').must_equal(Vedeu.keymaps)
|
29
29
|
end
|
@@ -38,11 +38,11 @@ module Vedeu
|
|
38
38
|
end
|
39
39
|
|
40
40
|
describe '.keypress' do
|
41
|
-
let(:
|
41
|
+
let(:_name) { 'test' }
|
42
42
|
|
43
43
|
before { Vedeu.stubs(:log) }
|
44
44
|
|
45
|
-
subject { described.keypress(key,
|
45
|
+
subject { described.keypress(key, _name) }
|
46
46
|
|
47
47
|
context 'when the key is not provided' do
|
48
48
|
it { subject.must_equal(false) }
|
@@ -68,10 +68,43 @@ module Vedeu
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
describe '.registered?' do
|
72
|
+
subject { described.registered?(key, _name) }
|
73
|
+
|
74
|
+
context 'when the name was given' do
|
75
|
+
let(:_name) { :some_keymap }
|
76
|
+
|
77
|
+
context 'when the key was given' do
|
78
|
+
let(:key) { 'a' }
|
79
|
+
|
80
|
+
context 'when the key is defined for the keymap' do
|
81
|
+
# @todo Add more tests.
|
82
|
+
# it { skip }
|
83
|
+
|
84
|
+
# it { subject.must_equal(true) }
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when the key is not defined for the keymap' do
|
88
|
+
it { subject.must_equal(false) }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when the key was not given' do
|
93
|
+
let(:key) {}
|
94
|
+
|
95
|
+
it { proc { subject }.must_raise(Vedeu::Error::MissingRequired) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when the name was not given' do
|
100
|
+
it { proc { subject }.must_raise(Vedeu::Error::MissingRequired) }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
71
104
|
describe '.valid?' do
|
72
|
-
let(:
|
105
|
+
let(:_name) { 'test' }
|
73
106
|
|
74
|
-
subject { described.valid?(key,
|
107
|
+
subject { described.valid?(key, _name) }
|
75
108
|
|
76
109
|
context 'when the key is not provided' do
|
77
110
|
it { subject.must_equal(false) }
|
@@ -118,6 +118,34 @@ module Vedeu
|
|
118
118
|
}
|
119
119
|
end
|
120
120
|
|
121
|
+
describe '#editable' do
|
122
|
+
let(:_value) {}
|
123
|
+
|
124
|
+
subject { instance.editable(_value) }
|
125
|
+
|
126
|
+
context 'when the value is nil' do
|
127
|
+
it { subject.must_equal(false) }
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'when the value is false' do
|
131
|
+
let(:_value) { false }
|
132
|
+
|
133
|
+
it { subject.must_equal(false) }
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'when the value is true' do
|
137
|
+
let(:_value) { true }
|
138
|
+
|
139
|
+
it { subject.must_equal(true) }
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe '#editable!' do
|
144
|
+
subject { instance.editable! }
|
145
|
+
|
146
|
+
it { subject.must_equal(true) }
|
147
|
+
end
|
148
|
+
|
121
149
|
describe '#focus!' do
|
122
150
|
subject { instance.focus! }
|
123
151
|
|
@@ -10,20 +10,22 @@ module Vedeu
|
|
10
10
|
let(:instance) { described.new(attributes) }
|
11
11
|
let(:attributes) {
|
12
12
|
{
|
13
|
-
client:
|
14
|
-
colour:
|
15
|
-
delay:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
client: client,
|
14
|
+
colour: colour,
|
15
|
+
delay: delay,
|
16
|
+
editable: editable,
|
17
|
+
group: group,
|
18
|
+
name: _name,
|
19
|
+
parent: parent,
|
20
|
+
style: style,
|
21
|
+
visible: visible,
|
22
|
+
zindex: zindex,
|
22
23
|
}
|
23
24
|
}
|
24
25
|
let(:client) {}
|
25
26
|
let(:colour) {}
|
26
27
|
let(:delay) { 0.0 }
|
28
|
+
let(:editable) { false }
|
27
29
|
let(:group) { '' }
|
28
30
|
let(:_name) { 'hydrogen' }
|
29
31
|
let(:parent) {}
|
@@ -38,6 +40,7 @@ module Vedeu
|
|
38
40
|
it { subject.must_be_instance_of(described) }
|
39
41
|
it { subject.instance_variable_get('@client').must_equal(client) }
|
40
42
|
it { subject.instance_variable_get('@delay').must_equal(delay) }
|
43
|
+
it { subject.instance_variable_get('@editable').must_equal(editable) }
|
41
44
|
it { subject.instance_variable_get('@group').must_equal(group) }
|
42
45
|
it { subject.instance_variable_get('@name').must_equal(_name) }
|
43
46
|
it { subject.instance_variable_get('@parent').must_equal(parent) }
|
@@ -54,6 +57,9 @@ module Vedeu
|
|
54
57
|
instance.must_respond_to(:client=)
|
55
58
|
instance.must_respond_to(:delay)
|
56
59
|
instance.must_respond_to(:delay=)
|
60
|
+
instance.must_respond_to(:editable)
|
61
|
+
instance.must_respond_to(:editable=)
|
62
|
+
instance.must_respond_to(:editable?)
|
57
63
|
instance.must_respond_to(:group)
|
58
64
|
instance.must_respond_to(:group=)
|
59
65
|
instance.must_respond_to(:name)
|
@@ -43,11 +43,13 @@ module Vedeu
|
|
43
43
|
|
44
44
|
it { subject.must_be_instance_of(FalseClass) }
|
45
45
|
|
46
|
+
it { instance.must_respond_to(:enabled?) }
|
46
47
|
it { instance.must_respond_to(:maximise) }
|
47
48
|
it { instance.must_respond_to(:maximised?) }
|
48
49
|
it { instance.must_respond_to(:unmaximise) }
|
49
50
|
it { instance.must_respond_to(:visible) }
|
50
51
|
it { instance.must_respond_to(:visible?) }
|
52
|
+
it { instance.must_respond_to(:editable?) }
|
51
53
|
end
|
52
54
|
|
53
55
|
describe '#null' do
|
@@ -9,15 +9,17 @@ module Vedeu
|
|
9
9
|
let(:described) { Vedeu::Output::Wordwrap }
|
10
10
|
let(:instance) { described.new(text, options) }
|
11
11
|
let(:text) { '' }
|
12
|
+
let(:mode) { :default }
|
13
|
+
let(:_name) {}
|
14
|
+
let(:width) { 30 }
|
12
15
|
let(:options) {
|
13
16
|
{
|
14
17
|
ellipsis: '...',
|
15
18
|
mode: mode,
|
19
|
+
name: _name,
|
16
20
|
width: width,
|
17
21
|
}
|
18
22
|
}
|
19
|
-
let(:mode) { :default }
|
20
|
-
let(:width) { 30 }
|
21
23
|
|
22
24
|
let(:text_line) {
|
23
25
|
"Krypton (from Greek: κρυπτός kryptos 'the hidden one')."
|
@@ -51,16 +51,8 @@ module Vedeu
|
|
51
51
|
subject { instance.add(:hydrogen) }
|
52
52
|
|
53
53
|
it { instance.must_respond_to(:<<) }
|
54
|
-
it { subject.must_be_instance_of(Collection) }
|
54
|
+
it { subject.must_be_instance_of(Vedeu::Repositories::Collection) }
|
55
55
|
it { subject.all.must_equal([:hydrogen]) }
|
56
|
-
|
57
|
-
context 'with multiple objects' do
|
58
|
-
subject { instance.add(:hydrogen, :helium) }
|
59
|
-
|
60
|
-
it 'adds all the objects to the collection' do
|
61
|
-
subject.all.must_equal([:hydrogen, :helium])
|
62
|
-
end
|
63
|
-
end
|
64
56
|
end
|
65
57
|
|
66
58
|
describe '#all' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vedeu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.38
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gavin Laking
|
@@ -296,6 +296,7 @@ files:
|
|
296
296
|
- docs/view.md
|
297
297
|
- examples/dsl_alignment.rb
|
298
298
|
- examples/dsl_demo_groups.rb
|
299
|
+
- examples/dsl_editor.rb
|
299
300
|
- examples/dsl_hello_worlds.rb
|
300
301
|
- examples/dsl_horizontal_alignment.rb
|
301
302
|
- examples/dsl_vertical_alignment.rb
|
@@ -659,7 +660,6 @@ files:
|
|
659
660
|
- test/support/coverage.rb
|
660
661
|
- test/support/examples/borders_app.rb
|
661
662
|
- test/support/examples/drb_app.rb
|
662
|
-
- test/support/examples/editor_app.rb
|
663
663
|
- test/support/examples/focus_app.rb
|
664
664
|
- test/support/examples/hello_world.rb
|
665
665
|
- test/support/examples/material_colours_app.rb
|
@@ -863,7 +863,6 @@ test_files:
|
|
863
863
|
- test/support/coverage.rb
|
864
864
|
- test/support/examples/borders_app.rb
|
865
865
|
- test/support/examples/drb_app.rb
|
866
|
-
- test/support/examples/editor_app.rb
|
867
866
|
- test/support/examples/focus_app.rb
|
868
867
|
- test/support/examples/hello_world.rb
|
869
868
|
- test/support/examples/material_colours_app.rb
|
@@ -1,70 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'vedeu'
|
5
|
-
|
6
|
-
# An example application to demonstrate colours, cursor and interface movement,
|
7
|
-
# maximising/unmaximising of interfaces and toggling of cursors and interfaces.
|
8
|
-
#
|
9
|
-
# If you have cloned this repository from GitHub, you can run this example:
|
10
|
-
#
|
11
|
-
# ./test/support/examples/material_colours_app.rb
|
12
|
-
#
|
13
|
-
class VedeuEditorApp
|
14
|
-
|
15
|
-
Vedeu.bind(:_initialize_) { Vedeu.trigger(:_refresh_) }
|
16
|
-
|
17
|
-
# Be aware that running an application with profiling enabled will affect
|
18
|
-
# performance.
|
19
|
-
Vedeu.configure do
|
20
|
-
debug!
|
21
|
-
fake!
|
22
|
-
log '/tmp/vedeu_editor_app.log'
|
23
|
-
# profile!
|
24
|
-
# renderers Vedeu::Renderers::File.new
|
25
|
-
end
|
26
|
-
|
27
|
-
Vedeu.interface 'main_interface' do
|
28
|
-
border 'main_interface' do
|
29
|
-
colour foreground: '#ffffff', background: :default
|
30
|
-
title 'Editor'
|
31
|
-
caption('Ctrl+C = Quit')
|
32
|
-
end
|
33
|
-
colour foreground: '#ffffff', background: :default
|
34
|
-
cursor!
|
35
|
-
geometry 'main_interface' do
|
36
|
-
x columns(1)
|
37
|
-
xn columns(11)
|
38
|
-
y rows(1)
|
39
|
-
yn rows(1) + 10
|
40
|
-
end
|
41
|
-
zindex 1
|
42
|
-
end
|
43
|
-
|
44
|
-
Vedeu.keymap('_global_') do
|
45
|
-
key(:up) { Vedeu.trigger(:_cursor_up_) }
|
46
|
-
key(:right) { Vedeu.trigger(:_cursor_right_) }
|
47
|
-
key(:down) { Vedeu.trigger(:_cursor_down_) }
|
48
|
-
key(:left) { Vedeu.trigger(:_cursor_left_) }
|
49
|
-
|
50
|
-
key('q') { Vedeu.trigger(:_exit_) }
|
51
|
-
key(:escape) { Vedeu.trigger(:_mode_switch_) }
|
52
|
-
key(:shift_tab) { Vedeu.trigger(:_focus_prev_) }
|
53
|
-
key(:tab) { Vedeu.trigger(:_focus_next_) }
|
54
|
-
end
|
55
|
-
|
56
|
-
Vedeu.renders do
|
57
|
-
view 'main_interface' do
|
58
|
-
line { line '' }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
Vedeu.focus_by_name 'main_interface'
|
63
|
-
|
64
|
-
def self.start(argv = ARGV)
|
65
|
-
Vedeu::Launcher.execute!(argv)
|
66
|
-
end
|
67
|
-
|
68
|
-
end # VedeuEditorApp
|
69
|
-
|
70
|
-
VedeuEditorApp.start(ARGV)
|