neovim 0.7.1 → 0.9.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 (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)