neovim 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/bin/neovim-ruby-host +1 -2
- data/lib/neovim.rb +13 -12
- data/lib/neovim/api_info.rb +1 -1
- data/lib/neovim/async_session.rb +4 -6
- data/lib/neovim/buffer.rb +2 -62
- data/lib/neovim/client.rb +0 -4
- data/lib/neovim/current.rb +9 -0
- data/lib/neovim/event_loop.rb +14 -13
- data/lib/neovim/host.rb +17 -55
- data/lib/neovim/line_range.rb +61 -0
- data/lib/neovim/manifest.rb +62 -0
- data/lib/neovim/msgpack_stream.rb +3 -6
- data/lib/neovim/notification.rb +5 -1
- data/lib/neovim/plugin.rb +77 -35
- data/lib/neovim/request.rb +5 -1
- data/lib/neovim/version.rb +1 -1
- data/spec/acceptance/neovim-ruby-host_spec.rb +15 -24
- data/spec/helper.rb +2 -0
- data/spec/neovim/async_session_spec.rb +2 -2
- data/spec/neovim/buffer_spec.rb +3 -41
- data/spec/neovim/current_spec.rb +14 -0
- data/spec/neovim/event_loop_spec.rb +54 -6
- data/spec/neovim/host_spec.rb +7 -46
- data/spec/neovim/line_range_spec.rb +68 -0
- data/spec/neovim/manifest_spec.rb +113 -0
- data/spec/neovim/msgpack_stream_spec.rb +5 -3
- data/spec/neovim/plugin_spec.rb +33 -33
- data/spec/neovim/session_spec.rb +97 -18
- data/spec/neovim_spec.rb +13 -4
- metadata +9 -3
@@ -23,17 +23,14 @@ module Neovim
|
|
23
23
|
self
|
24
24
|
end
|
25
25
|
|
26
|
-
def run(
|
27
|
-
|
26
|
+
def run(message_cb, setup_cb=nil)
|
27
|
+
data_cb = Proc.new do |data|
|
28
28
|
@unpacker.feed_each(data) do |msg|
|
29
29
|
message_cb.call(msg)
|
30
30
|
end
|
31
31
|
end
|
32
|
-
end
|
33
32
|
|
34
|
-
|
35
|
-
@event_loop.stop
|
36
|
-
self
|
33
|
+
@event_loop.run(data_cb, setup_cb)
|
37
34
|
end
|
38
35
|
end
|
39
36
|
end
|
data/lib/neovim/notification.rb
CHANGED
data/lib/neovim/plugin.rb
CHANGED
@@ -1,15 +1,60 @@
|
|
1
1
|
module Neovim
|
2
2
|
class Plugin
|
3
|
-
def self.from_config_block(&block)
|
4
|
-
new.tap do |instance|
|
3
|
+
def self.from_config_block(source, &block)
|
4
|
+
new(source).tap do |instance|
|
5
5
|
block.call(DSL.new(instance)) if block
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
attr_accessor :
|
9
|
+
attr_accessor :handlers
|
10
|
+
attr_reader :source
|
10
11
|
|
11
|
-
def initialize
|
12
|
-
@
|
12
|
+
def initialize(source)
|
13
|
+
@handlers = []
|
14
|
+
@source = source
|
15
|
+
end
|
16
|
+
|
17
|
+
def specs
|
18
|
+
@handlers.map(&:to_spec)
|
19
|
+
end
|
20
|
+
|
21
|
+
class Handler
|
22
|
+
attr_reader :block
|
23
|
+
|
24
|
+
def initialize(source, type, name, sync, options, block)
|
25
|
+
@source = source
|
26
|
+
@type = type.to_sym
|
27
|
+
@name = name.to_s
|
28
|
+
@sync = !!sync
|
29
|
+
@options = options
|
30
|
+
@block = block || ::Proc.new {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def qualified_name
|
34
|
+
if @type == :autocmd
|
35
|
+
pattern = @options.fetch(:pattern, "*")
|
36
|
+
"#{@source}:#{@type}:#{@name}:#{pattern}"
|
37
|
+
else
|
38
|
+
"#{@source}:#{@type}:#{@name}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def sync?
|
43
|
+
@sync
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_spec
|
47
|
+
{
|
48
|
+
:type => @type,
|
49
|
+
:name => @name,
|
50
|
+
:sync => @sync,
|
51
|
+
:opts => @options,
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def call(*args)
|
56
|
+
@block.call(*args)
|
57
|
+
end
|
13
58
|
end
|
14
59
|
|
15
60
|
class DSL < BasicObject
|
@@ -17,44 +62,41 @@ module Neovim
|
|
17
62
|
@plugin = plugin
|
18
63
|
end
|
19
64
|
|
20
|
-
def command(name,
|
21
|
-
options
|
22
|
-
|
23
|
-
options[:range] = ::Kernel.String(options[:range])
|
65
|
+
def command(name, options={}, &block)
|
66
|
+
register_handler(:command, name, options, block)
|
67
|
+
end
|
24
68
|
|
25
|
-
|
26
|
-
|
27
|
-
:name => name.to_sym,
|
28
|
-
:sync => !!options.delete(:sync),
|
29
|
-
:opts => options,
|
30
|
-
:proc => block || ::Proc.new {}
|
31
|
-
)
|
69
|
+
def function(name, options={}, &block)
|
70
|
+
register_handler(:function, name, options, block)
|
32
71
|
end
|
33
72
|
|
34
|
-
def
|
35
|
-
options
|
36
|
-
|
37
|
-
|
73
|
+
def autocmd(name, options={}, &block)
|
74
|
+
register_handler(:autocmd, name, options, block)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def register_handler(type, name, _options, block)
|
80
|
+
if type == :autocmd
|
81
|
+
options = _options.dup
|
82
|
+
else
|
83
|
+
options = standardize_range(_options.dup)
|
84
|
+
end
|
38
85
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
:opts => options,
|
44
|
-
:proc => block || ::Proc.new {}
|
86
|
+
sync = options.delete(:sync)
|
87
|
+
|
88
|
+
@plugin.handlers.push(
|
89
|
+
Handler.new(@plugin.source, type, name, sync, options, block)
|
45
90
|
)
|
46
91
|
end
|
47
92
|
|
48
|
-
def
|
49
|
-
options
|
93
|
+
def standardize_range(options)
|
94
|
+
if options.key?(:range)
|
95
|
+
options[:range] = "" if options[:range] == true
|
96
|
+
options[:range] = ::Kernel.String(options[:range])
|
97
|
+
end
|
50
98
|
|
51
|
-
|
52
|
-
:type => :autocmd,
|
53
|
-
:name => name.to_sym,
|
54
|
-
:sync => !!options.delete(:sync),
|
55
|
-
:opts => options,
|
56
|
-
:proc => block || ::Proc.new {}
|
57
|
-
)
|
99
|
+
options
|
58
100
|
end
|
59
101
|
end
|
60
102
|
end
|
data/lib/neovim/request.rb
CHANGED
@@ -3,12 +3,16 @@ module Neovim
|
|
3
3
|
attr_reader :method_name, :arguments
|
4
4
|
|
5
5
|
def initialize(method_name, args, msgpack_stream, request_id)
|
6
|
-
@method_name = method_name.
|
6
|
+
@method_name = method_name.to_s
|
7
7
|
@arguments = args
|
8
8
|
@msgpack_stream = msgpack_stream
|
9
9
|
@request_id = request_id
|
10
10
|
end
|
11
11
|
|
12
|
+
def sync?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
12
16
|
def respond(value)
|
13
17
|
@msgpack_stream.send([1, @request_id, nil, value])
|
14
18
|
self
|
data/lib/neovim/version.rb
CHANGED
@@ -2,10 +2,11 @@ require "helper"
|
|
2
2
|
require "tmpdir"
|
3
3
|
|
4
4
|
RSpec.describe "neovim-ruby-host" do
|
5
|
-
|
5
|
+
it "loads and runs plugins from Ruby source files" do
|
6
6
|
Dir.mktmpdir do |pwd|
|
7
7
|
Dir.chdir(pwd) do
|
8
|
-
File.
|
8
|
+
plugin1_path = File.expand_path("./plugin1.rb")
|
9
|
+
File.write(plugin1_path, <<-RUBY)
|
9
10
|
Neovim.plugin do |plug|
|
10
11
|
plug.command(:SyncAdd, :args => 2, :sync => true) do |nvim, x, y|
|
11
12
|
x + y
|
@@ -13,7 +14,8 @@ RSpec.describe "neovim-ruby-host" do
|
|
13
14
|
end
|
14
15
|
RUBY
|
15
16
|
|
16
|
-
File.
|
17
|
+
plugin2_path = File.expand_path("./plugin2.rb")
|
18
|
+
File.write(plugin2_path, <<-RUBY)
|
17
19
|
Neovim.plugin do |plug|
|
18
20
|
plug.command(:AsyncSetLine, :args => 1) do |nvim, str|
|
19
21
|
nvim.current.line = str
|
@@ -23,35 +25,24 @@ RSpec.describe "neovim-ruby-host" do
|
|
23
25
|
|
24
26
|
nvim = Neovim.attach_child(["--headless", "-u", "NONE", "-N", "-n"])
|
25
27
|
|
26
|
-
# Start the remote host
|
27
28
|
host_exe = File.expand_path("../../../bin/neovim-ruby-host", __FILE__)
|
28
|
-
nvim.command(
|
29
|
+
nvim.command("let host = rpcstart('#{host_exe}', ['#{plugin1_path}', '#{plugin2_path}'])")
|
29
30
|
|
30
|
-
|
31
|
-
expect(nvim.eval(
|
31
|
+
expect(nvim.eval("rpcrequest(host, 'poll')")).to eq("ok")
|
32
|
+
expect(nvim.eval("rpcrequest(host, '#{plugin1_path}:command:SyncAdd', 1, 2)")).to eq(3)
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
nvim.command("put =result")
|
38
|
-
nvim.command("normal o")
|
39
|
-
|
40
|
-
# Set the current line via the AsyncSetLine method
|
41
|
-
nvim.command(%{call rpcnotify(host, "AsyncSetLine", "foo")})
|
34
|
+
expect {
|
35
|
+
nvim.eval("rpcnotify(host, '#{plugin2_path}:command:AsyncSetLine', 'foo')")
|
36
|
+
nvim.eval("rpcrequest(host, 'poll')")
|
37
|
+
}.to change { nvim.current.buffer.lines.to_a }.from([""]).to(["foo"])
|
42
38
|
|
43
|
-
# Make an unknown notification
|
44
39
|
expect {
|
45
|
-
nvim.
|
40
|
+
nvim.eval("rpcnotify(host, 'Unknown')")
|
46
41
|
}.not_to raise_error
|
47
42
|
|
48
|
-
# Make an unknown request
|
49
43
|
expect {
|
50
|
-
nvim.
|
51
|
-
}.to raise_error(ArgumentError
|
52
|
-
|
53
|
-
# Assert the contents of the buffer
|
54
|
-
expect(nvim.current.buffer.lines).to eq(["", "3", "foo"])
|
44
|
+
nvim.eval("call rpcrequest(host, 'Unknown')")
|
45
|
+
}.to raise_error(ArgumentError)
|
55
46
|
end
|
56
47
|
end
|
57
48
|
end
|
data/spec/helper.rb
CHANGED
@@ -28,7 +28,7 @@ module Neovim
|
|
28
28
|
srv_thr.join
|
29
29
|
|
30
30
|
expect(request).to be_a(Request)
|
31
|
-
expect(request.method_name).to eq(
|
31
|
+
expect(request.method_name).to eq("func")
|
32
32
|
expect(request.arguments).to eq([1, 2, 3])
|
33
33
|
end
|
34
34
|
|
@@ -57,7 +57,7 @@ module Neovim
|
|
57
57
|
srv_thr.join
|
58
58
|
|
59
59
|
expect(notification).to be_a(Notification)
|
60
|
-
expect(notification.method_name).to eq(
|
60
|
+
expect(notification.method_name).to eq("func")
|
61
61
|
expect(notification.arguments).to eq([1, 2, 3])
|
62
62
|
end
|
63
63
|
|
data/spec/neovim/buffer_spec.rb
CHANGED
@@ -6,53 +6,15 @@ module Neovim
|
|
6
6
|
let(:buffer) { client.current.buffer }
|
7
7
|
|
8
8
|
describe "#lines" do
|
9
|
-
|
10
|
-
|
11
|
-
client.command("normal o2")
|
12
|
-
client.command("normal o3")
|
13
|
-
end
|
14
|
-
|
15
|
-
it "returns the buffer's lines as an array" do
|
16
|
-
expect(buffer.lines).to eq(["1", "2", "3"])
|
17
|
-
end
|
18
|
-
|
19
|
-
it "can be indexed into" do
|
20
|
-
expect(buffer.lines[1]).to eq("2")
|
21
|
-
end
|
22
|
-
|
23
|
-
it "can be sliced with a length" do
|
24
|
-
expect(buffer.lines[0, 2]).to eq(["1", "2"])
|
25
|
-
end
|
26
|
-
|
27
|
-
it "can be sliced with a range" do
|
28
|
-
expect(buffer.lines[0..1]).to eq(["1", "2"])
|
29
|
-
end
|
30
|
-
|
31
|
-
it "can be updated at an index" do
|
32
|
-
buffer.lines[0] = "foo"
|
33
|
-
expect(buffer.lines).to eq(["foo", "2", "3"])
|
34
|
-
end
|
35
|
-
|
36
|
-
it "can be updated with a length" do
|
37
|
-
buffer.lines[0, 2] = ["foo"]
|
38
|
-
expect(buffer.lines).to eq(["foo", "3"])
|
39
|
-
end
|
40
|
-
|
41
|
-
it "can be updated with a range" do
|
42
|
-
buffer.lines[0..1] = ["foo"]
|
43
|
-
expect(buffer.lines).to eq(["foo", "3"])
|
44
|
-
end
|
45
|
-
|
46
|
-
it "exposes the Enumerable interface" do
|
47
|
-
succ_lines = buffer.lines.collect(&:succ)
|
48
|
-
expect(succ_lines).to eq(["2", "3", "4"])
|
9
|
+
it "returns a LineRange" do
|
10
|
+
expect(buffer.lines).to be_a(LineRange)
|
49
11
|
end
|
50
12
|
end
|
51
13
|
|
52
14
|
describe "#lines=" do
|
53
15
|
it "updates the buffers lines" do
|
54
16
|
buffer.lines = ["one", "two"]
|
55
|
-
expect(buffer.lines).to eq(["one", "two"])
|
17
|
+
expect(buffer.lines.to_a).to eq(["one", "two"])
|
56
18
|
end
|
57
19
|
end
|
58
20
|
end
|
data/spec/neovim/current_spec.rb
CHANGED
@@ -74,5 +74,19 @@ module Neovim
|
|
74
74
|
}.to change { current.tabpage.index }.to(initial_index)
|
75
75
|
end
|
76
76
|
end
|
77
|
+
|
78
|
+
describe "#range" do
|
79
|
+
it "returns the current range" do
|
80
|
+
expect(current.range).to be_a(LineRange)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#range=" do
|
85
|
+
it "sets the current range" do
|
86
|
+
current.buffer.lines = ["1", "2", "3"]
|
87
|
+
current.range = (1..2)
|
88
|
+
expect(current.range.to_a).to eq(["2", "3"])
|
89
|
+
end
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
@@ -5,6 +5,19 @@ require "fileutils"
|
|
5
5
|
|
6
6
|
module Neovim
|
7
7
|
RSpec.describe EventLoop do
|
8
|
+
it "calls the setup callback" do
|
9
|
+
messages = []
|
10
|
+
rd, wr = IO.pipe
|
11
|
+
event_loop = EventLoop.new(rd, wr)
|
12
|
+
|
13
|
+
fiber = Fiber.new do
|
14
|
+
setup_cb = Proc.new { Fiber.yield(:setup) }
|
15
|
+
event_loop.run(nil, setup_cb)
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(fiber.resume).to eq(:setup)
|
19
|
+
end
|
20
|
+
|
8
21
|
shared_context "socket behavior" do
|
9
22
|
it "sends and receives data" do
|
10
23
|
messages = []
|
@@ -14,12 +27,13 @@ module Neovim
|
|
14
27
|
messages << client.readpartial(1024)
|
15
28
|
|
16
29
|
client.write("OK")
|
30
|
+
client.close
|
31
|
+
server.close
|
17
32
|
end
|
18
33
|
|
19
34
|
fiber = Fiber.new do
|
20
|
-
|
21
|
-
|
22
|
-
end
|
35
|
+
msg_cb = Proc.new { |msg| Fiber.yield(msg) }
|
36
|
+
event_loop.send("data").run(msg_cb)
|
23
37
|
end
|
24
38
|
|
25
39
|
expect(fiber.resume).to eq("OK")
|
@@ -44,15 +58,49 @@ module Neovim
|
|
44
58
|
include_context "socket behavior"
|
45
59
|
end
|
46
60
|
|
61
|
+
context "stdio" do
|
62
|
+
it "sends and receives data" do
|
63
|
+
old_stdout = STDOUT.dup
|
64
|
+
old_stdin = STDIN.dup
|
65
|
+
|
66
|
+
begin
|
67
|
+
srv_stdout, cl_stdout = IO.pipe
|
68
|
+
cl_stdin, srv_stdin = IO.pipe
|
69
|
+
|
70
|
+
STDOUT.reopen(cl_stdout)
|
71
|
+
STDIN.reopen(cl_stdin)
|
72
|
+
|
73
|
+
event_loop = EventLoop.stdio
|
74
|
+
messages = []
|
75
|
+
|
76
|
+
srv_thr = Thread.new do
|
77
|
+
messages << srv_stdout.readpartial(1024)
|
78
|
+
srv_stdin.write("OK")
|
79
|
+
end
|
80
|
+
|
81
|
+
fiber = Fiber.new do
|
82
|
+
msg_cb = Proc.new { |msg| Fiber.yield(msg) }
|
83
|
+
event_loop.send("data").run(msg_cb)
|
84
|
+
end
|
85
|
+
|
86
|
+
expect(fiber.resume).to eq("OK")
|
87
|
+
srv_thr.join
|
88
|
+
expect(messages).to eq(["data"])
|
89
|
+
ensure
|
90
|
+
STDOUT.reopen(old_stdout)
|
91
|
+
STDIN.reopen(old_stdin)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
47
96
|
context "child" do
|
48
97
|
it "sends and receives data" do
|
49
98
|
event_loop = EventLoop.child(["-n", "-u", "NONE"])
|
50
99
|
message = MessagePack.pack([0, 0, :vim_strwidth, ["hi"]])
|
51
100
|
|
52
101
|
fiber = Fiber.new do
|
53
|
-
|
54
|
-
|
55
|
-
end
|
102
|
+
msg_cb = Proc.new { |msg| Fiber.yield(msg) }
|
103
|
+
event_loop.send(message).run(msg_cb)
|
56
104
|
end
|
57
105
|
|
58
106
|
expect(fiber.resume).to eq(MessagePack.pack([1, 0, nil, 2]))
|