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.
@@ -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
@@ -3,6 +3,8 @@ require 'time'
3
3
 
4
4
  module Vedeu
5
5
 
6
+ # Allows the creation of a lock-less log device.
7
+ #
6
8
  # @api private
7
9
  class MonoLogger < Logger
8
10
 
@@ -42,6 +42,7 @@ module Vedeu
42
42
  return [] if storage.empty?
43
43
 
44
44
  return storage.keys if storage.is_a?(Hash)
45
+ return storage.to_a if storage.is_a?(Set)
45
46
 
46
47
  storage
47
48
  end
@@ -127,8 +127,13 @@ module Vedeu
127
127
  end
128
128
 
129
129
  describe '.resize' do
130
- it 'triggers the :_clear_, and :_refresh_ events' do
131
- skip
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
- describe '.start' do
8
- it { skip }
9
- end
7
+ before { Terminal.stubs(:open).returns(['']) }
10
8
 
11
- describe '.restart' do
12
- it { skip }
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 { skip }
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 { skip }
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 { skip }
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 { Interfaces.reset }
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
- it 'raises an exception if the buffer/interface cannot be found' do
14
- proc { Compositor.render('') }.must_raise(BufferNotFound)
14
+ before do
15
+ Vedeu.interface('indium') do
16
+ width 10
17
+ height 1
18
+ end
15
19
  end
16
20
 
17
- context 'when the buffer is nil' do
18
- it 'clears the defined area for the interface' do
19
- Vedeu.interface('xenon') do
20
- x 1
21
- y 1
22
- width 5
23
- height 3
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
- Vedeu.focus('xenon')
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
- Compositor.render('xenon').must_equal([
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
- "\e[1;1H\e[?25l"
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
- context 'when the buffer is not nil' do
39
- it 'renders the content in the defined area for the interface' do
40
- Vedeu.interface('neon') do
41
- x 1
42
- y 1
43
- width 5
44
- height 3
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
- Vedeu.focus('neon')
92
+ context 'when there is no new, current or previous content' do
93
+ let(:clear) { { name: 'indium', lines: [] } }
48
94
 
49
- class MyCompositorView < Vedeu::View
50
- def render
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
- MyCompositorView.render
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
- Compositor.render('neon').must_equal([
62
- "\e[1;1H \e[1;1H" \
63
- "\e[2;1H \e[2;1H" \
64
- "\e[3;1H \e[3;1H" \
65
- "\e[1;1Hargon" \
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
- "\e[1;1H\e[?25l"
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