neovim 0.0.1

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.
@@ -0,0 +1,44 @@
1
+ require "msgpack"
2
+
3
+ module Neovim
4
+ class MsgpackStream
5
+ def initialize(event_loop)
6
+ @event_loop = event_loop
7
+ @unpacker = MessagePack::Unpacker.new
8
+ end
9
+
10
+ def register_session(session)
11
+ session.api_info.types.each do |type, info|
12
+ klass = Neovim.const_get(type)
13
+ id = info.fetch("id")
14
+
15
+ @unpacker.register_type(id) do |data|
16
+ klass.new(MessagePack.unpack(data), session)
17
+ end
18
+ end
19
+ end
20
+
21
+ def send(msg)
22
+ @event_loop.send(MessagePack.pack(msg))
23
+ self
24
+ end
25
+
26
+ def run(&message_cb)
27
+ @event_loop.run do |data|
28
+ @unpacker.feed_each(data) do |msg|
29
+ message_cb.call(msg)
30
+ end
31
+ end
32
+ end
33
+
34
+ def stop
35
+ @event_loop.stop
36
+ self
37
+ end
38
+
39
+ def shutdown
40
+ @event_loop.shutdown
41
+ self
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ module Neovim
2
+ class Object
3
+ attr_reader :index
4
+
5
+ def initialize(index, session)
6
+ @index = index
7
+ @session = session
8
+ end
9
+
10
+ def respond_to?(method_name)
11
+ super || methods.include?(method_name.to_sym)
12
+ end
13
+
14
+ def method_missing(method_name, *args)
15
+ if methods.include?(method_name)
16
+ @session.request(qualify(method_name), @index, *args)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def to_msgpack(packer)
23
+ packer.pack(@index)
24
+ end
25
+
26
+ def methods
27
+ super | @session.api_methods_for_prefix(function_prefix)
28
+ end
29
+
30
+ private
31
+
32
+ def function_prefix
33
+ "#{self.class.to_s.split("::").last.downcase}_"
34
+ end
35
+
36
+ def qualify(method_name)
37
+ :"#{function_prefix}#{method_name}"
38
+ end
39
+ end
40
+
41
+ Buffer = Class.new(Object)
42
+ Tabpage = Class.new(Object)
43
+ Window = Class.new(Object)
44
+ end
@@ -0,0 +1,35 @@
1
+ require "neovim/api_info"
2
+
3
+ module Neovim
4
+ class Session
5
+ attr_reader :api_info
6
+
7
+ def initialize(async_session)
8
+ @async_session = async_session
9
+
10
+ @api_info = APIInfo.new(request(:vim_get_api_info))
11
+ @async_session.register_session(self)
12
+ end
13
+
14
+ def request(method, *args)
15
+ err = res = nil
16
+
17
+ @async_session.request(method, *args) do |error, response|
18
+ err, res = error, response
19
+ @async_session.stop
20
+ end.run
21
+
22
+ err ? raise(ArgumentError, err) : res
23
+ end
24
+
25
+ def api_methods_for_prefix(prefix)
26
+ @api_info.functions.inject([]) do |acc, function|
27
+ if function["name"] =~ /\A#{prefix}/
28
+ acc + [function["name"].sub(/\A#{prefix}/, "").to_sym]
29
+ else
30
+ acc
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ module Neovim
2
+ VERSION = Gem::Version.new("0.0.1")
3
+ end
data/neovim.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "neovim/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "neovim"
8
+ spec.version = Neovim::VERSION
9
+ spec.authors = ["Alex Genco"]
10
+ spec.email = ["alexgenco@gmail.com"]
11
+ spec.summary = %q{A Ruby client for Neovim}
12
+ spec.homepage = "https://github.com/alexgenco/neovim-ruby"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^spec/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "msgpack", "0.7.0dev1"
21
+ spec.add_dependency "eventmachine", "~> 1.0"
22
+
23
+ spec.add_development_dependency "bundler"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "coveralls", "~> 0.7.2"
27
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,26 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+ require "neovim"
4
+ require "timeout"
5
+
6
+ if ENV["REPORT_COVERAGE"]
7
+ require "coveralls"
8
+ Coveralls.wear!
9
+ end
10
+
11
+ ENV["NVIM_EXECUTABLE"] = File.expand_path("../../vendor/neovim/build/bin/nvim", __FILE__)
12
+
13
+ RSpec.configure do |config|
14
+ config.expect_with :rspec do |exp|
15
+ exp.syntax = :expect
16
+ end
17
+
18
+ config.disable_monkey_patching!
19
+ config.order = :random
20
+
21
+ Kernel.srand config.seed
22
+
23
+ config.around do |spec|
24
+ Timeout.timeout(1) { spec.run }
25
+ end
26
+ end
@@ -0,0 +1,96 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe AsyncSession do
5
+ it "receives requests" do
6
+ server = TCPServer.new("0.0.0.0", 0)
7
+ event_loop = EventLoop.tcp("0.0.0.0", server.addr[1])
8
+ stream = MsgpackStream.new(event_loop)
9
+ async = AsyncSession.new(stream)
10
+ messages = []
11
+
12
+ srv_thr = Thread.new do
13
+ client = server.accept
14
+ client.write(MessagePack.pack(
15
+ [0, 123, "func", [1, 2, 3]]
16
+ ))
17
+
18
+ client.close
19
+ server.close
20
+ end
21
+
22
+ req_cb = Proc.new do |*payload|
23
+ messages << payload
24
+ async.shutdown
25
+ end
26
+
27
+ async.run(req_cb)
28
+ srv_thr.join
29
+
30
+ expect(messages.first.size).to eq(3)
31
+ expect(messages.first[0..1]).to eq(["func", [1, 2, 3]])
32
+ expect(messages.first[2]).to be_a(AsyncSession::Responder)
33
+ end
34
+
35
+ it "receives notifications" do
36
+ server = TCPServer.new("0.0.0.0", 0)
37
+ event_loop = EventLoop.tcp("0.0.0.0", server.addr[1])
38
+ stream = MsgpackStream.new(event_loop)
39
+ async = AsyncSession.new(stream)
40
+ messages = []
41
+
42
+ srv_thr = Thread.new do
43
+ client = server.accept
44
+ client.write(MessagePack.pack(
45
+ [2, "func", [1, 2, 3]]
46
+ ))
47
+
48
+ client.close
49
+ server.close
50
+ end
51
+
52
+ not_cb = Proc.new do |*payload|
53
+ messages << payload
54
+ async.shutdown
55
+ end
56
+
57
+ async.run(nil, not_cb)
58
+ srv_thr.join
59
+
60
+ expect(messages).to eq([["func", [1, 2, 3]]])
61
+ end
62
+
63
+ it "receives responses to requests" do
64
+ server = TCPServer.new("0.0.0.0", 0)
65
+ event_loop = EventLoop.tcp("0.0.0.0", server.addr[1])
66
+ stream = MsgpackStream.new(event_loop)
67
+ async = AsyncSession.new(stream)
68
+ messages = []
69
+
70
+ srv_thr = Thread.new do
71
+ client = server.accept
72
+ messages << client.read_nonblock(1024)
73
+
74
+ client.write(MessagePack.pack(
75
+ [1, 0, [0, "error"], "result"]
76
+ ))
77
+
78
+ client.close
79
+ server.close
80
+ end
81
+
82
+ async.request("func", 1, 2, 3) do |error, result|
83
+ expect(error).to eq("error")
84
+ expect(result).to eq("result")
85
+ async.shutdown
86
+ end
87
+
88
+ async.run
89
+ srv_thr.join
90
+
91
+ expect(messages).to eq(
92
+ [MessagePack.pack([0, 0, "func", [1, 2, 3]])]
93
+ )
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,37 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe Buffer do
5
+ let(:buffer) { Neovim.attach_child(["-n", "-u", "NONE"]).current.buffer }
6
+
7
+ describe "#respond_to?" do
8
+ it "returns true for Buffer functions" do
9
+ expect(buffer).to respond_to(:line_count)
10
+ end
11
+
12
+ it "returns true for Ruby functions" do
13
+ expect(buffer).to respond_to(:inspect)
14
+ end
15
+
16
+ it "returns false otherwise" do
17
+ expect(buffer).not_to respond_to(:foobar)
18
+ end
19
+ end
20
+
21
+ describe "#method_missing" do
22
+ it "enables buffer_* function calls" do
23
+ expect(buffer.line_count).to be(1)
24
+ end
25
+ end
26
+
27
+ describe "#methods" do
28
+ it "returns builtin methods" do
29
+ expect(buffer.methods).to include(:inspect)
30
+ end
31
+
32
+ it "returns api methods" do
33
+ expect(buffer.methods).to include(:get_mark)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe Client do
5
+ let(:client) { Neovim.attach_child(["-n", "-u", "NONE"]) }
6
+
7
+ describe "#respond_to?" do
8
+ it "returns true for vim functions" do
9
+ expect(client).to respond_to(:strwidth)
10
+ end
11
+
12
+ it "returns true for Ruby functions" do
13
+ expect(client).to respond_to(:inspect)
14
+ end
15
+
16
+ it "returns false otherwise" do
17
+ expect(client).not_to respond_to(:foobar)
18
+ end
19
+ end
20
+
21
+ describe "#method_missing" do
22
+ it "enables vim_* function calls" do
23
+ expect(client.strwidth("hi")).to eq(2)
24
+ end
25
+
26
+ it "raises exceptions for unknown methods" do
27
+ expect {
28
+ client.foobar
29
+ }.to raise_error(NoMethodError)
30
+ end
31
+
32
+ it "raises exceptions for incorrect usage" do
33
+ expect {
34
+ client.strwidth("too", "many")
35
+ }.to raise_error("Wrong number of arguments: expecting 1 but got 2")
36
+ end
37
+ end
38
+
39
+ describe "#methods" do
40
+ it "includes builtin methods" do
41
+ expect(client.methods).to include(:inspect)
42
+ end
43
+
44
+ it "includes api methods" do
45
+ expect(client.methods).to include(:strwidth)
46
+ end
47
+ end
48
+
49
+ describe "#current" do
50
+ it "returns the target" do
51
+ expect(client.current.buffer).to be_a(Buffer)
52
+ expect(client.current.window).to be_a(Window)
53
+ expect(client.current.tabpage).to be_a(Tabpage)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,78 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe Current do
5
+ let(:client) { Neovim.attach_child(["-n", "-u", "NONE"]) }
6
+ let(:current) { client.current }
7
+
8
+ describe "#line" do
9
+ it "returns an empty string if the current line is empty" do
10
+ expect(current.line).to eq("")
11
+ end
12
+
13
+ it "returns the contents of the line" do
14
+ current.line = "New content"
15
+ expect(current.line).to eq("New content")
16
+ end
17
+ end
18
+
19
+ describe "#line=" do
20
+ it "sets the content of the current line" do
21
+ current.line = "New content"
22
+ expect(current.line).to eq("New content")
23
+ end
24
+ end
25
+
26
+ describe "#buffer" do
27
+ it "returns the current buffer" do
28
+ expect(current.buffer).to be_a(Buffer)
29
+ end
30
+ end
31
+
32
+ describe "#buffer=" do
33
+ it "sets the current buffer" do
34
+ initial_index = current.buffer.index
35
+ client.command("vnew")
36
+
37
+ expect {
38
+ current.buffer = initial_index
39
+ }.to change { current.buffer.index }
40
+ end
41
+ end
42
+
43
+ describe "#window" do
44
+ it "returns the current window" do
45
+ expect(current.window).to be_a(Window)
46
+ end
47
+ end
48
+
49
+ describe "#window=" do
50
+ it "sets the current window" do
51
+ client.command("vsp")
52
+ expect(current.window.index).not_to eq(1)
53
+
54
+ expect {
55
+ current.window = 1
56
+ }.to change { current.window.index }.to(1)
57
+ end
58
+ end
59
+
60
+ describe "#tabpage" do
61
+ it "returns the current tabpage" do
62
+ expect(current.tabpage).to be_a(Tabpage)
63
+ end
64
+ end
65
+
66
+ describe "#tabpage=" do
67
+ it "sets the current tabpage" do
68
+ initial_index = current.tabpage.index
69
+ client.command("tabnew")
70
+ expect(current.tabpage.index).not_to eq(initial_index)
71
+
72
+ expect {
73
+ current.tabpage = initial_index
74
+ }.to change { current.tabpage.index }.to(initial_index)
75
+ end
76
+ end
77
+ end
78
+ end