vedeu 0.1.17 → 0.1.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/README.md +17 -3
  4. data/lib/vedeu.rb +12 -7
  5. data/lib/vedeu/api/api.rb +37 -13
  6. data/lib/vedeu/api/composition.rb +1 -6
  7. data/lib/vedeu/api/helpers.rb +2 -0
  8. data/lib/vedeu/api/interface.rb +47 -55
  9. data/lib/vedeu/api/line.rb +6 -0
  10. data/lib/vedeu/api/stream.rb +9 -1
  11. data/lib/vedeu/application.rb +38 -50
  12. data/lib/vedeu/configuration.rb +163 -44
  13. data/lib/vedeu/launcher.rb +3 -6
  14. data/lib/vedeu/models/attributes/background.rb +9 -1
  15. data/lib/vedeu/models/attributes/colour_translator.rb +40 -2
  16. data/lib/vedeu/models/attributes/foreground.rb +9 -1
  17. data/lib/vedeu/models/colour.rb +6 -0
  18. data/lib/vedeu/models/composition.rb +8 -1
  19. data/lib/vedeu/models/geometry.rb +27 -14
  20. data/lib/vedeu/models/interface.rb +59 -0
  21. data/lib/vedeu/models/line.rb +4 -0
  22. data/lib/vedeu/models/stream.rb +10 -0
  23. data/lib/vedeu/models/style.rb +2 -0
  24. data/lib/vedeu/support/buffer.rb +12 -1
  25. data/lib/vedeu/support/buffers.rb +10 -0
  26. data/lib/vedeu/support/clear.rb +4 -0
  27. data/lib/vedeu/support/esc.rb +26 -8
  28. data/lib/vedeu/support/event.rb +28 -0
  29. data/lib/vedeu/support/events.rb +2 -0
  30. data/lib/vedeu/support/focus.rb +14 -6
  31. data/lib/vedeu/support/grid.rb +6 -0
  32. data/lib/vedeu/support/groups.rb +13 -3
  33. data/lib/vedeu/support/input.rb +7 -2
  34. data/lib/vedeu/support/log.rb +7 -1
  35. data/lib/vedeu/support/position.rb +6 -0
  36. data/lib/vedeu/support/render.rb +38 -0
  37. data/lib/vedeu/support/terminal.rb +69 -15
  38. data/lib/vedeu/support/trace.rb +8 -0
  39. data/lib/vedeu/support/view.rb +6 -0
  40. data/test/integration/run_once_test.rb +26 -0
  41. data/test/lib/vedeu/api/api_test.rb +19 -6
  42. data/test/lib/vedeu/api/interface_test.rb +67 -1
  43. data/test/lib/vedeu/api/line_test.rb +10 -0
  44. data/test/lib/vedeu/api/stream_test.rb +8 -0
  45. data/test/lib/vedeu/configuration_test.rb +119 -12
  46. data/test/lib/vedeu/models/attributes/background_test.rb +1 -1
  47. data/test/lib/vedeu/models/attributes/foreground_test.rb +1 -1
  48. data/test/lib/vedeu/models/interface_test.rb +22 -0
  49. data/test/lib/vedeu/support/buffer_test.rb +44 -0
  50. data/test/lib/vedeu/support/events_test.rb +3 -9
  51. data/test/lib/vedeu/support/input_test.rb +1 -0
  52. data/test/lib/vedeu/support/terminal_test.rb +128 -5
  53. data/test/test_helper.rb +2 -2
  54. data/vedeu.gemspec +1 -1
  55. metadata +5 -2
@@ -76,7 +76,7 @@ module Vedeu
76
76
 
77
77
  class Log
78
78
 
79
- # @return []
79
+ # @return [TrueClass]
80
80
  def self.logger
81
81
  @logger ||= MonoLogger.new(filename).tap do |log|
82
82
  log.formatter = proc do |_, time, _, message|
@@ -87,16 +87,22 @@ module Vedeu
87
87
 
88
88
  private
89
89
 
90
+ # @api private
91
+ # @return [String]
90
92
  def self.filename
91
93
  @_filename ||= directory + '/vedeu.log'
92
94
  end
93
95
 
96
+ # @api private
97
+ # @return [String]
94
98
  def self.directory
95
99
  FileUtils.mkdir_p(path) unless File.directory?(path)
96
100
 
97
101
  path
98
102
  end
99
103
 
104
+ # @api private
105
+ # @return [String]
100
106
  def self.path
101
107
  Dir.home + '/.vedeu'
102
108
  end
@@ -22,14 +22,20 @@ module Vedeu
22
22
 
23
23
  private
24
24
 
25
+ # @api private
26
+ # @return [String]
25
27
  def sequence
26
28
  ["\e[", y, ';', x, 'H'].join
27
29
  end
28
30
 
31
+ # @api private
32
+ # @return [Fixnum]
29
33
  def y
30
34
  (@y == 0 || @y == nil) ? 1 : @y
31
35
  end
32
36
 
37
+ # @api private
38
+ # @return [Fixnum]
33
39
  def x
34
40
  (@x == 0 || @x == nil) ? 1 : @x
35
41
  end
@@ -1,18 +1,28 @@
1
1
  module Vedeu
2
2
  class Render
3
3
 
4
+ # Attempts to convert the provided interface object with associated lines,
5
+ # streams, colours, styles, etc, into a single string containing all content
6
+ # and escape sequences.
7
+ #
8
+ # @api private
4
9
  # @param interface [Interface]
5
10
  # @return [String]
6
11
  def self.call(interface)
7
12
  new(interface).render
8
13
  end
9
14
 
15
+ # Initializes a new Render object with the provided interface.
16
+ #
10
17
  # @param interface [Interface]
11
18
  # @return [Render]
12
19
  def initialize(interface)
13
20
  @interface = interface
14
21
  end
15
22
 
23
+ # Produces a single string which contains all content and escape sequences
24
+ # required to render this interface to a position in the terminal window.
25
+ #
16
26
  # @return [String]
17
27
  def render
18
28
  out = [ Clear.call(interface) ]
@@ -33,6 +43,9 @@ module Vedeu
33
43
  # The client application may have created a line that us too long for the
34
44
  # interface. This code tries to truncate streams whilst preserving styles
35
45
  # and colours.
46
+ #
47
+ # @api private
48
+ # @return [Array]
36
49
  def processed_lines
37
50
  return [] unless lines.any? { |line| line.streams.any? }
38
51
 
@@ -71,22 +84,47 @@ module Vedeu
71
84
  end
72
85
  end
73
86
 
87
+ # Converts all streams within a line into a single line of text to then
88
+ # check that this line (without formatting, as that is not visible) exceeds
89
+ # the width of the interface.
90
+ #
91
+ # @api private
92
+ # @param line [Line]
93
+ # @return [TrueClass|FalseClass]
74
94
  def exceeds_width?(line)
75
95
  line.streams.map(&:text).join.size > width
76
96
  end
77
97
 
98
+ # Truncates the provided text.
99
+ #
100
+ # @api private
101
+ # @param text [String] The text to be truncated.
102
+ # @param value [Fixnum] The total length of the text after truncation.
103
+ # @return [String]
78
104
  def truncate(text, value)
79
105
  text.chomp.slice(0...value)
80
106
  end
81
107
 
108
+ # Provides a collection of lines associated with the interface.
109
+ #
110
+ # @api private
111
+ # @return [Array]
82
112
  def lines
83
113
  interface.lines
84
114
  end
85
115
 
116
+ # Provides the currently available height of the interface.
117
+ #
118
+ # @api private
119
+ # @return [Fixnum]
86
120
  def height
87
121
  interface.viewport_height
88
122
  end
89
123
 
124
+ # Provides the currently available width of the interface.
125
+ #
126
+ # @api private
127
+ # @return [Fixnum]
90
128
  def width
91
129
  interface.viewport_width
92
130
  end
@@ -1,24 +1,23 @@
1
1
  module Vedeu
2
2
  module Terminal
3
+
3
4
  extend self
4
5
 
5
- # @param mode [Symbol]
6
6
  # @param block [Proc]
7
7
  # @return []
8
- def open(mode, &block)
9
- @mode = mode
8
+ def open(&block)
9
+ fail InvalidSyntax, '`open` requires a block.' unless block_given?
10
10
 
11
- if block_given?
12
- if raw_mode?
13
- console.raw { initialize_screen { yield } }
11
+ if raw_mode?
12
+ console.raw { initialize_screen { yield } }
14
13
 
15
- else
16
- console.cooked { initialize_screen { yield } }
14
+ else
15
+ console.cooked { initialize_screen { yield } }
17
16
 
18
- end
19
17
  end
20
18
  ensure
21
19
  restore_screen
20
+
22
21
  end
23
22
 
24
23
  # @return [String]
@@ -69,9 +68,35 @@ module Vedeu
69
68
  output Esc.string 'show_cursor' unless raw_mode?
70
69
  end
71
70
 
71
+ # @return [Boolean]
72
+ def cooked_mode?
73
+ mode == :cooked
74
+ end
75
+
76
+ # @return [Symbol]
77
+ def cooked_mode!
78
+ @_mode = :cooked
79
+ end
80
+
72
81
  # @return [Boolean]
73
82
  def raw_mode?
74
- @mode == :raw
83
+ mode == :raw
84
+ end
85
+
86
+ # @return [Symbol]
87
+ def raw_mode!
88
+ @_mode = :raw
89
+ end
90
+
91
+ # @return [Symbol]
92
+ def switch_mode!
93
+ if raw_mode?
94
+ cooked_mode!
95
+
96
+ else
97
+ raw_mode!
98
+
99
+ end
75
100
  end
76
101
 
77
102
  # @return [String]
@@ -79,26 +104,54 @@ module Vedeu
79
104
  Esc.set_position((height - 1), 1) + Esc.string('clear_line')
80
105
  end
81
106
 
82
- # @return [Fixnum]
83
- def colour_mode
84
- Configuration.options[:colour_mode]
107
+ # Returns the mode of the terminal, either `:raw` or `:cooked`
108
+ #
109
+ # @return [Symbol]
110
+ def mode
111
+ @_mode ||= Configuration.terminal_mode
85
112
  end
86
113
 
114
+ # Returns a coordinate tuple of the format [y, x], where `y` is the row/line
115
+ # and `x` is the column/character.
116
+ #
87
117
  # @return [Array]
88
118
  def centre
89
119
  [(height / 2), (width / 2)]
90
120
  end
91
121
 
92
- # @return [Fixnum] The total width of the current terminal.
122
+ # Returns the `y` (row/line) component of the coordinate tuple provided by
123
+ # {Terminal.centre}
124
+ #
125
+ # @return [Fixnum]
126
+ def centre_y
127
+ centre.first
128
+ end
129
+
130
+ # Returns the `x` (column/character) component of the coodinate tuple
131
+ # provided by {Terminal.centre}
132
+ #
133
+ # @return [Fixnum]
134
+ def centre_x
135
+ centre.last
136
+ end
137
+
138
+ # Returns the total width (number of columns/characters) of the current
139
+ # terminal.
140
+ #
141
+ # @return [Fixnum]
93
142
  def width
94
143
  size.last
95
144
  end
96
145
 
97
- # @return [Fixnum] The total height of the current terminal.
146
+ # Returns the total height (number of rows/lines) of the current terminal.
147
+ #
148
+ # @return [Fixnum]
98
149
  def height
99
150
  size.first
100
151
  end
101
152
 
153
+ # Returns a tuple containing the height and width of the current terminal.
154
+ #
102
155
  # @return [Array]
103
156
  def size
104
157
  console.winsize
@@ -108,5 +161,6 @@ module Vedeu
108
161
  def console
109
162
  IO.console
110
163
  end
164
+
111
165
  end
112
166
  end
@@ -28,18 +28,26 @@ module Vedeu
28
28
 
29
29
  private
30
30
 
31
+ # @api private
32
+ # @return []
31
33
  def watched
32
34
  options[:event]
33
35
  end
34
36
 
37
+ # @api private
38
+ # @return []
35
39
  def klass
36
40
  options[:klass]
37
41
  end
38
42
 
43
+ # @api private
44
+ # @return [Hash]
39
45
  def options
40
46
  defaults.merge!(@options)
41
47
  end
42
48
 
49
+ # @api private
50
+ # @return [Hash]
43
51
  def defaults
44
52
  {
45
53
  event: 'call',
@@ -30,14 +30,20 @@ module Vedeu
30
30
 
31
31
  attr_reader :object
32
32
 
33
+ # @api private
34
+ # @return [Array]
33
35
  def interfaces
34
36
  composition.interfaces
35
37
  end
36
38
 
39
+ # @api private
40
+ # @return [Composition]
37
41
  def composition
38
42
  @_composition ||= Composition.new(attributes)
39
43
  end
40
44
 
45
+ # @api private
46
+ # @return []
41
47
  def attributes
42
48
  render
43
49
  end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class MyFirstApplication
4
+ include Vedeu
5
+
6
+ interface 'hydrogen' do
7
+ x 2
8
+ y 2
9
+ width 50
10
+ height 2
11
+ end
12
+
13
+ def self.start
14
+ Vedeu::Launcher.new(['--run-once', '--noninteractive']).execute!
15
+ end
16
+ end
17
+
18
+ describe 'Run the application once, printing a message on the screen and ' \
19
+ 'gracefully terminating.' do
20
+ it 'writes a message to the screen' do
21
+ skip
22
+ stdout, stderr = capture_io { MyFirstApplication.start }
23
+ stdout.must_equal('Great success! Now, try something a little harder.')
24
+ stderr.must_equal('')
25
+ end
26
+ end
@@ -24,10 +24,6 @@ module Vedeu
24
24
  end
25
25
 
26
26
  describe '.events' do
27
- it 'should not be visible to the client' do
28
- skip
29
- end
30
-
31
27
  it 'returns the Events singleton' do
32
28
  Vedeu.events.must_be_instance_of(Vedeu::Events)
33
29
  end
@@ -45,7 +41,7 @@ module Vedeu
45
41
  it 'creates and stores a new interface' do
46
42
  Vedeu::Buffers.reset
47
43
 
48
- Vedeu.interface('Vedeu.interface').must_equal(true)
44
+ Vedeu.interface('Vedeu.interface').must_be_instance_of(API::Interface)
49
45
  end
50
46
  end
51
47
 
@@ -53,11 +49,24 @@ module Vedeu
53
49
  before { event.stubs(:trigger).returns(nil) }
54
50
 
55
51
  it 'returns nil' do
56
- skip
57
52
  Vedeu.keypress('k').must_equal(nil)
58
53
  end
59
54
  end
60
55
 
56
+ describe '.log' do
57
+ it 'writes the message to the log file when debugging is enabled' do
58
+ Configuration.stub(:debug?, true) do
59
+ Vedeu.log('some message...').must_equal(true)
60
+ end
61
+ end
62
+
63
+ it 'returns nil when debugging is disabled' do
64
+ Configuration.stub(:debug?, false) do
65
+ Vedeu.log('some message...').must_equal(nil)
66
+ end
67
+ end
68
+ end
69
+
61
70
  describe '.trigger' do
62
71
  it 'triggers the specifed event and returns the collection of events' \
63
72
  ' which this trigger triggers' do
@@ -128,6 +137,10 @@ module Vedeu
128
137
  }
129
138
  )
130
139
  end
140
+
141
+ it 'raises an exception if a block was not given' do
142
+ proc { Vedeu.views }.must_raise(InvalidSyntax)
143
+ end
131
144
  end
132
145
 
133
146
  describe '.width' do
@@ -8,7 +8,7 @@ module Vedeu
8
8
  interface = Interface.new({ name: 'widget' })
9
9
 
10
10
  it 'creates and stores a new interface' do
11
- interface.define.must_equal(true)
11
+ interface.define.must_be_instance_of(API::Interface)
12
12
  end
13
13
 
14
14
  it 'allows the setting of colours' do
@@ -834,6 +834,72 @@ module Vedeu
834
834
  )
835
835
  end
836
836
 
837
+ it 'allows inline values for line' do
838
+ Vedeu.interface 'helium' do
839
+ end
840
+ attributes = Vedeu.view 'helium' do
841
+ line 'A headline, if you will.'
842
+ line # with a spacer line
843
+ line 'This is a line of text...'
844
+ line do
845
+ text '...we can mix and match...'
846
+ end
847
+ line '...to our hearts content.'
848
+ end
849
+ attributes[:interfaces].first[:lines].size.must_equal(5)
850
+ end
851
+ end
852
+
853
+ describe '#cursor' do
854
+ it 'raises an exception if the value is invalid' do
855
+ proc {
856
+ Vedeu.interface 'beryllium' do
857
+ cursor :invalid
858
+ end
859
+ }.must_raise(InvalidSyntax)
860
+ end
861
+
862
+ it 'sets the cursor to true (visible)' do
863
+ Vedeu.interface 'beryllium' do
864
+ cursor true
865
+ end
866
+
867
+ Vedeu.use('beryllium').attributes[:cursor].must_equal(true)
868
+ end
869
+
870
+ it 'sets the cursor to false (hidden)' do
871
+ Vedeu.interface 'beryllium' do
872
+ cursor false
873
+ end
874
+
875
+ Vedeu.use('beryllium').attributes[:cursor].must_equal(false)
876
+ end
877
+ end
878
+
879
+ describe '#centred' do
880
+ it 'raises an exception if the value is invalid' do
881
+ proc {
882
+ Vedeu.interface 'boron' do
883
+ centred :invalid
884
+ end
885
+ }.must_raise(InvalidSyntax)
886
+ end
887
+
888
+ it 'sets the centred to true (visible)' do
889
+ Vedeu.interface 'boron' do
890
+ centred true
891
+ end
892
+
893
+ Vedeu.use('boron').attributes[:geometry][:centred].must_equal(true)
894
+ end
895
+
896
+ it 'sets the centred to false (hidden)' do
897
+ Vedeu.interface 'boron' do
898
+ centred false
899
+ end
900
+
901
+ Vedeu.use('boron').attributes[:geometry][:centred].must_equal(false)
902
+ end
837
903
  end
838
904
  end
839
905
  end