vedeu 0.1.15 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +2 -0
  3. data/README.md +116 -98
  4. data/lib/vedeu.rb +24 -11
  5. data/lib/vedeu/api/api.rb +174 -33
  6. data/lib/vedeu/api/composition.rb +2 -13
  7. data/lib/vedeu/api/helpers.rb +41 -0
  8. data/lib/vedeu/api/interface.rb +147 -34
  9. data/lib/vedeu/api/line.rb +47 -0
  10. data/lib/vedeu/api/stream.rb +41 -0
  11. data/lib/vedeu/application.rb +9 -2
  12. data/lib/vedeu/configuration.rb +66 -8
  13. data/lib/vedeu/launcher.rb +11 -0
  14. data/lib/vedeu/models/attributes/background.rb +29 -0
  15. data/lib/vedeu/models/attributes/coercions.rb +30 -0
  16. data/lib/vedeu/models/attributes/colour_translator.rb +106 -16
  17. data/lib/vedeu/models/attributes/foreground.rb +29 -0
  18. data/lib/vedeu/models/attributes/presentation.rb +15 -0
  19. data/lib/vedeu/models/colour.rb +12 -7
  20. data/lib/vedeu/models/composition.rb +23 -5
  21. data/lib/vedeu/models/geometry.rb +101 -16
  22. data/lib/vedeu/models/interface.rb +36 -28
  23. data/lib/vedeu/models/line.rb +16 -14
  24. data/lib/vedeu/models/stream.rb +17 -25
  25. data/lib/vedeu/models/style.rb +29 -0
  26. data/lib/vedeu/support/buffer.rb +36 -21
  27. data/lib/vedeu/support/buffers.rb +88 -0
  28. data/lib/vedeu/{output → support}/clear.rb +9 -2
  29. data/lib/vedeu/support/esc.rb +16 -2
  30. data/lib/vedeu/support/event.rb +104 -0
  31. data/lib/vedeu/support/events.rb +61 -0
  32. data/lib/vedeu/support/focus.rb +69 -0
  33. data/lib/vedeu/{api → support}/grid.rb +29 -25
  34. data/lib/vedeu/support/groups.rb +51 -0
  35. data/lib/vedeu/support/input.rb +5 -0
  36. data/lib/vedeu/support/log.rb +105 -0
  37. data/lib/vedeu/support/menu.rb +19 -0
  38. data/lib/vedeu/support/position.rb +7 -0
  39. data/lib/vedeu/{output → support}/render.rb +12 -6
  40. data/lib/vedeu/support/terminal.rb +21 -0
  41. data/lib/vedeu/support/trace.rb +54 -0
  42. data/lib/vedeu/{output → support}/view.rb +15 -10
  43. data/test/lib/vedeu/api/api_test.rb +55 -29
  44. data/test/lib/vedeu/api/interface_test.rb +3 -49
  45. data/test/lib/vedeu/api/line_test.rb +71 -0
  46. data/test/lib/vedeu/api/stream_test.rb +25 -0
  47. data/test/lib/vedeu/models/attributes/background_test.rb +83 -0
  48. data/test/lib/vedeu/models/attributes/coercer_test.rb +52 -0
  49. data/test/lib/vedeu/models/attributes/foreground_test.rb +83 -0
  50. data/test/lib/vedeu/models/attributes/presentation_test.rb +30 -0
  51. data/test/lib/vedeu/models/composition_test.rb +6 -6
  52. data/test/lib/vedeu/models/geometry_test.rb +34 -0
  53. data/test/lib/vedeu/models/interface_test.rb +0 -12
  54. data/test/lib/vedeu/models/line_test.rb +1 -13
  55. data/test/lib/vedeu/models/stream_test.rb +4 -50
  56. data/test/lib/vedeu/models/style_test.rb +39 -0
  57. data/test/lib/vedeu/support/buffer_test.rb +7 -3
  58. data/test/lib/vedeu/support/buffers_test.rb +15 -0
  59. data/test/lib/vedeu/{output → support}/clear_test.rb +8 -1
  60. data/test/lib/vedeu/support/esc_test.rb +2 -2
  61. data/test/lib/vedeu/support/event_test.rb +41 -0
  62. data/test/lib/vedeu/support/events_test.rb +70 -0
  63. data/test/lib/vedeu/support/focus_test.rb +114 -0
  64. data/test/lib/vedeu/support/grid_test.rb +31 -0
  65. data/test/lib/vedeu/support/groups_test.rb +65 -0
  66. data/test/lib/vedeu/{output → support}/render_test.rb +8 -1
  67. data/test/lib/vedeu/{output → support}/view_test.rb +1 -1
  68. data/test/test_helper.rb +3 -1
  69. data/vedeu.gemspec +3 -2
  70. metadata +67 -31
  71. data/lib/vedeu/api/events.rb +0 -46
  72. data/lib/vedeu/api/log.rb +0 -84
  73. data/lib/vedeu/models/attributes/attributes.rb +0 -25
  74. data/lib/vedeu/models/store.rb +0 -29
  75. data/lib/vedeu/output/buffers.rb +0 -65
  76. data/test/lib/vedeu/api/events_test.rb +0 -36
  77. data/test/lib/vedeu/api/grid_test.rb +0 -33
  78. data/test/lib/vedeu/models/attributes/attributes_test.rb +0 -39
  79. data/test/lib/vedeu/models/attributes/colour_translator_test.rb +0 -78
  80. data/test/lib/vedeu/models/store_test.rb +0 -57
  81. data/test/lib/vedeu/output/buffers_test.rb +0 -35
@@ -1,4 +1,5 @@
1
1
  class Fixnum
2
+
2
3
  # Augment Fixnum to calculate column width in a grid-based layout.
3
4
  #
4
5
  # The grid system splits the terminal width into 12 equal parts, by dividing
@@ -11,44 +12,47 @@ class Fixnum
11
12
  # # Terminal is 92 characters wide, maximum value is
12
13
  # # therefore 84, meaning a column is 7 characters wide.
13
14
  def columns
14
- Vedeu::API::Grid.columns(self)
15
+ Vedeu::Grid.columns(self)
15
16
  end
16
17
  end
17
18
 
18
19
  module Vedeu
19
- module API
20
- OutOfRange = Class.new(StandardError)
20
+ class Grid
21
21
 
22
- class Grid
23
- def self.columns(value)
24
- new(value).columns
25
- end
22
+ # @param value [Fixnum]
23
+ # @return []
24
+ def self.columns(value)
25
+ new(value).columns
26
+ end
26
27
 
27
- def initialize(value)
28
- @value = value
29
- end
28
+ # @param value [Fixnum]
29
+ # @return [Grid]
30
+ def initialize(value)
31
+ @value = value
32
+ end
30
33
 
31
- def columns
32
- fail OutOfRange, 'Valid range is 1..12.' if out_of_range?
34
+ # @return []
35
+ def columns
36
+ fail OutOfRange, 'Valid range is 1..12.' if out_of_range?
33
37
 
34
- column * value
35
- end
38
+ column * value
39
+ end
36
40
 
37
- private
41
+ private
38
42
 
39
- attr_reader :value
43
+ attr_reader :value
40
44
 
41
- def column
42
- actual / 12
43
- end
45
+ def column
46
+ actual / 12
47
+ end
44
48
 
45
- def actual
46
- Terminal.width
47
- end
49
+ def actual
50
+ Terminal.width
51
+ end
48
52
 
49
- def out_of_range?
50
- value < 1 || value > 12
51
- end
53
+ def out_of_range?
54
+ value < 1 || value > 12
52
55
  end
56
+
53
57
  end
54
58
  end
@@ -0,0 +1,51 @@
1
+ module Vedeu
2
+ class Groups
3
+
4
+ # @return [Groups]
5
+ def initialize; end
6
+
7
+ # @return [Set]
8
+ def all
9
+ @_storage
10
+ end
11
+
12
+ # @param name [String]
13
+ # @return [Set]
14
+ def find(name)
15
+ storage.fetch(name) do
16
+ fail GroupNotFound, 'Cannot find interface group with this name.'
17
+ end
18
+ end
19
+
20
+ # @param group [String]
21
+ # @param name [String]
22
+ # @param delay [Float]
23
+ # @return [Groups|FalseClass]
24
+ def add(group, name, delay = 0.0)
25
+ return false if group.empty?
26
+
27
+ storage[group] << name
28
+
29
+ Vedeu.event("_refresh_group_#{group}_".to_sym, { delay: delay }) do
30
+ Buffers.refresh_group(group)
31
+ end
32
+
33
+ self
34
+ end
35
+
36
+ # @return [Hash]
37
+ def reset
38
+ @_storage = in_memory
39
+ end
40
+
41
+ private
42
+
43
+ def storage
44
+ @_storage ||= in_memory
45
+ end
46
+
47
+ def in_memory
48
+ Hash.new { |hash, key| hash[key] = Set.new }
49
+ end
50
+ end
51
+ end
@@ -1,11 +1,15 @@
1
1
  module Vedeu
2
2
  class Input
3
+
4
+ # @return []
3
5
  def self.capture
4
6
  new.capture
5
7
  end
6
8
 
9
+ # @return []
7
10
  def initialize; end
8
11
 
12
+ # @return []
9
13
  def capture
10
14
  Vedeu.trigger(:_keypress_, keypress)
11
15
  end
@@ -53,5 +57,6 @@ module Vedeu
53
57
 
54
58
  translated
55
59
  end
60
+
56
61
  end
57
62
  end
@@ -0,0 +1,105 @@
1
+ require 'fileutils'
2
+ require 'time'
3
+
4
+ module Vedeu
5
+ class MonoLogger < Logger
6
+ # Create a trappable Logger instance.
7
+ #
8
+ # @param logdev [String|IO] The filename (String) or IO object (typically
9
+ # STDOUT, STDERR or an open file).
10
+ # @param shift_age [] Number of old log files to keep, or frequency of
11
+ # rotation (daily, weekly, monthly).
12
+ # @param shift_size [] Maximum log file size (only applies when shift_age
13
+ # is a number).
14
+ #
15
+ # @example
16
+ # Logger.new(name, shift_age = 7, shift_size = 1048576)
17
+ # Logger.new(name, shift_age = 'weekly')
18
+ #
19
+ def initialize(logdev, shift_age=nil, shift_size=nil)
20
+ @progname = nil
21
+ @level = DEBUG
22
+ @default_formatter = Formatter.new
23
+ @formatter = nil
24
+ @logdev = nil
25
+ if logdev
26
+ @logdev = LocklessLogDevice.new(logdev)
27
+ end
28
+ end
29
+
30
+ class LocklessLogDevice < LogDevice
31
+ def initialize(log = nil)
32
+ @dev = @filename = @shift_age = @shift_size = nil
33
+ if log.respond_to?(:write) and log.respond_to?(:close)
34
+ @dev = log
35
+ else
36
+ @dev = open_logfile(log)
37
+ @dev.sync = true
38
+ @filename = log
39
+ end
40
+ end
41
+
42
+ def write(message)
43
+ @dev.write(message)
44
+ rescue Exception => ignored
45
+ warn("log writing failed. #{ignored}")
46
+ end
47
+
48
+ def close
49
+ @dev.close rescue nil
50
+ end
51
+
52
+ private
53
+
54
+ def open_logfile(filename)
55
+ if (FileTest.exist?(filename))
56
+ open(filename, (File::WRONLY | File::APPEND))
57
+ else
58
+ create_logfile(filename)
59
+ end
60
+ end
61
+
62
+ def create_logfile(filename)
63
+ logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
64
+ logdev.sync = true
65
+ add_log_header(logdev)
66
+ logdev
67
+ end
68
+
69
+ def add_log_header(file)
70
+ file.write(
71
+ "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
72
+ )
73
+ end
74
+ end
75
+ end
76
+
77
+ class Log
78
+
79
+ # @return []
80
+ def self.logger
81
+ @logger ||= MonoLogger.new(filename).tap do |log|
82
+ log.formatter = proc do |_, time, _, message|
83
+ time.utc.iso8601 + ": " + message + "\n"
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def self.filename
91
+ @_filename ||= directory + '/vedeu.log'
92
+ end
93
+
94
+ def self.directory
95
+ FileUtils.mkdir_p(path) unless File.directory?(path)
96
+
97
+ path
98
+ end
99
+
100
+ def self.path
101
+ Dir.home + '/.vedeu'
102
+ end
103
+
104
+ end
105
+ end
@@ -1,5 +1,8 @@
1
1
  module Vedeu
2
2
  class Menu
3
+
4
+ # @param collection []
5
+ # @return [Menu]
3
6
  def initialize(collection)
4
7
  @collection = collection
5
8
  @current = 0
@@ -7,6 +10,7 @@ module Vedeu
7
10
  @events = events
8
11
  end
9
12
 
13
+ # @return []
10
14
  def events
11
15
  @_events ||= Vedeu.events.add(self) do
12
16
  event(:menu_next) { next_item }
@@ -22,24 +26,29 @@ module Vedeu
22
26
  end
23
27
  end
24
28
 
29
+ # @return []
25
30
  def current
26
31
  @current
27
32
  end
28
33
 
34
+ # @return []
29
35
  def selected
30
36
  @selected
31
37
  end
32
38
 
39
+ # @return []
33
40
  def current_item
34
41
  @collection[@current]
35
42
  end
36
43
 
44
+ # @return []
37
45
  def selected_item
38
46
  return nil unless @selected
39
47
 
40
48
  @collection[@selected]
41
49
  end
42
50
 
51
+ # @return [Array]
43
52
  def items
44
53
  items = []
45
54
  @collection.each_with_index do |item, index|
@@ -60,52 +69,62 @@ module Vedeu
60
69
  items
61
70
  end
62
71
 
72
+ # @return []
63
73
  def view
64
74
  items[@current, @collection.size]
65
75
  end
66
76
 
77
+ # @return []
67
78
  def top_item
68
79
  @current = 0
69
80
 
70
81
  items
71
82
  end
72
83
 
84
+ # @return []
73
85
  def bottom_item
74
86
  @current = last
75
87
 
76
88
  items
77
89
  end
78
90
 
91
+ # @return []
79
92
  def next_item
80
93
  @current += 1 if @current < last
81
94
 
82
95
  items
83
96
  end
84
97
 
98
+ # @return []
85
99
  def prev_item
86
100
  @current -= 1 if @current > 0
87
101
 
88
102
  items
89
103
  end
90
104
 
105
+ # @return []
91
106
  def select_item
92
107
  @selected = @current
93
108
 
94
109
  items
95
110
  end
96
111
 
112
+ # @return []
97
113
  def deselect_item
98
114
  @selected = nil
99
115
 
100
116
  items
101
117
  end
102
118
 
119
+ # @return []
103
120
  def last
104
121
  @collection.size - 1
105
122
  end
106
123
 
124
+ # @return []
107
125
  def size
108
126
  @collection.size
109
127
  end
128
+
110
129
  end
111
130
  end
@@ -1,9 +1,15 @@
1
1
  module Vedeu
2
2
  class Position
3
+
4
+ # @param y [Fixnum]
5
+ # @param x [Fixnum]
6
+ # @return [Position]
3
7
  def initialize(y = 1, x = 1)
4
8
  @y, @x = y, x
5
9
  end
6
10
 
11
+ # @param block [Proc]
12
+ # @return [String]
7
13
  def to_s(&block)
8
14
  if block_given?
9
15
  [ sequence, yield, sequence ].join
@@ -27,5 +33,6 @@ module Vedeu
27
33
  def x
28
34
  (@x == 0 || @x == nil) ? 1 : @x
29
35
  end
36
+
30
37
  end
31
38
  end
@@ -1,13 +1,19 @@
1
1
  module Vedeu
2
2
  class Render
3
+
4
+ # @param interface [Interface]
5
+ # @return [String]
3
6
  def self.call(interface)
4
7
  new(interface).render
5
8
  end
6
9
 
10
+ # @param interface [Interface]
11
+ # @return [Render]
7
12
  def initialize(interface)
8
13
  @interface = interface
9
14
  end
10
15
 
16
+ # @return [String]
11
17
  def render
12
18
  out = [ Clear.call(interface) ]
13
19
  processed_lines.each_with_index do |line, index|
@@ -42,7 +48,7 @@ module Vedeu
42
48
 
43
49
  processed << Stream.new({
44
50
  colour: stream.colour.attributes,
45
- style: stream.style,
51
+ style: stream.style.values,
46
52
  text: truncate(stream.text, remainder),
47
53
  })
48
54
 
@@ -55,7 +61,7 @@ module Vedeu
55
61
  Line.new({
56
62
  colour: line.colour.attributes,
57
63
  streams: processed,
58
- style: line.style,
64
+ style: line.style.values,
59
65
  })
60
66
 
61
67
  else
@@ -66,8 +72,7 @@ module Vedeu
66
72
  end
67
73
 
68
74
  def exceeds_width?(line)
69
- content = line.streams.map(&:text).join
70
- content.size > width
75
+ line.streams.map(&:text).join.size > width
71
76
  end
72
77
 
73
78
  def truncate(text, value)
@@ -79,11 +84,12 @@ module Vedeu
79
84
  end
80
85
 
81
86
  def height
82
- interface.height
87
+ interface.viewport_height
83
88
  end
84
89
 
85
90
  def width
86
- interface.width
91
+ interface.viewport_width
87
92
  end
93
+
88
94
  end
89
95
  end