vedeu 0.2.10 → 0.2.11

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