neovim 0.8.1 → 0.9.0.pre.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +36 -0
  3. data/.github/workflows/linter.yml +32 -0
  4. data/.github/workflows/tests.yml +62 -0
  5. data/.rubocop.yml +19 -2
  6. data/CHANGELOG.md +6 -0
  7. data/CODE_OF_CONDUCT.md +3 -3
  8. data/README.md +19 -17
  9. data/Rakefile +28 -24
  10. data/exe/neovim-ruby-host +2 -15
  11. data/lib/neovim/buffer.rb +15 -1
  12. data/lib/neovim/client.rb +89 -1
  13. data/lib/neovim/connection.rb +0 -1
  14. data/lib/neovim/event_loop.rb +6 -3
  15. data/lib/neovim/host/cli.rb +41 -0
  16. data/lib/neovim/logging.rb +1 -1
  17. data/lib/neovim/ruby_provider.rb +25 -8
  18. data/lib/neovim/ruby_provider/object_ext.rb +5 -0
  19. data/lib/neovim/session.rb +13 -18
  20. data/lib/neovim/tabpage.rb +1 -1
  21. data/lib/neovim/version.rb +1 -1
  22. data/lib/neovim/window.rb +15 -1
  23. data/neovim.gemspec +1 -1
  24. data/script/ci/download_nvim.sh +40 -0
  25. data/script/run_acceptance.rb +15 -11
  26. data/spec/acceptance/ruby_spec.vim +6 -1
  27. data/spec/acceptance/rubyeval_spec.vim +22 -0
  28. data/spec/acceptance/rubyfile/set_pwd_before.rb +1 -1
  29. data/spec/acceptance/rubyfile_spec.vim +4 -6
  30. data/spec/helper.rb +20 -1
  31. data/spec/neovim/api_spec.rb +1 -1
  32. data/spec/neovim/buffer_spec.rb +4 -6
  33. data/spec/neovim/client_spec.rb +3 -3
  34. data/spec/neovim/current_spec.rb +1 -2
  35. data/spec/neovim/event_loop_spec.rb +10 -0
  36. data/spec/neovim/host/cli_spec.rb +94 -0
  37. data/spec/neovim/host_spec.rb +2 -7
  38. data/spec/neovim/line_range_spec.rb +1 -3
  39. data/spec/neovim/remote_object_spec.rb +1 -2
  40. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +6 -7
  41. data/spec/neovim/ruby_provider/object_ext_spec.rb +10 -0
  42. data/spec/neovim/ruby_provider/vim_spec.rb +1 -1
  43. data/spec/neovim/ruby_provider/window_ext_spec.rb +7 -10
  44. data/spec/neovim/session_spec.rb +13 -46
  45. data/spec/neovim/window_spec.rb +1 -1
  46. data/spec/neovim_spec.rb +10 -63
  47. data/spec/support.rb +25 -0
  48. metadata +21 -12
  49. data/.travis.yml +0 -25
  50. data/appveyor.yml +0 -35
  51. data/script/validate_docs.rb +0 -29
@@ -1 +1 @@
1
- Vim.command("let s:var = ['#{Dir.pwd.sub(/^C:/, '')}']")
1
+ Vim.command("let s:var = ['#{Dir.pwd.sub(/^[A-Z]:/, '')}']")
@@ -3,19 +3,17 @@ let s:expect = themis#helper("expect")
3
3
 
4
4
  function! s:suite.before() abort
5
5
  let s:pwd = getcwd()
6
- cd spec/acceptance/rubyfile
6
+ cd ./spec/acceptance/rubyfile
7
7
  unlet! s:var
8
+
9
+ 1,$delete
10
+ call append(0, ["one", "two"])
8
11
  endfunction
9
12
 
10
13
  function! s:suite.after() abort
11
14
  execute("cd " . s:pwd)
12
15
  endfunction
13
16
 
14
- function! s:suite.before_each() abort
15
- 1,$delete
16
- call append(0, ["one", "two"])
17
- endfunction
18
-
19
17
  function! s:suite.has_nvim() abort
20
18
  call s:expect(has("nvim")).to_equal(1)
21
19
  endfunction
@@ -11,6 +11,8 @@ require "timeout"
11
11
 
12
12
  require File.expand_path("support.rb", __dir__)
13
13
 
14
+ ENV["NVIM_RUBY_LOG_LEVEL"] ||= "FATAL"
15
+
14
16
  RSpec.configure do |config|
15
17
  config.expect_with :rspec do |exp|
16
18
  exp.syntax = :expect
@@ -40,12 +42,29 @@ RSpec.configure do |config|
40
42
  timeout = spec.metadata.fetch(:timeout, 3)
41
43
 
42
44
  begin
43
- Timeout.timeout(timeout) { spec.run }
45
+ Timeout.timeout(timeout) do
46
+ Support.clean_persistent_client
47
+ spec.run
48
+ end
44
49
  ensure
45
50
  Support.teardown_workspace
46
51
  end
47
52
  end
48
53
 
54
+ config.before(:example, :nvim_version) do |spec|
55
+ comparator = spec.metadata.fetch(:nvim_version)
56
+ requirement = Gem::Requirement.create(comparator)
57
+ nvim_version = Gem::Version.new(Support.nvim_version)
58
+
59
+ if !requirement.satisfied_by?(nvim_version)
60
+ skip "Skipping on nvim #{nvim_version} (requires #{comparator})"
61
+ end
62
+ end
63
+
64
+ config.after(:suite) do
65
+ Support.persistent_client.shutdown
66
+ end
67
+
49
68
  Kernel.srand config.seed
50
69
  end
51
70
 
@@ -2,7 +2,7 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe API do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
5
+ let(:client) { Support.persistent_client }
6
6
 
7
7
  let(:api) do
8
8
  API.new(
@@ -2,7 +2,7 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe Buffer do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
5
+ let(:client) { Support.persistent_client }
6
6
  let(:buffer) { client.current.buffer }
7
7
 
8
8
  before do
@@ -11,8 +11,6 @@ module Neovim
11
11
  client.command("normal gg")
12
12
  end
13
13
 
14
- after { client.shutdown }
15
-
16
14
  describe "#lines" do
17
15
  it "returns a LineRange" do
18
16
  expect(buffer.lines).to be_a(LineRange)
@@ -37,9 +35,9 @@ module Neovim
37
35
 
38
36
  describe "#number" do
39
37
  it "returns the buffer number" do
40
- expect(buffer.number).to eq(1)
41
- client.command("new")
42
- expect(client.get_current_buf.number).to eq(2)
38
+ expect do
39
+ client.command("new")
40
+ end.to change { client.get_current_buf.number }
43
41
  end
44
42
  end
45
43
 
@@ -2,8 +2,7 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe Client do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
6
- after { client.shutdown }
5
+ let(:client) { Support.persistent_client }
7
6
 
8
7
  describe "#set_option" do
9
8
  it "sets an option from two arguments" do
@@ -27,8 +26,9 @@ module Neovim
27
26
 
28
27
  describe "#shutdown" do
29
28
  it "causes nvim to exit" do
29
+ client = Neovim.attach_child(Support.child_argv)
30
30
  client.shutdown
31
- expect { client.strwidth("hi") }.to raise_error(Neovim::Session::Exited)
31
+ expect { client.strwidth("hi") }.to raise_error(Neovim::Session::Disconnected)
32
32
  end
33
33
  end
34
34
 
@@ -2,9 +2,8 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe Current do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
5
+ let(:client) { Support.persistent_client }
6
6
  let(:current) { client.current }
7
- after { client.shutdown }
8
7
 
9
8
  describe "#line" do
10
9
  it "returns an empty string if the current line is empty" do
@@ -58,6 +58,16 @@ module Neovim
58
58
  expect(message.method_name).to eq("foo_method")
59
59
  end
60
60
 
61
+ it "returns the last message received" do
62
+ server_wr.write(MessagePack.pack([0, 1, :foo_method, []]))
63
+ server_wr.flush
64
+
65
+ message = event_loop.run { |req| event_loop.stop; req }
66
+
67
+ expect(message.sync?).to eq(true)
68
+ expect(message.method_name).to eq("foo_method")
69
+ end
70
+
61
71
  it "shuts down after receiving EOFError" do
62
72
  run_thread = Thread.new do
63
73
  event_loop.run
@@ -0,0 +1,94 @@
1
+ require "helper"
2
+ require "neovim/host/cli"
3
+
4
+ begin
5
+ require "pty"
6
+ rescue LoadError
7
+ # Not available on Windows
8
+ end
9
+
10
+ module Neovim
11
+ class Host
12
+ RSpec.describe CLI do
13
+ let(:stdin) { StringIO.new }
14
+ let(:stdout) { StringIO.new }
15
+ let(:stderr) { StringIO.new }
16
+
17
+ specify "-V" do
18
+ expect do
19
+ CLI.run("/exe/nv-rb-host", ["-V"], stdin, stdout, stderr)
20
+ end.to raise_error(SystemExit) { |e| expect(e.status).to eq(0) }
21
+
22
+ expect(stderr.string).to be_empty
23
+ expect(stdout.string).to eq(Neovim::VERSION.to_s + "\n")
24
+ end
25
+
26
+ specify "-h" do
27
+ expect do
28
+ CLI.run("/exe/nv-rb-host", ["-h"], stdin, stdout, stderr)
29
+ end.to raise_error(SystemExit) { |e| expect(e.status).to eq(0) }
30
+
31
+ expect(stderr.string).to be_empty
32
+ expect(stdout.string).to eq("Usage: nv-rb-host [-hV] rplugin_path ...\n")
33
+ end
34
+
35
+ it "fails with invalid arguments" do
36
+ expect do
37
+ CLI.run("/exe/nv-rb-host", ["-x"], stdin, stdout, stderr)
38
+ end.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
39
+
40
+ expect(stdout.string).to be_empty
41
+ expect(stderr.string).to eq("invalid option: -x\n")
42
+ end
43
+
44
+ it "fails when run interactively" do
45
+ if !defined?(PTY)
46
+ skip "Skipping without `pty` library."
47
+ end
48
+
49
+ PTY.open do |tty,|
50
+ expect do
51
+ CLI.run("/exe/nv-rb-host", ["plugin.rb"], tty, stdout, stderr)
52
+ end.to raise_error(SystemExit) { |e| expect(e.status).to eq(1) }
53
+
54
+ expect(stdout.string).to be_empty
55
+ expect(stderr.string).to eq("Can't run nv-rb-host interactively.\n")
56
+ end
57
+ end
58
+
59
+ it "starts a stdio host" do
60
+ nvim_r, host_w = IO.pipe
61
+ host_r, nvim_w = IO.pipe
62
+
63
+ nvim_u = MessagePack::Unpacker.new(nvim_r)
64
+ nvim_p = MessagePack::Packer.new(nvim_w)
65
+
66
+ Support.file_path("plugin").tap do |path|
67
+ File.write(path, "Neovim.plugin { |p| p.function('Foo') }")
68
+
69
+ thr = Thread.new do
70
+ CLI.run("/exe/nv-rb-host", [path], host_r, host_w, stderr)
71
+ end
72
+
73
+ begin
74
+ nvim_p.write([0, 1, :poll, []]).flush
75
+
76
+ expect(nvim_u.read[0..1]).to eq([2, "nvim_set_client_info"])
77
+ expect(nvim_u.read[0..2]).to eq([0, 2, "nvim_get_api_info"])
78
+
79
+ nvim_p.write([1, 2, nil, [10, {"functions" => {}, "types" => {}}]]).flush
80
+ expect(nvim_u.read).to eq([1, 1, nil, "ok"])
81
+
82
+ nvim_p.write([0, 3, :specs, [path]]).flush
83
+ *prefix, (payload, *) = nvim_u.read
84
+
85
+ expect(prefix).to eq([1, 3, nil])
86
+ expect(payload["name"]).to eq("Foo")
87
+ ensure
88
+ thr.kill.join
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -41,10 +41,7 @@ module Neovim
41
41
  end
42
42
  end
43
43
 
44
- after do
45
- host_thread.kill while host_thread.alive?
46
- host_thread.join
47
- end
44
+ after { host_thread.kill.join }
48
45
 
49
46
  context "poll" do
50
47
  it "initializes a client, sets client info, and responds 'ok'" do
@@ -72,9 +69,7 @@ module Neovim
72
69
 
73
70
  expect(method).to eq("nvim_get_api_info")
74
71
 
75
- session = Session.new(EventLoop.child(Support.child_argv))
76
- api_info = session.request(:nvim_get_api_info)
77
- session.shutdown
72
+ api_info = Support.persistent_client.get_api_info
78
73
 
79
74
  nvim_wr.write([1, reqid, nil, api_info]).flush
80
75
 
@@ -2,7 +2,7 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe LineRange do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
5
+ let(:client) { Support.persistent_client }
6
6
  let(:buffer) { client.current.buffer }
7
7
  let(:line_range) { LineRange.new(buffer) }
8
8
 
@@ -10,8 +10,6 @@ module Neovim
10
10
  buffer.set_lines(0, -1, true, ["1", "2", "3", "4"])
11
11
  end
12
12
 
13
- after { client.shutdown }
14
-
15
13
  describe "#each" do
16
14
  it "yields each line" do
17
15
  yielded = []
@@ -2,8 +2,7 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe RemoteObject do
5
- let(:client) { Neovim.attach_child(Support.child_argv) }
6
- after { client.shutdown }
5
+ let(:client) { Support.persistent_client }
7
6
 
8
7
  context Window do
9
8
  let(:window) { client.current.window }
@@ -4,13 +4,11 @@ require "neovim/ruby_provider/buffer_ext"
4
4
  module Neovim
5
5
  RSpec.describe Buffer do
6
6
  let!(:nvim) do
7
- Neovim.attach_child(Support.child_argv).tap do |nvim|
8
- stub_const("::Vim", nvim)
7
+ Support.persistent_client.tap do |client|
8
+ stub_const("::Vim", client)
9
9
  end
10
10
  end
11
11
 
12
- after { nvim.shutdown }
13
-
14
12
  describe ".current" do
15
13
  it "returns the current buffer from the global Vim client" do
16
14
  expect(Buffer.current).to eq(nvim.get_current_buf)
@@ -27,9 +25,10 @@ module Neovim
27
25
 
28
26
  describe ".[]" do
29
27
  it "returns the buffer from the global Vim client at the given index" do
30
- expect(Buffer[0]).to eq(nvim.get_current_buf)
31
- nvim.command("new")
32
- expect(Buffer[1]).to eq(nvim.get_current_buf)
28
+ buffer = Buffer[0]
29
+
30
+ expect(buffer).to be_a(Buffer)
31
+ expect(buffer).to eq(nvim.list_bufs[0])
33
32
  end
34
33
  end
35
34
  end
@@ -0,0 +1,10 @@
1
+ require "helper"
2
+ require "neovim/ruby_provider/object_ext"
3
+
4
+ RSpec.describe Object do
5
+ describe "#to_msgpack" do
6
+ it "converts classes to strings" do
7
+ expect(MessagePack.pack(String)).to eq(MessagePack.pack("String"))
8
+ end
9
+ end
10
+ end
@@ -52,7 +52,7 @@ RSpec.describe Vim do
52
52
  end
53
53
 
54
54
  it "refreshes global variables" do
55
- client = Neovim.attach_child(Support.child_argv)
55
+ client = Support.persistent_client
56
56
  client.command("vs foo")
57
57
 
58
58
  Vim.__client = client
@@ -4,13 +4,11 @@ require "neovim/ruby_provider/window_ext"
4
4
  module Neovim
5
5
  RSpec.describe Window do
6
6
  let!(:nvim) do
7
- Neovim.attach_child(Support.child_argv).tap do |nvim|
8
- stub_const("::Vim", nvim)
7
+ Support.persistent_client.tap do |client|
8
+ stub_const("::Vim", client)
9
9
  end
10
10
  end
11
11
 
12
- after { nvim.shutdown }
13
-
14
12
  describe ".current" do
15
13
  it "returns the current window from the global Vim client" do
16
14
  expect(Window.current).to eq(nvim.get_current_win)
@@ -33,17 +31,16 @@ module Neovim
33
31
 
34
32
  describe ".[]" do
35
33
  it "returns the window at the given index" do
36
- expect do
37
- nvim.command("new")
38
- end.to change { Window[1] }.from(nil).to(kind_of(Window))
34
+ window = Window[0]
35
+
36
+ expect(window).to be_a(Window)
37
+ expect(window).to eq(nvim.list_wins[0])
39
38
  end
40
39
 
41
40
  it "only includes windows within a tabpage" do
42
- nvim.command("new")
43
-
44
41
  expect do
45
42
  nvim.command("tabnew")
46
- end.to change { Window[1] }.from(kind_of(Window)).to(nil)
43
+ end.to change { Window[0] }
47
44
  end
48
45
  end
49
46
  end
@@ -2,10 +2,8 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe Session do
5
- let(:event_loop) { EventLoop.child(Support.child_argv) }
6
- let!(:session) { Session.new(event_loop) }
7
-
8
- after { session.shutdown }
5
+ let(:client) { Support.persistent_client }
6
+ let(:session) { client.session }
9
7
 
10
8
  describe "#request" do
11
9
  it "synchronously returns a result" do
@@ -18,18 +16,6 @@ module Neovim
18
16
  end.to raise_error(/wrong number of arguments/i)
19
17
  end
20
18
 
21
- it "handles large data" do
22
- large_str = Array.new(1024 * 17) { SecureRandom.hex(1) }.join
23
- session.request(:nvim_set_current_line, large_str)
24
- expect(session.request(:nvim_get_current_line)).to eq(large_str)
25
- end
26
-
27
- it "raises an exception when a command causes nvim to exit" do
28
- expect do
29
- session.request(:nvim_command, "qa!")
30
- end.to raise_error(Neovim::Session::Exited, /exited/)
31
- end
32
-
33
19
  it "fails outside of the main thread", :silence_thread_exceptions do
34
20
  expect do
35
21
  Thread.new { session.request(:nvim_strwidth, "foo") }.join
@@ -38,18 +24,6 @@ module Neovim
38
24
  end
39
25
 
40
26
  describe "#notify" do
41
- it "doesn't raise exceptions" do
42
- expect do
43
- session.notify(:nvim_strwidth, "too", "many")
44
- end.not_to raise_error
45
- end
46
-
47
- it "handles large data" do
48
- large_str = Array.new(1024 * 17) { SecureRandom.hex(1) }.join
49
- session.notify(:nvim_set_current_line, large_str)
50
- expect(session.request(:nvim_get_current_line)).to eq(large_str)
51
- end
52
-
53
27
  it "succeeds outside of the main thread" do
54
28
  expect do
55
29
  Thread.new { session.notify(:nvim_set_current_line, "foo") }.join
@@ -57,33 +31,26 @@ module Neovim
57
31
  end
58
32
  end
59
33
 
60
- describe "#run" do
61
- it "enqueues messages received during blocking requests" do
62
- session.request(:nvim_subscribe, "my_event")
63
- session.request(:nvim_command, "call rpcnotify(0, 'my_event', 'foo')")
34
+ describe "#next" do
35
+ it "returns the next message from the event loop" do
36
+ cid, = session.request(:nvim_get_api_info)
37
+ session.request(:nvim_command, "call rpcnotify(#{cid}, 'my_event', 'foo')")
64
38
 
65
- message = nil
66
- session.run do |msg|
67
- message = msg
68
- session.shutdown
69
- end
39
+ message = session.next
70
40
 
71
41
  expect(message.sync?).to eq(false)
72
42
  expect(message.method_name).to eq("my_event")
73
43
  expect(message.arguments).to eq(["foo"])
74
44
  end
75
45
 
76
- it "supports requests within callbacks" do
77
- session.request(:nvim_subscribe, "my_event")
78
- session.request(:nvim_command, "call rpcnotify(0, 'my_event', 'foo')")
46
+ it "returns asynchronous notification errors", nvim_version: ">= 0.4.pre.dev" do
47
+ session.notify(:nvim_set_current_line, "too", "many", "args")
79
48
 
80
- result = nil
81
- session.run do |msg|
82
- result = session.request(:nvim_strwidth, msg.arguments.first)
83
- session.shutdown
84
- end
49
+ message = session.next
85
50
 
86
- expect(result).to be(3)
51
+ expect(message.sync?).to eq(false)
52
+ expect(message.method_name).to eq("nvim_error_event")
53
+ expect(message.arguments).to eq([0, "Wrong number of arguments: expecting 1 but got 3"])
87
54
  end
88
55
  end
89
56
  end