vedeu 0.1.15 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +2 -0
- data/README.md +116 -98
- data/lib/vedeu.rb +24 -11
- data/lib/vedeu/api/api.rb +174 -33
- data/lib/vedeu/api/composition.rb +2 -13
- data/lib/vedeu/api/helpers.rb +41 -0
- data/lib/vedeu/api/interface.rb +147 -34
- data/lib/vedeu/api/line.rb +47 -0
- data/lib/vedeu/api/stream.rb +41 -0
- data/lib/vedeu/application.rb +9 -2
- data/lib/vedeu/configuration.rb +66 -8
- data/lib/vedeu/launcher.rb +11 -0
- data/lib/vedeu/models/attributes/background.rb +29 -0
- data/lib/vedeu/models/attributes/coercions.rb +30 -0
- data/lib/vedeu/models/attributes/colour_translator.rb +106 -16
- data/lib/vedeu/models/attributes/foreground.rb +29 -0
- data/lib/vedeu/models/attributes/presentation.rb +15 -0
- data/lib/vedeu/models/colour.rb +12 -7
- data/lib/vedeu/models/composition.rb +23 -5
- data/lib/vedeu/models/geometry.rb +101 -16
- data/lib/vedeu/models/interface.rb +36 -28
- data/lib/vedeu/models/line.rb +16 -14
- data/lib/vedeu/models/stream.rb +17 -25
- data/lib/vedeu/models/style.rb +29 -0
- data/lib/vedeu/support/buffer.rb +36 -21
- data/lib/vedeu/support/buffers.rb +88 -0
- data/lib/vedeu/{output → support}/clear.rb +9 -2
- data/lib/vedeu/support/esc.rb +16 -2
- data/lib/vedeu/support/event.rb +104 -0
- data/lib/vedeu/support/events.rb +61 -0
- data/lib/vedeu/support/focus.rb +69 -0
- data/lib/vedeu/{api → support}/grid.rb +29 -25
- data/lib/vedeu/support/groups.rb +51 -0
- data/lib/vedeu/support/input.rb +5 -0
- data/lib/vedeu/support/log.rb +105 -0
- data/lib/vedeu/support/menu.rb +19 -0
- data/lib/vedeu/support/position.rb +7 -0
- data/lib/vedeu/{output → support}/render.rb +12 -6
- data/lib/vedeu/support/terminal.rb +21 -0
- data/lib/vedeu/support/trace.rb +54 -0
- data/lib/vedeu/{output → support}/view.rb +15 -10
- data/test/lib/vedeu/api/api_test.rb +55 -29
- data/test/lib/vedeu/api/interface_test.rb +3 -49
- data/test/lib/vedeu/api/line_test.rb +71 -0
- data/test/lib/vedeu/api/stream_test.rb +25 -0
- data/test/lib/vedeu/models/attributes/background_test.rb +83 -0
- data/test/lib/vedeu/models/attributes/coercer_test.rb +52 -0
- data/test/lib/vedeu/models/attributes/foreground_test.rb +83 -0
- data/test/lib/vedeu/models/attributes/presentation_test.rb +30 -0
- data/test/lib/vedeu/models/composition_test.rb +6 -6
- data/test/lib/vedeu/models/geometry_test.rb +34 -0
- data/test/lib/vedeu/models/interface_test.rb +0 -12
- data/test/lib/vedeu/models/line_test.rb +1 -13
- data/test/lib/vedeu/models/stream_test.rb +4 -50
- data/test/lib/vedeu/models/style_test.rb +39 -0
- data/test/lib/vedeu/support/buffer_test.rb +7 -3
- data/test/lib/vedeu/support/buffers_test.rb +15 -0
- data/test/lib/vedeu/{output → support}/clear_test.rb +8 -1
- data/test/lib/vedeu/support/esc_test.rb +2 -2
- data/test/lib/vedeu/support/event_test.rb +41 -0
- data/test/lib/vedeu/support/events_test.rb +70 -0
- data/test/lib/vedeu/support/focus_test.rb +114 -0
- data/test/lib/vedeu/support/grid_test.rb +31 -0
- data/test/lib/vedeu/support/groups_test.rb +65 -0
- data/test/lib/vedeu/{output → support}/render_test.rb +8 -1
- data/test/lib/vedeu/{output → support}/view_test.rb +1 -1
- data/test/test_helper.rb +3 -1
- data/vedeu.gemspec +3 -2
- metadata +67 -31
- data/lib/vedeu/api/events.rb +0 -46
- data/lib/vedeu/api/log.rb +0 -84
- data/lib/vedeu/models/attributes/attributes.rb +0 -25
- data/lib/vedeu/models/store.rb +0 -29
- data/lib/vedeu/output/buffers.rb +0 -65
- data/test/lib/vedeu/api/events_test.rb +0 -36
- data/test/lib/vedeu/api/grid_test.rb +0 -33
- data/test/lib/vedeu/models/attributes/attributes_test.rb +0 -39
- data/test/lib/vedeu/models/attributes/colour_translator_test.rb +0 -78
- data/test/lib/vedeu/models/store_test.rb +0 -57
- data/test/lib/vedeu/output/buffers_test.rb +0 -35
@@ -0,0 +1,29 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Style
|
3
|
+
|
4
|
+
attr_reader :values
|
5
|
+
|
6
|
+
# @param values [String|Array]
|
7
|
+
# @return [Style]
|
8
|
+
def initialize(values)
|
9
|
+
@values = values
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
def to_s
|
14
|
+
escape_sequences
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def escape_sequences
|
20
|
+
@_sequences ||= if values.nil? || values.empty?
|
21
|
+
''
|
22
|
+
|
23
|
+
else
|
24
|
+
Array(values).flatten.map { |value| Esc.string(value) }.join
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/vedeu/support/buffer.rb
CHANGED
@@ -1,41 +1,56 @@
|
|
1
1
|
module Vedeu
|
2
2
|
class Buffer
|
3
|
-
attr_reader :clear, :current, :group, :name, :_next
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
|
4
|
+
attr_reader :back, :front, :interface
|
5
|
+
|
6
|
+
# @param attributes [Hash]
|
7
|
+
# @return [Buffer]
|
8
|
+
def initialize(attributes = {})
|
9
|
+
@attributes = attributes
|
10
|
+
|
11
|
+
@back = attributes.fetch(:back)
|
12
|
+
@front = attributes.fetch(:front)
|
13
|
+
@interface = attributes.fetch(:interface)
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
+
# @param view [Interface]
|
17
|
+
# @return [Buffer]
|
18
|
+
def enqueue(view)
|
19
|
+
merge({ back: view })
|
16
20
|
end
|
17
21
|
|
22
|
+
# @return [Buffer]
|
18
23
|
def refresh
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
clear
|
24
|
+
return merge({ front: back, back: nil }).render if content_available?
|
25
|
+
return clear if no_content_available?
|
26
|
+
return render
|
27
|
+
end
|
24
28
|
|
25
|
-
|
26
|
-
|
29
|
+
def render
|
30
|
+
Terminal.output(front.to_s)
|
27
31
|
|
28
|
-
|
32
|
+
self
|
33
|
+
end
|
29
34
|
|
30
|
-
|
35
|
+
def clear
|
36
|
+
Terminal.output(interface.clear)
|
31
37
|
|
32
38
|
self
|
33
39
|
end
|
34
40
|
|
35
41
|
private
|
36
42
|
|
37
|
-
def merge(
|
38
|
-
Buffer.new(@
|
43
|
+
def merge(new_attributes)
|
44
|
+
Buffer.new(@attributes.merge(new_attributes))
|
39
45
|
end
|
46
|
+
|
47
|
+
def content_available?
|
48
|
+
!!(back)
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_content_available?
|
52
|
+
front.nil?
|
53
|
+
end
|
54
|
+
|
40
55
|
end
|
41
56
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Vedeu
|
2
|
+
module Buffers
|
3
|
+
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# @param attributes [Hash]
|
7
|
+
# @return [Hash]
|
8
|
+
def create(attributes)
|
9
|
+
store_attributes(attributes)
|
10
|
+
|
11
|
+
groups.add(attributes[:group], attributes[:name], attributes[:delay])
|
12
|
+
|
13
|
+
store_interface(Interface.new(attributes))
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Hash]
|
17
|
+
def reset
|
18
|
+
@_storage = {}
|
19
|
+
@_buffers = {}
|
20
|
+
groups.reset
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param name [String]
|
24
|
+
# @return [Hash]
|
25
|
+
def retrieve_attributes(name)
|
26
|
+
storage.fetch(name) { fail EntityNotFound, 'Interface was not found.' }
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param name [String]
|
30
|
+
# @return [Buffer]
|
31
|
+
def retrieve_interface(name)
|
32
|
+
buffers.fetch(name) { fail EntityNotFound, 'Interface was not found.' }
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param attributes [Hash]
|
36
|
+
# @return [Hash]
|
37
|
+
def store_attributes(attributes)
|
38
|
+
storage.store(attributes[:name], attributes)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param interface [Interface]
|
42
|
+
# @return [Buffer]
|
43
|
+
def store_interface(interface)
|
44
|
+
update(interface.name,
|
45
|
+
Buffer.new(interface: interface, back: nil, front: nil))
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param name [String]
|
49
|
+
# @param view [Interface]
|
50
|
+
# @return []
|
51
|
+
def enqueue(name, view)
|
52
|
+
update(name, retrieve_interface(name).enqueue(view))
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Array]
|
56
|
+
def refresh_all
|
57
|
+
buffers.keys.map { |name| refresh(name) }
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Array]
|
61
|
+
def refresh_group(group_name)
|
62
|
+
groups.find(group_name).map { |name| refresh(name) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def refresh(name)
|
66
|
+
update(name, retrieve_interface(name).refresh)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def update(name, buffer)
|
72
|
+
buffers.store(name, buffer)
|
73
|
+
end
|
74
|
+
|
75
|
+
def groups
|
76
|
+
@_groups ||= Groups.new
|
77
|
+
end
|
78
|
+
|
79
|
+
def buffers
|
80
|
+
@_buffers ||= {}
|
81
|
+
end
|
82
|
+
|
83
|
+
def storage
|
84
|
+
@_storage ||= {}
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -1,16 +1,22 @@
|
|
1
1
|
module Vedeu
|
2
2
|
class Clear
|
3
|
+
|
4
|
+
# @param interface [Interface]
|
5
|
+
# @return [String]
|
3
6
|
def self.call(interface)
|
4
7
|
new(interface).clear
|
5
8
|
end
|
6
9
|
|
10
|
+
# @param interface [Interface]
|
11
|
+
# @return [Clear]
|
7
12
|
def initialize(interface)
|
8
13
|
@interface = interface
|
9
14
|
end
|
10
15
|
|
16
|
+
# @return [String]
|
11
17
|
def clear
|
12
18
|
rows.inject([colours]) do |line, index|
|
13
|
-
line << interface.origin(index) { ' ' * interface.
|
19
|
+
line << interface.origin(index) { ' ' * interface.viewport_width }
|
14
20
|
end.join
|
15
21
|
end
|
16
22
|
|
@@ -23,7 +29,8 @@ module Vedeu
|
|
23
29
|
end
|
24
30
|
|
25
31
|
def rows
|
26
|
-
interface.
|
32
|
+
interface.viewport_height.times
|
27
33
|
end
|
34
|
+
|
28
35
|
end
|
29
36
|
end
|
data/lib/vedeu/support/esc.rb
CHANGED
@@ -1,18 +1,25 @@
|
|
1
1
|
module Vedeu
|
2
2
|
module Esc
|
3
|
+
|
3
4
|
extend self
|
4
5
|
|
6
|
+
# @param y [Fixnum]
|
7
|
+
# @param x [Fixnum]
|
8
|
+
# @param block [Proc]
|
9
|
+
# @return [String]
|
5
10
|
def set_position(y = 1, x = 1, &block)
|
6
11
|
Position.new(y, x).to_s(&block)
|
7
12
|
end
|
8
13
|
|
14
|
+
# @param value [String]
|
15
|
+
# @return [String]
|
9
16
|
def string(value = '')
|
10
17
|
case value
|
11
18
|
when 'bg_reset' then "\e[48;2;49m"
|
12
19
|
when 'blink' then "\e[5m"
|
13
20
|
when 'blink_off' then "\e[25m"
|
14
21
|
when 'bold' then "\e[1m"
|
15
|
-
when 'bold_off' then "\e[
|
22
|
+
when 'bold_off' then "\e[22m"
|
16
23
|
when 'clear' then "\e[38;2;39m\e[48;2;49m\e[2J"
|
17
24
|
when 'clear_line' then "\e[38;2;39m\e[48;2;49m\e[2K"
|
18
25
|
when 'colour_reset' then "\e[38;2;39m\e[48;2;49m"
|
@@ -23,7 +30,7 @@ module Vedeu
|
|
23
30
|
when 'negative' then "\e[7m"
|
24
31
|
when 'positive' then "\e[27m"
|
25
32
|
when 'reset' then "\e[0m"
|
26
|
-
when 'normal' then "\e[24m\e[
|
33
|
+
when 'normal' then "\e[24m\e[22m\e[27m"
|
27
34
|
when 'dim' then "\e[2m"
|
28
35
|
when 'show_cursor' then "\e[?25h"
|
29
36
|
when 'underline' then "\e[4m"
|
@@ -32,5 +39,12 @@ module Vedeu
|
|
32
39
|
''
|
33
40
|
end
|
34
41
|
end
|
42
|
+
|
43
|
+
# private
|
44
|
+
|
45
|
+
# def method_missing(method, *args, &block)
|
46
|
+
# self.send(:string, method, &block)
|
47
|
+
# end
|
48
|
+
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Event
|
3
|
+
|
4
|
+
# @param closure [Proc]
|
5
|
+
# @param options [Hash]
|
6
|
+
# @return [Event]
|
7
|
+
def initialize(closure, options = {})
|
8
|
+
@closure = closure
|
9
|
+
@options = options
|
10
|
+
@deadline = 0
|
11
|
+
@executed_at = 0
|
12
|
+
@now = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
# @params args [Array]
|
16
|
+
# @return []
|
17
|
+
def trigger(*args)
|
18
|
+
return execute(*args) unless debouncing? || throttling?
|
19
|
+
|
20
|
+
return execute(*args) if debouncing? && set_executed > deadline
|
21
|
+
|
22
|
+
return execute(*args) if throttling? && elapsed_time > delay
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :closure
|
28
|
+
attr_accessor :deadline, :executed_at, :now
|
29
|
+
|
30
|
+
def execute(*args)
|
31
|
+
reset_deadline
|
32
|
+
|
33
|
+
set_executed
|
34
|
+
|
35
|
+
reset_time
|
36
|
+
|
37
|
+
closure.call(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def throttling?
|
41
|
+
set_time
|
42
|
+
|
43
|
+
options[:delay] > 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def debouncing?
|
47
|
+
set_time
|
48
|
+
|
49
|
+
set_deadline unless has_deadline?
|
50
|
+
|
51
|
+
options[:debounce] > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def elapsed_time
|
55
|
+
now - @executed_at
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_executed
|
59
|
+
@executed_at = now
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_time
|
63
|
+
@now = Time.now.to_f
|
64
|
+
end
|
65
|
+
|
66
|
+
def reset_time
|
67
|
+
@now = 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_deadline?
|
71
|
+
@deadline > 0
|
72
|
+
end
|
73
|
+
|
74
|
+
def reset_deadline
|
75
|
+
@deadline = 0
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_deadline
|
79
|
+
@deadline = now + debounce
|
80
|
+
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def debounce
|
85
|
+
options[:debounce]
|
86
|
+
end
|
87
|
+
|
88
|
+
def delay
|
89
|
+
options[:delay]
|
90
|
+
end
|
91
|
+
|
92
|
+
def options
|
93
|
+
defaults.merge!(@options)
|
94
|
+
end
|
95
|
+
|
96
|
+
def defaults
|
97
|
+
{
|
98
|
+
delay: 0,
|
99
|
+
debounce: 0
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Events
|
3
|
+
|
4
|
+
# @param block [Proc]
|
5
|
+
# @return [Events]
|
6
|
+
def initialize(&block)
|
7
|
+
@handlers = Hash.new { |hash, key| hash[key] = { events: [] } }
|
8
|
+
|
9
|
+
instance_eval(&block) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param object []
|
13
|
+
# @param block [Proc]
|
14
|
+
# @return []
|
15
|
+
def add(object, &block)
|
16
|
+
@self_before_instance_eval = eval('self', block.binding)
|
17
|
+
|
18
|
+
instance_eval(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see Vedeu::API#event
|
22
|
+
def event(name, opts = {}, &block)
|
23
|
+
handlers[name][:events] << Event.new(block, opts)
|
24
|
+
handlers[name]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Unregisters the event by name, effectively deleting the associated events
|
28
|
+
# bound with it also.
|
29
|
+
#
|
30
|
+
# @param name [Symbol]
|
31
|
+
# @return []
|
32
|
+
def unevent(name)
|
33
|
+
handlers.delete_if { |k, v| k == name }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a collection of the names of all the registered events.
|
37
|
+
#
|
38
|
+
# @return [Array]
|
39
|
+
def registered
|
40
|
+
handlers.keys
|
41
|
+
end
|
42
|
+
|
43
|
+
# @see Vedeu::API#trigger
|
44
|
+
def trigger(name, *args)
|
45
|
+
handlers[name][:events].each { |event| event.trigger(*args) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def reset
|
49
|
+
@handlers = Hash.new { |hash, key| hash[key] = { events: [] } }
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :handlers
|
55
|
+
|
56
|
+
def method_missing(method, *args, &block)
|
57
|
+
@self_before_instance_eval.send(method, *args, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Vedeu
|
2
|
+
NoInterfacesDefined = Class.new(StandardError)
|
3
|
+
InterfaceNotFound = Class.new(StandardError)
|
4
|
+
|
5
|
+
# Maintains which interface is current in focus.
|
6
|
+
class Focus
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
register_events
|
10
|
+
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(name)
|
15
|
+
if registered?(name)
|
16
|
+
storage
|
17
|
+
|
18
|
+
else
|
19
|
+
storage << name
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_name(name)
|
25
|
+
fail InterfaceNotFound unless storage.include?(name)
|
26
|
+
|
27
|
+
storage.rotate!(storage.index(name))
|
28
|
+
|
29
|
+
current
|
30
|
+
end
|
31
|
+
|
32
|
+
def current
|
33
|
+
fail NoInterfacesDefined if storage.empty?
|
34
|
+
|
35
|
+
storage.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def next_item
|
39
|
+
storage.rotate!
|
40
|
+
|
41
|
+
current
|
42
|
+
end
|
43
|
+
|
44
|
+
def prev_item
|
45
|
+
storage.rotate!(-1)
|
46
|
+
|
47
|
+
current
|
48
|
+
end
|
49
|
+
|
50
|
+
def register_events
|
51
|
+
Vedeu.event(:_focus_next_) { next_item }
|
52
|
+
Vedeu.event(:_focus_prev_) { prev_item }
|
53
|
+
Vedeu.event(:_focus_by_name_) { |name| by_name(name) }
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def registered?(name)
|
59
|
+
return false if storage.empty?
|
60
|
+
|
61
|
+
storage.include?(name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def storage
|
65
|
+
@storage ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|