neovim 0.7.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/docs.yml +39 -0
  3. data/.github/workflows/tests.yml +64 -0
  4. data/.gitignore +2 -0
  5. data/CHANGELOG.md +22 -0
  6. data/CODE_OF_CONDUCT.md +3 -3
  7. data/README.md +19 -20
  8. data/Rakefile +21 -11
  9. data/exe/neovim-ruby-host +5 -0
  10. data/lib/neovim/buffer.rb +120 -41
  11. data/lib/neovim/client.rb +304 -39
  12. data/lib/neovim/client_info.rb +46 -0
  13. data/lib/neovim/connection.rb +7 -2
  14. data/lib/neovim/event_loop.rb +8 -4
  15. data/lib/neovim/host/cli.rb +41 -0
  16. data/lib/neovim/host.rb +3 -0
  17. data/lib/neovim/logging.rb +1 -1
  18. data/lib/neovim/message.rb +1 -1
  19. data/lib/neovim/plugin/dsl.rb +6 -0
  20. data/lib/neovim/plugin.rb +7 -2
  21. data/lib/neovim/remote_object.rb +5 -2
  22. data/lib/neovim/ruby_provider/object_ext.rb +5 -0
  23. data/lib/neovim/ruby_provider/vim.rb +6 -5
  24. data/lib/neovim/ruby_provider.rb +29 -10
  25. data/lib/neovim/session.rb +21 -16
  26. data/lib/neovim/tabpage.rb +8 -15
  27. data/lib/neovim/version.rb +1 -1
  28. data/lib/neovim/window.rb +45 -33
  29. data/lib/neovim.rb +12 -3
  30. data/neovim.gemspec +4 -5
  31. data/script/ci/download_nvim.sh +40 -0
  32. data/script/dump_api.rb +1 -1
  33. data/script/generate_docs.rb +6 -7
  34. data/script/run_acceptance.rb +15 -11
  35. data/spec/acceptance/client_info_spec.vim +42 -0
  36. data/spec/acceptance/rplugin_command_spec.vim +2 -2
  37. data/spec/acceptance/ruby_spec.vim +18 -11
  38. data/spec/acceptance/rubydo_spec.vim +9 -0
  39. data/spec/acceptance/rubyeval_spec.vim +22 -0
  40. data/spec/acceptance/rubyfile/curbuf_ivar_get.rb +1 -1
  41. data/spec/acceptance/rubyfile/curbuf_ivar_set.rb +1 -1
  42. data/spec/acceptance/rubyfile/define_foo.rb +1 -1
  43. data/spec/acceptance/rubyfile/nested_inner.rb +1 -1
  44. data/spec/acceptance/rubyfile/set_pwd_after.rb +1 -1
  45. data/spec/acceptance/rubyfile/set_pwd_before.rb +1 -1
  46. data/spec/acceptance/rubyfile_spec.vim +19 -19
  47. data/spec/acceptance/runtime/init.vim +2 -2
  48. data/spec/acceptance/runtime/rplugin/ruby/commands.rb +2 -2
  49. data/spec/helper.rb +25 -7
  50. data/spec/neovim/api_spec.rb +1 -1
  51. data/spec/neovim/buffer_spec.rb +10 -6
  52. data/spec/neovim/client_info_spec.rb +77 -0
  53. data/spec/neovim/client_spec.rb +9 -2
  54. data/spec/neovim/connection_spec.rb +32 -4
  55. data/spec/neovim/current_spec.rb +1 -2
  56. data/spec/neovim/event_loop_spec.rb +16 -0
  57. data/spec/neovim/host/cli_spec.rb +94 -0
  58. data/spec/neovim/host_spec.rb +16 -14
  59. data/spec/neovim/line_range_spec.rb +1 -3
  60. data/spec/neovim/remote_object_spec.rb +1 -2
  61. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +6 -7
  62. data/spec/neovim/ruby_provider/object_ext_spec.rb +10 -0
  63. data/spec/neovim/ruby_provider/vim_spec.rb +1 -1
  64. data/spec/neovim/ruby_provider/window_ext_spec.rb +7 -10
  65. data/spec/neovim/session_spec.rb +13 -40
  66. data/spec/neovim/window_spec.rb +1 -1
  67. data/spec/neovim_spec.rb +28 -51
  68. data/spec/support.rb +27 -1
  69. metadata +26 -44
  70. data/.coveralls.yml +0 -1
  71. data/.rubocop.yml +0 -118
  72. data/.travis.yml +0 -22
  73. data/appveyor.yml +0 -31
  74. data/bin/neovim-ruby-host +0 -18
  75. data/script/validate_docs.rb +0 -29
@@ -77,8 +77,8 @@ function! s:suite.supports_register() abort
77
77
  endfunction
78
78
 
79
79
  function! s:suite.supports_completion() abort
80
- RPluginCommandCompletion
81
- call s:expect(g:rplugin_command_completion).to_equal("buffer")
80
+ RPluginCommandCompletion foo
81
+ call s:expect(g:rplugin_command_completion).to_equal(["buffer", "foo"])
82
82
  endfunction
83
83
 
84
84
  function! s:suite.supports_eval() abort
@@ -2,8 +2,14 @@ let s:suite = themis#suite(":ruby")
2
2
  let s:expect = themis#helper("expect")
3
3
 
4
4
  function! s:suite.before_each() abort
5
+ let s:pwd = getcwd()
5
6
  1,$delete
6
7
  call append(0, ["one", "two"])
8
+ unlet! s:var
9
+ endfunction
10
+
11
+ function! s:suite.after_each() abort
12
+ execute("cd " . s:pwd)
7
13
  endfunction
8
14
 
9
15
  function! s:suite.has_nvim() abort
@@ -11,41 +17,42 @@ function! s:suite.has_nvim() abort
11
17
  endfunction
12
18
 
13
19
  function! s:suite.defines_a_ruby_method() abort
14
- ruby def foo; Vim.command("let g:called = 1"); end
20
+ ruby def foo; Vim.command("let s:var = 1"); end
15
21
  ruby foo
16
22
 
17
- call s:expect(g:called).to_equal(1)
23
+ call s:expect(s:var).to_equal(1)
18
24
  endfunction
19
25
 
20
26
  function! s:suite.persists_curbuf_state() abort
21
27
  ruby $curbuf.instance_variable_set(:@foo, 123)
22
- ruby Vim.command("let g:foo = #{$curbuf.instance_variable_get(:@foo)}")
28
+ ruby Vim.command("let s:var = #{$curbuf.instance_variable_get(:@foo)}")
23
29
 
24
- call s:expect(g:foo).to_equal(123)
30
+ call s:expect(s:var).to_equal(123)
25
31
  endfunction
26
32
 
27
33
  function! s:suite.updates_working_directory() abort
28
34
  cd /
29
- ruby Vim.command("let g:ruby_pwd = '#{Dir.pwd.sub(/^C:/, "")}'")
35
+ ruby Vim.command("let s:var = '#{Dir.pwd.sub(/^[A-Z]:/, "")}'")
30
36
  cd -
31
37
 
32
- call s:expect(g:ruby_pwd).to_equal("/")
38
+ call s:expect(s:var).to_equal("/")
33
39
  endfunction
34
40
 
35
41
  function! s:suite.updates_working_directory_implicitly() abort
36
42
  split | lcd /
37
- ruby Vim.command("let g:before_pwd = '#{Dir.pwd}'")
43
+ ruby Vim.command("let s:var = ['#{Dir.pwd}']")
38
44
  wincmd p
39
- ruby Vim.command("let g:after_pwd = '#{Dir.pwd}'")
45
+ ruby Vim.command("call add(s:var, '#{Dir.pwd}')")
40
46
  wincmd p | lcd -
41
47
 
42
- call s:expect(g:before_pwd).not.to_equal(g:after_pwd)
48
+ call s:expect(len(s:var)).to_equal(2)
49
+ call s:expect(s:var[0]).not.to_equal(s:var[1])
43
50
  endfunction
44
51
 
45
52
  function! s:suite.supports_nesting() abort
46
- ruby Vim.command("ruby Vim.command('let g:ruby_nested = 123')")
53
+ ruby Vim.command("ruby Vim.command('let s:var = 123')")
47
54
 
48
- call s:expect(g:ruby_nested).to_equal(123)
55
+ call s:expect(s:var).to_equal(123)
49
56
  endfunction
50
57
 
51
58
  function! s:suite.handles_standard_error() abort
@@ -42,6 +42,15 @@ function! s:suite.updates_all_lines() abort
42
42
  call s:expect(getline(1, 4)).to_equal(["ONE", "TWO", "THREE", "FOUR"])
43
43
  endfunction
44
44
 
45
+ function! s:suite.ignores_line_deletion() abort
46
+ " Just ensure `Index out of bounds` exception isn't raised.
47
+ "
48
+ " Deleting or adding lines inside `:rubydo` is documented as not supported.
49
+ " Therefore this will remain inconsistent with Vim, which deletes all but
50
+ " the first line (?)
51
+ %rubydo Vim.command("%d")
52
+ endfunction
53
+
45
54
  function! s:suite.handles_standard_error() abort
46
55
  try
47
56
  1rubydo raise "BOOM"
@@ -0,0 +1,22 @@
1
+ let s:suite = themis#suite(":rubyeval")
2
+ let s:expect = themis#helper("expect")
3
+
4
+ function! s:suite.evaluates_ruby_objects() abort
5
+ call s:expect(rubyeval("123")).to_equal(123)
6
+ call s:expect(rubyeval("1.2")).to_equal(1.2)
7
+ call s:expect(rubyeval("'test'")).to_equal("test")
8
+ call s:expect(rubyeval("nil")).to_equal(v:null)
9
+ call s:expect(rubyeval("true")).to_equal(v:true)
10
+ call s:expect(rubyeval("false")).to_equal(v:false)
11
+ call s:expect(rubyeval("{x: 1}")).to_equal({"x": 1})
12
+ call s:expect(rubyeval(":test")).to_equal("test")
13
+ call s:expect(rubyeval(":test.class")).to_equal("Symbol")
14
+ endfunction
15
+
16
+ function! s:suite.propagates_exceptions() abort
17
+ try
18
+ rubyeval("raise 'BOOM'")
19
+ throw "Nothing raised"
20
+ catch /BOOM/
21
+ endtry
22
+ endfunction
@@ -1 +1 @@
1
- Vim.command("let g:foo = #{$curbuf.instance_variable_get(:@foo)}")
1
+ Vim.command("let s:var = #{$curbuf.instance_variable_get(:@var)}")
@@ -1 +1 @@
1
- $curbuf.instance_variable_set(:@foo, 123)
1
+ $curbuf.instance_variable_set(:@var, 123)
@@ -1,3 +1,3 @@
1
1
  def foo
2
- Vim.command("let g:called = 1")
2
+ Vim.command("let s:var = 1")
3
3
  end
@@ -1 +1 @@
1
- Vim.command("let g:ruby_nested = 123")
1
+ Vim.command("let s:var = 123")
@@ -1 +1 @@
1
- Vim.command("let g:pwd_after = '#{Dir.pwd}'")
1
+ Vim.command("call add(s:var, '#{Dir.pwd}')")
@@ -1 +1 @@
1
- Vim.command("let g:pwd_before = '#{Dir.pwd.sub(/^C:/, '')}'")
1
+ Vim.command("let s:var = ['#{Dir.pwd.sub(/^[A-Z]:/, '')}']")
@@ -2,19 +2,18 @@ let s:suite = themis#suite(":rubyfile")
2
2
  let s:expect = themis#helper("expect")
3
3
 
4
4
  function! s:suite.before() abort
5
- let g:return_pwd = getcwd()
6
- cd spec/acceptance/rubyfile
7
- endfunction
8
-
9
- function! s:suite.after() abort
10
- execute("cd " . g:return_pwd)
11
- endfunction
5
+ let s:pwd = getcwd()
6
+ cd ./spec/acceptance/rubyfile
7
+ unlet! s:var
12
8
 
13
- function! s:suite.before_each() abort
14
9
  1,$delete
15
10
  call append(0, ["one", "two"])
16
11
  endfunction
17
12
 
13
+ function! s:suite.after() abort
14
+ execute("cd " . s:pwd)
15
+ endfunction
16
+
18
17
  function! s:suite.has_nvim() abort
19
18
  call s:expect(has("nvim")).to_equal(1)
20
19
  endfunction
@@ -23,42 +22,43 @@ function! s:suite.defines_a_ruby_method() abort
23
22
  rubyfile ./define_foo.rb
24
23
  rubyfile ./call_foo.rb
25
24
 
26
- call s:expect(g:called).to_equal(1)
25
+ call s:expect(s:var).to_equal(1)
27
26
  endfunction
28
27
 
29
28
  function! s:suite.persists_curbuf_state() abort
30
29
  rubyfile ./curbuf_ivar_set.rb
31
30
  rubyfile ./curbuf_ivar_get.rb
32
31
 
33
- call s:expect(g:foo).to_equal(123)
32
+ call s:expect(s:var).to_equal(123)
34
33
  endfunction
35
34
 
36
35
  function! s:suite.updates_working_directory() abort
37
- let g:rubyfile = getcwd() . "/set_pwd_before.rb"
36
+ let s:rubyfile = getcwd() . "/set_pwd_before.rb"
38
37
  cd /
39
- exec "rubyfile " . g:rubyfile
38
+ exec "rubyfile " . s:rubyfile
40
39
  cd -
41
40
 
42
- call s:expect(g:pwd_before).to_equal("/")
41
+ call s:expect(s:var).to_equal(["/"])
43
42
  endfunction
44
43
 
45
44
  function! s:suite.updates_working_directory_implicitly() abort
46
- let g:before_file = getcwd() . "/set_pwd_before.rb"
47
- let g:after_file = getcwd() . "/set_pwd_after.rb"
45
+ let s:before_file = getcwd() . "/set_pwd_before.rb"
46
+ let s:after_file = getcwd() . "/set_pwd_after.rb"
48
47
 
49
48
  split | lcd /
50
- exec "rubyfile " . g:before_file
49
+ exec "rubyfile " . s:before_file
51
50
  wincmd p
52
- exec "rubyfile " . g:after_file
51
+ exec "rubyfile " . s:after_file
53
52
  wincmd p | lcd -
54
53
 
55
- call s:expect(g:pwd_before).not.to_equal(g:pwd_after)
54
+ call s:expect(len(s:var)).to_equal(2)
55
+ call s:expect(s:var[0]).not.to_equal(s:var[1])
56
56
  endfunction
57
57
 
58
58
  function! s:suite.supports_nesting() abort
59
59
  rubyfile ./nested.rb
60
60
 
61
- call s:expect(g:ruby_nested).to_equal(123)
61
+ call s:expect(s:var).to_equal(123)
62
62
  endfunction
63
63
 
64
64
  function! s:suite.handles_standard_error() abort
@@ -1,7 +1,7 @@
1
1
  let s:lib_path = getcwd() . "/lib"
2
- let s:bin_path = getcwd() . "/bin/neovim-ruby-host"
2
+ let s:exe_path = getcwd() . "/exe/neovim-ruby-host"
3
3
  let g:acceptance_rtp = getcwd() . "/spec/acceptance/runtime"
4
- let g:ruby_host_prog = printf("ruby -I %s %s", s:lib_path, s:bin_path)
4
+ let g:ruby_host_prog = printf("ruby -I %s %s", s:lib_path, s:exe_path)
5
5
 
6
6
  ruby require "rspec/expectations"
7
7
  ruby include ::RSpec::Matchers.dup
@@ -43,10 +43,10 @@ Neovim.plugin do |plug|
43
43
  nvim.set_var("rplugin_command_register", reg)
44
44
  end
45
45
 
46
- plug.command(:RPluginCommandCompletion, complete: "buffer", sync: true) do |nvim|
46
+ plug.command(:RPluginCommandCompletion, complete: "buffer", nargs: 1, sync: true) do |nvim, arg|
47
47
  attrs = nvim.command_output("silent command RPluginCommandCompletion")
48
48
  compl = attrs.split($/).last.split[2]
49
- nvim.set_var("rplugin_command_completion", compl)
49
+ nvim.set_var("rplugin_command_completion", [compl, arg])
50
50
  end
51
51
 
52
52
  plug.command(:RPluginCommandEval, eval: "g:to_eval", sync: true) do |nvim, to_eval|
data/spec/helper.rb CHANGED
@@ -1,10 +1,5 @@
1
1
  require "bundler/setup"
2
2
 
3
- if ENV["REPORT_COVERAGE"]
4
- require "coveralls"
5
- Coveralls.wear!
6
- end
7
-
8
3
  require "fileutils"
9
4
  require "msgpack"
10
5
  require "neovim"
@@ -14,7 +9,9 @@ require "securerandom"
14
9
  require "stringio"
15
10
  require "timeout"
16
11
 
17
- require File.expand_path("../support.rb", __FILE__)
12
+ require File.expand_path("support.rb", __dir__)
13
+
14
+ ENV["NVIM_RUBY_LOG_LEVEL"] ||= "FATAL"
18
15
 
19
16
  RSpec.configure do |config|
20
17
  config.expect_with :rspec do |exp|
@@ -45,12 +42,33 @@ RSpec.configure do |config|
45
42
  timeout = spec.metadata.fetch(:timeout, 3)
46
43
 
47
44
  begin
48
- Timeout.timeout(timeout) { spec.run }
45
+ Timeout.timeout(timeout) do
46
+ Support.clean_persistent_client
47
+ spec.run
48
+ end
49
49
  ensure
50
50
  Support.teardown_workspace
51
51
  end
52
52
  end
53
53
 
54
+ config.before(:example, :nvim_version) do |spec|
55
+ comparator = spec.metadata.fetch(:nvim_version)
56
+ requirement = Gem::Requirement.create(comparator)
57
+
58
+ nvim_version = Support
59
+ .nvim_version
60
+ .split("+")
61
+ .first
62
+
63
+ if !requirement.satisfied_by?(Gem::Version.new(nvim_version))
64
+ skip "Skipping on nvim #{nvim_version} (requires #{comparator})"
65
+ end
66
+ end
67
+
68
+ config.after(:suite) do
69
+ Support.persistent_client.shutdown
70
+ end
71
+
54
72
  Kernel.srand config.seed
55
73
  end
56
74
 
@@ -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
 
@@ -124,6 +122,12 @@ module Neovim
124
122
  end.to change { buffer.lines.to_a }.to(["first", "one", "two"])
125
123
  end
126
124
 
125
+ it "allows newlines" do
126
+ expect do
127
+ buffer.append(0, "first\nsecond")
128
+ end.to change { buffer.lines.to_a }.to(["first", "second", "one", "two"])
129
+ end
130
+
127
131
  it "doesn't move the cursor" do
128
132
  expect do
129
133
  buffer.append(0, "first")
@@ -0,0 +1,77 @@
1
+ require "neovim/client_info"
2
+ require "neovim/host"
3
+ require "neovim/plugin"
4
+
5
+ module Neovim
6
+ RSpec.describe ClientInfo do
7
+ describe "#to_args" do
8
+ context ".for_host" do
9
+ it "returns script-host info" do
10
+ plugin = double(Plugin, script_host?: true)
11
+ host = double(Host, plugins: [plugin])
12
+ info = ClientInfo.for_host(host)
13
+
14
+ expect(info.to_args).to match(
15
+ [
16
+ "ruby-script-host",
17
+ {
18
+ "major" => duck_type(:to_int),
19
+ "minor" => duck_type(:to_int),
20
+ "patch" => duck_type(:to_int)
21
+ },
22
+ :host,
23
+ {
24
+ poll: {},
25
+ specs: {nargs: 1}
26
+ },
27
+ duck_type(:to_hash)
28
+ ]
29
+ )
30
+ end
31
+
32
+ it "returns rplugin info" do
33
+ plugin = double(Plugin, script_host?: false)
34
+ host = double(Host, plugins: [plugin])
35
+ info = ClientInfo.for_host(host)
36
+
37
+ expect(info.to_args).to match(
38
+ [
39
+ "ruby-rplugin-host",
40
+ {
41
+ "major" => duck_type(:to_int),
42
+ "minor" => duck_type(:to_int),
43
+ "patch" => duck_type(:to_int)
44
+ },
45
+ :host,
46
+ {
47
+ poll: {},
48
+ specs: {nargs: 1}
49
+ },
50
+ duck_type(:to_hash)
51
+ ]
52
+ )
53
+ end
54
+ end
55
+
56
+ context ".for_client" do
57
+ it "returns remote client info" do
58
+ info = ClientInfo.for_client
59
+
60
+ expect(info.to_args).to match(
61
+ [
62
+ "ruby-client",
63
+ {
64
+ "major" => duck_type(:to_int),
65
+ "minor" => duck_type(:to_int),
66
+ "patch" => duck_type(:to_int)
67
+ },
68
+ :remote,
69
+ {},
70
+ duck_type(:to_hash)
71
+ ]
72
+ )
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -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
@@ -25,6 +24,14 @@ module Neovim
25
24
  end
26
25
  end
27
26
 
27
+ describe "#shutdown" do
28
+ it "causes nvim to exit" do
29
+ client = Neovim.attach_child(Support.child_argv)
30
+ client.shutdown
31
+ expect { client.strwidth("hi") }.to raise_error(Neovim::Session::Disconnected)
32
+ end
33
+ end
34
+
28
35
  describe "#respond_to?" do
29
36
  it "returns true for vim functions" do
30
37
  expect(client).to respond_to(:strwidth)