neovim 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -1
  3. data/.travis.yml +2 -3
  4. data/CHANGELOG.md +29 -0
  5. data/Gemfile +0 -11
  6. data/README.md +3 -3
  7. data/Rakefile +1 -1
  8. data/appveyor.yml +9 -1
  9. data/lib/neovim.rb +3 -3
  10. data/lib/neovim/client.rb +2 -3
  11. data/lib/neovim/connection.rb +69 -0
  12. data/lib/neovim/event_loop.rb +34 -34
  13. data/lib/neovim/host.rb +47 -51
  14. data/lib/neovim/host/loader.rb +1 -4
  15. data/lib/neovim/logging.rb +8 -8
  16. data/lib/neovim/message.rb +70 -0
  17. data/lib/neovim/plugin.rb +0 -3
  18. data/lib/neovim/plugin/handler.rb +6 -6
  19. data/lib/neovim/remote_object.rb +1 -1
  20. data/lib/neovim/ruby_provider.rb +25 -14
  21. data/lib/neovim/session.rb +36 -43
  22. data/lib/neovim/version.rb +1 -1
  23. data/neovim.gemspec +4 -0
  24. data/spec/acceptance/runtime/rplugin/ruby/autocmds.rb +3 -3
  25. data/spec/acceptance/runtime/rplugin/ruby/commands.rb +15 -15
  26. data/spec/acceptance/runtime/rplugin/ruby/functions.rb +5 -5
  27. data/spec/acceptance_spec.rb +19 -16
  28. data/spec/helper.rb +15 -0
  29. data/spec/neovim/connection_spec.rb +79 -0
  30. data/spec/neovim/event_loop_spec.rb +36 -50
  31. data/spec/neovim/host/loader_spec.rb +16 -9
  32. data/spec/neovim/host_spec.rb +82 -92
  33. data/spec/neovim/logging_spec.rb +6 -6
  34. data/spec/neovim/message_spec.rb +119 -0
  35. data/spec/neovim/plugin_spec.rb +31 -31
  36. data/spec/neovim/session_spec.rb +1 -1
  37. metadata +38 -15
  38. data/lib/neovim/event_loop/connection.rb +0 -78
  39. data/lib/neovim/event_loop/message_builder.rb +0 -127
  40. data/lib/neovim/event_loop/serializer.rb +0 -37
  41. data/spec/acceptance/runtime/rplugin.vim +0 -37
  42. data/spec/neovim/event_loop/connection_spec.rb +0 -89
  43. data/spec/neovim/event_loop/message_builder_spec.rb +0 -105
  44. data/spec/neovim/event_loop/serializer_spec.rb +0 -63
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.6.2")
2
+ VERSION = Gem::Version.new("0.7.0")
3
3
  end
@@ -17,11 +17,15 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^spec/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.2.0")
21
+
20
22
  spec.add_dependency "msgpack", "~> 1.1"
21
23
  spec.add_dependency "multi_json", "~> 1.0"
22
24
 
23
25
  spec.add_development_dependency "bundler"
24
26
  spec.add_development_dependency "rake"
25
27
  spec.add_development_dependency "pry"
28
+ spec.add_development_dependency "pry-byebug"
29
+ spec.add_development_dependency "coveralls"
26
30
  spec.add_development_dependency "rspec", "~> 3.0"
27
31
  end
@@ -1,9 +1,9 @@
1
1
  Neovim.plugin do |plug|
2
- plug.autocmd(:BufEnter, :pattern => "*.rb") do |nvim|
2
+ plug.autocmd(:BufEnter, pattern: "*.rb") do |nvim|
3
3
  nvim.get_current_buf.set_var("rplugin_autocmd_BufEnter", true)
4
4
  end
5
5
 
6
- plug.autocmd(:BufEnter, :pattern => "*.c", :eval => "g:to_eval") do |nvim, to_eval|
7
- nvim.set_var("rplugin_autocmd_BufEnter_eval", to_eval.merge(:b => 43))
6
+ plug.autocmd(:BufEnter, pattern: "*.c", eval: "g:to_eval") do |nvim, to_eval|
7
+ nvim.set_var("rplugin_autocmd_BufEnter_eval", to_eval.merge(b: 43))
8
8
  end
9
9
  end
@@ -3,61 +3,61 @@ Neovim.plugin do |plug|
3
3
  nvim.set_var("rplugin_command_nargs_0", true)
4
4
  end
5
5
 
6
- plug.command(:RPluginCommandNargs1, :nargs => 1) do |nvim, arg|
6
+ plug.command(:RPluginCommandNargs1, nargs: 1) do |nvim, arg|
7
7
  nvim.set_var("rplugin_command_nargs_1", arg)
8
8
  end
9
9
 
10
- plug.command(:RPluginCommandNargsN, :nargs => "*") do |nvim, *args|
10
+ plug.command(:RPluginCommandNargsN, nargs: "*") do |nvim, *args|
11
11
  nvim.set_var("rplugin_command_nargs_n", args)
12
12
  end
13
13
 
14
- plug.command(:RPluginCommandNargsQ, :nargs => "?") do |nvim, arg|
14
+ plug.command(:RPluginCommandNargsQ, nargs: "?") do |nvim, arg|
15
15
  nvim.set_var("rplugin_command_nargs_q", arg)
16
16
  end
17
17
 
18
- plug.command(:RPluginCommandNargsP, :nargs => "+") do |nvim, *args|
18
+ plug.command(:RPluginCommandNargsP, nargs: "+") do |nvim, *args|
19
19
  nvim.set_var("rplugin_command_nargs_p", args)
20
20
  end
21
21
 
22
- plug.command(:RPluginCommandRange, :range => true) do |nvim, *range|
22
+ plug.command(:RPluginCommandRange, range: true) do |nvim, *range|
23
23
  nvim.set_var("rplugin_command_range", range)
24
24
  end
25
25
 
26
- plug.command(:RPluginCommandRangeP, :range => "%") do |nvim, *range|
26
+ plug.command(:RPluginCommandRangeP, range: "%") do |nvim, *range|
27
27
  nvim.set_var("rplugin_command_range_p", range)
28
28
  end
29
29
 
30
- plug.command(:RPluginCommandRangeN, :range => 1) do |nvim, *range|
30
+ plug.command(:RPluginCommandRangeN, range: 1) do |nvim, *range|
31
31
  nvim.set_var("rplugin_command_range_n", range)
32
32
  end
33
33
 
34
- plug.command(:RPluginCommandCountN, :count => 1) do |nvim, *count|
34
+ plug.command(:RPluginCommandCountN, count: 1) do |nvim, *count|
35
35
  nvim.set_var("rplugin_command_count_n", count)
36
36
  end
37
37
 
38
- plug.command(:RPluginCommandBang, :bang => true) do |nvim, bang|
38
+ plug.command(:RPluginCommandBang, bang: true) do |nvim, bang|
39
39
  nvim.set_var("rplugin_command_bang", bang)
40
40
  end
41
41
 
42
- plug.command(:RPluginCommandRegister, :register => true) do |nvim, reg|
42
+ plug.command(:RPluginCommandRegister, register: true) do |nvim, reg|
43
43
  nvim.set_var("rplugin_command_register", reg)
44
44
  end
45
45
 
46
- plug.command(:RPluginCommandCompletion, :complete => "buffer") do |nvim|
46
+ plug.command(:RPluginCommandCompletion, complete: "buffer") do |nvim|
47
47
  attrs = nvim.command_output("silent command RPluginCommandCompletion")
48
48
  compl = attrs.split($/).last.split[2]
49
49
  nvim.set_var("rplugin_command_completion", compl)
50
50
  end
51
51
 
52
- plug.command(:RPluginCommandEval, :eval => "g:to_eval") do |nvim, to_eval|
53
- nvim.set_var("rplugin_command_eval", to_eval.merge(:b => 43))
52
+ plug.command(:RPluginCommandEval, eval: "g:to_eval") do |nvim, to_eval|
53
+ nvim.set_var("rplugin_command_eval", to_eval.merge(b: 43))
54
54
  end
55
55
 
56
- plug.command(:RPluginCommandSync, :sync => true) do |nvim|
56
+ plug.command(:RPluginCommandSync, sync: true) do |nvim|
57
57
  nvim.set_var("rplugin_command_sync", true)
58
58
  end
59
59
 
60
- plug.command(:RPluginCommandRecursive, :sync => true, :nargs => 1) do |nvim, n|
60
+ plug.command(:RPluginCommandRecursive, sync: true, nargs: 1) do |nvim, n|
61
61
  if Integer(n) >= 10
62
62
  nvim.set_var("rplugin_command_recursive", n)
63
63
  else
@@ -3,19 +3,19 @@ Neovim.plugin do |plug|
3
3
  nvim.set_var("rplugin_function_args", args)
4
4
  end
5
5
 
6
- plug.function(:RPluginFunctionRange, :range => true) do |nvim, *range|
6
+ plug.function(:RPluginFunctionRange, range: true) do |nvim, *range|
7
7
  nvim.set_var("rplugin_function_range", range)
8
8
  end
9
9
 
10
- plug.function(:RPluginFunctionEval, :eval => "g:to_eval") do |nvim, to_eval|
11
- nvim.set_var("rplugin_function_eval", to_eval.merge(:b => 43))
10
+ plug.function(:RPluginFunctionEval, eval: "g:to_eval") do |nvim, to_eval|
11
+ nvim.set_var("rplugin_function_eval", to_eval.merge(b: 43))
12
12
  end
13
13
 
14
- plug.function(:RPluginFunctionSync, :sync => true) do |nvim|
14
+ plug.function(:RPluginFunctionSync, sync: true) do |nvim|
15
15
  true
16
16
  end
17
17
 
18
- plug.function(:RPluginFunctionRecursive, :sync => true, :nargs => 1) do |nvim, n|
18
+ plug.function(:RPluginFunctionRecursive, sync: true, nargs: 1) do |nvim, n|
19
19
  if n >= 10
20
20
  n
21
21
  else
@@ -3,10 +3,11 @@ ENV.delete("VIMRUNTIME")
3
3
 
4
4
  require "json"
5
5
  require "net/http"
6
+ require "openssl"
6
7
  require "open-uri"
7
8
  require "tempfile"
8
9
 
9
- RSpec.describe "Acceptance", :timeout => 10 do
10
+ RSpec.describe "Acceptance", timeout: 10 do
10
11
  let(:root) { File.expand_path("../acceptance", __FILE__) }
11
12
  let(:init) { File.join(root, "runtime/init.vim") }
12
13
  let(:manifest) { File.join(root, "runtime/rplugin.vim") }
@@ -19,7 +20,7 @@ RSpec.describe "Acceptance", :timeout => 10 do
19
20
  ["ruby", "rubyfile", "rubydo"].each do |feature|
20
21
  specify ":#{feature}" do
21
22
  run_vader("#{feature}_spec.vim") do |status, output|
22
- expect(status).to be_success, lambda { output.read }
23
+ expect(status).to be_success, -> { output.read }
23
24
  end
24
25
  end
25
26
  end
@@ -36,7 +37,7 @@ RSpec.describe "Acceptance", :timeout => 10 do
36
37
  ["command", "function", "autocmd"].each do |feature|
37
38
  specify "##{feature}" do
38
39
  run_vader("rplugin_#{feature}_spec.vim") do |status, output|
39
- expect(status).to be_success, lambda { output.read }
40
+ expect(status).to be_success, -> { output.read }
40
41
  end
41
42
  end
42
43
  end
@@ -44,23 +45,25 @@ RSpec.describe "Acceptance", :timeout => 10 do
44
45
 
45
46
  describe "Generated documentation" do
46
47
  it "is up to date" do
48
+ url = "https://api.github.com/repos/neovim/neovim/releases/latest"
49
+
47
50
  begin
48
- url = "https://api.github.com/repos/neovim/neovim/releases/latest"
49
51
  response = open(url) { |json| JSON.load(json) }
50
- release_version = response["name"][/NVIM v?(.+)$/, 1]
51
-
52
- client_file = File.read(
53
- File.expand_path("../../lib/neovim/client.rb", __FILE__)
54
- )
55
- docs_version = client_file[
56
- /The methods documented here were generated using NVIM v?(.+)$/,
57
- 1
58
- ]
59
-
60
- expect(docs_version).to eq(release_version)
61
- rescue SocketError, OpenURI::HTTPError => e
52
+ rescue SocketError, OpenURI::HTTPError, OpenSSL::SSL::SSLError => e
62
53
  skip "Skipping: #{e}"
63
54
  end
55
+
56
+ release_version = response["name"][/NVIM v?(.+)$/, 1]
57
+
58
+ client_file = File.read(
59
+ File.expand_path("../../lib/neovim/client.rb", __FILE__)
60
+ )
61
+ docs_version = client_file[
62
+ /The methods documented here were generated using NVIM v?(.+)$/,
63
+ 1
64
+ ]
65
+
66
+ expect(docs_version).to eq(release_version)
64
67
  end
65
68
  end
66
69
 
@@ -25,6 +25,21 @@ RSpec.configure do |config|
25
25
  config.order = :random
26
26
  config.color = true
27
27
 
28
+ config.around(:example, :silence_thread_exceptions) do |spec|
29
+ if Thread.respond_to?(:report_on_exception)
30
+ original = Thread.report_on_exception
31
+
32
+ begin
33
+ Thread.report_on_exception = false
34
+ spec.run
35
+ ensure
36
+ Thread.report_on_exception = original
37
+ end
38
+ else
39
+ spec.run
40
+ end
41
+ end
42
+
28
43
  config.around(:example) do |spec|
29
44
  Support.setup_workspace
30
45
  timeout = spec.metadata.fetch(:timeout, 3)
@@ -0,0 +1,79 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe Connection do
5
+ let(:nil_io) { StringIO.new }
6
+
7
+ describe "#write" do
8
+ it "writes msgpack to the underlying file descriptor" do
9
+ rd, wr = IO.pipe
10
+ connection = Connection.new(nil_io, wr)
11
+ connection.write("some data")
12
+ wr.close
13
+
14
+ expect(MessagePack.unpack(rd.read)).to eq("some data")
15
+ end
16
+ end
17
+
18
+ describe "#read" do
19
+ it "reads msgpack from the underlying file descriptor" do
20
+ rd, wr = IO.pipe
21
+ wr.write(MessagePack.pack("some data"))
22
+ wr.close
23
+
24
+ connection = Connection.new(rd, nil_io)
25
+ expect(connection.read).to eq("some data")
26
+ end
27
+ end
28
+
29
+ describe "#register_type" do
30
+ it "registers a msgpack ext type" do
31
+ ext_class = Struct.new(:id) do
32
+ def self.from_msgpack_ext(data)
33
+ new(data.unpack('N')[0])
34
+ end
35
+
36
+ def to_msgpack_ext
37
+ [self.id].pack('C')
38
+ end
39
+ end
40
+
41
+ client_rd, server_wr = IO.pipe
42
+ server_rd, client_wr = IO.pipe
43
+
44
+ connection = Connection.new(client_rd, client_wr)
45
+
46
+ connection.register_type(42) do |id|
47
+ ext_class.new(id)
48
+ end
49
+
50
+ factory = MessagePack::Factory.new
51
+ factory.register_type(42, ext_class)
52
+ obj = ext_class.new(1)
53
+ factory.packer(server_wr).write(obj).flush
54
+
55
+ expect(connection.read).to eq(obj)
56
+ end
57
+ end
58
+
59
+
60
+ describe "#close" do
61
+ it "closes IO handles" do
62
+ rd, wr = ::IO.pipe
63
+ Connection.new(rd, wr).close
64
+
65
+ expect(rd).to be_closed
66
+ expect(wr).to be_closed
67
+ end
68
+
69
+ it "kills spawned processes" do
70
+ io = ::IO.popen("cat", "rb+")
71
+ pid = io.pid
72
+ expect(pid).to respond_to(:to_int)
73
+
74
+ Connection.new(io, nil_io).close
75
+ expect { Process.kill(0, pid) }.to raise_error(Errno::ESRCH)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -10,71 +10,57 @@ module Neovim
10
10
  let(:server_rd) { pull_pipe[0] }
11
11
  let(:server_wr) { push_pipe[1] }
12
12
 
13
- let(:connection) { EventLoop::Connection.new(client_rd, client_wr) }
13
+ let(:connection) { Connection.new(client_rd, client_wr) }
14
14
  let(:event_loop) { EventLoop.new(connection) }
15
15
 
16
- describe "#run" do
17
- it "reads requests" do
18
- server_wr.write(MessagePack.pack([0, 1, :foo_method, []]))
19
- server_wr.flush
20
-
21
- request = nil
22
- event_loop.run do |req|
23
- request = req
24
- event_loop.stop
25
- end
26
- expect(request.method_name).to eq("foo_method")
16
+ describe "#request" do
17
+ it "writes a msgpack request" do
18
+ event_loop.request(1, :method, 1, 2)
19
+ message = server_rd.readpartial(1024)
20
+ expect(message).to eq(MessagePack.pack([0, 1, "method", [1, 2]]))
27
21
  end
22
+ end
28
23
 
29
- it "writes requests" do
30
- response = nil
31
-
32
- event_loop.request(:foo_method) do |res|
33
- response = res
34
- event_loop.stop
35
- end
36
-
37
- server_wr.write(MessagePack.pack([1, 1, nil, :value]))
38
- server_wr.flush
39
-
40
- event_loop.run
41
- expect(response.value!).to eq("value")
24
+ describe "#respond" do
25
+ it "writes a msgpack response" do
26
+ event_loop.respond(2, "value", "error")
27
+ message = server_rd.readpartial(1024)
28
+ expect(message).to eq(MessagePack.pack([1, 2, "error", "value"]))
42
29
  end
30
+ end
43
31
 
44
- it "writes responses" do
45
- event_loop.respond(1, :foo_response, nil)
46
-
47
- server_wr.write(MessagePack.pack([2, :noop, []]))
48
- server_wr.flush
49
-
50
- event_loop.run { event_loop.stop }
51
- expect(server_rd.readpartial(1024)).to eq(
52
- MessagePack.pack([1, 1, nil, :foo_response])
53
- )
32
+ describe "#notify" do
33
+ it "writes a msgpack notification" do
34
+ event_loop.notify(:method, 1, 2)
35
+ message = server_rd.readpartial(1024)
36
+ expect(message).to eq(MessagePack.pack([2, "method", [1, 2]]))
54
37
  end
38
+ end
55
39
 
56
- it "reads notifications" do
57
- server_wr.write(MessagePack.pack([2, :foo_notification, []]))
40
+ describe "#run" do
41
+ it "yields received messages to the block" do
42
+ server_wr.write(MessagePack.pack([0, 1, :foo_method, []]))
58
43
  server_wr.flush
59
44
 
60
- notification = nil
61
- event_loop.run do |ntf|
62
- notification = ntf
45
+ message = nil
46
+ event_loop.run do |req|
47
+ message = req
63
48
  event_loop.stop
64
49
  end
65
- expect(notification.method_name).to eq("foo_notification")
66
- end
67
50
 
68
- it "writes notifications" do
69
- event_loop.notify(:foo_notification)
51
+ expect(message.sync?).to eq(true)
52
+ expect(message.method_name).to eq("foo_method")
53
+ end
70
54
 
71
- server_wr.write(MessagePack.pack([2, :noop, []]))
72
- server_wr.flush
55
+ it "shuts down after receiving EOFError" do
56
+ run_thread = Thread.new do
57
+ event_loop.run
58
+ end
73
59
 
74
- event_loop.run { event_loop.stop }
75
- expect(server_rd.readpartial(1024)).to eq(
76
- MessagePack.pack([2, :foo_notification, []])
77
- )
60
+ server_wr.close
61
+ run_thread.join
62
+ expect(client_rd).to be_closed
63
+ expect(client_wr).to be_closed
78
64
  end
79
65
  end
80
66
  end
@@ -6,7 +6,7 @@ module Neovim
6
6
  RSpec.describe Loader do
7
7
  describe "#load" do
8
8
  let(:plugin_path) { Support.file_path("plug.rb") }
9
- let(:host) { instance_double(Host, :register => nil) }
9
+ let(:host) { instance_double(Host, plugins: []) }
10
10
  let(:loader) { Loader.new(host) }
11
11
 
12
12
  before do
@@ -14,26 +14,33 @@ module Neovim
14
14
  end
15
15
 
16
16
  it "registers plugins defined in the provided files" do
17
- expect(host).to receive(:register).with(kind_of(Plugin))
18
- loader.load([plugin_path])
17
+ expect do
18
+ loader.load([plugin_path])
19
+ end.to change { host.plugins.size }.by(1)
19
20
  end
20
21
 
21
22
  it "registers multiple plugins defined in the provided files" do
22
23
  File.write(plugin_path, "Neovim.plugin; Neovim.plugin")
23
- expect(host).to receive(:register).with(kind_of(Plugin)).twice
24
- loader.load([plugin_path])
24
+
25
+ expect do
26
+ loader.load([plugin_path])
27
+ end.to change { host.plugins.size }.by(2)
25
28
  end
26
29
 
27
30
  it "doesn't register plugins when none are defined" do
28
31
  File.write(plugin_path, "class FooClass; end")
29
- expect(host).not_to receive(:register)
30
- loader.load([plugin_path])
32
+
33
+ expect do
34
+ loader.load([plugin_path])
35
+ end.not_to change { host.plugins.size }
31
36
  end
32
37
 
33
38
  it "doesn't leak constants defined in plugins" do
34
39
  File.write(plugin_path, "class FooClass; end")
35
- loader.load([plugin_path])
36
- expect(Kernel.const_defined?(:FooClass)).to be(false)
40
+
41
+ expect do
42
+ loader.load([plugin_path])
43
+ end.not_to change { Kernel.const_defined?(:FooClass) }.from(false)
37
44
  end
38
45
 
39
46
  it "doesn't leak the overidden Neovim.plugin method" do