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
@@ -0,0 +1,110 @@
1
+ module Vedeu
2
+
3
+ module Configuration
4
+
5
+ # The Configuration::CLI class parses command-line arguments using
6
+ # OptionParser into options used by Vedeu to affect certain behaviours.
7
+ #
8
+ # @api private
9
+ class CLI
10
+
11
+ # Configure Vedeu via command-line arguments. Options set here via
12
+ # arguments override the client application configuration set via
13
+ # {Vedeu::API#configure}.
14
+ #
15
+ # @param args [Array]
16
+ # @return [Hash]
17
+ def self.configure(args = [])
18
+ new(args = []).configuration
19
+ end
20
+
21
+ # Returns an instance of Configuration::CLI.
22
+ #
23
+ # @param args [Array]
24
+ # @return [Configuration::CLI]
25
+ def initialize(args = [])
26
+ @args = args
27
+ end
28
+
29
+ # Returns the configuration options set up by parsing the command-line
30
+ # arguments passed to the client application.
31
+ #
32
+ # @return [Hash]
33
+ def configuration
34
+ parser = OptionParser.new do |opts|
35
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
36
+
37
+ opts.on('-i', '--interactive',
38
+ 'Run the application in interactive mode (default).') do
39
+ options[:interactive] = true
40
+ end
41
+
42
+ opts.on('-I', '--noninteractive', '--standalone',
43
+ 'Run the application non-interactively; i.e. not requiring ' \
44
+ 'intervention from the user.') do
45
+ options[:interactive] = false
46
+ end
47
+
48
+ opts.on('-1', '--run-once',
49
+ 'Run the application loop once.') do
50
+ options[:once] = true
51
+ end
52
+
53
+ opts.on('-n', '--run-many',
54
+ 'Run the application loop continuously (default).') do
55
+ options[:once] = false
56
+ end
57
+
58
+ opts.on('-c', '--cooked', 'Run application in cooked mode.') do
59
+ options[:terminal_mode] = :cooked
60
+ end
61
+
62
+ opts.on('-r', '--raw', 'Run application in raw mode (default).') do
63
+ options[:terminal_mode] = :raw
64
+ end
65
+
66
+ opts.on('-d', '--debug', 'Run application with debugging on.') do
67
+ options[:debug] = true
68
+ end
69
+
70
+ opts.on('-D', '--trace', 'Run application with debugging on with ' \
71
+ 'method and event tracing (noisy!).') do
72
+ options[:debug] = true
73
+ options[:trace] = true
74
+ end
75
+
76
+ opts.on('-C', '--colour-mode [COLOURS]', Integer,
77
+ 'Run application in either `8`, `16`, `256` or `16777216` ' \
78
+ 'colour mode.') do |colours|
79
+ if [8, 16, 256, 16777216].include?(colours)
80
+ options[:colour_mode] = colours
81
+
82
+ else
83
+ options[:colour_mode] = 8
84
+
85
+ end
86
+ end
87
+ end
88
+ parser.parse!(args)
89
+
90
+ options
91
+ end
92
+
93
+ private
94
+
95
+ attr_reader :args
96
+
97
+ # Returns the options set via command-line arguments parsed by
98
+ # OptionParser, or an empty Hash if none were set or parsed.
99
+ #
100
+ # @api private
101
+ # @return [Hash]
102
+ def options
103
+ @_options ||= {}
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
110
+ end
@@ -1,74 +1,30 @@
1
1
  module Vedeu
2
2
 
3
- # Allows the customisation of Vedeu's behaviour through command-line
4
- # arguments.
3
+ # Allows the customisation of Vedeu's behaviour through the configuration API
4
+ # or command-line arguments.
5
+
6
+ # Provides access to Vedeu's configuration, which was set with sensible
7
+ # defaults (influenced by environment variables), overridden by client
8
+ # application settings (via the configuration API), or any command-line
9
+ # arguments provided.
5
10
  #
6
- # @api public
11
+ # @api private
7
12
  module Configuration
8
13
 
9
14
  extend self
10
15
 
11
- # Parses arguments passed on the command-line or via {Vedeu::Launcher} into
12
- # options used by Vedeu to affect certain behaviours.
16
+ # Configure Vedeu with sensible defaults. If the client application sets
17
+ # options, override the defaults with those, and if command-line arguments
18
+ # are provided at application invocation, override any options with the
19
+ # arguments provided.
13
20
  #
14
21
  # @param args [Array]
22
+ # @param block [Proc]
15
23
  # @return [Hash]
16
- def configure(args = [])
17
- parser = OptionParser.new do |opts|
18
- opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
19
-
20
- opts.on('-i', '--interactive',
21
- 'Run the application in interactive mode (default).') do
22
- options[:interactive] = true
23
- end
24
-
25
- opts.on('-I', '--noninteractive', '--standalone',
26
- 'Run the application non-interactively; i.e. not requiring ' \
27
- 'intervention from the user.') do
28
- options[:interactive] = false
29
- end
30
-
31
- opts.on('-1', '--run-once',
32
- 'Run the application loop once.') do
33
- options[:once] = true
34
- end
35
-
36
- opts.on('-n', '--run-many',
37
- 'Run the application loop continuously (default).') do
38
- options[:once] = false
39
- end
40
-
41
- opts.on('-c', '--cooked', 'Run application in cooked mode.') do
42
- options[:terminal_mode] = :cooked
43
- end
44
-
45
- opts.on('-r', '--raw', 'Run application in raw mode (default).') do
46
- options[:terminal_mode] = :raw
47
- end
48
-
49
- opts.on('-d', '--debug', 'Run application with debugging on.') do
50
- options[:debug] = true
51
- end
24
+ def configure(args = [], &block)
25
+ options.merge!(API.configure(&block)) if block_given?
52
26
 
53
- opts.on('-D', '--trace', 'Run application with debugging on with ' \
54
- 'method and event tracing (noisy!).') do
55
- options[:debug] = true
56
- options[:trace] = true
57
- end
58
-
59
- opts.on('-C', '--colour-mode [COLOURS]', Integer,
60
- 'Run application in either `8`, `16`, `256` or `16777216` ' \
61
- 'colour mode.') do |colours|
62
- if [8, 16, 256, 16777216].include?(colours)
63
- options[:colour_mode] = colours
64
-
65
- else
66
- options[:colour_mode] = 8
67
-
68
- end
69
- end
70
- end
71
- parser.parse!(args)
27
+ options.merge!(CLI.configure(args)) if args.any?
72
28
 
73
29
  options
74
30
  end
@@ -133,23 +89,37 @@ module Vedeu
133
89
  end
134
90
  alias_method :trace, :trace?
135
91
 
136
- # Returns all the options current configured.
92
+ # Resets all options to Vedeu defaults.
137
93
  #
138
94
  # @return [Hash]
139
- def options
140
- @options ||= defaults
95
+ def reset
96
+ @options = defaults
141
97
  end
142
98
 
143
- # Resets all options to Vedeu defaults.
99
+ # Vedeu's default system keys. Use {#system_keys}.
144
100
  #
101
+ # @api private
145
102
  # @return [Hash]
146
- def reset
147
- @options = defaults
103
+ def default_system_keys
104
+ {
105
+ exit: 'q',
106
+ focus_next: :tab,
107
+ focus_prev: :shift_tab,
108
+ mode_switch: :escape,
109
+ }
148
110
  end
149
111
 
150
112
  private
151
113
 
152
- # The Vedeu default options, which of course are influenced by enviroment
114
+ # Returns all the options current configured.
115
+ #
116
+ # @api private
117
+ # @return [Hash]
118
+ def options
119
+ @options ||= defaults
120
+ end
121
+
122
+ # The Vedeu default options, which of course are influenced by environment
153
123
  # variables also.
154
124
  #
155
125
  # @api private
@@ -161,28 +131,20 @@ module Vedeu
161
131
  interactive: true,
162
132
  once: false,
163
133
  system_keys: default_system_keys,
164
- terminal_mode: :raw, #cooked
134
+ terminal_mode: :raw,
165
135
  trace: detect_trace_mode,
166
136
  }
167
137
  end
168
138
 
169
- # Vedeu's system keys.
170
- def default_system_keys
171
- {
172
- exit: 'q',
173
- focus_next: :tab,
174
- focus_prev: :shift_tab,
175
- mode_switch: :escape,
176
- }
177
- end
178
-
179
- # Determine the terminal colour mode via enviroment variables, or be
180
- # optimistic and settle for 256 colours.
139
+ # Attempt to determine the terminal colour mode via environment variables,
140
+ # or be optimistic and settle for 256 colours.
181
141
  #
182
142
  # @api private
183
143
  # @return [Fixnum]
184
144
  # :nocov:
185
145
  def detect_colour_mode
146
+ return 16777216 if ENV['VEDEU_TESTMODE']
147
+
186
148
  if ENV['VEDEU_TERM']
187
149
  case ENV['VEDEU_TERM']
188
150
  when /-256color$/ then 256
@@ -204,23 +166,17 @@ module Vedeu
204
166
  end
205
167
  # :nocov:
206
168
 
207
- # Determine the debug mode via an enviroment variable.
169
+ # Determine the debug mode via an environment variable.
208
170
  #
209
171
  # @api private
210
172
  # @return [Boolean]
211
173
  # :nocov:
212
174
  def detect_debug_mode
213
- if ENV['VEDEU_DEBUG']
214
- case ENV['VEDEU_DEBUG']
215
- when 'true' then true
216
- when 'false' then false
217
- else false
218
- end
175
+ return false if ENV['VEDEU_TESTMODE']
219
176
 
220
- else
221
- false
177
+ return true if ENV['VEDEU_DEBUG']
222
178
 
223
- end
179
+ false
224
180
  end
225
181
  # :nocov:
226
182
 
@@ -230,17 +186,11 @@ module Vedeu
230
186
  # @return [Boolean]
231
187
  # :nocov:
232
188
  def detect_trace_mode
233
- if ENV['VEDEU_TRACE']
234
- case ENV['VEDEU_TRACE']
235
- when 'true' then true
236
- when 'false' then false
237
- else false
238
- end
189
+ return false if ENV['VEDEU_TESTMODE']
239
190
 
240
- else
241
- false
191
+ return true if ENV['VEDEU_TRACE']
242
192
 
243
- end
193
+ false
244
194
  end
245
195
  # :nocov:
246
196
 
@@ -48,7 +48,6 @@ module Vedeu
48
48
 
49
49
  private
50
50
 
51
- # @return [Array]
52
51
  attr_reader :argv
53
52
 
54
53
  end
@@ -11,13 +11,14 @@ module Vedeu
11
11
  # :black, :red, :green, :yellow, :blue, :magenta, :cyan, :white, :default.
12
12
  #
13
13
  # When a number between 0 and 255 is provided, Vedeu will use the terminal
14
- # colour corresponding with that colour. TODO: Create chart.
14
+ # colour corresponding with that colour.
15
15
  #
16
16
  # Finally, when provided a CSS/HTML colour string e.g. '#ff0000', Vedeu will
17
17
  # translate that to the 8-bit escape sequence or if you have a capable
18
18
  # terminal and the `VEDEU_TERM=xterm-truecolor` environment variable set,
19
19
  # a 24-bit representation.
20
20
  #
21
+ # @todo More documentation required (create a fancy chart!)
21
22
  # @api private
22
23
  class ColourTranslator
23
24
 
@@ -60,7 +61,6 @@ module Vedeu
60
61
 
61
62
  private
62
63
 
63
- # @return [Fixnum|NilClass|Symbol|String]
64
64
  attr_reader :colour
65
65
 
66
66
  # @api private
@@ -7,7 +7,6 @@ module Vedeu
7
7
  # @api private
8
8
  class Colour
9
9
 
10
- # @return [Hash]
11
10
  attr_reader :attributes
12
11
 
13
12
  # Returns a new instance of Colour.
@@ -1,6 +1,8 @@
1
1
  module Vedeu
2
2
 
3
3
  # A composition is a collection of interfaces.
4
+ #
5
+ # @api private
4
6
  class Composition
5
7
 
6
8
  attr_reader :attributes
@@ -44,14 +46,6 @@ module Vedeu
44
46
  {}
45
47
  end
46
48
 
47
- # Returns the complete escape sequence which this composition renders to.
48
- # This is used by {Vedeu::Terminal.output} to draw the view.
49
- #
50
- # @return [String]
51
- def to_s
52
- interfaces.map(&:to_s).join
53
- end
54
-
55
49
  private
56
50
 
57
51
  # The default values for a new instance of Composition.
@@ -0,0 +1,261 @@
1
+ module Vedeu
2
+
3
+ # Each interface has its own Cursor which maintains the position and
4
+ # visibility of the cursor within that interface.
5
+ #
6
+ # @api private
7
+ class Cursor
8
+
9
+ extend Forwardable
10
+
11
+ def_delegators :geometry, :top, :right, :bottom, :left
12
+
13
+ # Provides a new instance of Cursor.
14
+ #
15
+ # @param attributes [Hash] The stored attributes for a cursor.
16
+ # @return [Cursor]
17
+ def initialize(attributes = {})
18
+ @attributes = defaults.merge!(attributes)
19
+
20
+ @name = @attributes[:name]
21
+ @state = @attributes[:state]
22
+ @x = @attributes[:x]
23
+ @y = @attributes[:y]
24
+ end
25
+
26
+ # Returns an attribute hash for the current position and visibility of the
27
+ # cursor.
28
+ #
29
+ # @return [Hash]
30
+ def attributes
31
+ {
32
+ name: name,
33
+ state: state,
34
+ x: x,
35
+ y: y,
36
+ }
37
+ end
38
+ alias_method :refresh, :attributes
39
+
40
+ # Move the cursor up one row.
41
+ #
42
+ # @return [Cursor]
43
+ def move_up
44
+ unless y == top || y - 1 < top
45
+ @y -= 1
46
+ end
47
+
48
+ attributes
49
+ end
50
+
51
+ # Move the cursor down one row.
52
+ #
53
+ # @return [Cursor]
54
+ def move_down
55
+ unless y == bottom || y + 1 >= bottom
56
+ @y += 1
57
+ end
58
+
59
+ attributes
60
+ end
61
+
62
+ # Move the cursor left one column.
63
+ #
64
+ # @return [Cursor]
65
+ def move_left
66
+ unless x == left || x - 1 < left
67
+ @x -= 1
68
+ end
69
+
70
+ attributes
71
+ end
72
+
73
+ # Move the cursor right one column.
74
+ #
75
+ # @return [Cursor]
76
+ def move_right
77
+ unless x == right || x + 1 >= right
78
+ @x += 1
79
+ end
80
+
81
+ attributes
82
+ end
83
+
84
+ # Make the cursor visible if it is not already.
85
+ #
86
+ # @return [Symbol]
87
+ def show
88
+ @state = :show
89
+
90
+ attributes
91
+ end
92
+
93
+ # Make the cursor invisible if it is not already.
94
+ #
95
+ # @return [Symbol]
96
+ def hide
97
+ @state = :hide
98
+
99
+ attributes
100
+ end
101
+
102
+ # Toggle the visibility of the cursor.
103
+ #
104
+ # @return [Symbol]
105
+ def toggle
106
+ if visible?
107
+ @state = :hide
108
+
109
+ else
110
+ @state = :show
111
+
112
+ end
113
+
114
+ attributes
115
+ end
116
+
117
+ # Returns an escape sequence to position the cursor and set its visibility.
118
+ # When passed a block, will position the cursor, yield and return the
119
+ # original position.
120
+ #
121
+ # @param block [Proc]
122
+ # @return [String]
123
+ def to_s(&block)
124
+ if block_given?
125
+ [ sequence, yield, sequence ].join
126
+
127
+ else
128
+ sequence
129
+
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ attr_reader :name, :state
136
+
137
+ # Returns the escape sequence to position the cursor and set its visibility.
138
+ #
139
+ # @api private
140
+ # @return [String]
141
+ def sequence
142
+ [ position, visibility ].join
143
+ end
144
+
145
+ # Returns the escape sequence to position the cursor.
146
+ #
147
+ # @api private
148
+ # @return [String]
149
+ def position
150
+ ["\e[", y, ';', x, 'H'].join
151
+ end
152
+
153
+ # Returns the escape sequence for setting the visibility of the cursor.
154
+ #
155
+ # @api private
156
+ # @return [String]
157
+ def visibility
158
+ return Esc.string('show_cursor') if visible?
159
+
160
+ Esc.string('hide_cursor')
161
+ end
162
+
163
+ # Return a boolean indicating the visibility of the cursor, invisible if
164
+ # the state is not defined.
165
+ #
166
+ # @api private
167
+ # @return [Boolean]
168
+ def visible?
169
+ return false unless states.include?(state)
170
+ return false if state == :hide
171
+
172
+ true
173
+ end
174
+
175
+ # Returns the y coordinate of the cursor, unless out of range, in which case
176
+ # sets y to the first row (top) of the interface.
177
+ #
178
+ # @api private
179
+ # @return [Fixnum]
180
+ def y
181
+ if y_out_of_range?
182
+ @y = top
183
+
184
+ else
185
+ @y
186
+
187
+ end
188
+ end
189
+
190
+ # Returns the x coordinate of the cursor, unless out of range, in which case
191
+ # sets x to the first column (left) of the interface.
192
+ #
193
+ # @api private
194
+ # @return [Fixnum]
195
+ def x
196
+ if x_out_of_range?
197
+ @x = left
198
+
199
+ else
200
+ @x
201
+
202
+ end
203
+ end
204
+
205
+ # Returns a boolean indicating whether the previous y coordinate is still
206
+ # inside the interface or terminal.
207
+ #
208
+ # @api private
209
+ # @return [Boolean]
210
+ def y_out_of_range?
211
+ @y < top || @y > bottom
212
+ end
213
+
214
+ # Returns a boolean indicating whether the previous x coordinate is still
215
+ # inside the interface or terminal.
216
+ #
217
+ # @api private
218
+ # @return [Boolean]
219
+ def x_out_of_range?
220
+ @x < left || @x > right
221
+ end
222
+
223
+ # Returns the position and size of the interface.
224
+ #
225
+ # @api private
226
+ # @return [Geometry]
227
+ def geometry
228
+ @geometry ||= Vedeu::Geometry.new(interface[:geometry])
229
+ end
230
+
231
+ # Returns the attributes of a named interface.
232
+ #
233
+ # @api private
234
+ # @return [Hash]
235
+ def interface
236
+ Vedeu::Interfaces.find(name)
237
+ end
238
+
239
+ # The valid visibility states for the cursor.
240
+ #
241
+ # @api private
242
+ # @return [Array]
243
+ def states
244
+ [:show, :hide]
245
+ end
246
+
247
+ # The default values for a new instance of Cursor.
248
+ #
249
+ # @api private
250
+ # @return [Hash]
251
+ def defaults
252
+ {
253
+ name: '',
254
+ x: 1,
255
+ y: 1,
256
+ state: :hide,
257
+ }
258
+ end
259
+ end
260
+
261
+ end