vedeu 0.2.4 → 0.2.5

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