neovim 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,17 +23,14 @@ module Neovim
23
23
  self
24
24
  end
25
25
 
26
- def run(&message_cb)
27
- @event_loop.run do |data|
26
+ def run(message_cb, setup_cb=nil)
27
+ data_cb = Proc.new do |data|
28
28
  @unpacker.feed_each(data) do |msg|
29
29
  message_cb.call(msg)
30
30
  end
31
31
  end
32
- end
33
32
 
34
- def stop
35
- @event_loop.stop
36
- self
33
+ @event_loop.run(data_cb, setup_cb)
37
34
  end
38
35
  end
39
36
  end
@@ -3,8 +3,12 @@ module Neovim
3
3
  attr_reader :method_name, :arguments
4
4
 
5
5
  def initialize(method_name, args)
6
- @method_name = method_name.to_sym
6
+ @method_name = method_name.to_s
7
7
  @arguments = args
8
8
  end
9
+
10
+ def sync?
11
+ false
12
+ end
9
13
  end
10
14
  end
data/lib/neovim/plugin.rb CHANGED
@@ -1,15 +1,60 @@
1
1
  module Neovim
2
2
  class Plugin
3
- def self.from_config_block(&block)
4
- new.tap do |instance|
3
+ def self.from_config_block(source, &block)
4
+ new(source).tap do |instance|
5
5
  block.call(DSL.new(instance)) if block
6
6
  end
7
7
  end
8
8
 
9
- attr_accessor :specs
9
+ attr_accessor :handlers
10
+ attr_reader :source
10
11
 
11
- def initialize
12
- @specs = []
12
+ def initialize(source)
13
+ @handlers = []
14
+ @source = source
15
+ end
16
+
17
+ def specs
18
+ @handlers.map(&:to_spec)
19
+ end
20
+
21
+ class Handler
22
+ attr_reader :block
23
+
24
+ def initialize(source, type, name, sync, options, block)
25
+ @source = source
26
+ @type = type.to_sym
27
+ @name = name.to_s
28
+ @sync = !!sync
29
+ @options = options
30
+ @block = block || ::Proc.new {}
31
+ end
32
+
33
+ def qualified_name
34
+ if @type == :autocmd
35
+ pattern = @options.fetch(:pattern, "*")
36
+ "#{@source}:#{@type}:#{@name}:#{pattern}"
37
+ else
38
+ "#{@source}:#{@type}:#{@name}"
39
+ end
40
+ end
41
+
42
+ def sync?
43
+ @sync
44
+ end
45
+
46
+ def to_spec
47
+ {
48
+ :type => @type,
49
+ :name => @name,
50
+ :sync => @sync,
51
+ :opts => @options,
52
+ }
53
+ end
54
+
55
+ def call(*args)
56
+ @block.call(*args)
57
+ end
13
58
  end
14
59
 
15
60
  class DSL < BasicObject
@@ -17,44 +62,41 @@ module Neovim
17
62
  @plugin = plugin
18
63
  end
19
64
 
20
- def command(name, _options={}, &block)
21
- options = _options.dup
22
- options[:range] = "" if options[:range] == true
23
- options[:range] = ::Kernel.String(options[:range])
65
+ def command(name, options={}, &block)
66
+ register_handler(:command, name, options, block)
67
+ end
24
68
 
25
- @plugin.specs.push(
26
- :type => :command,
27
- :name => name.to_sym,
28
- :sync => !!options.delete(:sync),
29
- :opts => options,
30
- :proc => block || ::Proc.new {}
31
- )
69
+ def function(name, options={}, &block)
70
+ register_handler(:function, name, options, block)
32
71
  end
33
72
 
34
- def function(name, _options, &block)
35
- options = _options.dup
36
- options[:range] = "" if options[:range] == true
37
- options[:range] = ::Kernel.String(options[:range])
73
+ def autocmd(name, options={}, &block)
74
+ register_handler(:autocmd, name, options, block)
75
+ end
76
+
77
+ private
78
+
79
+ def register_handler(type, name, _options, block)
80
+ if type == :autocmd
81
+ options = _options.dup
82
+ else
83
+ options = standardize_range(_options.dup)
84
+ end
38
85
 
39
- @plugin.specs.push(
40
- :type => :function,
41
- :name => name.to_sym,
42
- :sync => !!options.delete(:sync),
43
- :opts => options,
44
- :proc => block || ::Proc.new {}
86
+ sync = options.delete(:sync)
87
+
88
+ @plugin.handlers.push(
89
+ Handler.new(@plugin.source, type, name, sync, options, block)
45
90
  )
46
91
  end
47
92
 
48
- def autocmd(name, _options={}, &block)
49
- options = _options.dup
93
+ def standardize_range(options)
94
+ if options.key?(:range)
95
+ options[:range] = "" if options[:range] == true
96
+ options[:range] = ::Kernel.String(options[:range])
97
+ end
50
98
 
51
- @plugin.specs.push(
52
- :type => :autocmd,
53
- :name => name.to_sym,
54
- :sync => !!options.delete(:sync),
55
- :opts => options,
56
- :proc => block || ::Proc.new {}
57
- )
99
+ options
58
100
  end
59
101
  end
60
102
  end
@@ -3,12 +3,16 @@ module Neovim
3
3
  attr_reader :method_name, :arguments
4
4
 
5
5
  def initialize(method_name, args, msgpack_stream, request_id)
6
- @method_name = method_name.to_sym
6
+ @method_name = method_name.to_s
7
7
  @arguments = args
8
8
  @msgpack_stream = msgpack_stream
9
9
  @request_id = request_id
10
10
  end
11
11
 
12
+ def sync?
13
+ true
14
+ end
15
+
12
16
  def respond(value)
13
17
  @msgpack_stream.send([1, @request_id, nil, value])
14
18
  self
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.0.3")
2
+ VERSION = Gem::Version.new("0.0.4")
3
3
  end
@@ -2,10 +2,11 @@ require "helper"
2
2
  require "tmpdir"
3
3
 
4
4
  RSpec.describe "neovim-ruby-host" do
5
- specify do
5
+ it "loads and runs plugins from Ruby source files" do
6
6
  Dir.mktmpdir do |pwd|
7
7
  Dir.chdir(pwd) do
8
- File.write("./plugin1.rb", <<-RUBY)
8
+ plugin1_path = File.expand_path("./plugin1.rb")
9
+ File.write(plugin1_path, <<-RUBY)
9
10
  Neovim.plugin do |plug|
10
11
  plug.command(:SyncAdd, :args => 2, :sync => true) do |nvim, x, y|
11
12
  x + y
@@ -13,7 +14,8 @@ RSpec.describe "neovim-ruby-host" do
13
14
  end
14
15
  RUBY
15
16
 
16
- File.write("./plugin2.rb", <<-RUBY)
17
+ plugin2_path = File.expand_path("./plugin2.rb")
18
+ File.write(plugin2_path, <<-RUBY)
17
19
  Neovim.plugin do |plug|
18
20
  plug.command(:AsyncSetLine, :args => 1) do |nvim, str|
19
21
  nvim.current.line = str
@@ -23,35 +25,24 @@ RSpec.describe "neovim-ruby-host" do
23
25
 
24
26
  nvim = Neovim.attach_child(["--headless", "-u", "NONE", "-N", "-n"])
25
27
 
26
- # Start the remote host
27
28
  host_exe = File.expand_path("../../../bin/neovim-ruby-host", __FILE__)
28
- nvim.command(%{let host = rpcstart("#{host_exe}", ["./plugin1.rb", "./plugin2.rb"])})
29
+ nvim.command("let host = rpcstart('#{host_exe}', ['#{plugin1_path}', '#{plugin2_path}'])")
29
30
 
30
- # Send a "poll" request
31
- expect(nvim.eval(%{rpcrequest(host, "poll")})).to eq("ok")
31
+ expect(nvim.eval("rpcrequest(host, 'poll')")).to eq("ok")
32
+ expect(nvim.eval("rpcrequest(host, '#{plugin1_path}:command:SyncAdd', 1, 2)")).to eq(3)
32
33
 
33
- # Make a request to the synchronous SyncAdd method and store the result
34
- nvim.command(%{let result = rpcrequest(host, "SyncAdd", 1, 2)})
35
-
36
- # Write the result to the buffer
37
- nvim.command("put =result")
38
- nvim.command("normal o")
39
-
40
- # Set the current line via the AsyncSetLine method
41
- nvim.command(%{call rpcnotify(host, "AsyncSetLine", "foo")})
34
+ expect {
35
+ nvim.eval("rpcnotify(host, '#{plugin2_path}:command:AsyncSetLine', 'foo')")
36
+ nvim.eval("rpcrequest(host, 'poll')")
37
+ }.to change { nvim.current.buffer.lines.to_a }.from([""]).to(["foo"])
42
38
 
43
- # Make an unknown notification
44
39
  expect {
45
- nvim.command(%{call rpcnotify(host, "Unknown")})
40
+ nvim.eval("rpcnotify(host, 'Unknown')")
46
41
  }.not_to raise_error
47
42
 
48
- # Make an unknown request
49
43
  expect {
50
- nvim.command(%{call rpcrequest(host, "Unknown")})
51
- }.to raise_error(ArgumentError, /unknown request/i)
52
-
53
- # Assert the contents of the buffer
54
- expect(nvim.current.buffer.lines).to eq(["", "3", "foo"])
44
+ nvim.eval("call rpcrequest(host, 'Unknown')")
45
+ }.to raise_error(ArgumentError)
55
46
  end
56
47
  end
57
48
  end
data/spec/helper.rb CHANGED
@@ -8,6 +8,8 @@ if ENV["REPORT_COVERAGE"]
8
8
  Coveralls.wear!
9
9
  end
10
10
 
11
+ Thread.abort_on_exception = true
12
+
11
13
  ENV["NVIM_EXECUTABLE"] = File.expand_path("../../vendor/neovim/build/bin/nvim", __FILE__)
12
14
 
13
15
  RSpec.configure do |config|
@@ -28,7 +28,7 @@ module Neovim
28
28
  srv_thr.join
29
29
 
30
30
  expect(request).to be_a(Request)
31
- expect(request.method_name).to eq(:func)
31
+ expect(request.method_name).to eq("func")
32
32
  expect(request.arguments).to eq([1, 2, 3])
33
33
  end
34
34
 
@@ -57,7 +57,7 @@ module Neovim
57
57
  srv_thr.join
58
58
 
59
59
  expect(notification).to be_a(Notification)
60
- expect(notification.method_name).to eq(:func)
60
+ expect(notification.method_name).to eq("func")
61
61
  expect(notification.arguments).to eq([1, 2, 3])
62
62
  end
63
63
 
@@ -6,53 +6,15 @@ module Neovim
6
6
  let(:buffer) { client.current.buffer }
7
7
 
8
8
  describe "#lines" do
9
- before do
10
- client.command("normal i1")
11
- client.command("normal o2")
12
- client.command("normal o3")
13
- end
14
-
15
- it "returns the buffer's lines as an array" do
16
- expect(buffer.lines).to eq(["1", "2", "3"])
17
- end
18
-
19
- it "can be indexed into" do
20
- expect(buffer.lines[1]).to eq("2")
21
- end
22
-
23
- it "can be sliced with a length" do
24
- expect(buffer.lines[0, 2]).to eq(["1", "2"])
25
- end
26
-
27
- it "can be sliced with a range" do
28
- expect(buffer.lines[0..1]).to eq(["1", "2"])
29
- end
30
-
31
- it "can be updated at an index" do
32
- buffer.lines[0] = "foo"
33
- expect(buffer.lines).to eq(["foo", "2", "3"])
34
- end
35
-
36
- it "can be updated with a length" do
37
- buffer.lines[0, 2] = ["foo"]
38
- expect(buffer.lines).to eq(["foo", "3"])
39
- end
40
-
41
- it "can be updated with a range" do
42
- buffer.lines[0..1] = ["foo"]
43
- expect(buffer.lines).to eq(["foo", "3"])
44
- end
45
-
46
- it "exposes the Enumerable interface" do
47
- succ_lines = buffer.lines.collect(&:succ)
48
- expect(succ_lines).to eq(["2", "3", "4"])
9
+ it "returns a LineRange" do
10
+ expect(buffer.lines).to be_a(LineRange)
49
11
  end
50
12
  end
51
13
 
52
14
  describe "#lines=" do
53
15
  it "updates the buffers lines" do
54
16
  buffer.lines = ["one", "two"]
55
- expect(buffer.lines).to eq(["one", "two"])
17
+ expect(buffer.lines.to_a).to eq(["one", "two"])
56
18
  end
57
19
  end
58
20
  end
@@ -74,5 +74,19 @@ module Neovim
74
74
  }.to change { current.tabpage.index }.to(initial_index)
75
75
  end
76
76
  end
77
+
78
+ describe "#range" do
79
+ it "returns the current range" do
80
+ expect(current.range).to be_a(LineRange)
81
+ end
82
+ end
83
+
84
+ describe "#range=" do
85
+ it "sets the current range" do
86
+ current.buffer.lines = ["1", "2", "3"]
87
+ current.range = (1..2)
88
+ expect(current.range.to_a).to eq(["2", "3"])
89
+ end
90
+ end
77
91
  end
78
92
  end
@@ -5,6 +5,19 @@ require "fileutils"
5
5
 
6
6
  module Neovim
7
7
  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
+
8
21
  shared_context "socket behavior" do
9
22
  it "sends and receives data" do
10
23
  messages = []
@@ -14,12 +27,13 @@ module Neovim
14
27
  messages << client.readpartial(1024)
15
28
 
16
29
  client.write("OK")
30
+ client.close
31
+ server.close
17
32
  end
18
33
 
19
34
  fiber = Fiber.new do
20
- event_loop.send("data").run do |msg|
21
- Fiber.yield(msg)
22
- end
35
+ msg_cb = Proc.new { |msg| Fiber.yield(msg) }
36
+ event_loop.send("data").run(msg_cb)
23
37
  end
24
38
 
25
39
  expect(fiber.resume).to eq("OK")
@@ -44,15 +58,49 @@ module Neovim
44
58
  include_context "socket behavior"
45
59
  end
46
60
 
61
+ context "stdio" do
62
+ it "sends and receives data" do
63
+ old_stdout = STDOUT.dup
64
+ old_stdin = STDIN.dup
65
+
66
+ begin
67
+ srv_stdout, cl_stdout = IO.pipe
68
+ cl_stdin, srv_stdin = IO.pipe
69
+
70
+ STDOUT.reopen(cl_stdout)
71
+ STDIN.reopen(cl_stdin)
72
+
73
+ event_loop = EventLoop.stdio
74
+ messages = []
75
+
76
+ srv_thr = Thread.new do
77
+ messages << srv_stdout.readpartial(1024)
78
+ srv_stdin.write("OK")
79
+ end
80
+
81
+ fiber = Fiber.new do
82
+ msg_cb = Proc.new { |msg| Fiber.yield(msg) }
83
+ event_loop.send("data").run(msg_cb)
84
+ end
85
+
86
+ expect(fiber.resume).to eq("OK")
87
+ srv_thr.join
88
+ expect(messages).to eq(["data"])
89
+ ensure
90
+ STDOUT.reopen(old_stdout)
91
+ STDIN.reopen(old_stdin)
92
+ end
93
+ end
94
+ end
95
+
47
96
  context "child" do
48
97
  it "sends and receives data" do
49
98
  event_loop = EventLoop.child(["-n", "-u", "NONE"])
50
99
  message = MessagePack.pack([0, 0, :vim_strwidth, ["hi"]])
51
100
 
52
101
  fiber = Fiber.new do
53
- event_loop.send(message).run do |msg|
54
- Fiber.yield(msg)
55
- end
102
+ msg_cb = Proc.new { |msg| Fiber.yield(msg) }
103
+ event_loop.send(message).run(msg_cb)
56
104
  end
57
105
 
58
106
  expect(fiber.resume).to eq(MessagePack.pack([1, 0, nil, 2]))