vedeu 0.2.10 → 0.2.11

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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/docs/events.md +6 -0
  3. data/examples/{cursor_app/cursor_app.rb → cursor_app.rb} +1 -1
  4. data/examples/{lines_app/lines_app.rb → lines_app.rb} +1 -1
  5. data/lib/vedeu.rb +48 -28
  6. data/lib/vedeu/api/api.rb +8 -95
  7. data/lib/vedeu/application.rb +6 -2
  8. data/lib/vedeu/{models → colours}/background.rb +1 -1
  9. data/lib/vedeu/{models → colours}/colour.rb +0 -0
  10. data/lib/vedeu/{models → colours}/foreground.rb +2 -2
  11. data/lib/vedeu/{support/colour_translator.rb → colours/translator.rb} +7 -7
  12. data/lib/vedeu/input/input.rb +13 -5
  13. data/lib/vedeu/models/geometry.rb +30 -2
  14. data/lib/vedeu/models/key.rb +39 -0
  15. data/lib/vedeu/output/compositor.rb +30 -76
  16. data/lib/vedeu/output/output.rb +74 -0
  17. data/lib/vedeu/output/viewport.rb +36 -44
  18. data/lib/vedeu/repositories/buffers.rb +5 -18
  19. data/lib/vedeu/repositories/cursors.rb +16 -8
  20. data/lib/vedeu/repositories/events.rb +96 -9
  21. data/lib/vedeu/repositories/focus.rb +21 -20
  22. data/lib/vedeu/repositories/groups.rb +3 -11
  23. data/lib/vedeu/repositories/interfaces.rb +6 -9
  24. data/lib/vedeu/repositories/keymaps.rb +8 -3
  25. data/lib/vedeu/repositories/menus.rb +6 -21
  26. data/lib/vedeu/{models → repositories/models}/buffer.rb +62 -28
  27. data/lib/vedeu/{models → repositories/models}/cursor.rb +8 -2
  28. data/lib/vedeu/{models → repositories/models}/event.rb +7 -0
  29. data/lib/vedeu/repositories/models/group.rb +56 -0
  30. data/lib/vedeu/{models → repositories/models}/interface.rb +6 -0
  31. data/lib/vedeu/{models → repositories/models}/keymap.rb +7 -1
  32. data/lib/vedeu/{models → repositories/models}/menu.rb +9 -0
  33. data/lib/vedeu/{models → repositories/models}/offset.rb +8 -1
  34. data/lib/vedeu/repositories/offsets.rb +17 -12
  35. data/lib/vedeu/support/bounding_area.rb +127 -0
  36. data/lib/vedeu/support/common.rb +8 -0
  37. data/lib/vedeu/support/exceptions.rb +2 -12
  38. data/lib/vedeu/support/model.rb +14 -0
  39. data/lib/vedeu/support/refresh.rb +8 -7
  40. data/lib/vedeu/support/registrar.rb +7 -1
  41. data/lib/vedeu/support/repository.rb +31 -10
  42. data/lib/vedeu/support/sentence.rb +67 -0
  43. data/lib/vedeu/support/terminal.rb +19 -0
  44. data/lib/vedeu/support/trace.rb +2 -5
  45. data/test/integration/api/api_test.rb +97 -0
  46. data/test/integration/api_dsl/dsl_api_test.rb +4 -0
  47. data/test/integration/api_dsl/dsl_composition_test.rb +4 -0
  48. data/test/integration/api_dsl/dsl_defined_test.rb +4 -0
  49. data/test/integration/api_dsl/dsl_helpers_test.rb +4 -0
  50. data/test/integration/api_dsl/dsl_interface_test.rb +4 -0
  51. data/test/integration/api_dsl/dsl_keymap.rb +4 -0
  52. data/test/integration/api_dsl/dsl_line_test.rb +4 -0
  53. data/test/integration/api_dsl/dsl_menu_test.rb +4 -0
  54. data/test/integration/api_dsl/dsl_stream_test.rb +138 -0
  55. data/test/lib/vedeu/api/api_test.rb +1 -25
  56. data/test/lib/vedeu/api/helpers_test.rb +0 -10
  57. data/test/lib/vedeu/{models → colours}/background_test.rb +0 -0
  58. data/test/lib/vedeu/{models → colours}/colour_test.rb +0 -0
  59. data/test/lib/vedeu/{models → colours}/foreground_test.rb +0 -0
  60. data/test/lib/vedeu/{support/colour_translator_test.rb → colours/translator_test.rb} +3 -3
  61. data/test/lib/vedeu/input/input_test.rb +16 -47
  62. data/test/lib/vedeu/models/geometry_test.rb +46 -0
  63. data/test/lib/vedeu/models/group_test.rb +99 -0
  64. data/test/lib/vedeu/models/key_test.rb +41 -0
  65. data/test/lib/vedeu/output/compositor_test.rb +25 -101
  66. data/test/lib/vedeu/output/output_test.rb +108 -0
  67. data/test/lib/vedeu/repositories/buffers_test.rb +0 -8
  68. data/test/lib/vedeu/repositories/cursors_test.rb +34 -0
  69. data/test/lib/vedeu/repositories/focus_test.rb +37 -28
  70. data/test/lib/vedeu/repositories/interfaces_test.rb +1 -1
  71. data/test/lib/vedeu/repositories/keymaps_test.rb +6 -20
  72. data/test/lib/vedeu/repositories/menus_test.rb +0 -6
  73. data/test/lib/vedeu/{models → repositories/models}/buffer_test.rb +24 -27
  74. data/test/lib/vedeu/{models → repositories/models}/cursor_test.rb +0 -0
  75. data/test/lib/vedeu/{models → repositories/models}/event_test.rb +0 -0
  76. data/test/lib/vedeu/{models → repositories/models}/interface_test.rb +0 -0
  77. data/test/lib/vedeu/{models → repositories/models}/keymap_test.rb +0 -0
  78. data/test/lib/vedeu/{models → repositories/models}/menu_test.rb +0 -0
  79. data/test/lib/vedeu/{models → repositories/models}/offset_test.rb +0 -0
  80. data/test/lib/vedeu/support/bounding_area_test.rb +139 -0
  81. data/test/lib/vedeu/support/coercions_test.rb +6 -17
  82. data/test/lib/vedeu/support/grid_test.rb +1 -1
  83. data/test/lib/vedeu/support/model_test.rb +23 -0
  84. data/test/lib/vedeu/support/presentation_test.rb +0 -10
  85. data/test/lib/vedeu/support/refresh_test.rb +2 -2
  86. data/test/lib/vedeu/support/repository_test.rb +63 -64
  87. data/test/lib/vedeu/support/sentence_test.rb +48 -0
  88. data/test/lib/vedeu/support/terminal_test.rb +86 -6
  89. data/test/support/test_classes/all.rb +5 -0
  90. data/test/support/test_classes/coercions.rb +16 -0
  91. data/test/support/test_classes/helpers.rb +19 -0
  92. data/test/support/test_classes/model.rb +23 -0
  93. data/test/support/test_classes/presentation.rb +16 -0
  94. data/test/support/test_classes/repositories.rb +26 -0
  95. data/test/support/test_modules/all.rb +1 -0
  96. data/test/support/test_modules/repository.rb +16 -0
  97. data/test/test_helper.rb +4 -0
  98. data/vedeu.gemspec +3 -3
  99. metadata +95 -50
  100. data/lib/vedeu/output/clear.rb +0 -88
  101. data/lib/vedeu/output/render.rb +0 -50
  102. data/lib/vedeu/repositories/positional.rb +0 -23
  103. data/test/lib/vedeu/output/clear_test.rb +0 -56
  104. data/test/lib/vedeu/output/render_test.rb +0 -100
  105. data/test/lib/vedeu/repositories/positional_test.rb +0 -50
@@ -23,7 +23,7 @@ module Vedeu
23
23
  @width = @attributes[:width]
24
24
  end
25
25
 
26
- # Returns the row/line position for the interface.
26
+ # Returns the row/line start position for the interface.
27
27
  #
28
28
  # @return [Fixnum]
29
29
  def y
@@ -36,7 +36,20 @@ module Vedeu
36
36
  end
37
37
  end
38
38
 
39
- # Returns the column position for the interface.
39
+ # Returns the row/line end position for the interface.
40
+ #
41
+ # @return [Fixnum]
42
+ def yn
43
+ if attributes[:yn].is_a?(Proc)
44
+ attributes[:yn].call
45
+
46
+ else
47
+ attributes[:yn]
48
+
49
+ end
50
+ end
51
+
52
+ # Returns the column/character start position for the interface.
40
53
  #
41
54
  # @return [Fixnum]
42
55
  def x
@@ -49,6 +62,19 @@ module Vedeu
49
62
  end
50
63
  end
51
64
 
65
+ # Returns the column/character end position for the interface.
66
+ #
67
+ # @return [Fixnum]
68
+ def xn
69
+ if attributes[:xn].is_a?(Proc)
70
+ attributes[:xn].call
71
+
72
+ else
73
+ attributes[:xn]
74
+
75
+ end
76
+ end
77
+
52
78
  # Returns a dynamic value calculated from the current terminal width,
53
79
  # combined with the desired column start point.
54
80
  #
@@ -481,6 +507,8 @@ module Vedeu
481
507
  width: Terminal.width,
482
508
  height: Terminal.height,
483
509
  centred: false,
510
+ yn: nil,
511
+ xn: nil,
484
512
  }
485
513
  end
486
514
 
@@ -0,0 +1,39 @@
1
+ module Vedeu
2
+
3
+ # A single keypress or combination of keypresses bound to a specific action.
4
+ class Key
5
+
6
+ # Returns a new instance of Key.
7
+ #
8
+ # @param input [String|Symbol]
9
+ # @param output [Proc]
10
+ # @return [Key]
11
+ def initialize(input, output)
12
+ @input = input
13
+ @output = output
14
+ end
15
+
16
+ # Returns the key defined.
17
+ #
18
+ # @return [String|Symbol]
19
+ def input
20
+ @input
21
+ end
22
+ alias_method :key, :input
23
+
24
+ # The procedure to call when the key is pressed.
25
+ def output
26
+ @output
27
+ end
28
+ alias_method :action, :output
29
+
30
+ # Pressing the key will call the procedure.
31
+ #
32
+ # @return [|Symbol]
33
+ def press
34
+ output.is_a?(Proc) ? output.call : :noop
35
+ end
36
+
37
+ end # Key
38
+
39
+ end # Vedeu
@@ -8,104 +8,58 @@ module Vedeu
8
8
 
9
9
  include Common
10
10
 
11
- # Convenience method to initialize a new Compositor and call its {#render}
11
+ # Convenience method to initialize a new Compositor and call its {#compose}
12
12
  # method.
13
13
  #
14
- # @param name [String] The name of the interface/buffer.
15
14
  # @return [Compositor]
16
- def self.render(name)
17
- new(name).render
15
+ # @see #initialize
16
+ def self.compose(interface, buffer)
17
+ new(interface, buffer).compose
18
18
  end
19
19
 
20
20
  # Initialize a new Compositor.
21
21
  #
22
- # @param name [String] The name of the interface/buffer.
22
+ # @param interface [Hash] The attributes of the interface to be refreshed.
23
+ # @param buffer [Hash] The atttributes of the buffer to refresh the
24
+ # interface with.
23
25
  # @return [Compositor]
24
- def initialize(name)
25
- @name = name
26
+ def initialize(interface, buffer)
27
+ @interface = interface
28
+ @buffer = buffer
26
29
  end
27
30
 
28
- # Send the view to the terminal.
29
- #
30
- # @return [Array]
31
- def render
32
- Terminal.output(view, cursor)
33
- end
34
-
35
- private
36
-
37
- attr_reader :name
38
-
39
- # Renders the cursor into the currently focussed interface. May be hidden.
40
- #
41
- # @return [String] The escape sequence to render the cursor as shown or
42
- # hidden.
43
- def cursor
44
- Interface.new(Interfaces.find(Focus.current)).cursor.to_s
45
- end
46
-
47
- # Return the content for this buffer.
48
- #
49
- # - If we have new content (i.e. content on 'back') to be shown, we first
50
- # clear the area occupied by the previous content, then clear the area for
51
- # the new content, and then finally render the new content.
52
- # - If there is no new content (i.e. 'back' is empty), check the 'front'
53
- # buffer and display that.
54
- # - If there is no new content, and the front buffer is empty, display the
55
- # 'previous' buffer.
56
- # - If the 'previous' buffer is empty, return an empty hash.
31
+ # Return a new instance of Interface built by combining the buffer content
32
+ # attributes with the stored interface attributes.
57
33
  #
58
- # @return [Hash]
59
- def view
60
- if buffer.back?
61
- Clear.call(compose(buffer.previous)) if buffer.previous?
62
-
63
- buffer.swap
34
+ # @return [Array<Hash>] The updated interface attributes.
35
+ def compose
36
+ buffer.content.each do |content|
37
+ change_geometry(content)
64
38
 
65
- Render.call(compose(buffer.front))
66
-
67
- elsif buffer.front?
68
- Render.call(compose(buffer.front))
69
-
70
- elsif buffer.previous?
71
- Render.call(compose(buffer.previous))
72
-
73
- else
74
- Clear.call(compose({}), { direct: false })
39
+ interface[:lines] = content[:lines]
40
+ change_colour(content)
41
+ change_style(content)
75
42
 
43
+ Output.render(Interface.new(interface))
76
44
  end
77
45
  end
78
46
 
79
- # Return a new instance of Interface built by combining the buffer content
80
- # attributes with the stored interface attributes.
81
- #
82
- # @return [Interface]
83
- def compose(content)
84
- if defined_value?(content[:geometry])
85
- content[:geometry].each do |k, v|
86
- interface[:geometry][k] = v if defined_value?(k)
87
- end
88
- end
47
+ private
89
48
 
90
- interface[:lines] = content[:lines]
91
- interface[:colour] = content[:colour] if defined_value?(content[:colour])
92
- interface[:style] = content[:style] if defined_value?(content[:style])
49
+ attr_reader :interface, :buffer
93
50
 
94
- Interface.new(interface)
51
+ def change_colour(content)
52
+ interface[:colour] = content[:colour] if defined_value?(content[:colour])
95
53
  end
96
54
 
97
- # Returns the attributes of the named interface (layout).
98
- #
99
- # @return [Hash]
100
- def interface
101
- @_interface ||= Interfaces.find(name)
55
+ def change_geometry(content)
56
+ content[:geometry].each do |k, v|
57
+ interface[:geometry][k] = v if defined_value?(k)
58
+ end if defined_value?(content[:geometry])
102
59
  end
103
60
 
104
- # Return the named Buffer (view).
105
- #
106
- # @return [Buffer]
107
- def buffer
108
- @_buffer ||= Buffers.find(name)
61
+ def change_style(content)
62
+ interface[:style] = content[:style] if defined_value?(content[:style])
109
63
  end
110
64
 
111
65
  end # Compositor
@@ -0,0 +1,74 @@
1
+ module Vedeu
2
+
3
+ class Output
4
+
5
+ # Writes content (the provided interface object with associated lines,
6
+ # streams, colours and styles) to the area defined by the interface.
7
+ #
8
+ # @return [Array|String]
9
+ # @see #initialize
10
+ def self.render(interface)
11
+ new(interface).render
12
+ end
13
+
14
+ # Return a new instance of Output.
15
+ #
16
+ # @param interface [Interface]
17
+ # @return [Output]
18
+ def initialize(interface)
19
+ @interface = interface
20
+ end
21
+
22
+ # Send the view to the terminal.
23
+ #
24
+ # @return [Array]
25
+ def render
26
+ Terminal.output(view, Focus.cursor)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :interface
32
+
33
+ # For each visible line of the interface, set the foreground and background
34
+ # colours to those specified when the interface was defined, then starting
35
+ # write space characters over the area which the interface occupies.
36
+ #
37
+ # @return [String]
38
+ def clear
39
+ Vedeu.log("Clearing view: '#{interface.name}'")
40
+
41
+ rows.inject([colours]) do |line, index|
42
+ line << interface.origin(index) { ' ' * interface.width }
43
+ end.join
44
+ end
45
+
46
+ # @return [String]
47
+ def colours
48
+ interface.colour.to_s
49
+ end
50
+
51
+ # @return [Enumerator]
52
+ def rows
53
+ interface.height.times
54
+ end
55
+
56
+ # Produces a single string which contains all content and escape sequences
57
+ # required to render this interface in the terminal window.
58
+ #
59
+ # @return [String]
60
+ def view
61
+ out = [ clear ]
62
+
63
+ Vedeu.log("Rendering view: '#{interface.name}'")
64
+
65
+ interface.viewport.each_with_index do |line, index|
66
+ out << interface.origin(index)
67
+ out << line.join
68
+ end
69
+ out.join
70
+ end
71
+
72
+ end # Output
73
+
74
+ end # Vedeu
@@ -8,10 +8,6 @@ module Vedeu
8
8
  #
9
9
  class Viewport
10
10
 
11
- extend Forwardable
12
-
13
- def_delegators :interface, :content, :height, :offset, :width
14
-
15
11
  # @see Viewport#show
16
12
  def self.show(interface)
17
13
  new(interface).show
@@ -52,38 +48,6 @@ module Vedeu
52
48
 
53
49
  # Scrolls the content vertically when the stored y offset for the interface
54
50
  # is outside of the visible area.
55
- #
56
- # @return [Fixnum]
57
- def line_adjustment
58
- if offset.y < lines.min
59
- set_top(offset.y)
60
-
61
- elsif offset.y > lines.max
62
- set_top(offset.y - (lines.max - lines.min))
63
-
64
- else
65
- # @top does not need adjusting
66
-
67
- end
68
- end
69
-
70
- # Scrolls the content horizontally when the stored x offset for the
71
- # interface is outside of the visible area.
72
- #
73
- # @return [Fixnum]
74
- def column_adjustment
75
- if offset.x < columns.min
76
- set_left(offset.x)
77
-
78
- elsif offset.x > columns.max
79
- set_left(offset.x - (columns.max - columns.min))
80
-
81
- else
82
- # @left does not need adjusting
83
-
84
- end
85
- end
86
-
87
51
  #
88
52
  # @note
89
53
  # @top = [value, 0].max # this allows us to set a top that is greater than
@@ -93,12 +57,19 @@ module Vedeu
93
57
  # # this does not allow us to have an offset greater
94
58
  # # than the content height.
95
59
  #
96
- # @param value [Fixnum]
97
60
  # @return [Fixnum]
98
- def set_top(value)
99
- @top = [value, 0].max
61
+ def line_adjustment
62
+ if offset.y < 0
63
+ @top = [offset.y, 0].max
64
+
65
+ elsif offset.y > height
66
+ @top = [(offset.y - height), 0].max
67
+
68
+ end
100
69
  end
101
70
 
71
+ # Scrolls the content horizontally when the stored x offset for the
72
+ # interface is outside of the visible area.
102
73
  #
103
74
  # @note
104
75
  # @left = [value, 0].max # this allows us to set a left that is greater
@@ -108,24 +79,29 @@ module Vedeu
108
79
  # # this does not allow us to have an offset greater
109
80
  # # than the content width.
110
81
  #
111
- # @param value [Fixnum]
112
82
  # @return [Fixnum]
113
- def set_left(value)
114
- @left = [value, 0].max
83
+ def column_adjustment
84
+ if offset.x < 0
85
+ @left = [offset.x, 0].max
86
+
87
+ elsif offset.x > width
88
+ @left = [(offset.x - width), 0].max
89
+
90
+ end
115
91
  end
116
92
 
117
93
  # Using the current x offset, return a range of visible lines.
118
94
  #
119
95
  # @return [Range]
120
96
  def lines
121
- @top..(@top + height - 1)
97
+ @top..(@top + height)
122
98
  end
123
99
 
124
100
  # Using the current y offset, return a range of visible columns.
125
101
  #
126
102
  # @return [Range]
127
103
  def columns
128
- @left..(@left + width - 1)
104
+ @left..(@left + width)
129
105
  end
130
106
 
131
107
  # Returns the height of the content, or when no content, the visible height
@@ -162,6 +138,22 @@ module Vedeu
162
138
  content.any?
163
139
  end
164
140
 
141
+ def content
142
+ interface.content
143
+ end
144
+
145
+ def offset
146
+ interface.offset
147
+ end
148
+
149
+ def width
150
+ interface.width - 1
151
+ end
152
+
153
+ def height
154
+ interface.height - 1
155
+ end
156
+
165
157
  end # Viewport
166
158
 
167
159
  end # Vedeu
@@ -28,38 +28,25 @@ module Vedeu
28
28
  else
29
29
  Vedeu.log("Adding new buffer: '#{name}'")
30
30
 
31
- Buffer.new({ name: name }).add(attributes)
31
+ model.new({ name: name }).add(attributes)
32
32
 
33
33
  end
34
34
 
35
35
  name
36
36
  end
37
37
 
38
- # Update the repository with the provided Buffer. Returns a boolean
39
- # indicating whether this was successful.
40
- #
41
- # @param buffer [Buffer]
42
- # @return [Boolean]
43
- def update(buffer)
44
- storage.store(buffer.name, buffer)
38
+ private
45
39
 
46
- true
40
+ # @return [Class] The model class for this repository.
41
+ def model
42
+ Vedeu::Buffer
47
43
  end
48
44
 
49
- private
50
-
51
45
  # @return [Hash]
52
46
  def in_memory
53
47
  {}
54
48
  end
55
49
 
56
- # @param name [String]
57
- # @raise [BufferNotFound] When the entity cannot be found with this name.
58
- # @return [BufferNotFound]
59
- def not_found(name)
60
- fail BufferNotFound, "Cannot find buffer: '#{name}'"
61
- end
62
-
63
50
  end # Buffers
64
51
 
65
52
  end # Vedeu