neovim 0.2.2 → 0.2.3

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.
@@ -1,5 +1,7 @@
1
1
  module Neovim
2
2
  # Provide an enumerable interface for dealing with ranges of lines.
3
+ #
4
+ # @api private
3
5
  class LineRange
4
6
  include Enumerable
5
7
 
@@ -111,6 +113,12 @@ module Neovim
111
113
  self
112
114
  end
113
115
 
116
+ # @param index [Fixnum]
117
+ # @param line [String]
118
+ def insert(index, lines)
119
+ @buffer.insert(index, Array(lines))
120
+ end
121
+
114
122
  # @param index [Fixnum]
115
123
  def delete(index)
116
124
  @buffer.del_line(abs_line(index))
@@ -2,6 +2,7 @@ require "logger"
2
2
 
3
3
  module Neovim
4
4
  # Mixed into classes for unified logging helper methods.
5
+ # @api private
5
6
  module Logging
6
7
  class << self
7
8
  attr_writer :logger
@@ -3,7 +3,9 @@ require "msgpack"
3
3
 
4
4
  module Neovim
5
5
  # Handles serializing RPC messages to MessagePack and passing them to
6
- # the event loop
6
+ # the event loop.
7
+ #
8
+ # @api private
7
9
  class MsgpackStream
8
10
  include Logging
9
11
 
@@ -40,7 +42,7 @@ module Neovim
40
42
  end
41
43
  end
42
44
  rescue => e
43
- fatal("got unexpected error #{e}")
45
+ fatal("got unexpected error #{e.inspect}")
44
46
  debug(e.backtrace.join("\n"))
45
47
  end
46
48
 
@@ -1,5 +1,6 @@
1
1
  module Neovim
2
2
  # An asynchronous message from +nvim+.
3
+ #
3
4
  # @api private
4
5
  class Notification
5
6
  attr_reader :method_name, :arguments
@@ -1,6 +1,7 @@
1
1
  require "neovim/plugin/dsl"
2
2
 
3
3
  module Neovim
4
+ # @api private
4
5
  class Plugin
5
6
  attr_accessor :handlers
6
7
  attr_reader :source
@@ -1,5 +1,6 @@
1
1
  module Neovim
2
2
  # A synchronous message from +nvim+.
3
+ #
3
4
  # @api private
4
5
  class Request
5
6
  attr_reader :method_name, :arguments
@@ -6,6 +6,8 @@ module Neovim
6
6
  # This class is used to define a +Neovim::Plugin+ to act as a backend for the
7
7
  # legacy +:ruby+, +:rubyfile+, and +:rubydo+ Vim commands. It is autoloaded
8
8
  # from +nvim+ and not intended to be loaded directly.
9
+ #
10
+ # @api private
9
11
  module RubyProvider
10
12
  def self.__define_plugin!
11
13
  Thread.abort_on_exception = true
@@ -7,6 +7,8 @@ require "fiber"
7
7
 
8
8
  module Neovim
9
9
  # Wraps an +AsyncSession+ in a synchronous API using +Fiber+s.
10
+ #
11
+ # @api private
10
12
  class Session
11
13
  include Logging
12
14
 
@@ -99,7 +101,7 @@ module Neovim
99
101
  Fiber.new { yield message if block_given? }.resume
100
102
  end
101
103
  ensure
102
- stop
104
+ shutdown
103
105
  end
104
106
 
105
107
  # Make an RPC request and return its response.
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.2.2")
2
+ VERSION = Gem::Version.new("0.2.3")
3
3
  end
@@ -38,4 +38,5 @@ RSpec.configure do |config|
38
38
  Kernel.srand config.seed
39
39
  end
40
40
 
41
+ Neovim.logger.level = Logger::FATAL
41
42
  Thread.abort_on_exception = true
@@ -4,6 +4,7 @@ module Neovim
4
4
  RSpec.describe Buffer do
5
5
  let(:client) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]) }
6
6
  let(:buffer) { client.current.buffer }
7
+ after { client.shutdown }
7
8
 
8
9
  describe "#lines" do
9
10
  it "returns a LineRange" do
@@ -108,6 +109,25 @@ module Neovim
108
109
  }.to change { buffer.lines.to_a }.to(["one", "two"])
109
110
  end
110
111
 
112
+ it "unshifts buffer lines using index 0" do
113
+ buffer.lines = []
114
+
115
+ expect {
116
+ buffer.append(0, "two")
117
+ buffer.append(0, "one")
118
+ }.to change { buffer.lines.to_a }.to(["one", "two", ""])
119
+ end
120
+
121
+ it "raises for out of bounds indexes" do
122
+ expect {
123
+ buffer.append(-1, "err")
124
+ }.to raise_error(/out of bounds/i)
125
+
126
+ expect {
127
+ buffer.append(10, "err")
128
+ }.to raise_error(/out of bounds/i)
129
+ end
130
+
111
131
  it "returns the appended line" do
112
132
  expect(buffer.append(0, "two")).to eq("two")
113
133
  end
@@ -3,6 +3,7 @@ require "helper"
3
3
  module Neovim
4
4
  RSpec.describe Client do
5
5
  let(:client) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]) }
6
+ after { client.shutdown }
6
7
 
7
8
  describe "#respond_to?" do
8
9
  it "returns true for vim functions" do
@@ -4,6 +4,7 @@ module Neovim
4
4
  RSpec.describe Current do
5
5
  let(:client) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]) }
6
6
  let(:current) { client.current }
7
+ after { client.shutdown }
7
8
 
8
9
  describe "#line" do
9
10
  it "returns an empty string if the current line is empty" do
@@ -0,0 +1,47 @@
1
+ require "helper"
2
+
3
+ module Neovim
4
+ class Host
5
+ RSpec.describe Loader do
6
+ describe "#load" do
7
+ let(:plugin_path) { Support.file_path("plug.rb") }
8
+ let(:host) { instance_double(Host, :register => nil) }
9
+ let(:loader) { Loader.new(host) }
10
+
11
+ before do
12
+ File.write(plugin_path, "Neovim.plugin")
13
+ end
14
+
15
+ it "registers plugins defined in the provided files" do
16
+ expect(host).to receive(:register).with(kind_of(Plugin))
17
+ loader.load([plugin_path])
18
+ end
19
+
20
+ it "registers multiple plugins defined in the provided files" do
21
+ File.write(plugin_path, "Neovim.plugin; Neovim.plugin")
22
+ expect(host).to receive(:register).with(kind_of(Plugin)).twice
23
+ loader.load([plugin_path])
24
+ end
25
+
26
+ it "doesn't register plugins when none are defined" do
27
+ File.write(plugin_path, "class FooClass; end")
28
+ expect(host).not_to receive(:register)
29
+ loader.load([plugin_path])
30
+ end
31
+
32
+ it "doesn't leak constants defined in plugins" do
33
+ File.write(plugin_path, "class FooClass; end")
34
+ loader.load([plugin_path])
35
+ expect(Kernel.const_defined?(:FooClass)).to be(false)
36
+ end
37
+
38
+ it "doesn't leak the overidden Neovim.plugin method" do
39
+ loader.load([plugin_path])
40
+ expect {
41
+ Neovim.plugin
42
+ }.to raise_error(/outside of a plugin host/)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -2,50 +2,138 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe Host do
5
+ let(:session) { instance_double(Session) }
6
+ let(:client) { instance_double(Client) }
7
+ let(:host) { Host.new(session, client) }
8
+
5
9
  describe ".load_from_files" do
6
- it "loads the defined plugins into a manifest" do
7
- plug1 = Support.file_path("plug1.rb")
8
- plug2 = Support.file_path("plug2.rb")
10
+ it "instantiates with a session and loads plugins" do
11
+ paths = ["/foo", "/bar"]
12
+ loader = instance_double(Host::Loader)
9
13
 
10
- File.write(plug1, "Neovim.plugin")
11
- File.write(plug2, "Neovim.plugin; Neovim.plugin")
14
+ expect(Host::Loader).to receive(:new).
15
+ with(kind_of(Host)).
16
+ and_return(loader)
17
+ expect(loader).to receive(:load).with(paths)
12
18
 
13
- manifest = Manifest.new
19
+ Host.load_from_files(paths, :session => session, :client => client)
20
+ end
21
+ end
22
+
23
+ describe "#handlers" do
24
+ it "has a default poll handler" do
25
+ expect(host.handlers["poll"]).to respond_to(:call)
26
+ end
27
+ end
14
28
 
15
- expect(manifest).to receive(:register).exactly(3).times
16
- host = Host.load_from_files([plug1, plug2], manifest)
17
- expect(host.manifest).to eq(manifest)
29
+ describe "#specs" do
30
+ it "has default specs" do
31
+ expect(host.specs).to eq({})
18
32
  end
33
+ end
19
34
 
20
- it "doesn't load plugin code into the global namespace" do
21
- plug = Support.file_path("plug.rb")
22
- File.write(plug, "class FooClass; end")
35
+ describe "#register" do
36
+ it "adds specs" do
37
+ plugin = Plugin.from_config_block("source") do |plug|
38
+ plug.command(:Foo)
39
+ end
23
40
 
24
- host = Host.load_from_files([plug])
25
- expect(Kernel.const_defined?("FooClass")).to be(false)
41
+ expect {
42
+ host.register(plugin)
43
+ }.to change { host.specs }.from({}).to("source" => plugin.specs)
44
+ end
45
+
46
+ it "adds plugin handlers" do
47
+ plugin = Plugin.from_config_block("source") do |plug|
48
+ plug.command(:Foo)
49
+ end
50
+
51
+ expect {
52
+ host.register(plugin)
53
+ }.to change {
54
+ host.handlers["source:command:Foo"]
55
+ }.from(nil).to(kind_of(Proc))
56
+ end
57
+
58
+ it "doesn't add top-level RPCs to specs" do
59
+ plugin = Plugin.from_config_block("source") do |plug|
60
+ plug.rpc(:Foo)
61
+ end
62
+
63
+ expect {
64
+ host.register(plugin)
65
+ }.to change { host.specs }.from({}).to("source" => [])
26
66
  end
27
67
  end
28
68
 
29
- describe "#run" do
30
- it "delegates messages to the manifest" do
31
- messages = []
32
- manifest = instance_double(Manifest)
33
- session = Session.child(["nvim", "-n", "-u", "NONE"])
69
+ describe "#handle" do
70
+ it "calls the poll handler" do
71
+ message = double(:message, :method_name => "poll", :sync? => true)
72
+
73
+ expect(message).to receive(:respond).with("ok")
74
+ host.handle(message)
75
+ end
34
76
 
35
- host = Host.new(manifest, session)
77
+ it "calls the specs handler" do
78
+ plugin = Plugin.from_config_block("source") do |plug|
79
+ plug.command(:Foo)
80
+ end
81
+ host.register(plugin)
36
82
 
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)
83
+ message = double(:message, :method_name => "specs", :sync? => true, :arguments => ["source"])
41
84
 
42
- session.stop
85
+ expect(message).to receive(:respond).with(plugin.specs)
86
+ host.handle(message)
87
+ end
88
+
89
+ it "calls a plugin sync handler" do
90
+ plugin = Plugin.from_config_block("source") do |plug|
91
+ plug.command(:Foo, :sync => true) { |client, arg| [client, arg] }
92
+ end
93
+ host.register(plugin)
94
+
95
+ message = double(:message, :method_name => "source:command:Foo", :sync? => true, :arguments => [:arg])
96
+
97
+ expect(message).to receive(:respond).with([client, :arg])
98
+ host.handle(message)
99
+ end
100
+
101
+ it "rescues plugin sync handler exceptions" do
102
+ plugin = Plugin.from_config_block("source") do |plug|
103
+ plug.command(:Foo, :sync => true) { raise "BOOM" }
104
+ end
105
+ host.register(plugin)
106
+
107
+ message = double(:message, :method_name => "source:command:Foo", :sync? => true, :arguments => [])
108
+
109
+ expect(message).to receive(:error).with("BOOM")
110
+ host.handle(message)
111
+ end
112
+
113
+ it "calls a plugin async handler" do
114
+ async_proc = Proc.new {}
115
+ plugin = Plugin.from_config_block("source") do |plug|
116
+ plug.command(:Foo, &async_proc)
43
117
  end
118
+ host.register(plugin)
119
+
120
+ message = double(:message, :method_name => "source:command:Foo", :sync? => false, :arguments => [:arg])
121
+
122
+ expect(async_proc).to receive(:call).with(client, :arg)
123
+ host.handle(message)
124
+ end
125
+
126
+ it "calls a default sync handler" do
127
+ message = double(:message, :method_name => "foobar", :sync? => true)
128
+
129
+ expect(message).to receive(:error).with("Unknown request foobar")
130
+ host.handle(message)
131
+ end
44
132
 
45
- session.request(:vim_subscribe, "my_event")
46
- session.request(:vim_command, "call rpcnotify(0, 'my_event', 'arg')")
133
+ it "calls a default async handler" do
134
+ message = double(:message, :method_name => "foobar", :sync? => false)
47
135
 
48
- host.run
136
+ host.handle(message)
49
137
  end
50
138
  end
51
139
  end
@@ -4,7 +4,7 @@ module Neovim
4
4
  RSpec.describe LineRange do
5
5
  let(:client) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]) }
6
6
  let(:buffer) { client.current.buffer }
7
- let(:line_range) { LineRange.new(buffer, 0, 3) }
7
+ let(:line_range) { LineRange.new(buffer, 0, -1) }
8
8
  let(:sub_range) { LineRange.new(buffer, 1, 2) }
9
9
 
10
10
  before do
@@ -14,6 +14,8 @@ module Neovim
14
14
  client.command("normal o4")
15
15
  end
16
16
 
17
+ after { client.shutdown }
18
+
17
19
  it "is enumerable" do
18
20
  expect(line_range).to be_an(Enumerable)
19
21
  expect(line_range).to respond_to(:each)
@@ -115,6 +117,46 @@ module Neovim
115
117
  end
116
118
  end
117
119
 
120
+ describe "#insert" do
121
+ before { line_range.replace(["1", "2"]) }
122
+
123
+ it "inserts lines at the beginning" do
124
+ expect {
125
+ line_range.insert(0, "z")
126
+ }.to change { line_range.to_a }.to(["z", "1", "2"])
127
+
128
+ expect {
129
+ line_range.insert(0, ["x", "y"])
130
+ }.to change { line_range.to_a }.to(["x", "y", "z", "1", "2"])
131
+ end
132
+
133
+ it "inserts lines in the middle" do
134
+ expect {
135
+ line_range.insert(1, "z")
136
+ }.to change { line_range.to_a }.to(["1", "z", "2"])
137
+
138
+ expect {
139
+ line_range.insert(1, ["x", "y"])
140
+ }.to change { line_range.to_a }.to(["1", "x", "y", "z", "2"])
141
+ end
142
+
143
+ it "inserts lines at the end" do
144
+ expect {
145
+ line_range.insert(-1, "x")
146
+ }.to change { line_range.to_a }.to(["1", "2", "x"])
147
+
148
+ expect {
149
+ line_range.insert(-1, ["y", "z"])
150
+ }.to change { line_range.to_a }.to(["1", "2", "x", "y", "z"])
151
+ end
152
+
153
+ it "raises on out of bounds indexes" do
154
+ expect {
155
+ line_range.insert(10, "x")
156
+ }.to raise_error(/out of bounds/i)
157
+ end
158
+ end
159
+
118
160
  describe "#delete" do
119
161
  it "deletes the line at the given index" do
120
162
  expect {
@@ -2,8 +2,11 @@ require "helper"
2
2
 
3
3
  module Neovim
4
4
  RSpec.describe RemoteObject do
5
+ let(:client) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]) }
6
+ after { client.shutdown }
7
+
5
8
  context Window do
6
- let(:window) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]).current.window }
9
+ let(:window) { client.current.window }
7
10
 
8
11
  describe "#respond_to?" do
9
12
  it "returns true for Window functions" do
@@ -37,7 +40,7 @@ module Neovim
37
40
  end
38
41
 
39
42
  context Tabpage do
40
- let(:tabpage) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]).current.tabpage }
43
+ let(:tabpage) { client.current.tabpage }
41
44
 
42
45
  describe "#respond_to?" do
43
46
  it "returns true for Tabpage functions" do
@@ -71,7 +74,7 @@ module Neovim
71
74
  end
72
75
 
73
76
  context Buffer do
74
- let(:buffer) { Neovim.attach_child(["nvim", "-n", "-u", "NONE"]).current.buffer }
77
+ let(:buffer) { client.current.buffer }
75
78
 
76
79
  describe "#respond_to?" do
77
80
  it "returns true for Buffer functions" do