vedeu 0.2.8 → 0.2.9
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/lib/vedeu.rb +1 -0
- data/lib/vedeu/application.rb +1 -1
- data/lib/vedeu/models/buffer.rb +103 -0
- data/lib/vedeu/output/clear.rb +41 -8
- data/lib/vedeu/output/compositor.rb +46 -21
- data/lib/vedeu/output/render.rb +1 -5
- data/lib/vedeu/repositories/buffers.rb +19 -76
- data/lib/vedeu/repositories/focus.rb +0 -16
- data/lib/vedeu/support/coercions.rb +3 -0
- data/lib/vedeu/support/colour_translator.rb +29 -0
- data/lib/vedeu/support/log.rb +2 -0
- data/lib/vedeu/support/repository.rb +1 -0
- data/test/lib/vedeu/api/api_test.rb +7 -2
- data/test/lib/vedeu/application_test.rb +20 -8
- data/test/lib/vedeu/models/buffer_test.rb +182 -0
- data/test/lib/vedeu/output/clear_test.rb +8 -5
- data/test/lib/vedeu/output/compositor_test.rb +91 -43
- data/test/lib/vedeu/output/render_test.rb +3 -50
- data/test/lib/vedeu/repositories/buffers_test.rb +4 -48
- data/test/lib/vedeu/repositories/focus_test.rb +0 -26
- data/test/lib/vedeu/support/repository_test.rb +38 -7
- data/vedeu.gemspec +1 -1
- metadata +5 -2
@@ -95,22 +95,6 @@ module Vedeu
|
|
95
95
|
Vedeu.trigger("_refresh_#{current}_".to_sym)
|
96
96
|
end
|
97
97
|
|
98
|
-
# Returns all registered interfaces by name.
|
99
|
-
#
|
100
|
-
# @return [Array]
|
101
|
-
def registered
|
102
|
-
storage
|
103
|
-
end
|
104
|
-
|
105
|
-
# Returns a boolean indicating whether the named interface is registered.
|
106
|
-
#
|
107
|
-
# @return [Boolean]
|
108
|
-
def registered?(name)
|
109
|
-
return false if storage.empty?
|
110
|
-
|
111
|
-
storage.include?(name)
|
112
|
-
end
|
113
|
-
|
114
98
|
private
|
115
99
|
|
116
100
|
# Return the name of the interface in focus after triggering the refresh
|
@@ -29,6 +29,9 @@ module Vedeu
|
|
29
29
|
# Whenever this module {Vedeu::Coercions} is included in another class or
|
30
30
|
# module, make its methods into class methods, so they may be called
|
31
31
|
# directly.
|
32
|
+
#
|
33
|
+
# @param receiver [Class] The class in which this module is included.
|
34
|
+
# @return []
|
32
35
|
def self.included(receiver)
|
33
36
|
receiver.extend(self)
|
34
37
|
end
|
@@ -80,11 +80,17 @@ module Vedeu
|
|
80
80
|
fail NotImplemented, 'Subclasses implement this.'
|
81
81
|
end
|
82
82
|
|
83
|
+
# Returns a boolean indicating whether the colour provided is a valid named
|
84
|
+
# colour.
|
85
|
+
#
|
83
86
|
# @return [Boolean]
|
84
87
|
def valid_name?
|
85
88
|
Esc.codes.keys.include?(colour)
|
86
89
|
end
|
87
90
|
|
91
|
+
# Returns a boolean indicating whether the colour provided is a terminal
|
92
|
+
# numbered colour.
|
93
|
+
#
|
88
94
|
# @return [Boolean]
|
89
95
|
def numbered?
|
90
96
|
colour.is_a?(Fixnum) && valid_range?
|
@@ -97,11 +103,16 @@ module Vedeu
|
|
97
103
|
fail NotImplemented, 'Subclasses implement this.'
|
98
104
|
end
|
99
105
|
|
106
|
+
# Returns a boolean indicating whether the numbered colour is within the
|
107
|
+
# range of valid terminal numbered colours.
|
108
|
+
#
|
100
109
|
# @return [Boolean]
|
101
110
|
def valid_range?
|
102
111
|
colour >= 0 && colour <= 255
|
103
112
|
end
|
104
113
|
|
114
|
+
# Returns a boolean indicated whether the colour is an HTML/CSS colour.
|
115
|
+
#
|
105
116
|
# @return [Boolean]
|
106
117
|
def rgb?
|
107
118
|
colour.is_a?(String) && valid_rgb?
|
@@ -114,11 +125,20 @@ module Vedeu
|
|
114
125
|
fail NotImplemented, 'Subclasses implement this.'
|
115
126
|
end
|
116
127
|
|
128
|
+
# Returns a boolean indicated whether the colour is a valid HTML/CSS colour.
|
129
|
+
#
|
117
130
|
# @return [Boolean]
|
118
131
|
def valid_rgb?
|
119
132
|
!!(colour =~ /^#([A-Fa-f0-9]{6})$/)
|
120
133
|
end
|
121
134
|
|
135
|
+
# Returns a collection of converted HTML/CSS octets as their decimal
|
136
|
+
# equivalents.
|
137
|
+
#
|
138
|
+
# @example
|
139
|
+
# colour = '#aadd55'
|
140
|
+
# css_to_rgb # => [170, 221, 85]
|
141
|
+
#
|
122
142
|
# @return [Array]
|
123
143
|
def css_to_rgb
|
124
144
|
[
|
@@ -139,16 +159,25 @@ module Vedeu
|
|
139
159
|
end
|
140
160
|
end
|
141
161
|
|
162
|
+
# Takes the red component of {css_to_rgb} and converts to the correct value
|
163
|
+
# for setting the terminal red value.
|
164
|
+
#
|
142
165
|
# @return [Fixnum]
|
143
166
|
def red
|
144
167
|
(css_to_rgb[0] / 51) * 36
|
145
168
|
end
|
146
169
|
|
170
|
+
# Takes the green component of {css_to_rgb} and converts to the correct value
|
171
|
+
# for setting the terminal green value.
|
172
|
+
#
|
147
173
|
# @return [Fixnum]
|
148
174
|
def green
|
149
175
|
(css_to_rgb[1] / 51) * 6
|
150
176
|
end
|
151
177
|
|
178
|
+
# Takes the blue component of {css_to_rgb} and converts to the correct value
|
179
|
+
# for setting the terminal blue value.
|
180
|
+
#
|
152
181
|
# @return [Fixnum]
|
153
182
|
def blue
|
154
183
|
(css_to_rgb[2] / 51) * 1
|
data/lib/vedeu/support/log.rb
CHANGED
@@ -127,8 +127,13 @@ module Vedeu
|
|
127
127
|
end
|
128
128
|
|
129
129
|
describe '.resize' do
|
130
|
-
|
131
|
-
|
130
|
+
before do
|
131
|
+
Interfaces.reset
|
132
|
+
Terminal.console.stubs(:print)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns a TrueClass' do
|
136
|
+
Vedeu.resize.must_be_instance_of(TrueClass)
|
132
137
|
end
|
133
138
|
end
|
134
139
|
|
@@ -4,24 +4,36 @@ module Vedeu
|
|
4
4
|
|
5
5
|
describe Application do
|
6
6
|
|
7
|
-
|
8
|
-
it { skip }
|
9
|
-
end
|
7
|
+
before { Terminal.stubs(:open).returns(['']) }
|
10
8
|
|
11
|
-
describe '.
|
12
|
-
it
|
9
|
+
describe '.start' do
|
10
|
+
it 'returns an Array' do
|
11
|
+
Application.start.must_be_instance_of(Array)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'alias method: .restart' do
|
15
|
+
it 'returns an Array' do
|
16
|
+
Application.restart.must_be_instance_of(Array)
|
17
|
+
end
|
18
|
+
end
|
13
19
|
end
|
14
20
|
|
15
21
|
describe '.stop' do
|
16
|
-
it
|
22
|
+
it 'raises an exception' do
|
23
|
+
proc { Application.stop }.must_raise(StopIteration)
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
27
|
describe '#initialize' do
|
20
|
-
it
|
28
|
+
it 'returns an Application' do
|
29
|
+
Application.new.must_be_instance_of(Application)
|
30
|
+
end
|
21
31
|
end
|
22
32
|
|
23
33
|
describe '#start' do
|
24
|
-
it
|
34
|
+
it 'returns an Array' do
|
35
|
+
Application.new.start.must_be_instance_of(Array)
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
39
|
end # Application
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Vedeu
|
4
|
+
|
5
|
+
describe Buffer do
|
6
|
+
|
7
|
+
let(:attributes) {
|
8
|
+
{
|
9
|
+
name: '',
|
10
|
+
back: back,
|
11
|
+
front: front,
|
12
|
+
previous: previous,
|
13
|
+
}
|
14
|
+
}
|
15
|
+
let(:back) { {} }
|
16
|
+
let(:front) { {} }
|
17
|
+
let(:previous) { {} }
|
18
|
+
|
19
|
+
describe '#initialize' do
|
20
|
+
it 'returns an instance of Buffer' do
|
21
|
+
Buffer.new(attributes).must_be_instance_of(Buffer)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#back' do
|
26
|
+
subject { Buffer.new(attributes).back }
|
27
|
+
|
28
|
+
it { subject.must_be_instance_of(Hash) }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#front' do
|
32
|
+
subject { Buffer.new(attributes).front }
|
33
|
+
|
34
|
+
it { subject.must_be_instance_of(Hash) }
|
35
|
+
|
36
|
+
context 'alias method: #current' do
|
37
|
+
subject { Buffer.new(attributes).current }
|
38
|
+
|
39
|
+
it { subject.must_be_instance_of(Hash) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#name' do
|
44
|
+
subject { Buffer.new(attributes).name }
|
45
|
+
|
46
|
+
it { subject.must_be_instance_of(String) }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#previous' do
|
50
|
+
subject { Buffer.new(attributes).previous }
|
51
|
+
|
52
|
+
it { subject.must_be_instance_of(Hash) }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#back?' do
|
56
|
+
subject { Buffer.new(attributes).back? }
|
57
|
+
|
58
|
+
context 'when there is content on the back buffer' do
|
59
|
+
let(:back) { { lines: [{ streams: [{ text: 'back' }] }] } }
|
60
|
+
|
61
|
+
it { subject.must_equal(true) }
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when there is no content on the back buffer' do
|
65
|
+
it { subject.must_equal(false) }
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when there is no content on the back buffer' do
|
69
|
+
let(:back) { { lines: [] } }
|
70
|
+
|
71
|
+
it { subject.must_equal(false) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#front?' do
|
76
|
+
subject { Buffer.new(attributes).front? }
|
77
|
+
|
78
|
+
context 'when there is content on the front buffer' do
|
79
|
+
let(:front) { { lines: [{ streams: [{ text: 'front' }] }] } }
|
80
|
+
|
81
|
+
it { subject.must_equal(true) }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when there is no content on the front buffer' do
|
85
|
+
it { subject.must_equal(false) }
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when there is no content on the front buffer' do
|
89
|
+
let(:front) { { lines: [] } }
|
90
|
+
|
91
|
+
it { subject.must_equal(false) }
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'alias method: #current?' do
|
95
|
+
subject { Buffer.new(attributes).current? }
|
96
|
+
|
97
|
+
context 'when there is no content on the front buffer' do
|
98
|
+
it { subject.must_equal(false) }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#previous?' do
|
104
|
+
subject { Buffer.new(attributes).previous? }
|
105
|
+
|
106
|
+
context 'when there is content on the previous buffer' do
|
107
|
+
let(:previous) { { lines: [{ streams: [{ text: 'previous' }] }] } }
|
108
|
+
|
109
|
+
it { subject.must_equal(true) }
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when there is no content on the previous buffer' do
|
113
|
+
it { subject.must_equal(false) }
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when there is no content on the previous buffer' do
|
117
|
+
let(:previous) { { lines: [] } }
|
118
|
+
|
119
|
+
it { subject.must_equal(false) }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#add' do
|
124
|
+
let(:attributes) {
|
125
|
+
{
|
126
|
+
back: { lines: [{ streams: [{ text: 'old_back' }] }] }
|
127
|
+
}
|
128
|
+
}
|
129
|
+
let(:buffer) { Buffer.new(attributes) }
|
130
|
+
let(:content) { { lines: [{ streams: [{ text: 'new_back' }] }] } }
|
131
|
+
|
132
|
+
subject { buffer.add(content) }
|
133
|
+
|
134
|
+
it { subject.must_equal(true) }
|
135
|
+
|
136
|
+
it 'replaces the back buffer with the content' do
|
137
|
+
buffer.back.must_equal({ lines: [{ streams: [{ text: 'old_back' }] }] })
|
138
|
+
|
139
|
+
subject
|
140
|
+
|
141
|
+
buffer.back.must_equal({ lines: [{ streams: [{ text: 'new_back' }] }] })
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe '#swap' do
|
146
|
+
let(:buffer) { Buffer.new(attributes) }
|
147
|
+
|
148
|
+
subject { buffer.swap }
|
149
|
+
|
150
|
+
context 'when there is new content on the back buffer' do
|
151
|
+
let(:back) { { lines: [{ streams: [{ text: 'back' }] }] } }
|
152
|
+
let(:front) { { lines: [{ streams: [{ text: 'front' }] }] } }
|
153
|
+
let(:previous) { { lines: [{ streams: [{ text: 'previous' }] }] } }
|
154
|
+
|
155
|
+
context 'when the buffer was updated successfully' do
|
156
|
+
it { subject.must_equal(true) }
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'replaces the previous buffer with the front buffer' do
|
160
|
+
subject
|
161
|
+
buffer.previous.must_equal(front)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'replaces the front buffer with the back buffer' do
|
165
|
+
subject
|
166
|
+
buffer.front.must_equal(back)
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'replaces the back buffer with an empty buffer' do
|
170
|
+
subject
|
171
|
+
buffer.back.must_equal({})
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'when there is no new content on the back buffer' do
|
176
|
+
it { subject.must_equal(false) }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end # Buffer
|
181
|
+
|
182
|
+
end # Vedeu
|
@@ -4,7 +4,10 @@ module Vedeu
|
|
4
4
|
|
5
5
|
describe Clear do
|
6
6
|
|
7
|
-
before
|
7
|
+
before do
|
8
|
+
Interfaces.reset
|
9
|
+
Terminal.console.stubs(:print)
|
10
|
+
end
|
8
11
|
|
9
12
|
describe '#initialize' do
|
10
13
|
it 'returns an instance of itself' do
|
@@ -22,10 +25,10 @@ module Vedeu
|
|
22
25
|
height: 2
|
23
26
|
}
|
24
27
|
})
|
25
|
-
Clear.call(interface).must_equal(
|
28
|
+
Clear.call(interface).must_equal([
|
26
29
|
"\e[1;1H \e[1;1H" \
|
27
30
|
"\e[2;1H \e[2;1H"
|
28
|
-
)
|
31
|
+
])
|
29
32
|
end
|
30
33
|
|
31
34
|
it 'returns the escape sequence to clear the whole interface with specified colours' do
|
@@ -40,11 +43,11 @@ module Vedeu
|
|
40
43
|
background: '#ffff00'
|
41
44
|
}
|
42
45
|
})
|
43
|
-
Clear.call(interface).must_equal(
|
46
|
+
Clear.call(interface).must_equal([
|
44
47
|
"\e[38;2;0;255;0m\e[48;2;255;255;0m" \
|
45
48
|
"\e[1;1H \e[1;1H" \
|
46
49
|
"\e[2;1H \e[2;1H"
|
47
|
-
)
|
50
|
+
])
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
@@ -5,73 +5,121 @@ module Vedeu
|
|
5
5
|
describe Compositor do
|
6
6
|
|
7
7
|
before do
|
8
|
+
Buffers.reset
|
8
9
|
Interfaces.reset
|
9
10
|
Terminal.console.stubs(:print)
|
10
11
|
end
|
11
12
|
|
12
13
|
describe '.render' do
|
13
|
-
|
14
|
-
|
14
|
+
before do
|
15
|
+
Vedeu.interface('indium') do
|
16
|
+
width 10
|
17
|
+
height 1
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
subject { Compositor.render('indium') }
|
22
|
+
|
23
|
+
context 'when the buffer does not exist' do
|
24
|
+
it 'raises an exception' do
|
25
|
+
proc { Compositor.render('') }.must_raise(BufferNotFound)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when the buffer exists' do
|
30
|
+
it 'returns a Array' do
|
31
|
+
subject.must_be_instance_of(Array)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when there is new content' do
|
35
|
+
let(:back) {
|
36
|
+
{ name: 'indium', lines: [{ streams: [{ text: 'back' }] }] }
|
37
|
+
}
|
38
|
+
before do
|
39
|
+
Buffers.add(back)
|
24
40
|
end
|
25
41
|
|
26
|
-
|
42
|
+
it 'returns the current/front content' do
|
43
|
+
subject.must_equal([
|
44
|
+
"\e[1;1H \e[1;1H\e[1;1Hback",
|
45
|
+
"\e[1;1H\e[?25l"
|
46
|
+
])
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'swaps the new content with the current content' do
|
50
|
+
Buffers.find('indium').back.must_equal(back)
|
27
51
|
|
28
|
-
|
29
|
-
"\e[1;1H \e[1;1H" \
|
30
|
-
"\e[2;1H \e[2;1H" \
|
31
|
-
"\e[3;1H \e[3;1H",
|
52
|
+
subject
|
32
53
|
|
33
|
-
|
34
|
-
|
54
|
+
Buffers.find('indium').back.must_equal({})
|
55
|
+
Buffers.find('indium').front.must_equal(back)
|
56
|
+
end
|
35
57
|
end
|
36
|
-
end
|
37
58
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
59
|
+
context 'when there is no new content' do
|
60
|
+
let(:front) { { name: 'indium', lines: [{ streams: [{ text: 'front' }] }] } }
|
61
|
+
|
62
|
+
before do
|
63
|
+
Buffers.add(front)
|
64
|
+
Buffers.find('indium').swap
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'returns the current/front content' do
|
68
|
+
subject.must_equal([
|
69
|
+
"\e[1;1H \e[1;1H\e[1;1Hfront",
|
70
|
+
"\e[1;1H\e[?25l"
|
71
|
+
])
|
45
72
|
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when there is no new or current content' do
|
76
|
+
let(:previous) { { name: 'indium', lines: [{ streams: [{ text: 'previous' }] }] } }
|
77
|
+
|
78
|
+
before do
|
79
|
+
Buffers.add(previous)
|
80
|
+
Buffers.find('indium').swap
|
81
|
+
Buffers.find('indium').swap
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'returns the previous content' do
|
85
|
+
subject.must_equal([
|
86
|
+
"\e[1;1H \e[1;1H\e[1;1Hprevious",
|
87
|
+
"\e[1;1H\e[?25l"
|
88
|
+
])
|
89
|
+
end
|
90
|
+
end
|
46
91
|
|
47
|
-
|
92
|
+
context 'when there is no new, current or previous content' do
|
93
|
+
let(:clear) { { name: 'indium', lines: [] } }
|
48
94
|
|
49
|
-
|
50
|
-
|
51
|
-
view 'neon' do
|
52
|
-
line 'argon'
|
53
|
-
line 'boron'
|
54
|
-
line 'radon'
|
55
|
-
end
|
56
|
-
end
|
95
|
+
before do
|
96
|
+
Buffers.add(clear)
|
57
97
|
end
|
58
98
|
|
59
|
-
|
99
|
+
it 'returns the escape sequences to clear the interface' do
|
100
|
+
subject.must_equal(["\e[1;1H \e[1;1H", "\e[1;1H\e[?25l"])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
60
104
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
"\e[2;1Hboron" \
|
67
|
-
"\e[3;1Hradon",
|
105
|
+
context 'when the interface cannot be found' do
|
106
|
+
before do
|
107
|
+
Interfaces.reset
|
108
|
+
Buffers.add({ name: 'indium' })
|
109
|
+
end
|
68
110
|
|
69
|
-
|
70
|
-
|
111
|
+
it 'raises an exception' do
|
112
|
+
proc { Compositor.render('indium') }.must_raise(InterfaceNotFound)
|
71
113
|
end
|
72
114
|
end
|
73
115
|
end
|
74
116
|
|
117
|
+
describe '#initialize' do
|
118
|
+
it 'returns an instance of Compositor' do
|
119
|
+
Compositor.new('indium').must_be_instance_of(Compositor)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
75
123
|
end # Compositor
|
76
124
|
|
77
125
|
end # Vedeu
|