vedeu 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -2
- data/Rakefile +8 -0
- data/bin/vedeu +1 -1
- data/config/cucumber.yml +8 -0
- data/features/getting_started.feature +10 -0
- data/features/step_definitions/vedeu_steps.rb +11 -0
- data/features/support/env.rb +12 -0
- data/lib/vedeu.rb +30 -9
- data/lib/vedeu/application.rb +1 -1
- data/lib/vedeu/launcher.rb +26 -0
- data/lib/vedeu/output/colour.rb +1 -1
- data/lib/vedeu/output/compositor.rb +9 -6
- data/lib/vedeu/output/directive.rb +1 -1
- data/lib/vedeu/output/geometry.rb +1 -1
- data/lib/vedeu/output/position.rb +2 -2
- data/lib/vedeu/output/style.rb +1 -1
- data/lib/vedeu/output/wordwrap.rb +2 -1
- data/lib/vedeu/process/event_loop.rb +2 -2
- data/lib/vedeu/process/input.rb +30 -0
- data/lib/vedeu/repository/command.rb +32 -0
- data/lib/vedeu/repository/command_repository.rb +27 -0
- data/lib/vedeu/{process → repository}/dummy_command.rb +2 -2
- data/lib/vedeu/repository/dummy_interface.rb +4 -0
- data/lib/vedeu/repository/interface.rb +52 -0
- data/lib/vedeu/repository/interface_repository.rb +49 -0
- data/lib/vedeu/repository/repository.rb +35 -0
- data/lib/vedeu/repository/storage.rb +46 -0
- data/lib/vedeu/support/terminal.rb +5 -6
- data/lib/vedeu/version.rb +1 -1
- data/test/lib/vedeu/application_test.rb +1 -1
- data/test/lib/vedeu/output/compositor_test.rb +15 -13
- data/test/lib/vedeu/output/directive_test.rb +1 -1
- data/test/lib/vedeu/output/position_test.rb +1 -1
- data/test/lib/vedeu/process/event_loop_test.rb +2 -3
- data/test/lib/vedeu/process/input_test.rb +19 -0
- data/test/lib/vedeu/repository/command_repository_test.rb +55 -0
- data/test/lib/vedeu/repository/command_test.rb +39 -0
- data/test/lib/vedeu/repository/interface_repository_test.rb +71 -0
- data/test/lib/vedeu/repository/interface_test.rb +65 -0
- data/test/lib/vedeu/repository/repository_test.rb +88 -0
- data/test/lib/vedeu/repository/storage_test.rb +50 -0
- data/test/test_helper.rb +8 -0
- data/vedeu.gemspec +3 -0
- metadata +75 -21
- data/lib/vedeu/interface/dummy_interface.rb +0 -14
- data/lib/vedeu/interface/interface.rb +0 -57
- data/lib/vedeu/interface/interfaces.rb +0 -66
- data/lib/vedeu/process/command.rb +0 -51
- data/lib/vedeu/process/commands.rb +0 -35
- data/test/lib/vedeu/interface/dummy_test.rb +0 -22
- data/test/lib/vedeu/interface/interface_test.rb +0 -45
- data/test/lib/vedeu/interface/interfaces_test.rb +0 -108
- data/test/lib/vedeu/process/command_test.rb +0 -48
- data/test/lib/vedeu/process/commands_test.rb +0 -56
- data/test/lib/vedeu/process/dummy_command_test.rb +0 -16
@@ -1,57 +0,0 @@
|
|
1
|
-
module Vedeu
|
2
|
-
class NotImplementedError < StandardError; end
|
3
|
-
|
4
|
-
class Interface
|
5
|
-
def initialize(options = {})
|
6
|
-
@options = options
|
7
|
-
@output = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def initial_state
|
11
|
-
raise NotImplementedError, 'Subclasses implement this method.'
|
12
|
-
end
|
13
|
-
|
14
|
-
def input
|
15
|
-
raise Collapse if evaluate == :stop
|
16
|
-
end
|
17
|
-
|
18
|
-
def output
|
19
|
-
write
|
20
|
-
end
|
21
|
-
|
22
|
-
def geometry
|
23
|
-
@geometry ||= Geometry.new(options[:geometry])
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
attr_reader :options
|
29
|
-
|
30
|
-
def evaluate
|
31
|
-
@output = Commands.execute(read)
|
32
|
-
end
|
33
|
-
|
34
|
-
def read
|
35
|
-
Terminal.input
|
36
|
-
end
|
37
|
-
|
38
|
-
def write
|
39
|
-
Compositor.arrange(@output, self)
|
40
|
-
end
|
41
|
-
|
42
|
-
def options
|
43
|
-
defaults.merge!(@options)
|
44
|
-
end
|
45
|
-
|
46
|
-
def defaults
|
47
|
-
{
|
48
|
-
geometry: {
|
49
|
-
y: 1,
|
50
|
-
x: 1,
|
51
|
-
width: :auto,
|
52
|
-
height: :auto
|
53
|
-
}
|
54
|
-
}
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module Vedeu
|
2
|
-
class UndefinedInterface < StandardError; end
|
3
|
-
|
4
|
-
module Interfaces
|
5
|
-
extend self
|
6
|
-
attr_accessor :interfaces
|
7
|
-
|
8
|
-
def define(&block)
|
9
|
-
if block_given?
|
10
|
-
yield self
|
11
|
-
else
|
12
|
-
self
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def defined
|
17
|
-
interfaces.empty? ? default : self
|
18
|
-
end
|
19
|
-
|
20
|
-
def list
|
21
|
-
interfaces.inspect
|
22
|
-
end
|
23
|
-
|
24
|
-
def add(name, options = {}, klass = DummyInterface)
|
25
|
-
interfaces[name] = klass.new(options) if valid?(klass)
|
26
|
-
self
|
27
|
-
end
|
28
|
-
|
29
|
-
def reset
|
30
|
-
@interfaces = {}
|
31
|
-
end
|
32
|
-
|
33
|
-
def find(name)
|
34
|
-
interfaces[name] || nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def initial_state
|
38
|
-
interfaces.values.map { |io| io.initial_state }
|
39
|
-
end
|
40
|
-
|
41
|
-
def input
|
42
|
-
interfaces.values.map { |io| io.input }
|
43
|
-
end
|
44
|
-
|
45
|
-
def output
|
46
|
-
interfaces.values.map { |io| io.output }
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def valid?(klass)
|
52
|
-
raise UndefinedInterface unless Object.const_defined?(klass.to_s)
|
53
|
-
true
|
54
|
-
end
|
55
|
-
|
56
|
-
def default
|
57
|
-
add(:dummy)
|
58
|
-
|
59
|
-
self
|
60
|
-
end
|
61
|
-
|
62
|
-
def interfaces
|
63
|
-
@interfaces ||= {}
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,51 +0,0 @@
|
|
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
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Vedeu
|
2
|
-
module Commands
|
3
|
-
extend self
|
4
|
-
|
5
|
-
def define(&block)
|
6
|
-
if block_given?
|
7
|
-
yield self
|
8
|
-
else
|
9
|
-
self
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute(command = "")
|
14
|
-
commands.fetch(command).call if exists?(command)
|
15
|
-
end
|
16
|
-
|
17
|
-
def list
|
18
|
-
commands.inspect
|
19
|
-
end
|
20
|
-
|
21
|
-
def add(name, klass, args = [], options = {})
|
22
|
-
commands.merge!(Command.define(name, klass, args, options))
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def exists?(command)
|
28
|
-
commands.fetch(command, false)
|
29
|
-
end
|
30
|
-
|
31
|
-
def commands
|
32
|
-
@commands ||= { "exit" => Proc.new { Exit.dispatch } }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require_relative '../../../test_helper'
|
2
|
-
|
3
|
-
module Vedeu
|
4
|
-
describe DummyInterface do
|
5
|
-
let(:described_class) { DummyInterface }
|
6
|
-
let(:described_instance) { described_class.new }
|
7
|
-
|
8
|
-
describe '#initial_state' do
|
9
|
-
let(:subject) { described_instance.initial_state }
|
10
|
-
|
11
|
-
it { subject.must_be_instance_of(NilClass) }
|
12
|
-
end
|
13
|
-
|
14
|
-
describe '#input' do
|
15
|
-
let(:subject) { described_instance.input }
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '#output' do
|
19
|
-
let(:subject) { described_instance.output }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require_relative '../../../test_helper'
|
2
|
-
|
3
|
-
module Vedeu
|
4
|
-
describe Interface do
|
5
|
-
let(:described_class) { Interface }
|
6
|
-
let(:described_instance) { described_class.new(options) }
|
7
|
-
let(:options) { {} }
|
8
|
-
|
9
|
-
it { described_instance.must_be_instance_of(Interface) }
|
10
|
-
|
11
|
-
describe '#initial_state' do
|
12
|
-
let(:subject) { described_instance.initial_state }
|
13
|
-
|
14
|
-
it { proc { subject }.must_raise(NotImplementedError) }
|
15
|
-
end
|
16
|
-
|
17
|
-
describe '#input' do
|
18
|
-
let(:subject) { described_instance.input }
|
19
|
-
|
20
|
-
before do
|
21
|
-
Terminal.stubs(:input).returns('stop')
|
22
|
-
Commands.stubs(:execute)
|
23
|
-
end
|
24
|
-
|
25
|
-
it { subject.must_be_instance_of(NilClass) }
|
26
|
-
end
|
27
|
-
|
28
|
-
describe '#output' do
|
29
|
-
let(:subject) { described_instance.output }
|
30
|
-
let(:command) { mock }
|
31
|
-
|
32
|
-
before { Compositor.stubs(:arrange).returns([]) }
|
33
|
-
|
34
|
-
it 'sends the output of the command to the compositor' do
|
35
|
-
subject.must_be_instance_of(Array)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '#geometry' do
|
40
|
-
let(:subject) { described_instance.geometry }
|
41
|
-
|
42
|
-
it { subject.must_be_instance_of(Geometry) }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,108 +0,0 @@
|
|
1
|
-
require_relative '../../../test_helper'
|
2
|
-
|
3
|
-
module Vedeu
|
4
|
-
describe Interfaces do
|
5
|
-
let(:described_class) { Interfaces }
|
6
|
-
|
7
|
-
describe '.define' do
|
8
|
-
let(:subject) { described_class.define }
|
9
|
-
|
10
|
-
it { subject.must_be_instance_of(Module) }
|
11
|
-
|
12
|
-
context 'when a block is given' do
|
13
|
-
let(:subject) { described_class.define { :some_block } }
|
14
|
-
|
15
|
-
it { subject.must_be_instance_of(Symbol) }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '.defined' do
|
20
|
-
let(:subject) { described_class.defined }
|
21
|
-
|
22
|
-
after { described_class.interfaces = {} }
|
23
|
-
|
24
|
-
context 'when interfaces are not defined' do
|
25
|
-
before { described_class.interfaces = {} }
|
26
|
-
|
27
|
-
it 'adds the default interface and returns all interfaces' do
|
28
|
-
subject.must_be_instance_of(Module)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'when interfaces are defined' do
|
33
|
-
before { described_class.interfaces = { mock: :interface } }
|
34
|
-
|
35
|
-
it { subject.must_be_instance_of(Module) }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe '.list' do
|
40
|
-
let(:subject) { described_class.list }
|
41
|
-
|
42
|
-
it { subject.must_be_instance_of(String) }
|
43
|
-
end
|
44
|
-
|
45
|
-
describe '.add' do
|
46
|
-
let(:subject) { described_class.add(interface, options, klass) }
|
47
|
-
let(:interface) {}
|
48
|
-
let(:klass) { DummyInterface }
|
49
|
-
let(:options) { {} }
|
50
|
-
|
51
|
-
it { subject.must_be_instance_of(Module) }
|
52
|
-
|
53
|
-
context 'when the interface class does not exist' do
|
54
|
-
before { Object.stubs(:const_defined?).returns(false) }
|
55
|
-
|
56
|
-
it { proc { subject }.must_raise(UndefinedInterface) }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '.reset' do
|
61
|
-
let(:subject) { described_class.reset }
|
62
|
-
let(:interface) { :dummy }
|
63
|
-
|
64
|
-
before { described_class.add(:dummy) }
|
65
|
-
|
66
|
-
it { subject.must_be_instance_of(Hash) }
|
67
|
-
|
68
|
-
it { subject.must_be_empty }
|
69
|
-
end
|
70
|
-
|
71
|
-
describe '.find' do
|
72
|
-
let(:subject) { described_class.find(interface) }
|
73
|
-
let(:interface) { :dummy }
|
74
|
-
|
75
|
-
context 'when the interface exists' do
|
76
|
-
before { described_class.add(:dummy) }
|
77
|
-
|
78
|
-
it { subject.must_be_instance_of(DummyInterface) }
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when the interface does not exist' do
|
82
|
-
before { described_class.reset }
|
83
|
-
|
84
|
-
it { subject.must_be_instance_of(NilClass) }
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '.initial_state' do
|
89
|
-
let(:subject) { described_class.initial_state }
|
90
|
-
|
91
|
-
it { subject.must_be_instance_of(Array) }
|
92
|
-
end
|
93
|
-
|
94
|
-
describe '.input' do
|
95
|
-
let(:subject) { described_class.input }
|
96
|
-
|
97
|
-
before { Terminal.stubs(:input).returns("some input") }
|
98
|
-
|
99
|
-
it { subject.must_be_instance_of(Array) }
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '.output' do
|
103
|
-
let(:subject) { described_class.output }
|
104
|
-
|
105
|
-
it { subject.must_be_instance_of(Array) }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require_relative '../../../test_helper'
|
2
|
-
|
3
|
-
module Vedeu
|
4
|
-
describe Command do
|
5
|
-
let(:described_class) { Command }
|
6
|
-
let(:described_instance) { described_class.new(cmd_name, cmd_klass, cmd_args, cmd_options) }
|
7
|
-
let(:cmd_name) { "dummy" }
|
8
|
-
let(:cmd_klass) { DummyCommand }
|
9
|
-
let(:cmd_args) { [] }
|
10
|
-
let(:cmd_options) { {} }
|
11
|
-
|
12
|
-
it { described_instance.must_be_instance_of(Command) }
|
13
|
-
|
14
|
-
describe '#define' do
|
15
|
-
subject do
|
16
|
-
described_class.define(cmd_name, cmd_klass, cmd_args, cmd_options)
|
17
|
-
end
|
18
|
-
|
19
|
-
it { subject.must_be_instance_of(Hash) }
|
20
|
-
|
21
|
-
it { subject.wont_be_empty }
|
22
|
-
|
23
|
-
context "when the command name is empty" do
|
24
|
-
let(:cmd_name) { "" }
|
25
|
-
|
26
|
-
it { proc { subject }.must_raise(InvalidCommand) }
|
27
|
-
end
|
28
|
-
|
29
|
-
context "when the command class is empty" do
|
30
|
-
let(:cmd_klass) { "" }
|
31
|
-
|
32
|
-
it { proc { subject }.must_raise(InvalidCommand) }
|
33
|
-
end
|
34
|
-
|
35
|
-
context "when the command class is not defined" do
|
36
|
-
before { Object.stubs(:const_defined?).returns(false) }
|
37
|
-
|
38
|
-
it { proc { subject }.must_raise(InvalidCommand) }
|
39
|
-
end
|
40
|
-
|
41
|
-
context "when the command class doesn't have a .dispatch method" do
|
42
|
-
before { cmd_klass.stubs(:singleton_methods).returns([]) }
|
43
|
-
|
44
|
-
it { proc { subject }.must_raise(InvalidCommand) }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|