vedeu 0.4.14 → 0.4.15

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.
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