neovim 0.0.5 → 0.0.6

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -2
  3. data/CHANGELOG.md +11 -0
  4. data/README.md +15 -4
  5. data/Rakefile +64 -4
  6. data/bin/j2mp +8 -0
  7. data/bin/mp2j +8 -0
  8. data/lib/neovim.rb +100 -17
  9. data/lib/neovim/api.rb +84 -0
  10. data/lib/neovim/async_session.rb +74 -21
  11. data/lib/neovim/buffer.rb +111 -4
  12. data/lib/neovim/client.rb +175 -4
  13. data/lib/neovim/current.rb +19 -8
  14. data/lib/neovim/event_loop.rb +55 -10
  15. data/lib/neovim/host.rb +21 -8
  16. data/lib/neovim/line_range.rb +55 -15
  17. data/lib/neovim/logging.rb +4 -0
  18. data/lib/neovim/manifest.rb +11 -3
  19. data/lib/neovim/msgpack_stream.rb +53 -19
  20. data/lib/neovim/notification.rb +2 -0
  21. data/lib/neovim/plugin.rb +12 -87
  22. data/lib/neovim/plugin/dsl.rb +81 -0
  23. data/lib/neovim/plugin/handler.rb +43 -0
  24. data/lib/neovim/remote_object.rb +64 -0
  25. data/lib/neovim/request.rb +4 -2
  26. data/lib/neovim/session.rb +167 -16
  27. data/lib/neovim/tabpage.rb +24 -2
  28. data/lib/neovim/version.rb +1 -1
  29. data/lib/neovim/window.rb +92 -2
  30. data/neovim.gemspec +1 -1
  31. data/spec/acceptance/neovim-ruby-host_spec.rb +16 -8
  32. data/spec/helper.rb +11 -3
  33. data/spec/neovim/api_spec.rb +40 -0
  34. data/spec/neovim/async_session_spec.rb +19 -25
  35. data/spec/neovim/current_spec.rb +64 -4
  36. data/spec/neovim/event_loop_spec.rb +18 -27
  37. data/spec/neovim/host_spec.rb +20 -1
  38. data/spec/neovim/manifest_spec.rb +0 -2
  39. data/spec/neovim/msgpack_stream_spec.rb +5 -6
  40. data/spec/neovim/{object_spec.rb → remote_object_spec.rb} +1 -4
  41. data/spec/neovim/session_spec.rb +18 -26
  42. data/spec/neovim_spec.rb +2 -3
  43. data/spec/support.rb +5 -5
  44. metadata +13 -6
  45. data/lib/neovim/api_info.rb +0 -27
  46. data/lib/neovim/object.rb +0 -40
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.executables = ["neovim-ruby-host"]
17
17
  spec.test_files = spec.files.grep(%r{^spec/})
18
18
  spec.require_paths = ["lib"]
19
19
 
@@ -1,14 +1,17 @@
1
1
  require "helper"
2
- require "tmpdir"
3
2
 
4
3
  RSpec.describe "neovim-ruby-host" do
5
4
  it "loads and runs plugins from Ruby source files" do
6
5
  plugin1_path = Support.file_path("plugin1.rb")
7
6
  File.write(plugin1_path, <<-RUBY)
8
7
  Neovim.plugin do |plug|
9
- plug.command(:SyncAdd, :args => 2, :sync => true) do |nvim, x, y|
8
+ plug.function(:SyncAdd, :args => 2, :sync => true) do |nvim, x, y|
10
9
  x + y
11
10
  end
11
+
12
+ plug.autocmd(:BufEnter, :pattern => "*.rb") do |nvim|
13
+ nvim.current.line = "Ruby file, eh?"
14
+ end
12
15
  end
13
16
  RUBY
14
17
 
@@ -27,19 +30,24 @@ RSpec.describe "neovim-ruby-host" do
27
30
  nvim.command("let host = rpcstart('#{host_exe}', ['#{plugin1_path}', '#{plugin2_path}'])")
28
31
 
29
32
  expect(nvim.eval("rpcrequest(host, 'poll')")).to eq("ok")
30
- expect(nvim.eval("rpcrequest(host, '#{plugin1_path}:command:SyncAdd', [1, 2])")).to eq(3)
33
+ expect(nvim.eval("rpcrequest(host, '#{plugin1_path}:function:SyncAdd', [1, 2])")).to eq(3)
34
+
35
+ expect {
36
+ nvim.command("call rpcnotify(host, '#{plugin1_path}:autocmd:BufEnter:*.rb')")
37
+ sleep 0.1
38
+ }.to change { nvim.current.buffer.lines.to_a }.from([""]).to(["Ruby file, eh?"])
31
39
 
32
40
  expect {
33
- nvim.eval("rpcnotify(host, '#{plugin2_path}:command:AsyncSetLine', ['foo'])")
34
- nvim.eval("rpcrequest(host, 'poll')")
35
- }.to change { nvim.current.buffer.lines.to_a }.from([""]).to(["foo"])
41
+ nvim.command("call rpcnotify(host, '#{plugin2_path}:command:AsyncSetLine', ['foo'])")
42
+ sleep 0.1
43
+ }.to change { nvim.current.buffer.lines.to_a }.from(["Ruby file, eh?"]).to(["foo"])
36
44
 
37
45
  expect {
38
- nvim.eval("rpcnotify(host, 'Unknown')")
46
+ nvim.command("call rpcnotify(host, 'Unknown')")
39
47
  }.not_to raise_error
40
48
 
41
49
  expect {
42
- nvim.eval("call rpcrequest(host, 'Unknown')")
50
+ nvim.command("call rpcrequest(host, 'Unknown')")
43
51
  }.to raise_error(ArgumentError)
44
52
  end
45
53
  end
@@ -13,7 +13,14 @@ end
13
13
 
14
14
  Thread.abort_on_exception = true
15
15
 
16
- ENV["NVIM_EXECUTABLE"] = File.expand_path("../../vendor/neovim/build/bin/nvim", __FILE__)
16
+ nvim_bin = File.expand_path("../../vendor/neovim/build/bin/nvim", __FILE__)
17
+
18
+ if File.exists?(nvim_bin)
19
+ ENV["NVIM_EXECUTABLE"] = nvim_bin
20
+ else
21
+ warn("Can't find vendored `nvim` executable. Build it with `rake neovim:build`")
22
+ exit(1)
23
+ end
17
24
 
18
25
  Neovim.logger = Logger.new(STDERR).tap do |logger|
19
26
  logger.level = ENV.fetch("NVIM_RUBY_LOG_LEVEL", Logger::WARN).to_i
@@ -26,15 +33,16 @@ RSpec.configure do |config|
26
33
 
27
34
  config.disable_monkey_patching!
28
35
  config.order = :random
36
+ config.color = true
29
37
 
30
38
  Kernel.srand config.seed
31
39
 
32
40
  config.around(:example) do |spec|
33
- Support.clean_workspace
41
+ Support.setup_workspace
34
42
  Timeout.timeout(2) { spec.run }
35
43
  end
36
44
 
37
45
  config.after(:suite) do
38
- Support.remove_workspace
46
+ Support.teardown_workspace
39
47
  end
40
48
  end
@@ -0,0 +1,40 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ RSpec.describe API do
5
+ describe ".null" do
6
+ it "returns an empty API object" do
7
+ api = API.null
8
+
9
+ expect(api.types).to eq([])
10
+ expect(api.functions).to eq([])
11
+ end
12
+ end
13
+
14
+ describe "#function" do
15
+ it "returns a corresponding Function object" do
16
+ api = API.new(
17
+ [nil, {"functions" => [
18
+ {"name" => "vim_strwidth", "async" => false}
19
+ ]}]
20
+ )
21
+
22
+ function = api.function("vim_strwidth")
23
+ expect(function).to be_a(API::Function)
24
+ expect(function.name).to eq("vim_strwidth")
25
+ expect(function.async).to be(false)
26
+ end
27
+ end
28
+
29
+ describe "#functions_with_prefix" do
30
+ it "returns relevant functions" do
31
+ api = API.new(
32
+ [nil, {"functions" => [{"name" => "vim_strwidth"}]}]
33
+ )
34
+
35
+ functions = api.functions_with_prefix("vim_")
36
+ expect(functions.first.name).to eq("vim_strwidth")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -5,7 +5,7 @@ module Neovim
5
5
  shared_context "async session behavior" do
6
6
  it "receives requests" do
7
7
  stream = MsgpackStream.new(event_loop)
8
- async = AsyncSession.new(stream)
8
+ async_session = AsyncSession.new(stream)
9
9
 
10
10
  server_thread = Thread.new do
11
11
  client = server.accept
@@ -15,16 +15,12 @@ module Neovim
15
15
  ))
16
16
  end
17
17
 
18
- req_cb = Proc.new do |request|
19
- Fiber.yield(request)
18
+ request = nil
19
+ async_session.run do |msg|
20
+ request = msg
21
+ async_session.shutdown
20
22
  end
21
23
 
22
- fiber = Fiber.new do
23
- async.run(req_cb)
24
- end
25
-
26
- request = fiber.resume
27
-
28
24
  server_thread.join
29
25
 
30
26
  expect(request).to be_a(Request)
@@ -34,7 +30,7 @@ module Neovim
34
30
 
35
31
  it "receives notifications" do
36
32
  stream = MsgpackStream.new(event_loop)
37
- async = AsyncSession.new(stream)
33
+ async_session = AsyncSession.new(stream)
38
34
 
39
35
  server_thread = Thread.new do
40
36
  client = server.accept
@@ -44,16 +40,12 @@ module Neovim
44
40
  ))
45
41
  end
46
42
 
47
- not_cb = Proc.new do |notification|
48
- Fiber.yield(notification)
43
+ notification = nil
44
+ async_session.run do |message|
45
+ notification = message
46
+ async_session.shutdown
49
47
  end
50
48
 
51
- fiber = Fiber.new do
52
- async.run(nil, not_cb)
53
- end
54
-
55
- notification = fiber.resume
56
-
57
49
  server_thread.join
58
50
 
59
51
  expect(notification).to be_a(Notification)
@@ -63,7 +55,7 @@ module Neovim
63
55
 
64
56
  it "receives responses to requests" do
65
57
  stream = MsgpackStream.new(event_loop)
66
- async = AsyncSession.new(stream)
58
+ async_session = AsyncSession.new(stream)
67
59
  messages = []
68
60
 
69
61
  server_thread = Thread.new do
@@ -75,15 +67,17 @@ module Neovim
75
67
  ))
76
68
  end
77
69
 
78
- fiber = Fiber.new do
79
- async.request("func", 1, 2, 3) do |error, result|
80
- Fiber.yield(error, result)
81
- end.run
82
- end
70
+ error, result = nil
71
+ async_session.request("func", 1, 2, 3) do |err, res|
72
+ error, result = err, res
73
+ async_session.shutdown
74
+ end.run
83
75
 
84
- expect(fiber.resume).to eq(["error", "result"])
76
+ expect(error).to eq("error")
77
+ expect(result).to eq("result")
85
78
 
86
79
  server_thread.join
80
+ async_session.shutdown
87
81
 
88
82
  expect(messages).to eq(
89
83
  [MessagePack.pack([0, 0, "func", [1, 2, 3]])]
@@ -30,13 +30,33 @@ module Neovim
30
30
  end
31
31
 
32
32
  describe "#buffer=" do
33
- it "sets the current buffer" do
33
+ it "sets the current buffer from an integer" do
34
34
  initial_index = current.buffer.index
35
35
  client.command("vnew")
36
36
 
37
37
  expect {
38
38
  current.buffer = initial_index
39
- }.to change { current.buffer.index }
39
+ }.to change { current.buffer.index }.to(initial_index)
40
+ end
41
+
42
+ it "sets the current buffer from a Buffer" do
43
+ b0 = current.buffer
44
+ client.command("vnew")
45
+ b1 = current.buffer
46
+
47
+ expect {
48
+ current.buffer = b0
49
+ }.to change { current.buffer }.from(b1).to(b0)
50
+ end
51
+
52
+ it "returns an integer" do
53
+ index = current.buffer.index
54
+ expect(current.buffer = index).to eq(index)
55
+ end
56
+
57
+ it "returns a Buffer" do
58
+ buffer = current.buffer
59
+ expect(current.buffer = buffer).to eq(buffer)
40
60
  end
41
61
  end
42
62
 
@@ -47,7 +67,7 @@ module Neovim
47
67
  end
48
68
 
49
69
  describe "#window=" do
50
- it "sets the current window" do
70
+ it "sets the current window from an integer" do
51
71
  client.command("vsp")
52
72
  expect(current.window.index).not_to eq(1)
53
73
 
@@ -55,6 +75,26 @@ module Neovim
55
75
  current.window = 1
56
76
  }.to change { current.window.index }.to(1)
57
77
  end
78
+
79
+ it "sets the current window from a Window" do
80
+ w0 = current.window
81
+ client.command("vsp")
82
+ w1 = current.window
83
+
84
+ expect {
85
+ current.window = w0
86
+ }.to change { current.window }.from(w1).to(w0)
87
+ end
88
+
89
+ it "returns an integer" do
90
+ index = current.window.index
91
+ expect(current.window = index).to eq(index)
92
+ end
93
+
94
+ it "returns a Window" do
95
+ w0 = current.window
96
+ expect(current.window = w0).to eq(w0)
97
+ end
58
98
  end
59
99
 
60
100
  describe "#tabpage" do
@@ -64,7 +104,7 @@ module Neovim
64
104
  end
65
105
 
66
106
  describe "#tabpage=" do
67
- it "sets the current tabpage" do
107
+ it "sets the current tabpage from an integer" do
68
108
  initial_index = current.tabpage.index
69
109
  client.command("tabnew")
70
110
  expect(current.tabpage.index).not_to eq(initial_index)
@@ -73,6 +113,26 @@ module Neovim
73
113
  current.tabpage = initial_index
74
114
  }.to change { current.tabpage.index }.to(initial_index)
75
115
  end
116
+
117
+ it "sets the current tabpage from a Tabpage" do
118
+ tp0 = current.tabpage
119
+ client.command("tabnew")
120
+ tp1 = current.tabpage
121
+
122
+ expect {
123
+ current.tabpage = tp0
124
+ }.to change { current.tabpage }.from(tp1).to(tp0)
125
+ end
126
+
127
+ it "returns an integer" do
128
+ index = current.tabpage.index
129
+ expect(current.tabpage = index).to eq(index)
130
+ end
131
+
132
+ it "returns a Tabpage" do
133
+ tp0 = current.tabpage
134
+ expect(current.tabpage = tp0).to eq(tp0)
135
+ end
76
136
  end
77
137
  end
78
138
  end
@@ -1,23 +1,9 @@
1
1
  require "helper"
2
2
  require "socket"
3
- require "msgpack"
4
3
  require "fileutils"
5
4
 
6
5
  module Neovim
7
6
  RSpec.describe EventLoop do
8
- it "calls the setup callback" do
9
- messages = []
10
- rd, wr = IO.pipe
11
- event_loop = EventLoop.new(rd, wr)
12
-
13
- fiber = Fiber.new do
14
- setup_cb = Proc.new { Fiber.yield(:setup) }
15
- event_loop.run(nil, setup_cb)
16
- end
17
-
18
- expect(fiber.resume).to eq(:setup)
19
- end
20
-
21
7
  shared_context "socket behavior" do
22
8
  it "sends and receives data" do
23
9
  messages = []
@@ -31,13 +17,15 @@ module Neovim
31
17
  server.close
32
18
  end
33
19
 
34
- fiber = Fiber.new do
35
- msg_cb = Proc.new { |msg| Fiber.yield(msg) }
36
- event_loop.send("data").run(msg_cb)
20
+ message = nil
21
+ event_loop.write("data").run do |msg|
22
+ message = msg
23
+ event_loop.stop
37
24
  end
38
25
 
39
- expect(fiber.resume).to eq("OK")
40
26
  server_thread.join
27
+ event_loop.shutdown
28
+ expect(message).to eq("OK")
41
29
  expect(messages).to eq(["data"])
42
30
  end
43
31
  end
@@ -76,13 +64,14 @@ module Neovim
76
64
  srv_stdin.write("OK")
77
65
  end
78
66
 
79
- fiber = Fiber.new do
80
- msg_cb = Proc.new { |msg| Fiber.yield(msg) }
81
- event_loop.send("data").run(msg_cb)
67
+ message = nil
68
+ event_loop.write("data").run do |msg|
69
+ message = msg
70
+ event_loop.stop
82
71
  end
83
72
 
84
- expect(fiber.resume).to eq("OK")
85
73
  server_thread.join
74
+ expect(message).to eq("OK")
86
75
  expect(messages).to eq(["data"])
87
76
  ensure
88
77
  STDOUT.reopen(old_stdout)
@@ -94,14 +83,16 @@ module Neovim
94
83
  context "child" do
95
84
  it "sends and receives data" do
96
85
  event_loop = EventLoop.child(["-n", "-u", "NONE"])
97
- message = MessagePack.pack([0, 0, :vim_strwidth, ["hi"]])
86
+ input = MessagePack.pack([0, 0, :vim_strwidth, ["hi"]])
98
87
 
99
- fiber = Fiber.new do
100
- msg_cb = Proc.new { |msg| Fiber.yield(msg) }
101
- event_loop.send(message).run(msg_cb)
88
+ message = nil
89
+ event_loop.write(input).run do |msg|
90
+ message = msg
91
+ event_loop.stop
102
92
  end
103
93
 
104
- expect(fiber.resume).to eq(MessagePack.pack([1, 0, nil, 2]))
94
+ event_loop.shutdown
95
+ expect(message).to eq(MessagePack.pack([1, 0, nil, 2]))
105
96
  end
106
97
  end
107
98
  end
@@ -27,7 +27,26 @@ module Neovim
27
27
  end
28
28
 
29
29
  describe "#run" do
30
- # TODO: Find a way to test this without excessive mocking
30
+ it "delegates messages to the manifest" do
31
+ messages = []
32
+ manifest = instance_double(Manifest)
33
+ session = Session.child(["-n", "-u", "NONE"])
34
+
35
+ host = Host.new(manifest, session)
36
+
37
+ expect(manifest).to receive(:handle) do |msg, client|
38
+ expect(msg.method_name).to eq("my_event")
39
+ expect(msg.arguments).to eq(["arg"])
40
+ expect(client).to be_a(Client)
41
+
42
+ session.stop
43
+ end
44
+
45
+ session.request(:vim_subscribe, "my_event")
46
+ session.request(:vim_command, "call rpcnotify(0, 'my_event', 'arg')")
47
+
48
+ host.run
49
+ end
31
50
  end
32
51
  end
33
52
  end
@@ -1,6 +1,4 @@
1
1
  require "helper"
2
- require "neovim/manifest"
3
- require "neovim/plugin"
4
2
 
5
3
  module Neovim
6
4
  RSpec.describe Manifest do