vedeu 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/Gemfile +0 -1
- data/Guardfile +0 -8
- data/README.md +33 -1
- data/Rakefile +0 -8
- data/bin/vedeu +9 -0
- data/lib/vedeu.rb +23 -6
- data/lib/vedeu/application.rb +47 -0
- data/lib/vedeu/interface/interface.rb +37 -0
- data/lib/vedeu/interface/interfaces.rb +49 -0
- data/lib/vedeu/output/background.rb +23 -0
- data/lib/vedeu/output/base.rb +49 -0
- data/lib/vedeu/output/colour.rb +30 -0
- data/lib/vedeu/output/compositor.rb +60 -0
- data/lib/vedeu/output/directive.rb +34 -0
- data/lib/vedeu/output/esc.rb +37 -0
- data/lib/vedeu/output/foreground.rb +23 -0
- data/lib/vedeu/output/position.rb +22 -0
- data/lib/vedeu/output/style.rb +32 -0
- data/lib/vedeu/output/translator.rb +62 -0
- data/lib/vedeu/process/command.rb +51 -0
- data/lib/vedeu/process/commands.rb +58 -0
- data/lib/vedeu/process/process.rb +31 -0
- data/lib/vedeu/support/terminal.rb +139 -0
- data/lib/vedeu/version.rb +1 -1
- data/test/lib/vedeu/application_test.rb +18 -0
- data/test/lib/vedeu/interface/interface_test.rb +76 -0
- data/test/lib/vedeu/interface/interfaces_test.rb +63 -0
- data/test/lib/vedeu/output/background_test.rb +10 -0
- data/test/lib/vedeu/output/base_test.rb +10 -0
- data/test/lib/vedeu/output/colour_test.rb +67 -0
- data/test/lib/vedeu/output/compositor_test.rb +106 -0
- data/test/lib/vedeu/output/directive_test.rb +55 -0
- data/test/lib/vedeu/output/esc_test.rb +71 -0
- data/test/lib/vedeu/output/foreground_test.rb +10 -0
- data/test/lib/vedeu/output/position_test.rb +33 -0
- data/test/lib/vedeu/output/style_test.rb +59 -0
- data/test/lib/vedeu/output/translator_test.rb +52 -0
- data/test/lib/vedeu/process/command_test.rb +54 -0
- data/test/lib/vedeu/process/commands_test.rb +62 -0
- data/test/lib/vedeu/process/process_test.rb +11 -0
- data/test/lib/vedeu/support/terminal_test.rb +140 -0
- data/test/lib/vedeu/version_test.rb +9 -0
- data/test/support/test_app/bin/testapp +32 -0
- data/test/test_helper.rb +4 -0
- data/vedeu.gemspec +0 -6
- metadata +60 -99
- data/.rubocop.yml +0 -2
- data/features/.gitkeep +0 -0
- data/lib/vedeu/buffer.rb +0 -106
- data/lib/vedeu/colour.rb +0 -98
- data/lib/vedeu/terminal.rb +0 -25
- data/test/lib/vedeu/buffer_test.rb +0 -114
- data/test/lib/vedeu/colour_test.rb +0 -57
- data/test/lib/vedeu/terminal_test.rb +0 -30
@@ -0,0 +1,34 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class InvalidDirective < StandardError; end
|
3
|
+
|
4
|
+
class Directive
|
5
|
+
class << self
|
6
|
+
def enact(directive)
|
7
|
+
new(directive).enact
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(directive)
|
12
|
+
@directive = directive
|
13
|
+
end
|
14
|
+
|
15
|
+
def enact
|
16
|
+
raise InvalidDirective unless valid_directive?
|
17
|
+
|
18
|
+
return Style.set(directive) if directive.is_a?(Symbol)
|
19
|
+
|
20
|
+
if directive.is_a?(Array)
|
21
|
+
return Position.set(*directive) if directive.first.is_a?(Numeric)
|
22
|
+
return Colour.set(directive) if directive.first.is_a?(Symbol)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :directive
|
29
|
+
|
30
|
+
def valid_directive?
|
31
|
+
directive.is_a?(Array) || directive.is_a?(Symbol)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Esc
|
3
|
+
class << self
|
4
|
+
def bold
|
5
|
+
[esc, '1m'].join
|
6
|
+
end
|
7
|
+
|
8
|
+
def clear
|
9
|
+
[esc, '2J'].join
|
10
|
+
end
|
11
|
+
|
12
|
+
def esc
|
13
|
+
[27.chr, '['].join
|
14
|
+
end
|
15
|
+
|
16
|
+
def hide_cursor
|
17
|
+
[esc, '?25l'].join
|
18
|
+
end
|
19
|
+
|
20
|
+
def inverse
|
21
|
+
[esc, '7m'].join
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset
|
25
|
+
[esc, '0m'].join
|
26
|
+
end
|
27
|
+
|
28
|
+
def show_cursor
|
29
|
+
[esc, '?25h'].join
|
30
|
+
end
|
31
|
+
|
32
|
+
def underline
|
33
|
+
[esc, '4m'].join
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Foreground < Base
|
3
|
+
private
|
4
|
+
|
5
|
+
def prefix
|
6
|
+
'38;5;'
|
7
|
+
end
|
8
|
+
|
9
|
+
def codes
|
10
|
+
{
|
11
|
+
black: 30,
|
12
|
+
red: 31,
|
13
|
+
green: 32,
|
14
|
+
yellow: 33,
|
15
|
+
blue: 34,
|
16
|
+
magenta: 35,
|
17
|
+
cyan: 36,
|
18
|
+
white: 37,
|
19
|
+
default: 39,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Position
|
3
|
+
class << self
|
4
|
+
def set(y = 0, x = 0)
|
5
|
+
new(y, x).set
|
6
|
+
end
|
7
|
+
alias_method :reset, :set
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(y = 0, x = 0)
|
11
|
+
@y, @x = y, x
|
12
|
+
end
|
13
|
+
|
14
|
+
def set
|
15
|
+
[Esc.esc, (y + 1), ';', (x + 1), 'H'].join
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_accessor :y, :x
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Style
|
3
|
+
class << self
|
4
|
+
def set(style)
|
5
|
+
new(style).set
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(style)
|
10
|
+
@style = style
|
11
|
+
end
|
12
|
+
|
13
|
+
def set
|
14
|
+
case style
|
15
|
+
when :bold then Esc.bold
|
16
|
+
when :clear then Esc.clear
|
17
|
+
when :hide_cursor then Esc.hide_cursor
|
18
|
+
when :inverse then Esc.inverse
|
19
|
+
when :reset then Esc.reset
|
20
|
+
when :normal then Esc.reset
|
21
|
+
when :show_cursor then Esc.show_cursor
|
22
|
+
when :underline then Esc.underline
|
23
|
+
else
|
24
|
+
""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :style
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Translator
|
3
|
+
class << self
|
4
|
+
def translate(html_colour = nil)
|
5
|
+
new(html_colour).translate
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(html_colour = nil)
|
10
|
+
@html_colour = html_colour
|
11
|
+
end
|
12
|
+
|
13
|
+
def translate
|
14
|
+
return unless valid?
|
15
|
+
[term_colour_base, red, green, blue].inject(:+)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :html_colour
|
21
|
+
|
22
|
+
def red
|
23
|
+
(html_colour[1..2].to_i(16) / colour_divide) * 36
|
24
|
+
end
|
25
|
+
|
26
|
+
def green
|
27
|
+
(html_colour[3..4].to_i(16) / colour_divide) * 6
|
28
|
+
end
|
29
|
+
|
30
|
+
def blue
|
31
|
+
(html_colour[5..6].to_i(16) / colour_divide) * 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def colour_divide
|
35
|
+
source_values / target_values
|
36
|
+
end
|
37
|
+
|
38
|
+
def source_values
|
39
|
+
256
|
40
|
+
end
|
41
|
+
|
42
|
+
def target_values
|
43
|
+
5
|
44
|
+
end
|
45
|
+
|
46
|
+
def term_colour_base
|
47
|
+
16
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid?
|
51
|
+
html_colour && valid_type? && valid_format?
|
52
|
+
end
|
53
|
+
|
54
|
+
def valid_type?
|
55
|
+
html_colour.is_a?(String)
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid_format?
|
59
|
+
html_colour =~ /^#([A-Fa-f0-9]{6})$/
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class InvalidCommand < StandardError; end
|
3
|
+
|
4
|
+
class Command
|
5
|
+
class << self
|
6
|
+
def define(name, klass, args = [], options = {})
|
7
|
+
new(name, klass, args, options).define
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(name, klass, args = [], options = {})
|
12
|
+
@name, @klass, @args, @options = name, klass, args, options
|
13
|
+
end
|
14
|
+
|
15
|
+
def define
|
16
|
+
{ name => executable } if valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :name, :klass, :args, :options
|
22
|
+
|
23
|
+
def executable
|
24
|
+
Proc.new { klass.dispatch(*args) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
empty_name? || empty_klass? || klass_defined? || dispatch_defined? || true
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty_name?
|
32
|
+
raise InvalidCommand, "Command name is missing." if name.to_s.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def empty_klass?
|
36
|
+
raise InvalidCommand, "Command class is missing." if klass.to_s.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def klass_defined?
|
40
|
+
unless Object.const_defined?(klass.to_s)
|
41
|
+
raise InvalidCommand, "Command class is not defined."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def dispatch_defined?
|
46
|
+
unless klass.singleton_methods(false).include?(:dispatch)
|
47
|
+
raise InvalidCommand, "Command dispatch method is not defined."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Commands
|
3
|
+
include Singleton
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def instance(&block)
|
7
|
+
@instance ||= new(&block)
|
8
|
+
end
|
9
|
+
alias_method :define, :instance
|
10
|
+
|
11
|
+
# def define(name, klass, args = [], options = {}, &block)
|
12
|
+
# instance.define(name, klass, args = [], options = {})
|
13
|
+
# end
|
14
|
+
|
15
|
+
def execute(command = "")
|
16
|
+
instance.execute(command)
|
17
|
+
end
|
18
|
+
|
19
|
+
def list
|
20
|
+
instance.list
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(&block)
|
25
|
+
@commands ||= { 'exit' => Proc.new { Exit.dispatch } }
|
26
|
+
|
27
|
+
yield self if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
def define(name, klass, args = [], options = {})
|
31
|
+
commands.merge!(Command.define(name, klass, args, options))
|
32
|
+
end
|
33
|
+
alias_method :add, :define
|
34
|
+
|
35
|
+
def execute(command)
|
36
|
+
commands.fetch(command).call if exists?(command)
|
37
|
+
end
|
38
|
+
|
39
|
+
def list
|
40
|
+
commands.inspect
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_accessor :commands
|
46
|
+
attr_accessor :instance
|
47
|
+
|
48
|
+
def exists?(command)
|
49
|
+
commands.fetch(command, false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Exit
|
54
|
+
def self.dispatch
|
55
|
+
:stop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Process
|
3
|
+
class << self
|
4
|
+
def event_loop
|
5
|
+
new.event_loop
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize; end
|
10
|
+
|
11
|
+
def event_loop
|
12
|
+
while true do
|
13
|
+
command = evaluate
|
14
|
+
|
15
|
+
break if command == :stop
|
16
|
+
|
17
|
+
Compositor.write(command)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def evaluate
|
24
|
+
Commands.execute(read)
|
25
|
+
end
|
26
|
+
|
27
|
+
def read
|
28
|
+
Terminal.input
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Vedeu
|
2
|
+
class Terminal
|
3
|
+
class << self
|
4
|
+
def input
|
5
|
+
console.gets.chomp
|
6
|
+
end
|
7
|
+
|
8
|
+
def output(stream = '')
|
9
|
+
console.puts(stream)
|
10
|
+
end
|
11
|
+
|
12
|
+
def width
|
13
|
+
size.last
|
14
|
+
end
|
15
|
+
|
16
|
+
def height
|
17
|
+
size.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def size
|
21
|
+
console.winsize
|
22
|
+
end
|
23
|
+
|
24
|
+
def open(options = {}, &block)
|
25
|
+
new(options).open(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def close
|
29
|
+
clear_screen
|
30
|
+
show_cursor
|
31
|
+
output(Position.reset)
|
32
|
+
end
|
33
|
+
|
34
|
+
def cooked(instance, &block)
|
35
|
+
console.cooked do
|
36
|
+
instance.initial_setup!
|
37
|
+
|
38
|
+
yield
|
39
|
+
end if block_given?
|
40
|
+
end
|
41
|
+
alias_method :open_cooked, :cooked
|
42
|
+
|
43
|
+
def raw(instance, &block)
|
44
|
+
console.raw do
|
45
|
+
instance.initial_setup!
|
46
|
+
|
47
|
+
yield
|
48
|
+
end if block_given?
|
49
|
+
end
|
50
|
+
alias_method :open_raw, :raw
|
51
|
+
|
52
|
+
def console
|
53
|
+
IO.console
|
54
|
+
end
|
55
|
+
|
56
|
+
def clear_screen
|
57
|
+
output(Esc.reset)
|
58
|
+
output(Esc.clear)
|
59
|
+
end
|
60
|
+
|
61
|
+
def clear_line(index)
|
62
|
+
output(Position.set(index, 0))
|
63
|
+
output(" " * width)
|
64
|
+
end
|
65
|
+
|
66
|
+
def show_cursor
|
67
|
+
output(Esc.show_cursor)
|
68
|
+
end
|
69
|
+
|
70
|
+
def hide_cursor
|
71
|
+
output(Esc.hide_cursor)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def initialize(options = {}, &block)
|
76
|
+
@options = options
|
77
|
+
|
78
|
+
yield self if block_given?
|
79
|
+
end
|
80
|
+
|
81
|
+
def open(&block)
|
82
|
+
terminal_mode(&block).fetch(mode, noop).call
|
83
|
+
end
|
84
|
+
|
85
|
+
def initial_setup!
|
86
|
+
Terminal.clear_screen if clear_screen?
|
87
|
+
set_cursor
|
88
|
+
output(Position.reset)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def terminal_mode(&block)
|
94
|
+
{
|
95
|
+
cooked: Proc.new { Terminal.cooked(self, &block) },
|
96
|
+
raw: Proc.new { Terminal.raw(self, &block) }
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
def cursor_mode
|
101
|
+
{
|
102
|
+
show: Proc.new { Terminal.show_cursor },
|
103
|
+
hide: Proc.new { Terminal.hide_cursor }
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_cursor
|
108
|
+
cursor_mode.fetch(cursor).call
|
109
|
+
end
|
110
|
+
|
111
|
+
def cursor
|
112
|
+
options.fetch(:cursor, :show)
|
113
|
+
end
|
114
|
+
|
115
|
+
def mode
|
116
|
+
options.fetch(:mode, :cooked)
|
117
|
+
end
|
118
|
+
|
119
|
+
def clear_screen?
|
120
|
+
options.fetch(:clear, true)
|
121
|
+
end
|
122
|
+
|
123
|
+
def noop
|
124
|
+
Proc.new {}
|
125
|
+
end
|
126
|
+
|
127
|
+
def options
|
128
|
+
defaults.merge!(@options)
|
129
|
+
end
|
130
|
+
|
131
|
+
def defaults
|
132
|
+
{
|
133
|
+
mode: :cooked, # or :raw
|
134
|
+
clear: true, # or false (clears the screen if true)
|
135
|
+
cursor: :show, # or :hide
|
136
|
+
}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|