neovim 0.6.2 → 0.9.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +5 -5
  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/.gitignore +5 -1
  6. data/.rubocop.yml +149 -0
  7. data/CHANGELOG.md +56 -0
  8. data/CODE_OF_CONDUCT.md +3 -3
  9. data/Gemfile +0 -11
  10. data/README.md +22 -23
  11. data/Rakefile +47 -15
  12. data/VimFlavor +1 -0
  13. data/exe/neovim-ruby-host +5 -0
  14. data/lib/neovim.rb +15 -6
  15. data/lib/neovim/api.rb +2 -1
  16. data/lib/neovim/buffer.rb +81 -53
  17. data/lib/neovim/client.rb +226 -41
  18. data/lib/neovim/client_info.rb +46 -0
  19. data/lib/neovim/connection.rb +73 -0
  20. data/lib/neovim/event_loop.rb +41 -37
  21. data/lib/neovim/executable.rb +1 -0
  22. data/lib/neovim/host.rb +50 -51
  23. data/lib/neovim/host/cli.rb +41 -0
  24. data/lib/neovim/host/loader.rb +1 -4
  25. data/lib/neovim/line_range.rb +16 -16
  26. data/lib/neovim/logging.rb +18 -18
  27. data/lib/neovim/message.rb +70 -0
  28. data/lib/neovim/plugin.rb +7 -5
  29. data/lib/neovim/plugin/dsl.rb +10 -4
  30. data/lib/neovim/plugin/handler.rb +8 -8
  31. data/lib/neovim/remote_object.rb +8 -5
  32. data/lib/neovim/ruby_provider.rb +52 -26
  33. data/lib/neovim/ruby_provider/buffer_ext.rb +1 -0
  34. data/lib/neovim/ruby_provider/object_ext.rb +5 -0
  35. data/lib/neovim/ruby_provider/vim.rb +19 -6
  36. data/lib/neovim/ruby_provider/window_ext.rb +1 -0
  37. data/lib/neovim/session.rb +45 -50
  38. data/lib/neovim/tabpage.rb +8 -15
  39. data/lib/neovim/version.rb +1 -1
  40. data/lib/neovim/window.rb +39 -36
  41. data/neovim.gemspec +11 -6
  42. data/script/ci/download_nvim.sh +40 -0
  43. data/script/{dump_api → dump_api.rb} +1 -1
  44. data/script/{generate_docs → generate_docs.rb} +6 -7
  45. data/script/{j2mp → j2mp.rb} +0 -0
  46. data/script/{mp2j → mp2j.rb} +0 -0
  47. data/script/run_acceptance.rb +39 -0
  48. data/spec/acceptance/client_info_spec.vim +42 -0
  49. data/spec/acceptance/rplugin_autocmd_spec.vim +20 -10
  50. data/spec/acceptance/rplugin_command_spec.vim +54 -56
  51. data/spec/acceptance/rplugin_function_spec.vim +28 -22
  52. data/spec/acceptance/ruby_spec.vim +52 -53
  53. data/spec/acceptance/rubydo_spec.vim +49 -52
  54. data/spec/acceptance/rubyeval_spec.vim +22 -0
  55. data/spec/acceptance/rubyfile/curbuf_ivar_get.rb +1 -1
  56. data/spec/acceptance/rubyfile/curbuf_ivar_set.rb +1 -1
  57. data/spec/acceptance/rubyfile/define_foo.rb +1 -1
  58. data/spec/acceptance/rubyfile/nested.rb +1 -1
  59. data/spec/acceptance/rubyfile/nested_inner.rb +1 -1
  60. data/spec/acceptance/rubyfile/set_pwd_after.rb +1 -1
  61. data/spec/acceptance/rubyfile/set_pwd_before.rb +1 -1
  62. data/spec/acceptance/rubyfile_spec.vim +60 -66
  63. data/spec/acceptance/runtime/init.vim +5 -4
  64. data/spec/acceptance/runtime/rplugin/ruby/autocmds.rb +7 -3
  65. data/spec/acceptance/runtime/rplugin/ruby/commands.rb +18 -17
  66. data/spec/acceptance/runtime/rplugin/ruby/functions.rb +9 -9
  67. data/spec/helper.rb +38 -9
  68. data/spec/neovim/api_spec.rb +2 -2
  69. data/spec/neovim/buffer_spec.rb +10 -6
  70. data/spec/neovim/client_info_spec.rb +77 -0
  71. data/spec/neovim/client_spec.rb +19 -12
  72. data/spec/neovim/connection_spec.rb +106 -0
  73. data/spec/neovim/current_spec.rb +13 -14
  74. data/spec/neovim/event_loop_spec.rb +48 -46
  75. data/spec/neovim/executable_spec.rb +2 -2
  76. data/spec/neovim/host/cli_spec.rb +94 -0
  77. data/spec/neovim/host/loader_spec.rb +18 -11
  78. data/spec/neovim/host_spec.rb +84 -92
  79. data/spec/neovim/line_range_spec.rb +17 -19
  80. data/spec/neovim/logging_spec.rb +3 -3
  81. data/spec/neovim/message_spec.rb +119 -0
  82. data/spec/neovim/plugin_spec.rb +34 -34
  83. data/spec/neovim/remote_object_spec.rb +1 -2
  84. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +8 -9
  85. data/spec/neovim/ruby_provider/object_ext_spec.rb +10 -0
  86. data/spec/neovim/ruby_provider/vim_spec.rb +5 -5
  87. data/spec/neovim/ruby_provider/window_ext_spec.rb +12 -15
  88. data/spec/neovim/session_spec.rb +20 -47
  89. data/spec/neovim/window_spec.rb +1 -2
  90. data/spec/neovim_spec.rb +28 -51
  91. data/spec/support.rb +27 -1
  92. metadata +83 -48
  93. data/.coveralls.yml +0 -1
  94. data/.gitmodules +0 -3
  95. data/.rspec +0 -1
  96. data/.travis.yml +0 -23
  97. data/appveyor.yml +0 -21
  98. data/bin/neovim-ruby-host +0 -18
  99. data/lib/neovim/event_loop/connection.rb +0 -78
  100. data/lib/neovim/event_loop/message_builder.rb +0 -127
  101. data/lib/neovim/event_loop/serializer.rb +0 -37
  102. data/spec/acceptance/runtime/rplugin.vim +0 -37
  103. data/spec/acceptance/runtime/vader.vim/autoload/vader.vim +0 -348
  104. data/spec/acceptance/runtime/vader.vim/autoload/vader/assert.vim +0 -116
  105. data/spec/acceptance/runtime/vader.vim/autoload/vader/helper.vim +0 -43
  106. data/spec/acceptance/runtime/vader.vim/autoload/vader/parser.vim +0 -179
  107. data/spec/acceptance/runtime/vader.vim/autoload/vader/syntax.vim +0 -73
  108. data/spec/acceptance/runtime/vader.vim/autoload/vader/window.vim +0 -205
  109. data/spec/acceptance/runtime/vader.vim/plugin/vader.vim +0 -37
  110. data/spec/acceptance_spec.rb +0 -82
  111. data/spec/neovim/event_loop/connection_spec.rb +0 -89
  112. data/spec/neovim/event_loop/message_builder_spec.rb +0 -105
  113. data/spec/neovim/event_loop/serializer_spec.rb +0 -63
@@ -1,21 +1,21 @@
1
1
  Neovim.plugin do |plug|
2
- plug.function(:RPluginFunctionArgs) do |nvim, *args|
3
- nvim.set_var("rplugin_function_args", args)
2
+ plug.function(:RPluginFunctionArgs, sync: true) do |nvim, *args|
3
+ args
4
4
  end
5
5
 
6
- plug.function(:RPluginFunctionRange, :range => true) do |nvim, *range|
7
- nvim.set_var("rplugin_function_range", range)
6
+ plug.function(:RPluginFunctionRange, range: true, sync: true) do |nvim, start, stop|
7
+ nvim.set_var("rplugin_function_range", [start, stop])
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", sync: true) do |nvim, to_eval|
11
+ to_eval.merge(b: 43)
12
12
  end
13
13
 
14
- plug.function(:RPluginFunctionSync, :sync => true) do |nvim|
15
- true
14
+ plug.function(:RPluginFunctionAsync) do |nvim|
15
+ nvim.set_var("rplugin_function_async", 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
@@ -1,20 +1,17 @@
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"
4
+ require "msgpack"
9
5
  require "neovim"
10
6
  require "pry"
11
7
  require "rubygems"
8
+ require "securerandom"
12
9
  require "stringio"
13
10
  require "timeout"
14
- require "securerandom"
15
- require "msgpack"
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|
@@ -25,17 +22,49 @@ RSpec.configure do |config|
25
22
  config.order = :random
26
23
  config.color = true
27
24
 
25
+ config.around(:example, :silence_thread_exceptions) do |spec|
26
+ if Thread.respond_to?(:report_on_exception)
27
+ original = Thread.report_on_exception
28
+
29
+ begin
30
+ Thread.report_on_exception = false
31
+ spec.run
32
+ ensure
33
+ Thread.report_on_exception = original
34
+ end
35
+ else
36
+ spec.run
37
+ end
38
+ end
39
+
28
40
  config.around(:example) do |spec|
29
41
  Support.setup_workspace
30
42
  timeout = spec.metadata.fetch(:timeout, 3)
31
43
 
32
44
  begin
33
- Timeout.timeout(timeout) { spec.run }
45
+ Timeout.timeout(timeout) do
46
+ Support.clean_persistent_client
47
+ spec.run
48
+ end
34
49
  ensure
35
50
  Support.teardown_workspace
36
51
  end
37
52
  end
38
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
+
39
68
  Kernel.srand config.seed
40
69
  end
41
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(
@@ -13,7 +13,7 @@ module Neovim
13
13
  {"name" => "nvim_func"},
14
14
  {"name" => "nvim_buf_func"},
15
15
  {"name" => "nvim_win_func"},
16
- {"name" => "nvim_tabpage_func"},
16
+ {"name" => "nvim_tabpage_func"}
17
17
  ]
18
18
  }
19
19
  ]
@@ -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,26 +2,33 @@ 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
10
- expect {
9
+ expect do
11
10
  client.set_option("makeprg", "rake")
12
- }.to change { client.evaluate("&makeprg") }.to("rake")
11
+ end.to change { client.evaluate("&makeprg") }.to("rake")
13
12
  end
14
13
 
15
14
  it "sets an option from a string" do
16
- expect {
15
+ expect do
17
16
  client.set_option("timeoutlen=0")
18
- }.to change { client.evaluate("&timeoutlen") }.to(0)
17
+ end.to change { client.evaluate("&timeoutlen") }.to(0)
19
18
  end
20
19
 
21
20
  it "sets a boolean option" do
22
- expect {
21
+ expect do
23
22
  client.set_option("expandtab")
24
- }.to change { client.evaluate("&expandtab") }.to(1)
23
+ end.to change { client.evaluate("&expandtab") }.to(1)
24
+ end
25
+ end
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)
25
32
  end
26
33
  end
27
34
 
@@ -45,15 +52,15 @@ module Neovim
45
52
  end
46
53
 
47
54
  it "raises exceptions for unknown methods" do
48
- expect {
55
+ expect do
49
56
  client.foobar
50
- }.to raise_error(NoMethodError)
57
+ end.to raise_error(NoMethodError)
51
58
  end
52
59
 
53
60
  it "raises exceptions for incorrect usage" do
54
- expect {
61
+ expect do
55
62
  client.strwidth("too", "many")
56
- }.to raise_error("Wrong number of arguments: expecting 1 but got 2")
63
+ end.to raise_error("Wrong number of arguments: expecting 1 but got 2")
57
64
  end
58
65
  end
59
66
 
@@ -0,0 +1,106 @@
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.new(nil_io, wr).write("some data").flush
11
+ data = rd.readpartial(1024)
12
+
13
+ expect(MessagePack.unpack(data)).to eq("some data")
14
+ end
15
+ end
16
+
17
+ describe "#flush" do
18
+ it "flushes writes to the underlying file descriptor" do
19
+ rd, wr = IO.pipe
20
+ connection = Connection.new(nil_io, wr).write("some data")
21
+
22
+ expect { rd.read_nonblock(16) }.to raise_error(IO::WaitReadable)
23
+
24
+ connection.flush
25
+
26
+ expect(rd.read_nonblock(16)).to eq(MessagePack.pack("some data"))
27
+ end
28
+
29
+ it "throws an exception when the file is closed" do
30
+ _, wr = IO.pipe
31
+ connection = Connection.new(nil_io, wr).write("some data")
32
+ wr.close
33
+
34
+ expect { connection.flush }.to raise_error(IOError)
35
+ end
36
+ end
37
+
38
+ describe "#read" do
39
+ it "reads msgpack from the underlying file descriptor" do
40
+ rd, wr = IO.pipe
41
+ wr.write(MessagePack.pack("some data"))
42
+ wr.flush
43
+
44
+ connection = Connection.new(rd, nil_io)
45
+ expect(connection.read).to eq("some data")
46
+ end
47
+
48
+ it "throws an exception when the file is closed" do
49
+ rd, wr = IO.pipe
50
+ wr.close
51
+
52
+ connection = Connection.new(rd, nil_io)
53
+ expect { connection.read }.to raise_error(EOFError)
54
+ end
55
+ end
56
+
57
+ describe "#register_type" do
58
+ it "registers a msgpack ext type" do
59
+ ext_class = Struct.new(:id) do
60
+ def self.from_msgpack_ext(data)
61
+ new(data.unpack("N")[0])
62
+ end
63
+
64
+ def to_msgpack_ext
65
+ [id].pack("C")
66
+ end
67
+ end
68
+
69
+ client_rd, server_wr = IO.pipe
70
+ _, client_wr = IO.pipe
71
+
72
+ connection = Connection.new(client_rd, client_wr)
73
+
74
+ connection.register_type(42) do |id|
75
+ ext_class.new(id)
76
+ end
77
+
78
+ factory = MessagePack::Factory.new
79
+ factory.register_type(42, ext_class)
80
+ obj = ext_class.new(1)
81
+ factory.packer(server_wr).write(obj).flush
82
+
83
+ expect(connection.read).to eq(obj)
84
+ end
85
+ end
86
+
87
+ describe "#close" do
88
+ it "closes IO handles" do
89
+ rd, wr = ::IO.pipe
90
+ Connection.new(rd, wr).close
91
+
92
+ expect(rd).to be_closed
93
+ expect(wr).to be_closed
94
+ end
95
+
96
+ it "kills spawned processes" do
97
+ io = ::IO.popen("cat", "rb+")
98
+ pid = io.pid
99
+ thr = Process.detach(pid)
100
+
101
+ Connection.new(io, nil_io).close
102
+ expect(thr.join.pid).to eq(pid)
103
+ end
104
+ end
105
+ end
106
+ end
@@ -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
@@ -35,9 +34,9 @@ module Neovim
35
34
  initial_index = current.buffer.index
36
35
  client.command("vnew")
37
36
 
38
- expect {
37
+ expect do
39
38
  current.buffer = initial_index
40
- }.to change { current.buffer.index }.to(initial_index)
39
+ end.to change { current.buffer.index }.to(initial_index)
41
40
  end
42
41
 
43
42
  it "sets the current buffer from a Buffer" do
@@ -45,9 +44,9 @@ module Neovim
45
44
  client.command("vnew")
46
45
  b1 = current.buffer
47
46
 
48
- expect {
47
+ expect do
49
48
  current.buffer = b0
50
- }.to change { current.buffer }.from(b1).to(b0)
49
+ end.to change { current.buffer }.from(b1).to(b0)
51
50
  end
52
51
 
53
52
  it "returns an integer" do
@@ -72,9 +71,9 @@ module Neovim
72
71
  start_index = current.window.index
73
72
  client.command("vsp")
74
73
 
75
- expect {
74
+ expect do
76
75
  current.window = start_index
77
- }.to change { current.window.index }.to(start_index)
76
+ end.to change { current.window.index }.to(start_index)
78
77
  end
79
78
 
80
79
  it "sets the current window from a Window" do
@@ -82,9 +81,9 @@ module Neovim
82
81
  client.command("vsp")
83
82
  w1 = current.window
84
83
 
85
- expect {
84
+ expect do
86
85
  current.window = w0
87
- }.to change { current.window }.from(w1).to(w0)
86
+ end.to change { current.window }.from(w1).to(w0)
88
87
  end
89
88
 
90
89
  it "returns an integer" do
@@ -110,9 +109,9 @@ module Neovim
110
109
  client.command("tabnew")
111
110
  expect(current.tabpage.index).not_to eq(initial_index)
112
111
 
113
- expect {
112
+ expect do
114
113
  current.tabpage = initial_index
115
- }.to change { current.tabpage.index }.to(initial_index)
114
+ end.to change { current.tabpage.index }.to(initial_index)
116
115
  end
117
116
 
118
117
  it "sets the current tabpage from a Tabpage" do
@@ -120,9 +119,9 @@ module Neovim
120
119
  client.command("tabnew")
121
120
  tp1 = current.tabpage
122
121
 
123
- expect {
122
+ expect do
124
123
  current.tabpage = tp0
125
- }.to change { current.tabpage }.from(tp1).to(tp0)
124
+ end.to change { current.tabpage }.from(tp1).to(tp0)
126
125
  end
127
126
 
128
127
  it "returns an integer" do