neovim 0.6.2 → 0.7.0

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.
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