vedeu 0.2.4 → 0.2.5

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/LICENSE.txt +5 -0
  4. data/bin/vedeu +3 -1
  5. data/docs/api.md +2 -0
  6. data/examples/cursor_app/cursor_app.rb +22 -7
  7. data/examples/hello_world.rb +42 -0
  8. data/lib/vedeu.rb +5 -5
  9. data/lib/vedeu/api/api.rb +16 -33
  10. data/lib/vedeu/api/helpers.rb +86 -0
  11. data/lib/vedeu/api/interface.rb +60 -17
  12. data/lib/vedeu/api/keymap.rb +5 -0
  13. data/lib/vedeu/api/line.rb +52 -34
  14. data/lib/vedeu/api/menu.rb +1 -1
  15. data/lib/vedeu/api/stream.rb +0 -34
  16. data/lib/vedeu/configuration/api.rb +10 -10
  17. data/lib/vedeu/configuration/cli.rb +1 -1
  18. data/lib/vedeu/launcher.rb +21 -6
  19. data/lib/vedeu/models/background.rb +1 -1
  20. data/lib/vedeu/models/composition.rb +1 -1
  21. data/lib/vedeu/models/cursor.rb +25 -35
  22. data/lib/vedeu/models/foreground.rb +1 -1
  23. data/lib/vedeu/models/geometry.rb +216 -6
  24. data/lib/vedeu/models/interface.rb +14 -16
  25. data/lib/vedeu/models/keymap.rb +38 -6
  26. data/lib/vedeu/models/line.rb +1 -1
  27. data/lib/vedeu/models/stream.rb +1 -1
  28. data/lib/vedeu/output/compositor.rb +1 -1
  29. data/lib/vedeu/output/render.rb +1 -5
  30. data/lib/vedeu/output/viewport.rb +37 -2
  31. data/lib/vedeu/repositories/buffers.rb +21 -27
  32. data/lib/vedeu/repositories/cursors.rb +3 -15
  33. data/lib/vedeu/repositories/focus.rb +2 -6
  34. data/lib/vedeu/repositories/groups.rb +1 -1
  35. data/lib/vedeu/repositories/interfaces.rb +1 -1
  36. data/lib/vedeu/repositories/keymaps.rb +26 -22
  37. data/lib/vedeu/repositories/menus.rb +1 -1
  38. data/lib/vedeu/repositories/offsets.rb +30 -12
  39. data/lib/vedeu/repositories/positional.rb +23 -0
  40. data/lib/vedeu/support/colour_translator.rb +1 -16
  41. data/lib/vedeu/support/esc.rb +23 -28
  42. data/lib/vedeu/support/event.rb +6 -14
  43. data/lib/vedeu/{output → support}/refresh.rb +0 -0
  44. data/lib/vedeu/support/registrar.rb +6 -14
  45. data/lib/vedeu/support/repository.rb +3 -2
  46. data/lib/vedeu/support/terminal.rb +9 -13
  47. data/lib/vedeu/support/trace.rb +2 -3
  48. data/test/integration/cursors_test.rb +9 -0
  49. data/test/integration/views/basic_view_test.rb +19 -0
  50. data/test/lib/vedeu/api/api_test.rb +28 -5
  51. data/test/lib/vedeu/api/composition_test.rb +7 -3
  52. data/test/lib/vedeu/api/defined_test.rb +9 -3
  53. data/test/lib/vedeu/api/helpers_test.rb +39 -5
  54. data/test/lib/vedeu/api/interface_test.rb +88 -8
  55. data/test/lib/vedeu/api/keymap_test.rb +5 -3
  56. data/test/lib/vedeu/api/line_test.rb +9 -3
  57. data/test/lib/vedeu/api/menu_test.rb +11 -7
  58. data/test/lib/vedeu/api/stream_test.rb +9 -31
  59. data/test/lib/vedeu/application_test.rb +25 -2
  60. data/test/lib/vedeu/configuration/api_test.rb +5 -3
  61. data/test/lib/vedeu/configuration/cli_test.rb +5 -3
  62. data/test/lib/vedeu/configuration/configuration_test.rb +5 -2
  63. data/test/lib/vedeu/input/input_test.rb +5 -2
  64. data/test/lib/vedeu/launcher_test.rb +37 -2
  65. data/test/lib/vedeu/models/background_test.rb +6 -2
  66. data/test/lib/vedeu/models/char_test.rb +9 -6
  67. data/test/lib/vedeu/models/colour_test.rb +6 -2
  68. data/test/lib/vedeu/models/composition_test.rb +4 -2
  69. data/test/lib/vedeu/models/cursor_test.rb +27 -16
  70. data/test/lib/vedeu/models/foreground_test.rb +6 -2
  71. data/test/lib/vedeu/models/geometry_test.rb +6 -2
  72. data/test/lib/vedeu/models/interface_test.rb +5 -2
  73. data/test/lib/vedeu/models/keymap_test.rb +6 -4
  74. data/test/lib/vedeu/models/line_test.rb +5 -2
  75. data/test/lib/vedeu/models/offset_test.rb +7 -3
  76. data/test/lib/vedeu/models/stream_test.rb +4 -2
  77. data/test/lib/vedeu/models/style_test.rb +5 -2
  78. data/test/lib/vedeu/output/clear_test.rb +6 -2
  79. data/test/lib/vedeu/output/compositor_test.rb +8 -4
  80. data/test/lib/vedeu/output/render_test.rb +9 -6
  81. data/test/lib/vedeu/output/view_test.rb +7 -3
  82. data/test/lib/vedeu/output/viewport_test.rb +42 -9
  83. data/test/lib/vedeu/repositories/buffers_test.rb +52 -12
  84. data/test/lib/vedeu/repositories/cursors_test.rb +4 -26
  85. data/test/lib/vedeu/repositories/events_test.rb +6 -2
  86. data/test/lib/vedeu/repositories/focus_test.rb +5 -2
  87. data/test/lib/vedeu/repositories/groups_test.rb +5 -2
  88. data/test/lib/vedeu/repositories/interfaces_test.rb +4 -2
  89. data/test/lib/vedeu/repositories/keymaps_test.rb +8 -2
  90. data/test/lib/vedeu/repositories/menus_test.rb +3 -2
  91. data/test/lib/vedeu/repositories/offsets_test.rb +26 -19
  92. data/test/lib/vedeu/repositories/positional_test.rb +50 -0
  93. data/test/lib/vedeu/support/coercions_test.rb +7 -3
  94. data/test/lib/vedeu/support/colour_translator_test.rb +6 -2
  95. data/test/lib/vedeu/support/common_test.rb +5 -3
  96. data/test/lib/vedeu/support/esc_test.rb +6 -2
  97. data/test/lib/vedeu/support/event_test.rb +6 -2
  98. data/test/lib/vedeu/support/grid_test.rb +9 -3
  99. data/test/lib/vedeu/support/keymap_validator_test.rb +5 -2
  100. data/test/lib/vedeu/support/log_test.rb +4 -2
  101. data/test/lib/vedeu/support/menu_test.rb +10 -2
  102. data/test/lib/vedeu/support/position_test.rb +10 -2
  103. data/test/lib/vedeu/support/presentation_test.rb +6 -3
  104. data/test/lib/vedeu/{output → support}/refresh_test.rb +6 -2
  105. data/test/lib/vedeu/support/registrar_test.rb +2 -2
  106. data/test/lib/vedeu/support/repository_test.rb +4 -3
  107. data/test/lib/vedeu/support/terminal_test.rb +6 -2
  108. data/test/lib/vedeu/support/trace_test.rb +17 -2
  109. data/test/lib/vedeu_test.rb +1 -1
  110. data/vedeu.gemspec +2 -2
  111. metadata +13 -13
  112. data/lib/vedeu/output/area.rb +0 -284
  113. data/lib/vedeu/support/move.rb +0 -50
  114. data/test/lib/vedeu/output/area_test.rb +0 -242
  115. data/test/lib/vedeu/support/move_test.rb +0 -35
@@ -7,10 +7,6 @@ module Vedeu
7
7
  # @api private
8
8
  class Render
9
9
 
10
- extend Forwardable
11
-
12
- def_delegators :interface, :viewport
13
-
14
10
  # Create a new instance of Render with the provided {Vedeu::Interface} and
15
11
  # then convert the interface into a single string of content and escape
16
12
  # sequences.
@@ -38,7 +34,7 @@ module Vedeu
38
34
 
39
35
  Vedeu.log("Rendering view: '#{interface.name}'")
40
36
 
41
- viewport.each_with_index do |line, index|
37
+ interface.viewport.each_with_index do |line, index|
42
38
  out << interface.origin(index)
43
39
  out << line.join
44
40
  end
@@ -29,6 +29,11 @@ module Vedeu
29
29
 
30
30
  # Returns the visible content for the interface.
31
31
  #
32
+ # @note If there are no lines of content, we return an empty array. If there
33
+ # are no more columns of content we return a space enclosed in an array;
34
+ # this prevents a weird line hopping bug which occurs when the current
35
+ # line has no more content, but subsequent lines do.
36
+ #
32
37
  # @return [Array]
33
38
  def show
34
39
  line_adjustment
@@ -36,13 +41,18 @@ module Vedeu
36
41
 
37
42
  return [] unless content?
38
43
 
39
- content[lines].map { |line| line.chars[columns] }.compact
44
+ (content[lines] || []).map do |line|
45
+ line.chars[columns] || [" "]
46
+ end.compact
40
47
  end
41
48
 
42
49
  private
43
50
 
44
51
  attr_reader :interface
45
52
 
53
+ # Scrolls the content vertically when the stored y offset for the interface
54
+ # is outside of the visible area.
55
+ #
46
56
  # @return [Fixnum]
47
57
  def line_adjustment
48
58
  if offset.y < lines.min
@@ -57,6 +67,9 @@ module Vedeu
57
67
  end
58
68
  end
59
69
 
70
+ # Scrolls the content horizontally when the stored x offset for the
71
+ # interface is outside of the visible area.
72
+ #
60
73
  # @return [Fixnum]
61
74
  def column_adjustment
62
75
  if offset.x < columns.min
@@ -71,23 +84,45 @@ module Vedeu
71
84
  end
72
85
  end
73
86
 
87
+ #
88
+ # @note
89
+ # @top = [value, 0].max # this allows us to set a top that is greater than
90
+ # # the content height.
91
+ #
92
+ # @top = [[value, (content_height - height)].min, 0].max
93
+ # # this does not allow us to have an offset greater
94
+ # # than the content height.
95
+ #
74
96
  # @param value [Fixnum]
75
97
  # @return [Fixnum]
76
98
  def set_top(value)
77
- @top = [[value, (content_height - height)].min, 0].max
99
+ @top = [value, 0].max
78
100
  end
79
101
 
102
+ #
103
+ # @note
104
+ # @left = [value, 0].max # this allows us to set a left that is greater
105
+ # # than the content width.
106
+ #
107
+ # @left = [[value, (content_width - width)].min, 0].max
108
+ # # this does not allow us to have an offset greater
109
+ # # than the content width.
110
+ #
80
111
  # @param value [Fixnum]
81
112
  # @return [Fixnum]
82
113
  def set_left(value)
83
114
  @left = [value, 0].max
84
115
  end
85
116
 
117
+ # Using the current x offset, return a range of visible lines.
118
+ #
86
119
  # @return [Range]
87
120
  def lines
88
121
  @top..(@top + height - 1)
89
122
  end
90
123
 
124
+ # Using the current y offset, return a range of visible columns.
125
+ #
91
126
  # @return [Range]
92
127
  def columns
93
128
  @left..(@left + width - 1)
@@ -35,6 +35,24 @@ module Vedeu
35
35
  attributes[:name]
36
36
  end
37
37
 
38
+ # Return the named back buffer.
39
+ #
40
+ # @param name [String]
41
+ # @raise [BufferNotFound] When the named buffer cannot be found.
42
+ # @return [Hash|Nil]
43
+ def back(name)
44
+ find(name)[:back_buffer]
45
+ end
46
+
47
+ # Return the named front buffer.
48
+ #
49
+ # @param name [String]
50
+ # @raise [BufferNotFound] When the named buffer cannot be found.
51
+ # @return [Hash|Nil]
52
+ def front(name)
53
+ find(name)[:front_buffer]
54
+ end
55
+
38
56
  # Returns the latest content for the named buffer. The latest content always
39
57
  # goes on to the back buffer. The content which was last output is on the
40
58
  # front buffer.
@@ -53,7 +71,7 @@ module Vedeu
53
71
  def latest(name)
54
72
  swap_buffers(name) if new_content?(name)
55
73
 
56
- front_buffer(name)
74
+ front(name)
57
75
  end
58
76
 
59
77
  private
@@ -80,31 +98,7 @@ module Vedeu
80
98
  # @param name [String]
81
99
  # @return [Boolean]
82
100
  def new_content?(name)
83
- defined_value?(back_buffer(name))
84
- end
85
-
86
- # Return a boolean indicating whether the named front buffer has content.
87
- #
88
- # @param name [String]
89
- # @return [Boolean]
90
- # def old_content?(name)
91
- # defined_value?(front_buffer(name))
92
- # end
93
-
94
- # Return the named back buffer.
95
- #
96
- # @param name [String]
97
- # @return [Hash|Nil]
98
- def back_buffer(name)
99
- find(name)[:back_buffer]
100
- end
101
-
102
- # Return the named front buffer.
103
- #
104
- # @param name [String]
105
- # @return [Hash|Nil]
106
- def front_buffer(name)
107
- find(name)[:front_buffer]
101
+ defined_value?(back(name))
108
102
  end
109
103
 
110
104
  # @return [Hash]
@@ -121,7 +115,7 @@ module Vedeu
121
115
  # @raise [BufferNotFound] When the entity cannot be found with this name.
122
116
  # @return [BufferNotFound]
123
117
  def not_found(name)
124
- fail BufferNotFound, "Cannot find buffer with this name: #{name.to_s}."
118
+ fail BufferNotFound, "Cannot find buffer with this name: #{name}."
125
119
  end
126
120
 
127
121
  end # Buffers
@@ -8,25 +8,13 @@ module Vedeu
8
8
 
9
9
  include Common
10
10
  include Repository
11
+ include Positional
11
12
  extend self
12
13
 
13
14
  # System events which when called will update the cursor visibility
14
15
  # accordingly for the interface in focus.
15
- Vedeu.event(:_cursor_hide_) { Cursors.hide }
16
- Vedeu.event(:_cursor_show_) { Cursors.show }
17
-
18
- # Adds an interface to the cursors repository.
19
- #
20
- # @param attributes [Hash]
21
- # @return [Hash]
22
- def add(attributes)
23
- validate_attributes!(attributes)
24
-
25
- Vedeu.log("#{action(__callee__)} cursor: '#{attributes[:name]}'")
26
-
27
- storage.store(attributes[:name], Cursor.new(attributes))
28
- end
29
- alias_method :update, :add
16
+ Vedeu.event(:_cursor_hide_) { Cursors.hide }
17
+ Vedeu.event(:_cursor_show_) { Cursors.show }
30
18
 
31
19
  # Make the cursor of this interface invisible.
32
20
  #
@@ -25,13 +25,9 @@ module Vedeu
25
25
  def add(attributes)
26
26
  validate_attributes!(attributes)
27
27
 
28
- if registered?(attributes[:name])
29
- storage
28
+ return storage << attributes[:name] unless registered?(attributes[:name])
30
29
 
31
- else
32
- storage << attributes[:name]
33
-
34
- end
30
+ storage
35
31
  end
36
32
 
37
33
  # Focus an interface by name.
@@ -48,7 +48,7 @@ module Vedeu
48
48
  # @return [GroupNotFound]
49
49
  def not_found(name)
50
50
  fail GroupNotFound,
51
- "Cannot find interface group with this name: #{name.to_s}."
51
+ "Cannot find interface group with this name: #{name}."
52
52
  end
53
53
 
54
54
  end # Groups
@@ -74,7 +74,7 @@ module Vedeu
74
74
  # @return [InterfaceNotFound]
75
75
  def not_found(name)
76
76
  fail InterfaceNotFound,
77
- "Interface was not found with this name: #{name.to_s}."
77
+ "Interface was not found with this name: #{name}."
78
78
  end
79
79
 
80
80
  end # Interfaces
@@ -12,6 +12,9 @@ module Vedeu
12
12
  # Stores the keymap attributes defined by the API.
13
13
  #
14
14
  # @param attributes [Hash]
15
+ # @option attributes :interfaces [Array] A list of the names of interfaces for which the
16
+ # keys are active for.
17
+ # @option attributes :keys [Array] A collection of key/action pairs.
15
18
  # @return [TrueClass|KeyInUse|FalseClass]
16
19
  def add(attributes)
17
20
  return false unless defined_value?(attributes[:keys])
@@ -72,10 +75,15 @@ module Vedeu
72
75
  end
73
76
  end
74
77
 
75
- # Return a collection of interface keys.
78
+ # Return a collection of interface keys. When the optional 'name' parameter
79
+ # is provided, then only the keys associated with that interface are
80
+ # returned.
76
81
  #
82
+ # @param interface [String]
77
83
  # @return [Hash]
78
- def interface_keys
84
+ def interface_keys(interface = nil)
85
+ return find(interface).keys if interface
86
+
79
87
  storage.reject do |k, _|
80
88
  k == '_global_keymap_'
81
89
  end.map { |_, v| v.keys }.flatten.uniq
@@ -89,7 +97,7 @@ module Vedeu
89
97
  system_keys.include?(key)
90
98
  end
91
99
 
92
- # Return a collection of system keys.
100
+ # Return the collection of system keys.
93
101
  #
94
102
  # @return [Array]
95
103
  def system_keys
@@ -121,10 +129,10 @@ module Vedeu
121
129
  focussed_interface = Vedeu::Focus.current
122
130
 
123
131
  if interface_key?(key, focussed_interface)
124
- find(focussed_interface).fetch(key, noop).call
132
+ find(focussed_interface).fetch(key, noop).call(:noop_interface)
125
133
 
126
134
  elsif global_key?(key)
127
- find('_global_keymap_').fetch(key, noop).call
135
+ find('_global_keymap_').fetch(key, noop).call(:noop_global)
128
136
 
129
137
  elsif system_key?(key)
130
138
  system_key(key)
@@ -134,13 +142,14 @@ module Vedeu
134
142
 
135
143
  end
136
144
  end
145
+ alias_method :keypress, :use
137
146
 
138
147
  private
139
148
 
140
149
  # Triggers the system event defined for this key.
141
150
  #
142
151
  # @param key [String|Symbol]
143
- # @return []
152
+ # @return [] The result(s) of triggering the event.
144
153
  def system_key(key)
145
154
  action = Vedeu::Configuration.system_keys.key(key)
146
155
  event = ['_', action, '_'].join.to_sym
@@ -153,34 +162,29 @@ module Vedeu
153
162
  # @param attributes [Hash]
154
163
  # @param interface [String]
155
164
  # @return []
156
- def register(attributes, interface = '')
165
+ def register(attributes, interface = '_global_keymap_')
157
166
  attributes[:keys].map do |keymap|
158
167
  KeymapValidator.check(storage, keymap[:key], interface)
159
168
 
160
- Vedeu.log("Registering key: '#{keymap[:key]}' with '#{namespace(interface)}'")
169
+ Vedeu.log("Registering key: '#{keymap[:key]}' with '#{interface}'")
161
170
 
162
- storage[namespace(interface)].merge!({ keymap[:key] => keymap[:action] })
171
+ storage[interface].merge!({ keymap[:key] => keymap[:action] })
163
172
  end
164
173
  end
165
174
 
166
- # Determine which interface to store the key with.
167
- #
168
- # @param interface [String]
169
- # @return [String]
170
- def namespace(interface = '')
171
- return defined_value?(interface) ? interface : '_global_keymap_'
172
- end
173
-
174
- # Returns a noop proc which when called returns :noop.
175
+ # Returns a noop proc which when called returns the argument or :noop.
175
176
  #
177
+ # @param value [Symbol]
176
178
  # @return [Proc]
177
- def noop
178
- proc { :noop }
179
+ def noop(value = :noop)
180
+ proc { value }
179
181
  end
180
182
 
181
- # @return [Array]
183
+ # @return [Hash]
182
184
  def in_memory
183
- { '_global_keymap_' => {} }
185
+ {
186
+ '_global_keymap_' => {}
187
+ }
184
188
  end
185
189
 
186
190
  end # Keymaps
@@ -70,7 +70,7 @@ module Vedeu
70
70
  # @raise [MenuNotFound] When the entity cannot be found with this name.
71
71
  # @return [MenuNotFound]
72
72
  def not_found(name)
73
- fail MenuNotFound, "Menu was not found with this name: #{name.to_s}."
73
+ fail MenuNotFound, "Menu was not found with this name: #{name}."
74
74
  end
75
75
 
76
76
  end # Menus
@@ -8,29 +8,39 @@ module Vedeu
8
8
 
9
9
  include Common
10
10
  include Repository
11
+ include Positional
11
12
  extend self
12
13
 
13
- # Add or update the offset coordinates for interface content.
14
- #
15
- # @param attributes [Hash]
16
- # @return [Offset]
17
- def add(attributes)
18
- validate_attributes!(attributes)
14
+ # @return [Array]
15
+ def down
16
+ move(1, 0)
17
+ end
19
18
 
20
- Vedeu.log("#{action(__callee__)} offset: '#{attributes[:name]}'")
19
+ # @return [Array]
20
+ def up
21
+ move(-1, 0)
22
+ end
21
23
 
22
- storage.store(attributes[:name], Offset.new(attributes))
24
+ # @return [Array]
25
+ def right
26
+ move(0, 1)
23
27
  end
24
- alias_method :update, :add
28
+
29
+ # @return [Array]
30
+ def left
31
+ move(0, -1)
32
+ end
33
+
34
+ private
25
35
 
26
36
  # @param y [Fixnum]
27
37
  # @param x [Fixnum]
28
- # @return [Offset]
38
+ # @return [Array]
29
39
  def move(y, x)
30
40
  find_or_create(Focus.current).move(y, x)
31
- end
32
41
 
33
- private
42
+ Focus.refresh
43
+ end
34
44
 
35
45
  # @return [Class]
36
46
  def entity
@@ -42,6 +52,14 @@ module Vedeu
42
52
  {}
43
53
  end
44
54
 
55
+ # System events which when called will move in the direction specified;
56
+ # these will update the cursor position or content offset (scrolling)
57
+ # according to the interface in focus.
58
+ Vedeu.event(:_cursor_up_) { up }
59
+ Vedeu.event(:_cursor_right_) { right }
60
+ Vedeu.event(:_cursor_down_) { down }
61
+ Vedeu.event(:_cursor_left_) { left }
62
+
45
63
  end # Offsets
46
64
 
47
65
  end # Vedeu
@@ -0,0 +1,23 @@
1
+ module Vedeu
2
+
3
+ # Repository helper module which reduces duplication in Offsets and Cursors.
4
+ #
5
+ module Positional
6
+
7
+ # Add or update the offset or cursor coordinates.
8
+ #
9
+ # @param attributes [Hash]
10
+ # @return [Offset]
11
+ def add(attributes)
12
+ validate_attributes!(attributes)
13
+
14
+ Vedeu.log("#{action(__callee__)} positional (#{entity}): " \
15
+ "'#{attributes[:name]}'")
16
+
17
+ storage.store(attributes[:name], entity.new(attributes))
18
+ end
19
+ alias_method :update, :add
20
+
21
+ end # Positional
22
+
23
+ end # Vedeu