neovim 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +9 -3
  4. data/CODE_OF_CONDUCT.md +46 -0
  5. data/README.md +2 -2
  6. data/Rakefile +6 -6
  7. data/lib/neovim.rb +8 -7
  8. data/lib/neovim/api.rb +87 -0
  9. data/lib/neovim/buffer.rb +7 -1
  10. data/lib/neovim/client.rb +32 -6
  11. data/lib/neovim/event_loop.rb +114 -0
  12. data/lib/neovim/event_loop/connection.rb +78 -0
  13. data/lib/neovim/event_loop/message_builder.rb +127 -0
  14. data/lib/neovim/event_loop/serializer.rb +37 -0
  15. data/lib/neovim/host.rb +28 -28
  16. data/lib/neovim/logging.rb +41 -19
  17. data/lib/neovim/plugin/dsl.rb +6 -6
  18. data/lib/neovim/remote_object.rb +2 -2
  19. data/lib/neovim/ruby_provider.rb +8 -6
  20. data/lib/neovim/ruby_provider/vim.rb +2 -2
  21. data/lib/neovim/session.rb +42 -79
  22. data/lib/neovim/tabpage.rb +1 -1
  23. data/lib/neovim/version.rb +1 -1
  24. data/lib/neovim/window.rb +1 -1
  25. data/script/dump_api +4 -2
  26. data/script/generate_docs +2 -1
  27. data/spec/{integration → acceptance}/rplugin_autocmd_spec.vim +1 -1
  28. data/spec/{integration → acceptance}/rplugin_command_spec.vim +6 -2
  29. data/spec/{integration → acceptance}/rplugin_function_spec.vim +5 -2
  30. data/spec/{integration → acceptance}/ruby_spec.vim +18 -0
  31. data/spec/{integration → acceptance}/rubydo_spec.vim +0 -0
  32. data/spec/{integration → acceptance}/rubyfile/call_foo.rb +0 -0
  33. data/spec/{integration → acceptance}/rubyfile/curbuf_ivar_get.rb +0 -0
  34. data/spec/{integration → acceptance}/rubyfile/curbuf_ivar_set.rb +0 -0
  35. data/spec/{integration → acceptance}/rubyfile/define_foo.rb +0 -0
  36. data/spec/acceptance/rubyfile/nested.rb +1 -0
  37. data/spec/acceptance/rubyfile/nested_inner.rb +1 -0
  38. data/spec/{integration → acceptance}/rubyfile/raise_standard_error.rb +0 -0
  39. data/spec/{integration → acceptance}/rubyfile/raise_syntax_error.rb +0 -0
  40. data/spec/acceptance/rubyfile/ruby_interface.rb +8 -0
  41. data/spec/{integration → acceptance}/rubyfile/set_pwd_after.rb +0 -0
  42. data/spec/{integration → acceptance}/rubyfile/set_pwd_before.rb +0 -0
  43. data/spec/{integration → acceptance}/rubyfile_spec.vim +9 -0
  44. data/spec/acceptance/runtime/init.vim +8 -0
  45. data/spec/acceptance/runtime/rplugin.vim +37 -0
  46. data/spec/{integration → acceptance}/runtime/rplugin/ruby/autocmds.rb +1 -1
  47. data/spec/{integration → acceptance}/runtime/rplugin/ruby/commands.rb +9 -1
  48. data/spec/{integration → acceptance}/runtime/rplugin/ruby/functions.rb +9 -1
  49. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader.vim +0 -0
  50. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/assert.vim +0 -0
  51. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/helper.vim +0 -0
  52. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/parser.vim +0 -0
  53. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/syntax.vim +0 -0
  54. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/window.vim +0 -0
  55. data/spec/{integration → acceptance}/runtime/vader.vim/plugin/vader.vim +0 -0
  56. data/spec/acceptance_spec.rb +74 -0
  57. data/spec/helper.rb +2 -32
  58. data/spec/neovim/api_spec.rb +59 -0
  59. data/spec/neovim/buffer_spec.rb +161 -2
  60. data/spec/neovim/client_spec.rb +18 -4
  61. data/spec/neovim/event_loop/connection_spec.rb +63 -0
  62. data/spec/neovim/event_loop/message_builder_spec.rb +105 -0
  63. data/spec/neovim/event_loop/serializer_spec.rb +63 -0
  64. data/spec/neovim/event_loop_spec.rb +81 -0
  65. data/spec/neovim/host/loader_spec.rb +0 -1
  66. data/spec/neovim/host_spec.rb +130 -161
  67. data/spec/neovim/logging_spec.rb +77 -5
  68. data/spec/neovim/session_spec.rb +54 -127
  69. data/spec/neovim/window_spec.rb +46 -0
  70. metadata +81 -81
  71. data/lib/neovim/session/api.rb +0 -95
  72. data/lib/neovim/session/event_loop.rb +0 -100
  73. data/lib/neovim/session/notification.rb +0 -19
  74. data/lib/neovim/session/request.rb +0 -31
  75. data/lib/neovim/session/rpc.rb +0 -95
  76. data/lib/neovim/session/serializer.rb +0 -62
  77. data/spec/integration/ruby_buffer_spec.rb +0 -151
  78. data/spec/integration/ruby_vim_spec.rb +0 -27
  79. data/spec/integration/ruby_window_spec.rb +0 -56
  80. data/spec/integration/runtime/init.vim +0 -9
  81. data/spec/integration_spec.rb +0 -119
  82. data/spec/neovim/session/api_spec.rb +0 -70
  83. data/spec/neovim/session/event_loop_spec.rb +0 -152
  84. data/spec/neovim/session/notification_spec.rb +0 -20
  85. data/spec/neovim/session/request_spec.rb +0 -36
  86. data/spec/neovim/session/rpc_spec.rb +0 -120
  87. data/spec/neovim/session/serializer_spec.rb +0 -62
@@ -0,0 +1,8 @@
1
+ let s:lib_path = getcwd() . "/../../lib/"
2
+ let s:bin_path = getcwd() . "/../../bin/neovim-ruby-host"
3
+ let g:ruby_host_prog = printf("ruby -I %s %s", s:lib_path, s:bin_path)
4
+
5
+ ruby require "rspec/expectations"
6
+ ruby include ::RSpec::Matchers.dup
7
+
8
+ set rtp=./runtime,./runtime/vader.vim,$VIMRUNTIME
@@ -0,0 +1,37 @@
1
+ " python3 plugins
2
+
3
+
4
+ " ruby plugins
5
+ call remote#host#RegisterPlugin('ruby', './runtime/rplugin/ruby/autocmds.rb', [
6
+ \ {'sync': v:false, 'name': 'BufEnter', 'type': 'autocmd', 'opts': {'pattern': '*.rb'}},
7
+ \ {'sync': v:false, 'name': 'BufEnter', 'type': 'autocmd', 'opts': {'pattern': '*.c', 'eval': 'g:to_eval'}},
8
+ \ ])
9
+ call remote#host#RegisterPlugin('ruby', './runtime/rplugin/ruby/commands.rb', [
10
+ \ {'sync': v:false, 'name': 'RPluginCommandNargs0', 'type': 'command', 'opts': {}},
11
+ \ {'sync': v:false, 'name': 'RPluginCommandNargs1', 'type': 'command', 'opts': {'nargs': 1}},
12
+ \ {'sync': v:false, 'name': 'RPluginCommandNargsN', 'type': 'command', 'opts': {'nargs': '*'}},
13
+ \ {'sync': v:false, 'name': 'RPluginCommandNargsQ', 'type': 'command', 'opts': {'nargs': '?'}},
14
+ \ {'sync': v:false, 'name': 'RPluginCommandNargsP', 'type': 'command', 'opts': {'nargs': '+'}},
15
+ \ {'sync': v:false, 'name': 'RPluginCommandRange', 'type': 'command', 'opts': {'range': ''}},
16
+ \ {'sync': v:false, 'name': 'RPluginCommandRangeP', 'type': 'command', 'opts': {'range': '%'}},
17
+ \ {'sync': v:false, 'name': 'RPluginCommandRangeN', 'type': 'command', 'opts': {'range': '1'}},
18
+ \ {'sync': v:false, 'name': 'RPluginCommandCountN', 'type': 'command', 'opts': {'count': 1}},
19
+ \ {'sync': v:false, 'name': 'RPluginCommandBang', 'type': 'command', 'opts': {'bang': ''}},
20
+ \ {'sync': v:false, 'name': 'RPluginCommandRegister', 'type': 'command', 'opts': {'register': ''}},
21
+ \ {'sync': v:false, 'name': 'RPluginCommandCompletion', 'type': 'command', 'opts': {'complete': 'buffer'}},
22
+ \ {'sync': v:false, 'name': 'RPluginCommandEval', 'type': 'command', 'opts': {'eval': 'g:to_eval'}},
23
+ \ {'sync': v:true, 'name': 'RPluginCommandSync', 'type': 'command', 'opts': {}},
24
+ \ {'sync': v:true, 'name': 'RPluginCommandRecursive', 'type': 'command', 'opts': {'nargs': 1}},
25
+ \ ])
26
+ call remote#host#RegisterPlugin('ruby', './runtime/rplugin/ruby/functions.rb', [
27
+ \ {'sync': v:false, 'name': 'RPluginFunctionArgs', 'type': 'function', 'opts': {}},
28
+ \ {'sync': v:false, 'name': 'RPluginFunctionRange', 'type': 'function', 'opts': {'range': ''}},
29
+ \ {'sync': v:false, 'name': 'RPluginFunctionEval', 'type': 'function', 'opts': {'eval': 'g:to_eval'}},
30
+ \ {'sync': v:true, 'name': 'RPluginFunctionSync', 'type': 'function', 'opts': {}},
31
+ \ {'sync': v:true, 'name': 'RPluginFunctionRecursive', 'type': 'function', 'opts': {'nargs': 1}},
32
+ \ ])
33
+
34
+
35
+ " python plugins
36
+
37
+
@@ -4,6 +4,6 @@ Neovim.plugin do |plug|
4
4
  end
5
5
 
6
6
  plug.autocmd(:BufEnter, :pattern => "*.c", :eval => "g:to_eval") do |nvim, to_eval|
7
- nvim.set_var("rplugin_autocmd_BufEnter_eval", to_eval)
7
+ nvim.set_var("rplugin_autocmd_BufEnter_eval", to_eval.merge(:b => 43))
8
8
  end
9
9
  end
@@ -50,10 +50,18 @@ Neovim.plugin do |plug|
50
50
  end
51
51
 
52
52
  plug.command(:RPluginCommandEval, :eval => "g:to_eval") do |nvim, to_eval|
53
- nvim.set_var("rplugin_command_eval", to_eval)
53
+ nvim.set_var("rplugin_command_eval", to_eval.merge(:b => 43))
54
54
  end
55
55
 
56
56
  plug.command(:RPluginCommandSync, :sync => true) do |nvim|
57
57
  nvim.set_var("rplugin_command_sync", true)
58
58
  end
59
+
60
+ plug.command(:RPluginCommandRecursive, :sync => true, :nargs => 1) do |nvim, n|
61
+ if Integer(n) >= 10
62
+ nvim.set_var("rplugin_command_recursive", n)
63
+ else
64
+ nvim.command("RPluginCommandRecursive #{n.succ}")
65
+ end
66
+ end
59
67
  end
@@ -8,10 +8,18 @@ Neovim.plugin do |plug|
8
8
  end
9
9
 
10
10
  plug.function(:RPluginFunctionEval, :eval => "g:to_eval") do |nvim, to_eval|
11
- nvim.set_var("rplugin_function_eval", to_eval)
11
+ nvim.set_var("rplugin_function_eval", to_eval.merge(:b => 43))
12
12
  end
13
13
 
14
14
  plug.function(:RPluginFunctionSync, :sync => true) do |nvim|
15
15
  true
16
16
  end
17
+
18
+ plug.function(:RPluginFunctionRecursive, :sync => true, :nargs => 1) do |nvim, n|
19
+ if n >= 10
20
+ n
21
+ else
22
+ nvim.evaluate("RPluginFunctionRecursive(#{n + 1})")
23
+ end
24
+ end
17
25
  end
@@ -0,0 +1,74 @@
1
+ ENV.delete("VIM")
2
+ ENV.delete("VIMRUNTIME")
3
+
4
+ require "json"
5
+ require "net/http"
6
+ require "open-uri"
7
+ require "tempfile"
8
+
9
+ RSpec.describe "Acceptance", :timeout => 10 do
10
+ let(:root) { File.expand_path("../acceptance", __FILE__) }
11
+ let(:init) { File.join(root, "runtime/init.vim") }
12
+ let(:manifest) { File.join(root, "runtime/rplugin.vim") }
13
+
14
+ around do |spec|
15
+ Dir.chdir(root) { spec.run }
16
+ end
17
+
18
+ describe "Vim compatibility" do
19
+ ["ruby", "rubyfile", "rubydo"].each do |feature|
20
+ specify ":#{feature}" do
21
+ run_vader("#{feature}_spec.vim") do |status, output|
22
+ expect(status).to be_success, lambda { output.read }
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "Remote plugin DSL" do
29
+ ["command", "function", "autocmd"].each do |feature|
30
+ specify "##{feature}" do
31
+ run_vader("rplugin_#{feature}_spec.vim") do |status, output|
32
+ expect(status).to be_success, lambda { output.read }
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "Generated documentation" do
39
+ it "is up to date" do
40
+ begin
41
+ url = "https://api.github.com/repos/neovim/neovim/releases/latest"
42
+ response = open(url) { |json| JSON.load(json) }
43
+
44
+ client_file = File.read(
45
+ File.expand_path("../../lib/neovim/client.rb", __FILE__)
46
+ )
47
+ docs_version = client_file[
48
+ /The methods documented here were generated using (.+)$/,
49
+ 1
50
+ ]
51
+
52
+ expect(docs_version).to eq(response["name"])
53
+ rescue SocketError, OpenURI::HTTPError => e
54
+ skip "Skipping: #{e}"
55
+ end
56
+ end
57
+ end
58
+
59
+ def run_nvim(env, *opts)
60
+ nvim = env.fetch("NVIM_EXECUTABLE", "nvim")
61
+ system(env, nvim, "--headless", "-n", "-u", init, *opts)
62
+ end
63
+
64
+ def run_vader(test_path)
65
+ Tempfile.open("vader.out") do |out|
66
+ run_nvim(
67
+ {"NVIM_RPLUGIN_MANIFEST" => manifest, "VADER_OUTPUT_FILE" => out.path},
68
+ "-c", "Vader! #{test_path}"
69
+ )
70
+
71
+ yield $?, out
72
+ end
73
+ end
74
+ end
@@ -11,6 +11,8 @@ require "pry"
11
11
  require "rubygems"
12
12
  require "stringio"
13
13
  require "timeout"
14
+ require "securerandom"
15
+ require "msgpack"
14
16
 
15
17
  require File.expand_path("../support.rb", __FILE__)
16
18
 
@@ -22,7 +24,6 @@ RSpec.configure do |config|
22
24
  config.disable_monkey_patching!
23
25
  config.order = :random
24
26
  config.color = true
25
- config.filter_run_excluding :embedded
26
27
 
27
28
  config.around(:example) do |spec|
28
29
  Support.setup_workspace
@@ -35,37 +36,6 @@ RSpec.configure do |config|
35
36
  end
36
37
  end
37
38
 
38
- config.around(:example, :silence_warnings) do |spec|
39
- old_logger = Neovim.logger
40
- log_target = StringIO.new
41
- Neovim.logger = Logger.new(log_target)
42
- Neovim.logger.level = Logger::WARN
43
-
44
- begin
45
- spec.run
46
-
47
- expect(log_target.string).not_to be_empty,
48
- ":silence_warnings used but nothing logged at WARN level"
49
- ensure
50
- Neovim.logger = old_logger
51
- end
52
- end
53
-
54
- config.before(:example, :nvim_version) do |spec|
55
- req = Gem::Requirement.new(spec.metadata[:nvim_version])
56
-
57
- begin
58
- nvim_vrs = Support.nvim_version
59
- vrs = Gem::Version.new(nvim_vrs)
60
- rescue ArgumentError
61
- vrs = Gem::Version.new(nvim_vrs.gsub("-", "."))
62
- end
63
-
64
- unless req.satisfied_by?(vrs.release)
65
- pending "Pending: Installed nvim (#{vrs}) doesn't satisfy '#{req}'."
66
- end
67
- end
68
-
69
39
  Kernel.srand config.seed
70
40
  end
71
41
 
@@ -0,0 +1,59 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe API do
5
+ let(:client) { Neovim.attach_child(Support.child_argv) }
6
+
7
+ let(:api) do
8
+ API.new(
9
+ [
10
+ nil,
11
+ {
12
+ "functions" => [
13
+ {"name" => "nvim_func"},
14
+ {"name" => "nvim_buf_func"},
15
+ {"name" => "nvim_win_func"},
16
+ {"name" => "nvim_tabpage_func"},
17
+ ]
18
+ }
19
+ ]
20
+ )
21
+ end
22
+
23
+ describe "#functions_for_object_method" do
24
+ it "returns relevant functions" do
25
+ function = api.function_for_object_method(client, :func)
26
+ expect(function.name).to eq("nvim_func")
27
+
28
+ function = api.function_for_object_method(client.get_current_buf, :func)
29
+ expect(function.name).to eq("nvim_buf_func")
30
+
31
+ function = api.function_for_object_method(client.get_current_win, :func)
32
+ expect(function.name).to eq("nvim_win_func")
33
+
34
+ function = api.function_for_object_method(client.get_current_tabpage, :func)
35
+ expect(function.name).to eq("nvim_tabpage_func")
36
+ end
37
+ end
38
+
39
+ describe "#functions_for_object" do
40
+ it "returns relevant functions" do
41
+ functions = api.functions_for_object(client)
42
+ expect(functions.size).to be(1)
43
+ expect(functions.first.name).to eq("nvim_func")
44
+
45
+ functions = api.functions_for_object(client.get_current_buf)
46
+ expect(functions.size).to be(1)
47
+ expect(functions.first.name).to eq("nvim_buf_func")
48
+
49
+ functions = api.functions_for_object(client.get_current_win)
50
+ expect(functions.size).to be(1)
51
+ expect(functions.first.name).to eq("nvim_win_func")
52
+
53
+ functions = api.functions_for_object(client.get_current_tabpage)
54
+ expect(functions.size).to be(1)
55
+ expect(functions.first.name).to eq("nvim_tabpage_func")
56
+ end
57
+ end
58
+ end
59
+ end
@@ -4,6 +4,13 @@ module Neovim
4
4
  RSpec.describe Buffer do
5
5
  let(:client) { Neovim.attach_child(Support.child_argv) }
6
6
  let(:buffer) { client.current.buffer }
7
+
8
+ before do
9
+ client.command("normal ione")
10
+ client.command("normal otwo")
11
+ client.command("normal gg")
12
+ end
13
+
7
14
  after { client.shutdown }
8
15
 
9
16
  describe "#lines" do
@@ -14,8 +21,160 @@ module Neovim
14
21
 
15
22
  describe "#lines=" do
16
23
  it "updates the buffer's lines" do
17
- buffer.lines = ["one", "two"]
18
- expect(buffer.lines.to_a).to eq(["one", "two"])
24
+ expect do
25
+ buffer.lines = ["two", "three"]
26
+ end.to change { buffer.lines.to_a }.to(["two", "three"])
27
+ end
28
+ end
29
+
30
+ describe "#set_name", "#name" do
31
+ it "updates the buffer name" do
32
+ expect do
33
+ buffer.set_name("test_buf")
34
+ end.to change { buffer.name }.to(/test_buf$/)
35
+ end
36
+ end
37
+
38
+ describe "#number" do
39
+ 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)
43
+ end
44
+ end
45
+
46
+ describe "#count" do
47
+ it "returns the number of lines" do
48
+ expect do
49
+ buffer.append(0, "zero")
50
+ end.to change { buffer.count }.from(2).to(3)
51
+ end
52
+ end
53
+
54
+ describe "#length" do
55
+ it "returns the number of lines" do
56
+ expect do
57
+ buffer.append(0, "zero")
58
+ end.to change { buffer.length }.from(2).to(3)
59
+ end
60
+ end
61
+
62
+ describe "#[]" do
63
+ it "returns the line at the line number" do
64
+ expect(buffer[1]).to eq("one")
65
+ end
66
+
67
+ it "raises on out of bounds" do
68
+ expect do
69
+ buffer[-1]
70
+ end.to raise_error(/out of bounds/)
71
+
72
+ expect do
73
+ buffer[4]
74
+ end.to raise_error(/out of bounds/)
75
+ end
76
+ end
77
+
78
+ describe "#[]=" do
79
+ it "sets the line at the line number" do
80
+ expect do
81
+ buffer[1] = "first"
82
+ end.to change { buffer[1] }.from("one").to("first")
83
+ end
84
+
85
+ it "raises on out of bounds" do
86
+ expect do
87
+ buffer[4] = "line"
88
+ end.to raise_error(/out of bounds/)
89
+
90
+ expect do
91
+ buffer[-1] = "line"
92
+ end.to raise_error(/out of bounds/)
93
+ end
94
+ end
95
+
96
+ describe "#delete" do
97
+ it "deletes at the line number" do
98
+ expect do
99
+ buffer.delete(2)
100
+ end.to change { buffer.lines.to_a }.to(["one"])
101
+ end
102
+
103
+ it "raises on out of bounds" do
104
+ expect do
105
+ buffer.delete(-1)
106
+ end.to raise_error(/out of bounds/)
107
+
108
+ expect do
109
+ buffer.delete(4)
110
+ end.to raise_error(/out of bounds/)
111
+ end
112
+ end
113
+
114
+ describe "#append" do
115
+ it "appends after the line" do
116
+ expect do
117
+ buffer.append(2, "last")
118
+ end.to change { buffer.lines.to_a }.to(["one", "two", "last"])
119
+ end
120
+
121
+ it "inserts before the first line" do
122
+ expect do
123
+ buffer.append(0, "first")
124
+ end.to change { buffer.lines.to_a }.to(["first", "one", "two"])
125
+ end
126
+
127
+ it "doesn't move the cursor" do
128
+ expect do
129
+ buffer.append(0, "first")
130
+ end.not_to change { client.get_current_win.cursor }
131
+ end
132
+
133
+ it "raises on out of bounds" do
134
+ expect do
135
+ buffer.append(-1, "line")
136
+ end.to raise_error(/out of bounds/)
137
+
138
+ expect do
139
+ buffer.append(4, "line")
140
+ end.to raise_error(/out of bounds/)
141
+ end
142
+ end
143
+
144
+ describe "#line_number" do
145
+ it "returns the current line number" do
146
+ expect do
147
+ client.command("normal j")
148
+ end.to change { buffer.line_number }.from(1).to(2)
149
+ end
150
+
151
+ it "returns nil on inactive buffers" do
152
+ expect do
153
+ client.command("new")
154
+ end.to change { buffer.line_number }.from(1).to(nil)
155
+ end
156
+ end
157
+
158
+ describe "#line" do
159
+ before { buffer.lines = ["one", "two"] }
160
+
161
+ it "returns the current line" do
162
+ expect do
163
+ client.command("normal j")
164
+ end.to change { buffer.line }.from("one").to("two")
165
+ end
166
+
167
+ it "returns nil for inactive buffers" do
168
+ client.command("new")
169
+ expect(buffer.line).to eq(nil)
170
+ end
171
+ end
172
+
173
+ describe "#line=" do
174
+ it "updates the current line" do
175
+ expect do
176
+ buffer.line = "first"
177
+ end.to change { buffer.line }.to("first")
19
178
  end
20
179
  end
21
180
  end