vedeu 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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