vedeu 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/README.md +1 -2
  4. data/Rakefile +5 -5
  5. data/bin/vedeu +8 -4
  6. data/docs/api.md +3 -1
  7. data/docs/events.md +43 -29
  8. data/docs/getting_started.md +2 -0
  9. data/examples/cursor_app/cursor_app.rb +85 -0
  10. data/examples/lines_app/lines_app.rb +60 -0
  11. data/lib/vedeu.rb +9 -3
  12. data/lib/vedeu/api/api.rb +28 -7
  13. data/lib/vedeu/api/composition.rb +2 -0
  14. data/lib/vedeu/api/helpers.rb +2 -0
  15. data/lib/vedeu/api/interface.rb +2 -20
  16. data/lib/vedeu/api/keymap.rb +2 -0
  17. data/lib/vedeu/api/line.rb +2 -0
  18. data/lib/vedeu/api/menu.rb +3 -1
  19. data/lib/vedeu/api/stream.rb +25 -2
  20. data/lib/vedeu/application.rb +4 -4
  21. data/lib/vedeu/configuration/api.rb +327 -0
  22. data/lib/vedeu/configuration/cli.rb +110 -0
  23. data/lib/vedeu/{configuration.rb → configuration/configuration.rb} +49 -99
  24. data/lib/vedeu/launcher.rb +0 -1
  25. data/lib/vedeu/models/attributes/colour_translator.rb +2 -2
  26. data/lib/vedeu/models/colour.rb +0 -1
  27. data/lib/vedeu/models/composition.rb +2 -8
  28. data/lib/vedeu/models/cursor.rb +261 -0
  29. data/lib/vedeu/models/geometry.rb +11 -19
  30. data/lib/vedeu/models/interface.rb +2 -12
  31. data/lib/vedeu/models/keymap.rb +2 -0
  32. data/lib/vedeu/models/line.rb +2 -0
  33. data/lib/vedeu/models/stream.rb +2 -0
  34. data/lib/vedeu/models/style.rb +2 -0
  35. data/lib/vedeu/output/clear.rb +0 -1
  36. data/lib/vedeu/output/compositor.rb +0 -1
  37. data/lib/vedeu/output/refresh.rb +3 -0
  38. data/lib/vedeu/output/render.rb +12 -6
  39. data/lib/vedeu/output/view.rb +1 -0
  40. data/lib/vedeu/repositories/cursors.rb +98 -0
  41. data/lib/vedeu/repositories/events.rb +0 -1
  42. data/lib/vedeu/repositories/focus.rb +18 -0
  43. data/lib/vedeu/repositories/menus.rb +4 -4
  44. data/lib/vedeu/support/common.rb +2 -1
  45. data/lib/vedeu/support/event.rb +1 -10
  46. data/lib/vedeu/support/grid.rb +1 -2
  47. data/lib/vedeu/{repositories → support}/keymap_validator.rb +5 -4
  48. data/lib/vedeu/support/log.rb +3 -0
  49. data/lib/vedeu/support/menu.rb +4 -1
  50. data/lib/vedeu/support/registrar.rb +2 -1
  51. data/test/integration/defining_interfaces_test.rb +0 -1
  52. data/test/integration/views/basic_view_test.rb +741 -739
  53. data/test/lib/vedeu/api/api_test.rb +14 -3
  54. data/test/lib/vedeu/api/helpers_test.rb +3 -3
  55. data/test/lib/vedeu/api/interface_test.rb +17 -70
  56. data/test/lib/vedeu/api/keymap_test.rb +2 -0
  57. data/test/lib/vedeu/api/line_test.rb +4 -4
  58. data/test/lib/vedeu/api/menu_test.rb +6 -5
  59. data/test/lib/vedeu/api/stream_test.rb +18 -0
  60. data/test/lib/vedeu/configuration/api_test.rb +248 -0
  61. data/test/lib/vedeu/configuration/cli_test.rb +88 -0
  62. data/test/lib/vedeu/configuration/configuration_test.rb +67 -0
  63. data/test/lib/vedeu/input/input_test.rb +2 -2
  64. data/test/lib/vedeu/models/attributes/background_test.rb +3 -3
  65. data/test/lib/vedeu/models/attributes/foreground_test.rb +3 -3
  66. data/test/lib/vedeu/models/composition_test.rb +0 -222
  67. data/test/lib/vedeu/models/cursor_test.rb +164 -0
  68. data/test/lib/vedeu/models/interface_test.rb +0 -11
  69. data/test/lib/vedeu/output/compositor_test.rb +2 -4
  70. data/test/lib/vedeu/output/render_test.rb +4 -41
  71. data/test/lib/vedeu/repositories/cursors_test.rb +13 -0
  72. data/test/lib/vedeu/repositories/focus_test.rb +14 -4
  73. data/test/lib/vedeu/repositories/menus_test.rb +36 -29
  74. data/test/lib/vedeu/{repositories → support}/keymap_validator_test.rb +0 -0
  75. data/test/lib/vedeu/support/menu_test.rb +3 -3
  76. data/test/lib/vedeu/support/registrar_test.rb +6 -0
  77. data/test/lib/vedeu/support/terminal_test.rb +2 -2
  78. data/test/test_helper.rb +1 -1
  79. data/vedeu.gemspec +1 -1
  80. metadata +23 -14
  81. data/elements.txt +0 -118
  82. data/lib/vedeu/support/cursor.rb +0 -96
  83. data/test/lib/vedeu/configuration_test.rb +0 -154
  84. data/test/lib/vedeu/support/cursor_test.rb +0 -79
  85. data/test/support/model_test_data.json +0 -437
@@ -3,22 +3,13 @@ module Vedeu
3
3
  # Calculates and provides interface geometry determined by both the client's
4
4
  # requirements and the terminal's current viewing area.
5
5
  #
6
- # With terminal geometry, the origin is top-left, y = 1, x = 1.
6
+ # Geometry for Vedeu, as the same for ANSI terminals, has the origin at
7
+ # top-left, y = 1, x = 1. The 'y' coordinate is deliberately first.
7
8
  #
8
9
  # @api private
9
10
  class Geometry
10
11
 
11
- # @return [Hash]
12
- attr_reader :attributes
13
-
14
- # @return [Boolean]
15
- attr_reader :centred
16
-
17
- # @return [Fixnum]
18
- attr_reader :height
19
-
20
- # @return [Fixnum]
21
- attr_reader :width
12
+ attr_reader :attributes, :centred, :height, :width
22
13
 
23
14
  # Returns a new instance of Geometry.
24
15
  #
@@ -110,8 +101,8 @@ module Vedeu
110
101
  Esc.set_position(virtual_y[index], left, &block)
111
102
  end
112
103
 
113
- # Returns a fixed or dynamic value depending on whether the interface is
114
- # centred or not.
104
+ # Returns the top coordinate of the interface, a fixed or dynamic value
105
+ # depending on whether the interface is centred or not.
115
106
  #
116
107
  # @return [Fixnum]
117
108
  def top
@@ -139,8 +130,8 @@ module Vedeu
139
130
  top - value
140
131
  end
141
132
 
142
- # Returns a fixed or dynamic value depending on whether the interface is
143
- # centred or not.
133
+ # Returns the left coordinate of the interface, a fixed or dynamic value
134
+ # depending on whether the interface is centred or not.
144
135
  #
145
136
  # @return [Fixnum]
146
137
  def left
@@ -168,7 +159,8 @@ module Vedeu
168
159
  left - value
169
160
  end
170
161
 
171
- # Returns a fixed or dynamic value depending on the value of {#top}.
162
+ # Returns the bottom coordinate of the interface, a fixed or dynamic value
163
+ # depending on the value of {#top}.
172
164
  #
173
165
  # @return [Fixnum]
174
166
  def bottom
@@ -190,8 +182,8 @@ module Vedeu
190
182
  bottom + value
191
183
  end
192
184
 
193
- # Returns a fixed or dynamic value depending on whether the interface is
194
- # centred or not.
185
+ # Returns the right coordinate of the interface, a fixed or dynamic value
186
+ # depending on the value of {#left}.
195
187
  #
196
188
  # @return [Fixnum]
197
189
  def right
@@ -3,6 +3,8 @@ module Vedeu
3
3
  # An Interface represents a portion of the terminal defined by
4
4
  # {Vedeu::Geometry}. It is a container for {Vedeu::Line} and {Vedeu::Stream}
5
5
  # objects.
6
+ #
7
+ # @api private
6
8
  class Interface
7
9
 
8
10
  include Coercions
@@ -79,17 +81,6 @@ module Vedeu
79
81
  @geometry ||= Geometry.new(attributes[:geometry])
80
82
  end
81
83
 
82
- # @return [String]
83
- def cursor
84
- @cursor ||= if attributes[:cursor] == true
85
- Esc.string('show_cursor')
86
-
87
- else
88
- Esc.string('hide_cursor')
89
-
90
- end
91
- end
92
-
93
84
  private
94
85
 
95
86
  # The default values for a new instance of Interface.
@@ -104,7 +95,6 @@ module Vedeu
104
95
  colour: {},
105
96
  style: '',
106
97
  geometry: {},
107
- cursor: true,
108
98
  delay: 0.0,
109
99
  parent: nil,
110
100
  }
@@ -2,6 +2,8 @@ module Vedeu
2
2
 
3
3
  # A Keymap is the binding of a keypress to one or more interfaces; or globally
4
4
  # to perform a client application defined action.
5
+ #
6
+ # @api private
5
7
  class Keymap
6
8
 
7
9
  include Common
@@ -3,6 +3,8 @@ module Vedeu
3
3
  # A Line represents a single row of the terminal. It is a container for
4
4
  # {Vedeu::Stream} objects. A line's width is determined by the
5
5
  # {Vedeu::Interface} it belongs to.
6
+ #
7
+ # @api private
6
8
  class Line
7
9
 
8
10
  include Coercions
@@ -3,6 +3,8 @@ module Vedeu
3
3
  # A Stream can represent a character or collection of characters as part of a
4
4
  # {Vedeu::Line} which you wish to colour and style independently of the other
5
5
  # characters in that line.
6
+ #
7
+ # @api private
6
8
  class Stream
7
9
 
8
10
  include Coercions
@@ -2,6 +2,8 @@ module Vedeu
2
2
 
3
3
  # Converts the style value or value collection into a terminal escape
4
4
  # sequence. Unrecognised values are discarded- an empty string is returned.
5
+ #
6
+ # @api private
5
7
  class Style
6
8
 
7
9
  include Vedeu::Common
@@ -36,7 +36,6 @@ module Vedeu
36
36
 
37
37
  private
38
38
 
39
- # @return [Interface]
40
39
  attr_reader :interface
41
40
 
42
41
  # @api private
@@ -31,7 +31,6 @@ module Vedeu
31
31
 
32
32
  private
33
33
 
34
- # @return [String]
35
34
  attr_reader :name
36
35
 
37
36
  # Renders the buffer unless empty, otherwise clears the area which the
@@ -8,6 +8,9 @@ module Vedeu
8
8
  include Vedeu::Common
9
9
  extend self
10
10
 
11
+ # System event to refresh all registered interfaces.
12
+ Vedeu.event(:_refresh_) { Vedeu::Refresh.all }
13
+
11
14
  # Refresh all registered interfaces.
12
15
  #
13
16
  # @return [Array]
@@ -39,13 +39,11 @@ module Vedeu
39
39
  out << interface.origin(index)
40
40
  out << line.to_s
41
41
  end
42
- out << interface.cursor
43
42
  out.join
44
43
  end
45
44
 
46
45
  private
47
46
 
48
- # @return [Interface]
49
47
  attr_reader :interface
50
48
 
51
49
  # The client application may have created a line that us too long for the
@@ -58,9 +56,9 @@ module Vedeu
58
56
  # @api private
59
57
  # @return [Array]
60
58
  def processed_lines
61
- return [] unless lines.any? { |line| line.streams.any? }
59
+ return [] unless visible_lines.any? { |line| line.streams.any? }
62
60
 
63
- lines.map do |line|
61
+ visible_lines.map do |line|
64
62
  if exceeds_width?(line)
65
63
  line_length = 0
66
64
  new_streams = []
@@ -142,14 +140,22 @@ module Vedeu
142
140
  text.chomp.slice(0...value)
143
141
  end
144
142
 
145
- # Provides a collection of lines associated with the interface.
143
+ # Provides the collection of visible lines associated with the interface.
146
144
  # If the option `:top` was set, we will start at that line. Any lines
147
145
  # outside of the height will not be rendered.
148
146
  #
149
147
  # @api private
150
148
  # @return [Array]
149
+ def visible_lines
150
+ lines[top..height]
151
+ end
152
+
153
+ # Provides the collection of lines associated with the interface.
154
+ #
155
+ # @api private
156
+ # @return [Array]
151
157
  def lines
152
- interface.lines[top..height]
158
+ interface.lines
153
159
  end
154
160
 
155
161
  # Provides the currently available height of the interface.
@@ -7,6 +7,7 @@ module Vedeu
7
7
  #
8
8
  # @deprecated May disappear in 0.3.0. Prefer {Vedeu::API#render} instead.
9
9
  # @see Vedeu::API#render
10
+ # @api private
10
11
  class View
11
12
 
12
13
  include Vedeu::API
@@ -0,0 +1,98 @@
1
+ module Vedeu
2
+
3
+ # Repository for storing, retrieving and manipulating the cursor position and
4
+ # visibility for an interface.
5
+ #
6
+ # @api private
7
+ module Cursors
8
+
9
+ include Common
10
+ extend self
11
+
12
+ # System events which when called will update the cursor position or
13
+ # visibility accordingly for the interface in focus.
14
+ Vedeu.event(:_cursor_up_) { Cursors.use(:move_up) }
15
+ Vedeu.event(:_cursor_right_) { Cursors.use(:move_right) }
16
+ Vedeu.event(:_cursor_down_) { Cursors.use(:move_down) }
17
+ Vedeu.event(:_cursor_left_) { Cursors.use(:move_left) }
18
+ Vedeu.event(:_cursor_hide_) { Cursors.use(:hide) }
19
+ Vedeu.event(:_cursor_show_) { Cursors.use(:show) }
20
+ Vedeu.event(:_cursor_refresh_) { Cursors.use(:refresh) }
21
+
22
+ # Adds an interface to the cursors repository.
23
+ #
24
+ # @param attributes [Hash]
25
+ # @return [Hash]
26
+ def add(attributes)
27
+ return false unless defined_value?(attributes[:name])
28
+
29
+ storage.store(attributes[:name], {
30
+ name: attributes[:name],
31
+ x: 1,
32
+ y: 1,
33
+ state: :show
34
+ })
35
+ end
36
+
37
+ # Find the cursor attributes by name.
38
+ #
39
+ # @param name [String]
40
+ # @return [Hash]
41
+ def find(name)
42
+ storage.fetch(name) do
43
+ fail CursorNotFound,
44
+ "Cursor was not found with this name: #{name.to_s}."
45
+ end
46
+ end
47
+
48
+ # Returns a boolean indicating whether the named interface is registered.
49
+ #
50
+ # @api private
51
+ # @return [Boolean]
52
+ def registered?(name)
53
+ return false if storage.empty?
54
+
55
+ storage.keys.include?(name)
56
+ end
57
+
58
+ # Perform an action (moving, showing or hiding) and save the new cursor
59
+ # state.
60
+ #
61
+ # @param action [Symbol] A symbol representing the method name to be called
62
+ # on the Cursor instance.
63
+ # @return [String] The escape sequence sent to the Terminal on completion
64
+ # of the action.
65
+ def use(action)
66
+ name = Focus.current
67
+ cursor = Cursor.new(find(name))
68
+
69
+ storage.store(name, cursor.send(action))
70
+
71
+ Terminal.output(cursor.to_s)
72
+ end
73
+
74
+ private
75
+
76
+ # Access to the storage for this repository.
77
+ #
78
+ # @api private
79
+ # @example
80
+ # { 'holmium' => { name: 'holmium', y: 12, x: 6, state: :show } }
81
+ #
82
+ # @return [Hash]
83
+ def storage
84
+ @_storage ||= in_memory
85
+ end
86
+
87
+ # Returns an empty collection ready for the storing of cursors by name with
88
+ # current attributes.
89
+ #
90
+ # @api private
91
+ # @return [Hash]
92
+ def in_memory
93
+ {}
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -69,7 +69,6 @@ module Vedeu
69
69
 
70
70
  private
71
71
 
72
- # @return [Hash]
73
72
  attr_reader :handlers
74
73
 
75
74
  # @api private
@@ -9,6 +9,24 @@ module Vedeu
9
9
 
10
10
  extend self
11
11
 
12
+ # System events which when called will change which interface is currently
13
+ # focussed. When the interface is brought into focus, its cursor position
14
+ # and visibility is restored.
15
+ Vedeu.event(:_focus_by_name_) do |name|
16
+ Vedeu::Focus.by_name(name)
17
+ Vedeu.trigger(:_cursor_refresh_)
18
+ end
19
+
20
+ Vedeu.event(:_focus_next_) do
21
+ Vedeu::Focus.next_item
22
+ Vedeu.trigger(:_cursor_refresh_)
23
+ end
24
+
25
+ Vedeu.event(:_focus_prev_) do
26
+ Vedeu::Focus.prev_item
27
+ Vedeu.trigger(:_cursor_refresh_)
28
+ end
29
+
12
30
  # Add an interface name to the focus list unless it is already registered.
13
31
  #
14
32
  # @param attributes [String]
@@ -30,6 +30,8 @@ module Vedeu
30
30
 
31
31
  Vedeu.log("Registering menu '#{attributes[:name]}'")
32
32
 
33
+ attributes.merge!({ items: Vedeu::Menu.new(attributes[:items]) })
34
+
33
35
  storage.store(attributes[:name], attributes)
34
36
  end
35
37
 
@@ -90,11 +92,9 @@ module Vedeu
90
92
  # Access a menu by name.
91
93
  #
92
94
  # @param name [String]
93
- # @return [Vedeu::Menu|MenuNotFound]
95
+ # @return [Vedeu::Menu]
94
96
  def use(name)
95
- find(name).fetch(:items) do
96
- fail MenuNotFound, "This menu '#{name}' has no items."
97
- end
97
+ find(name).fetch(:items)
98
98
  end
99
99
 
100
100
  private
@@ -7,9 +7,10 @@ module Vedeu
7
7
 
8
8
  # Returns a boolean indicating whether a variable has a useful value.
9
9
  #
10
- # @param variable [String|Symbol|Array] The variable to check.
10
+ # @param variable [String|Symbol|Array|Fixnum] The variable to check.
11
11
  # @return [Boolean]
12
12
  def defined_value?(variable)
13
+ return true if variable.is_a?(Fixnum)
13
14
  return true unless variable.nil? || variable.empty?
14
15
 
15
16
  false
@@ -32,17 +32,8 @@ module Vedeu
32
32
 
33
33
  private
34
34
 
35
- # @return [Proc]
36
35
  attr_reader :closure
37
-
38
- # @return []
39
- attr_accessor :deadline
40
-
41
- # @return []
42
- attr_accessor :executed_at
43
-
44
- # @return []
45
- attr_accessor :now
36
+ attr_accessor :deadline, :executed_at, :now
46
37
 
47
38
  # Execute the code stored in the event closure.
48
39
  #
@@ -1,5 +1,5 @@
1
1
  # Monkey-patch Ruby's Fixnum to provide a columns method.
2
- # TODO: Don't monkey-patch because it is naughty.
2
+ # @todo Don't monkey-patch because it is naughty.
3
3
  class Fixnum
4
4
 
5
5
  # Augment Fixnum to calculate column width in a grid-based layout.
@@ -47,7 +47,6 @@ module Vedeu
47
47
 
48
48
  private
49
49
 
50
- # @return [Fixnum]
51
50
  attr_reader :value
52
51
 
53
52
  # @api private
@@ -3,6 +3,7 @@ module Vedeu
3
3
  # Validates that a given key is can be used and is not already in-use, either
4
4
  # by the same interface, globally or as a system key.
5
5
  #
6
+ # @api private
6
7
  class KeymapValidator
7
8
 
8
9
  include Common
@@ -31,17 +32,17 @@ module Vedeu
31
32
  # @see KeymapValidator.check
32
33
  def check
33
34
  if system_key?(key)
34
- [false, "#{fail_message(key)} by the system."]
35
+ [false, fail_message(key) + ' by the system.']
35
36
 
36
37
  elsif global_key?(key)
37
- [false, "#{fail_message(key)} as a global key."]
38
+ [false, fail_message(key) + ' as a global key.']
38
39
 
39
40
  elsif interface_key?(key, interface)
40
41
  if defined_value?(interface)
41
- [false, "#{fail_message(key)} by this interface."]
42
+ [false, fail_message(key) + ' by this interface.']
42
43
 
43
44
  else
44
- [false, "#{fail_message(key)} by another interface and therefore " \
45
+ [false, fail_message(key) + ' by another interface and therefore ' \
45
46
  'cannot be global.']
46
47
 
47
48
  end