vedeu 0.4.14 → 0.4.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -3
  3. data/README.md +47 -35
  4. data/docs/views.md +1 -1
  5. data/examples/material_colours_app.rb +0 -5
  6. data/lib/vedeu/cursor/cursor.rb +4 -5
  7. data/lib/vedeu/cursor/move.rb +52 -84
  8. data/lib/vedeu/cursor/refresh_cursor.rb +12 -18
  9. data/lib/vedeu/debug.rb +3 -1
  10. data/lib/vedeu/geometry/area.rb +0 -2
  11. data/lib/vedeu/geometry/coordinate.rb +10 -0
  12. data/lib/vedeu/geometry/dimension.rb +34 -18
  13. data/lib/vedeu/geometry/null_geometry.rb +10 -1
  14. data/lib/vedeu/geometry/position.rb +1 -1
  15. data/lib/vedeu/geometry/position_validator.rb +2 -2
  16. data/lib/vedeu/input/mapper.rb +4 -18
  17. data/lib/vedeu/main_loop.rb +1 -3
  18. data/lib/vedeu/models/cell.rb +11 -17
  19. data/lib/vedeu/models/interface.rb +0 -7
  20. data/lib/vedeu/output/border.rb +34 -61
  21. data/lib/vedeu/output/clear.rb +39 -14
  22. data/lib/vedeu/output/colour.rb +15 -15
  23. data/lib/vedeu/output/esc.rb +1 -1
  24. data/lib/vedeu/output/html_char.rb +18 -24
  25. data/lib/vedeu/output/null_border.rb +14 -10
  26. data/lib/vedeu/output/presentation.rb +32 -8
  27. data/lib/vedeu/output/renderers/all.rb +1 -0
  28. data/lib/vedeu/output/renderers/text_renderer.rb +40 -0
  29. data/lib/vedeu/output/translator.rb +2 -4
  30. data/lib/vedeu/output/viewport.rb +22 -13
  31. data/lib/vedeu/output/virtual_terminal.rb +0 -1
  32. data/lib/vedeu/repositories/repositories/borders.rb +3 -4
  33. data/lib/vedeu/repositories/repositories/cursors.rb +13 -1
  34. data/lib/vedeu/repositories/repositories/geometries.rb +1 -1
  35. data/lib/vedeu/support/all.rb +1 -0
  36. data/lib/vedeu/support/options.rb +65 -0
  37. data/lib/vedeu/support/terminal.rb +3 -5
  38. data/test/lib/vedeu/cursor/cursor_test.rb +0 -5
  39. data/test/lib/vedeu/cursor/move_test.rb +87 -92
  40. data/test/lib/vedeu/geometry/null_geometry_test.rb +3 -1
  41. data/test/lib/vedeu/models/cell_test.rb +13 -16
  42. data/test/lib/vedeu/models/interface_test.rb +0 -17
  43. data/test/lib/vedeu/output/border_test.rb +0 -22
  44. data/test/lib/vedeu/output/clear_test.rb +4 -2
  45. data/test/lib/vedeu/output/null_border_test.rb +8 -4
  46. data/test/lib/vedeu/output/renderers/text_renderer_test.rb +24 -0
  47. data/test/lib/vedeu/repositories/repositories/borders_test.rb +1 -13
  48. data/test/lib/vedeu/support/options_test.rb +70 -0
  49. data/vedeu.gemspec +1 -1
  50. metadata +8 -2
@@ -107,17 +107,15 @@ module Vedeu
107
107
 
108
108
  # Subclasses implement this method.
109
109
  #
110
- # @param colour [String]
111
110
  # @return [String]
112
- def retrieve(colour)
111
+ def retrieve(*)
113
112
  ''
114
113
  end
115
114
 
116
115
  # Subclasses implement this method.
117
116
  #
118
- # @param colour [String]
119
117
  # @return [FalseClass]
120
- def registered?(colour)
118
+ def registered?(*)
121
119
  false
122
120
  end
123
121
 
@@ -118,41 +118,50 @@ module Vedeu
118
118
  left..(left + (geometry.width - 1))
119
119
  end
120
120
 
121
- # Returns the offset for the content (the number of columns to change the
122
- # viewport by on the x axis) determined by the offset (the cursor's x
123
- # offset position).
124
- #
125
121
  # @return [Fixnum]
126
122
  def left
127
- @left ||= (ox >= width && ((ox - width) > 0)) ? ox - width : 0
123
+ @left ||= content_offset(ox, width)
128
124
  end
129
125
 
130
- # Returns the offset for the content (the number of rows to change the
131
- # viewport by on the y axis) determined by the offset (the cursor's y offset
132
- # position.
133
- #
134
126
  # @return [Fixnum]
135
127
  def top
136
- @top ||= (oy >= height && ((oy - height) > 0)) ? oy - height : 0
128
+ @top ||= content_offset(oy, height)
129
+ end
130
+
131
+ # Returns the offset for the content (the number of rows or columns to
132
+ # change the viewport by on either the y or x axis) determined by the offset
133
+ # (the cursor's y or x offset position.
134
+ #
135
+ # @param offset [Fixnum] The cursor's {oy} or {ox} values.
136
+ # @param dimension [Fixnum] Either the height or width.
137
+ # @return [Fixnum]
138
+ def content_offset(offset, dimension)
139
+ if offset >= dimension && ((offset - dimension) > 0)
140
+ offset - dimension
141
+
142
+ else
143
+ 0
144
+
145
+ end
137
146
  end
138
147
 
139
148
  # Return the border associated with the interface we are drawing.
140
149
  #
141
- # @return [Vedeu::Border|Vedeu::NullBorder]
150
+ # @return (see Vedeu::Borders#by_name)
142
151
  def border
143
152
  @border ||= Vedeu.borders.by_name(name)
144
153
  end
145
154
 
146
155
  # Fetch the cursor associated with the interface we are drawing.
147
156
  #
148
- # @return [Vedeu::Cursor]
157
+ # @return (see Vedeu::Cursors#by_name)
149
158
  def cursor
150
159
  @cursor ||= Vedeu.cursors.by_name(name)
151
160
  end
152
161
 
153
162
  # Return the geometry associated with the interface we are drawing.
154
163
  #
155
- # @return [Vedeu::Geometry|Vedeu::NullGeometry]
164
+ # @return (see Vedeu::Geometries#by_name)
156
165
  def geometry
157
166
  @geometry || Vedeu.geometries.by_name(name)
158
167
  end
@@ -120,4 +120,3 @@ module Vedeu
120
120
  end # VirtualTerminal
121
121
 
122
122
  end # Vedeu
123
-
@@ -21,14 +21,13 @@ module Vedeu
21
21
  end
22
22
 
23
23
  # @param name [String] The name of the stored border.
24
- # @return [Vedeu::Border|Vedeu::NullBorder|NilClass]
24
+ # @return [Vedeu::Border|Vedeu::NullBorder]
25
25
  def by_name(name)
26
26
  if registered?(name)
27
27
  find(name)
28
28
 
29
- elsif Vedeu.interfaces.registered?(name)
30
- interface = Vedeu.interfaces.find(name)
31
- Vedeu::NullBorder.new(interface)
29
+ else
30
+ Vedeu::NullBorder.new(name)
32
31
 
33
32
  end
34
33
  end
@@ -11,7 +11,7 @@ module Vedeu
11
11
 
12
12
  # @return [Vedeu::Cursor]
13
13
  def self.cursor
14
- cursors.current
14
+ cursors.by_name(Vedeu.focus) if Vedeu.focus
15
15
  end
16
16
 
17
17
  # @return [Vedeu::Cursors]
@@ -24,6 +24,18 @@ module Vedeu
24
24
  @cursors = Vedeu::Cursors.register_repository(Vedeu::Cursor)
25
25
  end
26
26
 
27
+ # @param name [String] The name of the stored cursor.
28
+ # @return [Vedeu::Cursor]
29
+ def by_name(name)
30
+ if registered?(name)
31
+ find(name)
32
+
33
+ else
34
+ Vedeu::Cursor.new(name: name).store
35
+
36
+ end
37
+ end
38
+
27
39
  end # Cursors
28
40
 
29
41
  end # Vedeu
@@ -27,7 +27,7 @@ module Vedeu
27
27
  find(name)
28
28
 
29
29
  else
30
- Vedeu::NullGeometry.new
30
+ Vedeu::NullGeometry.new(name)
31
31
 
32
32
  end
33
33
  end
@@ -1,4 +1,5 @@
1
1
  require_relative 'common'
2
+ require_relative 'options'
2
3
  require_relative 'template'
3
4
  require_relative 'terminal'
4
5
  require_relative 'trace'
@@ -0,0 +1,65 @@
1
+ module Vedeu
2
+
3
+ # Converts an options Hash into a class containing methods for each of the
4
+ # keys, which when called returns the value associated. When the value is
5
+ # either true or false, an additional predicate method is created.
6
+ #
7
+ class Options
8
+
9
+ # @!attribute [r] _defined
10
+ # @return [Array<Symbol>]
11
+ attr_reader :_defined
12
+
13
+ # @param options [Hash]
14
+ # @return [Vedeu::Options]
15
+ def self.build(options = {})
16
+ new(options)._build
17
+ end
18
+
19
+ # @param options [Hash]
20
+ # @return [Vedeu::Options]
21
+ def initialize(options = {})
22
+ @_options = options
23
+ @_defined = []
24
+ end
25
+
26
+ # @return [Vedeu::Options]
27
+ def _build
28
+ _options.each do |name, value|
29
+ _create_method(name) { value }
30
+
31
+ if value.is_a?(TrueClass) || value.is_a?(FalseClass)
32
+ _create_alias("#{name}?", name)
33
+ end
34
+ end
35
+
36
+ self
37
+ end
38
+
39
+ private
40
+
41
+ # @!attribute [r] _options
42
+ # @return [Hash]
43
+ attr_reader :_options
44
+
45
+ # @param alias_name [String|Symbol]
46
+ # @param method_name [String|Symbol]
47
+ # @return [void]
48
+ def _create_alias(alias_name, method_name)
49
+ @_defined << alias_name.to_sym
50
+
51
+ define_singleton_method(alias_name, method(method_name))
52
+ end
53
+
54
+ # @param name [String|Symbol]
55
+ # @param block [Proc]
56
+ # @return [void]
57
+ def _create_method(name, &block)
58
+ @_defined << name.to_sym
59
+
60
+ self.class.send(:define_method, name, &block)
61
+ end
62
+
63
+ end # Option
64
+
65
+ end # Vedeu
@@ -14,10 +14,9 @@ module Vedeu
14
14
  # Opens a terminal screen in either `raw` or `cooked` mode. On exit,
15
15
  # attempts to restore the screen. See {Vedeu::Terminal#restore_screen}.
16
16
  #
17
- # @param block [Proc]
18
17
  # @raise [InvalidSyntax] The required block was not given.
19
18
  # @return [Array]
20
- def open(&block)
19
+ def open
21
20
  fail InvalidSyntax, 'block not given' unless block_given?
22
21
 
23
22
  if raw_mode?
@@ -91,12 +90,11 @@ module Vedeu
91
90
  true
92
91
  end
93
92
 
94
- # @param block [Proc]
95
93
  # @return [void]
96
- def initialize_screen(&block)
94
+ def initialize_screen
97
95
  output(Esc.string('screen_init'))
98
96
 
99
- yield
97
+ yield if block_given?
100
98
  end
101
99
 
102
100
  # Clears the entire terminal space.
@@ -37,11 +37,6 @@ module Vedeu
37
37
  it { subject.instance_variable_get('@visible').must_equal(true) }
38
38
  it { subject.instance_variable_get('@x').must_equal(19) }
39
39
  it { subject.instance_variable_get('@y').must_equal(8) }
40
-
41
- it do
42
- subject.instance_variable_get('@position').
43
- must_be_instance_of(Vedeu::Position)
44
- end
45
40
  end
46
41
 
47
42
  describe '#inspect' do
@@ -5,63 +5,65 @@ module Vedeu
5
5
  describe Move do
6
6
 
7
7
  let(:described) { Vedeu::Move }
8
- let(:instance) { described.new(cursor, interface, dy, dx) }
9
- let(:cursor) {
10
- Cursor.new(name: 'Move',
11
- ox: ox,
12
- oy: oy,
13
- visible: true,
14
- x: x,
15
- y: y)
16
- }
8
+ let(:instance) { described.new(_name, dy, dx) }
9
+ let(:_name) { '' }
10
+ let(:dy) { 0 }
11
+ let(:dx) { 0 }
17
12
  let(:ox) { 0 }
18
13
  let(:oy) { 0 }
19
14
  let(:x) { 1 }
20
15
  let(:y) { 1 }
21
16
 
22
- let(:interface) {
23
- Vedeu.interface 'magnesium' do
24
- geometry do
25
-
26
- end
27
- end
28
- }
29
- let(:interface_with_border) {
30
- Vedeu.interface 'manganese' do
17
+ before do
18
+ Vedeu.borders.reset
19
+ Vedeu.cursors.reset
20
+ Vedeu.geometries.reset
21
+ Vedeu.interfaces.reset
22
+
23
+ Vedeu::Cursor.new(name: 'move_with_border',
24
+ ox: ox,
25
+ oy: oy,
26
+ visible: true,
27
+ x: x,
28
+ y: y).store
29
+ Vedeu::Cursor.new(name: 'move_without_border',
30
+ ox: ox,
31
+ oy: oy,
32
+ visible: true,
33
+ x: x,
34
+ y: y).store
35
+ Vedeu.interface 'move_with_border' do
31
36
  border do
32
37
  # ...
33
38
  end
34
39
  geometry do
35
- height 5
36
- width 5
37
- x 5
38
- y 5
40
+ x 5
41
+ xn 10
42
+ y 5
43
+ yn 10
39
44
  end
40
45
  end
41
- }
42
- let(:interface_without_border) {
43
- Vedeu.interface 'meitnerium' do
46
+ Vedeu.interface 'move_without_border' do
44
47
  geometry do
45
- height 5
46
- width 5
47
- x 5
48
- y 5
48
+ x 5
49
+ xn 10
50
+ y 5
51
+ yn 10
49
52
  end
50
53
  end
51
- }
52
-
53
- let(:dy) { 0 }
54
- let(:dx) { 0 }
55
-
56
- before do
57
54
  IO.console.stubs(:winsize).returns([25, 80])
58
55
  IO.console.stubs(:print)
59
56
  end
57
+ after do
58
+ Vedeu.borders.reset
59
+ Vedeu.cursors.reset
60
+ Vedeu.geometries.reset
61
+ Vedeu.interfaces.reset
62
+ end
60
63
 
61
64
  describe '#initialize' do
62
65
  it { instance.must_be_instance_of(Vedeu::Move) }
63
- it { instance.instance_variable_get('@cursor').must_equal(cursor) }
64
- it { instance.instance_variable_get('@interface').must_equal(interface) }
66
+ it { instance.instance_variable_get('@name').must_equal(_name) }
65
67
  it { instance.instance_variable_get('@dy').must_equal(dy) }
66
68
  it { instance.instance_variable_get('@dx').must_equal(dx) }
67
69
  end
@@ -71,10 +73,6 @@ module Vedeu
71
73
  let(:_name) { 'manganese' }
72
74
 
73
75
  before do
74
- Vedeu.interfaces.reset
75
- Vedeu.cursors.reset
76
-
77
- interface_with_border
78
76
  Vedeu::Cursor.new(name: 'manganese', oy: 2, ox: 3, x: 8, y: 7).store
79
77
  end
80
78
 
@@ -119,122 +117,117 @@ module Vedeu
119
117
  end
120
118
 
121
119
  describe '.down' do
122
- subject { Move.down(cursor, interface) }
120
+ let(:_name) { 'move_down' }
121
+
122
+ subject { Move.down(_name) }
123
123
 
124
124
  it { subject.must_be_instance_of(Vedeu::Cursor) }
125
125
 
126
126
  it { subject.y.must_equal(2) }
127
127
 
128
- context 'when moving, the cursor must be within the boundary of the ' \
129
- 'interface' do
130
- subject { Move.down(cursor, interface_without_border) }
131
- let(:y) { 15 }
128
+ context 'when within the boundary of the interface' do
129
+ let(:_name) { 'move_without_border' }
130
+ let(:oy) { 15 }
132
131
 
133
132
  it 'does not move past the bottom of the interface' do
134
- subject.y.must_equal(6)
133
+ subject.y.must_equal(10)
135
134
  end
136
135
  end
137
136
 
138
- context 'when moving, the cursor must be within the border of the ' \
139
- 'interface' do
140
- subject { Move.down(cursor, interface_with_border) }
141
- let(:y) { 15 }
137
+ context 'when within the border of the interface' do
138
+ let(:_name) { 'move_with_border' }
139
+ let(:oy) { 15 }
142
140
 
143
141
  it 'does not move past the bottom border' do
144
- subject.y.must_equal(6)
142
+ subject.y.must_equal(9)
145
143
  end
146
144
  end
147
145
  end
148
146
 
149
147
  describe '.left' do
150
- subject { Move.left(cursor, interface) }
148
+ let(:_name) { 'move_left' }
149
+
150
+ subject { Move.left(_name) }
151
151
 
152
152
  it { subject.must_be_instance_of(Vedeu::Cursor) }
153
153
 
154
154
  it { subject.x.must_equal(1) }
155
155
 
156
- context 'when moving, the cursor must be within the boundary of the ' \
157
- 'interface' do
158
- subject { Move.left(cursor, interface_without_border) }
159
- let(:x) { 3 }
156
+ context 'when within the boundary of the interface' do
157
+ let(:_name) { 'move_without_border' }
160
158
 
161
159
  it 'does not move past the left of the interface' do
162
- subject.x.must_equal(3)
160
+ subject.x.must_equal(5)
163
161
  end
164
162
  end
165
163
 
166
- context 'when moving, the cursor must be within the border of the ' \
167
- 'interface' do
168
- subject { Move.left(cursor, interface_with_border) }
169
- let(:x) { 4 }
164
+ context 'when within the border of the interface' do
165
+ let(:_name) { 'move_with_border' }
170
166
 
171
167
  it 'does not move past the left border' do
172
- subject.x.must_equal(4)
168
+ subject.x.must_equal(6)
173
169
  end
174
170
  end
175
171
  end
176
172
 
177
173
  describe '.right' do
178
- subject { Move.right(cursor, interface) }
174
+ let(:_name) { 'move_right' }
175
+
176
+ subject { Move.right(_name) }
179
177
 
180
178
  it { subject.must_be_instance_of(Vedeu::Cursor) }
181
179
 
182
180
  it { subject.x.must_equal(2) }
183
181
 
184
- context 'when moving, the cursor must be within the boundary of the ' \
185
- 'interface' do
186
- subject { Move.right(cursor, interface_without_border) }
187
- let(:x) { 14 }
182
+ context 'when within the boundary of the interface' do
183
+ let(:_name) { 'move_without_border' }
184
+ let(:ox) { 15 }
188
185
 
189
186
  it 'does not move past the right of the interface' do
190
- subject.x.must_equal(6)
187
+ subject.x.must_equal(10)
191
188
  end
192
189
  end
193
190
 
194
- context 'when moving, the cursor must be within the border of the ' \
195
- 'interface' do
196
- subject { Move.right(cursor, interface_with_border) }
197
-
198
- let(:x) { 14 }
191
+ context 'when within the border of the interface' do
192
+ let(:_name) { 'move_with_border' }
193
+ let(:ox) { 15 }
199
194
 
200
195
  it 'does not move past the right border' do
201
- subject.x.must_equal(6)
196
+ subject.x.must_equal(9)
202
197
  end
203
198
  end
204
199
  end
205
200
 
206
201
  describe '.up' do
207
- subject { Move.up(cursor, interface) }
202
+ let(:_name) { 'move_up' }
203
+
204
+ subject { Move.up(_name) }
208
205
 
209
206
  it { subject.must_be_instance_of(Vedeu::Cursor) }
210
207
 
211
208
  it { subject.y.must_equal(1) }
212
209
 
213
- context 'when moving, the cursor must be within the boundary of the ' \
214
- 'interface' do
215
- subject { Move.up(cursor, interface_without_border) }
216
-
217
- let(:y) { 3 }
210
+ context 'when within the boundary of the interface' do
211
+ let(:_name) { 'move_without_border' }
218
212
 
219
213
  it 'does not move past the top of the interface' do
220
- subject.y.must_equal(3)
214
+ subject.y.must_equal(5)
221
215
  end
222
216
  end
223
217
 
224
- context 'when moving, the cursor must be within the border of the ' \
225
- 'interface' do
226
- subject { Move.up(cursor, interface_with_border) }
227
-
228
- let(:y) { 3 }
218
+ context 'when within the border of the interface' do
219
+ let(:_name) { 'move_with_border' }
229
220
 
230
221
  it 'does not move past the top border' do
231
- subject.y.must_equal(3)
222
+ subject.y.must_equal(6)
232
223
  end
233
224
  end
234
225
  end
235
226
 
236
227
  describe '#origin' do
237
- subject { Move.origin(cursor, interface) }
228
+ let(:_name) { 'move_origin' }
229
+
230
+ subject { Move.origin(_name) }
238
231
 
239
232
  it { subject.must_be_instance_of(Vedeu::Cursor) }
240
233
 
@@ -244,14 +237,14 @@ module Vedeu
244
237
  end
245
238
 
246
239
  context 'within the boundary of the interface' do
247
- subject { Move.origin(cursor, interface_without_border) }
240
+ let(:_name) { 'move_without_border' }
248
241
 
249
242
  it { subject.x.must_equal(5) }
250
243
  it { subject.y.must_equal(5) }
251
244
  end
252
245
 
253
246
  context 'within the border of the interface' do
254
- subject { Move.origin(cursor, interface_with_border) }
247
+ let(:_name) { 'move_with_border' }
255
248
 
256
249
  it { subject.x.must_equal(6) }
257
250
  it { subject.y.must_equal(6) }
@@ -259,7 +252,9 @@ module Vedeu
259
252
  end
260
253
 
261
254
  describe '#move' do
262
- subject { Move.new(cursor, interface, dy, dx).move }
255
+ let(:_name) { 'move_move' }
256
+
257
+ subject { Move.new(_name, dy, dx).move }
263
258
 
264
259
  it { subject.must_be_instance_of(Vedeu::Cursor) }
265
260
  end