neovim 0.7.1 → 0.9.0
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.
- checksums.yaml +5 -5
- data/.github/workflows/docs.yml +39 -0
- data/.github/workflows/tests.yml +64 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +22 -0
- data/CODE_OF_CONDUCT.md +3 -3
- data/README.md +19 -20
- data/Rakefile +21 -11
- data/exe/neovim-ruby-host +5 -0
- data/lib/neovim/buffer.rb +120 -41
- data/lib/neovim/client.rb +304 -39
- data/lib/neovim/client_info.rb +46 -0
- data/lib/neovim/connection.rb +7 -2
- data/lib/neovim/event_loop.rb +8 -4
- data/lib/neovim/host/cli.rb +41 -0
- data/lib/neovim/host.rb +3 -0
- data/lib/neovim/logging.rb +1 -1
- data/lib/neovim/message.rb +1 -1
- data/lib/neovim/plugin/dsl.rb +6 -0
- data/lib/neovim/plugin.rb +7 -2
- data/lib/neovim/remote_object.rb +5 -2
- data/lib/neovim/ruby_provider/object_ext.rb +5 -0
- data/lib/neovim/ruby_provider/vim.rb +6 -5
- data/lib/neovim/ruby_provider.rb +29 -10
- data/lib/neovim/session.rb +21 -16
- data/lib/neovim/tabpage.rb +8 -15
- data/lib/neovim/version.rb +1 -1
- data/lib/neovim/window.rb +45 -33
- data/lib/neovim.rb +12 -3
- data/neovim.gemspec +4 -5
- data/script/ci/download_nvim.sh +40 -0
- data/script/dump_api.rb +1 -1
- data/script/generate_docs.rb +6 -7
- data/script/run_acceptance.rb +15 -11
- data/spec/acceptance/client_info_spec.vim +42 -0
- data/spec/acceptance/rplugin_command_spec.vim +2 -2
- data/spec/acceptance/ruby_spec.vim +18 -11
- data/spec/acceptance/rubydo_spec.vim +9 -0
- data/spec/acceptance/rubyeval_spec.vim +22 -0
- data/spec/acceptance/rubyfile/curbuf_ivar_get.rb +1 -1
- data/spec/acceptance/rubyfile/curbuf_ivar_set.rb +1 -1
- data/spec/acceptance/rubyfile/define_foo.rb +1 -1
- data/spec/acceptance/rubyfile/nested_inner.rb +1 -1
- data/spec/acceptance/rubyfile/set_pwd_after.rb +1 -1
- data/spec/acceptance/rubyfile/set_pwd_before.rb +1 -1
- data/spec/acceptance/rubyfile_spec.vim +19 -19
- data/spec/acceptance/runtime/init.vim +2 -2
- data/spec/acceptance/runtime/rplugin/ruby/commands.rb +2 -2
- data/spec/helper.rb +25 -7
- data/spec/neovim/api_spec.rb +1 -1
- data/spec/neovim/buffer_spec.rb +10 -6
- data/spec/neovim/client_info_spec.rb +77 -0
- data/spec/neovim/client_spec.rb +9 -2
- data/spec/neovim/connection_spec.rb +32 -4
- data/spec/neovim/current_spec.rb +1 -2
- data/spec/neovim/event_loop_spec.rb +16 -0
- data/spec/neovim/host/cli_spec.rb +94 -0
- data/spec/neovim/host_spec.rb +16 -14
- data/spec/neovim/line_range_spec.rb +1 -3
- data/spec/neovim/remote_object_spec.rb +1 -2
- data/spec/neovim/ruby_provider/buffer_ext_spec.rb +6 -7
- data/spec/neovim/ruby_provider/object_ext_spec.rb +10 -0
- data/spec/neovim/ruby_provider/vim_spec.rb +1 -1
- data/spec/neovim/ruby_provider/window_ext_spec.rb +7 -10
- data/spec/neovim/session_spec.rb +13 -40
- data/spec/neovim/window_spec.rb +1 -1
- data/spec/neovim_spec.rb +28 -51
- data/spec/support.rb +27 -1
- metadata +26 -44
- data/.coveralls.yml +0 -1
- data/.rubocop.yml +0 -118
- data/.travis.yml +0 -22
- data/appveyor.yml +0 -31
- data/bin/neovim-ruby-host +0 -18
- data/script/validate_docs.rb +0 -29
@@ -0,0 +1,46 @@
|
|
1
|
+
require "neovim/version"
|
2
|
+
|
3
|
+
module Neovim
|
4
|
+
# @api private
|
5
|
+
class ClientInfo
|
6
|
+
HOST_METHOD_SPEC = {poll: {}, specs: {nargs: 1}}.freeze
|
7
|
+
|
8
|
+
ATTRIBUTES = {
|
9
|
+
website: "https://github.com/neovim/neovim-ruby",
|
10
|
+
license: "MIT"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
def self.for_host(host)
|
14
|
+
name = host.plugins.map(&:script_host?) == [true] ?
|
15
|
+
"ruby-script-host" :
|
16
|
+
"ruby-rplugin-host"
|
17
|
+
|
18
|
+
new(name, :host, HOST_METHOD_SPEC, ATTRIBUTES)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.for_client
|
22
|
+
new("ruby-client", :remote, {}, ATTRIBUTES)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(name, type, method_spec, attributes)
|
26
|
+
@name = name
|
27
|
+
@type = type
|
28
|
+
@method_spec = method_spec
|
29
|
+
@attributes = attributes
|
30
|
+
|
31
|
+
@version = ["major", "minor", "patch"]
|
32
|
+
.zip(Neovim::VERSION.segments)
|
33
|
+
.to_h
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_args
|
37
|
+
[
|
38
|
+
@name,
|
39
|
+
@version,
|
40
|
+
@type,
|
41
|
+
@method_spec,
|
42
|
+
@attributes
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/neovim/connection.rb
CHANGED
@@ -35,12 +35,12 @@ module Neovim
|
|
35
35
|
|
36
36
|
@unpacker = MessagePack::Unpacker.new(@rd)
|
37
37
|
@packer = MessagePack::Packer.new(@wr)
|
38
|
-
@running = false
|
39
38
|
end
|
40
39
|
|
41
40
|
def write(object)
|
42
41
|
log(:debug) { {object: object} }
|
43
|
-
@packer.write(object)
|
42
|
+
@packer.write(object)
|
43
|
+
self
|
44
44
|
end
|
45
45
|
|
46
46
|
def read
|
@@ -49,6 +49,11 @@ module Neovim
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
def flush
|
53
|
+
@packer.flush
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
52
57
|
def register_type(id)
|
53
58
|
@unpacker.register_type(id) do |data|
|
54
59
|
index = MessagePack.unpack(data)
|
data/lib/neovim/event_loop.rb
CHANGED
@@ -34,8 +34,9 @@ module Neovim
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def shutdown
|
37
|
-
|
37
|
+
@running = false
|
38
38
|
@shutdown = true
|
39
|
+
@connection.close
|
39
40
|
end
|
40
41
|
|
41
42
|
def request(request_id, method, *args)
|
@@ -69,20 +70,23 @@ module Neovim
|
|
69
70
|
|
70
71
|
def run
|
71
72
|
@running = true
|
73
|
+
last_value = nil
|
72
74
|
|
73
75
|
loop do
|
74
76
|
break unless @running
|
75
77
|
break if @shutdown
|
76
78
|
|
77
79
|
begin
|
78
|
-
yield
|
79
|
-
rescue EOFError => e
|
80
|
+
last_value = yield(read)
|
81
|
+
rescue EOFError, Errno::EPIPE => e
|
80
82
|
log_exception(:debug, e, __method__)
|
81
83
|
shutdown
|
82
84
|
rescue => e
|
83
85
|
log_exception(:error, e, __method__)
|
84
86
|
end
|
85
87
|
end
|
88
|
+
|
89
|
+
last_value
|
86
90
|
ensure
|
87
91
|
@connection.close if @shutdown
|
88
92
|
end
|
@@ -102,7 +106,7 @@ module Neovim
|
|
102
106
|
private
|
103
107
|
|
104
108
|
def read
|
105
|
-
array = @connection.read
|
109
|
+
array = @connection.flush.read
|
106
110
|
Message.from_array(array)
|
107
111
|
end
|
108
112
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "neovim/connection"
|
2
|
+
require "neovim/event_loop"
|
3
|
+
require "neovim/host"
|
4
|
+
require "neovim/version"
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
module Neovim
|
8
|
+
class Host
|
9
|
+
# @api private
|
10
|
+
class CLI
|
11
|
+
def self.run(path, argv, inn, out, err)
|
12
|
+
cmd = File.basename(path)
|
13
|
+
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.on("-V", "--version") do
|
16
|
+
out.puts Neovim::VERSION
|
17
|
+
exit(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-h", "--help") do
|
21
|
+
out.puts "Usage: #{cmd} [-hV] rplugin_path ..."
|
22
|
+
exit(0)
|
23
|
+
end
|
24
|
+
end.order!(argv)
|
25
|
+
|
26
|
+
if inn.tty?
|
27
|
+
err.puts("Can't run #{cmd} interactively.")
|
28
|
+
exit(1)
|
29
|
+
else
|
30
|
+
conn = Connection.new(inn, out)
|
31
|
+
event_loop = EventLoop.new(conn)
|
32
|
+
|
33
|
+
Host.run(argv, event_loop)
|
34
|
+
end
|
35
|
+
rescue OptionParser::InvalidOption => e
|
36
|
+
err.puts(e.message)
|
37
|
+
exit(1)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/neovim/host.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "neovim"
|
2
2
|
require "neovim/client"
|
3
|
+
require "neovim/client_info"
|
3
4
|
require "neovim/event_loop"
|
4
5
|
require "neovim/host/loader"
|
5
6
|
|
@@ -78,6 +79,8 @@ module Neovim
|
|
78
79
|
|
79
80
|
def initialize_client(request_id)
|
80
81
|
@session.request_id = request_id
|
82
|
+
@session.notify(:nvim_set_client_info, *ClientInfo.for_host(self).to_args)
|
83
|
+
|
81
84
|
@client = Client.from_event_loop(@event_loop, @session)
|
82
85
|
end
|
83
86
|
|
data/lib/neovim/logging.rb
CHANGED
data/lib/neovim/message.rb
CHANGED
data/lib/neovim/plugin/dsl.rb
CHANGED
@@ -68,6 +68,12 @@ module Neovim
|
|
68
68
|
|
69
69
|
private
|
70
70
|
|
71
|
+
# Mark this plugin as the Ruby script host started by nvim. Should only
|
72
|
+
# be used in +Neovim::RubyProvider+.
|
73
|
+
def script_host!
|
74
|
+
@plugin.script_host = true
|
75
|
+
end
|
76
|
+
|
71
77
|
# Register a setup block to run once before the host starts. The block
|
72
78
|
# should expect to receive a single argument, a +Neovim::Client+.
|
73
79
|
#
|
data/lib/neovim/plugin.rb
CHANGED
@@ -3,7 +3,7 @@ require "neovim/plugin/dsl"
|
|
3
3
|
module Neovim
|
4
4
|
# @api private
|
5
5
|
class Plugin
|
6
|
-
attr_accessor :handlers, :setup_blocks
|
6
|
+
attr_accessor :handlers, :setup_blocks, :script_host
|
7
7
|
attr_reader :source
|
8
8
|
|
9
9
|
def self.from_config_block(source)
|
@@ -13,9 +13,10 @@ module Neovim
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def initialize(source)
|
16
|
-
@handlers = []
|
17
16
|
@source = source
|
17
|
+
@handlers = []
|
18
18
|
@setup_blocks = []
|
19
|
+
@script_host = false
|
19
20
|
end
|
20
21
|
|
21
22
|
def specs
|
@@ -27,5 +28,9 @@ module Neovim
|
|
27
28
|
def setup(client)
|
28
29
|
@setup_blocks.each { |bl| bl.call(client) }
|
29
30
|
end
|
31
|
+
|
32
|
+
def script_host?
|
33
|
+
!!@script_host
|
34
|
+
end
|
30
35
|
end
|
31
36
|
end
|
data/lib/neovim/remote_object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "set"
|
2
|
+
|
1
3
|
module Neovim
|
2
4
|
# @abstract Superclass for all +nvim+ remote objects.
|
3
5
|
#
|
@@ -37,7 +39,7 @@ module Neovim
|
|
37
39
|
|
38
40
|
# Extend +methods+ to include RPC methods
|
39
41
|
def methods(*args)
|
40
|
-
super | rpc_methods
|
42
|
+
super | rpc_methods.to_a
|
41
43
|
end
|
42
44
|
|
43
45
|
# Extend +==+ to only look at class and index.
|
@@ -48,7 +50,8 @@ module Neovim
|
|
48
50
|
private
|
49
51
|
|
50
52
|
def rpc_methods
|
51
|
-
@
|
53
|
+
@rpc_methods ||=
|
54
|
+
@api.functions_for_object(self).map(&:method_name).to_set
|
52
55
|
end
|
53
56
|
end
|
54
57
|
end
|
@@ -15,7 +15,7 @@ module Vim
|
|
15
15
|
|
16
16
|
# Delegate all method calls to the underlying +Neovim::Client+ object.
|
17
17
|
def self.method_missing(method, *args, &block)
|
18
|
-
if @__client
|
18
|
+
if @__client
|
19
19
|
@__client.public_send(method, *args, &block).tap do
|
20
20
|
__refresh_globals(@__client)
|
21
21
|
end
|
@@ -33,13 +33,14 @@ module Vim
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.__refresh_globals(client)
|
36
|
-
|
36
|
+
bufid, winid = client.evaluate("[nvim_get_current_buf(), nvim_get_current_win()]")
|
37
|
+
session, api = client.session, client.api
|
37
38
|
|
38
|
-
$curbuf = @__buffer_cache.fetch(
|
39
|
-
@__buffer_cache[
|
39
|
+
$curbuf = @__buffer_cache.fetch(bufid) do
|
40
|
+
@__buffer_cache[bufid] = Buffer.new(bufid, session, api)
|
40
41
|
end
|
41
42
|
|
42
|
-
$curwin =
|
43
|
+
$curwin = Window.new(winid, session, api)
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
data/lib/neovim/ruby_provider.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "neovim/ruby_provider/vim"
|
2
|
+
require "neovim/ruby_provider/object_ext"
|
2
3
|
require "neovim/ruby_provider/buffer_ext"
|
3
4
|
require "neovim/ruby_provider/window_ext"
|
4
5
|
require "stringio"
|
@@ -14,8 +15,11 @@ module Neovim
|
|
14
15
|
Thread.abort_on_exception = true
|
15
16
|
|
16
17
|
Neovim.plugin do |plug|
|
18
|
+
plug.__send__(:script_host!)
|
19
|
+
|
17
20
|
__define_setup(plug)
|
18
21
|
__define_ruby_execute(plug)
|
22
|
+
__define_ruby_eval(plug)
|
19
23
|
__define_ruby_execute_file(plug)
|
20
24
|
__define_ruby_do_range(plug)
|
21
25
|
__define_ruby_chdir(plug)
|
@@ -42,12 +46,26 @@ module Neovim
|
|
42
46
|
def self.__define_ruby_execute(plug)
|
43
47
|
plug.__send__(:rpc, :ruby_execute) do |nvim, ruby|
|
44
48
|
__wrap_client(nvim) do
|
45
|
-
eval(ruby, TOPLEVEL_BINDING, "
|
49
|
+
eval(ruby, TOPLEVEL_BINDING, "ruby_execute")
|
46
50
|
end
|
51
|
+
nil
|
47
52
|
end
|
48
53
|
end
|
49
54
|
private_class_method :__define_ruby_execute
|
50
55
|
|
56
|
+
# Evaluate the provided Ruby code, exposing the +Vim+ constant for
|
57
|
+
# interactions with the editor and returning the value.
|
58
|
+
#
|
59
|
+
# This is used by the +:rubyeval+ command.
|
60
|
+
def self.__define_ruby_eval(plug)
|
61
|
+
plug.__send__(:rpc, :ruby_eval) do |nvim, ruby|
|
62
|
+
__wrap_client(nvim) do
|
63
|
+
eval(ruby, TOPLEVEL_BINDING, "ruby_eval")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
private_class_method :__define_ruby_eval
|
68
|
+
|
51
69
|
# Evaluate the provided Ruby file, exposing the +Vim+ constant for
|
52
70
|
# interactions with the editor.
|
53
71
|
#
|
@@ -55,6 +73,7 @@ module Neovim
|
|
55
73
|
def self.__define_ruby_execute_file(plug)
|
56
74
|
plug.__send__(:rpc, :ruby_execute_file) do |nvim, path|
|
57
75
|
__wrap_client(nvim) { load(path) }
|
76
|
+
nil
|
58
77
|
end
|
59
78
|
end
|
60
79
|
private_class_method :__define_ruby_execute_file
|
@@ -73,14 +92,15 @@ module Neovim
|
|
73
92
|
__start, __stop, __ruby = __args
|
74
93
|
__buffer = __nvim.get_current_buf
|
75
94
|
|
76
|
-
__update_lines_in_chunks(__buffer, __start, __stop,
|
95
|
+
__update_lines_in_chunks(__buffer, __start, __stop, 1_000) do |__lines|
|
77
96
|
__lines.map do |__line|
|
78
97
|
$_ = __line
|
79
|
-
eval(__ruby, binding, "
|
98
|
+
eval(__ruby, binding, "ruby_do_range")
|
80
99
|
$_
|
81
100
|
end
|
82
101
|
end
|
83
102
|
end
|
103
|
+
nil
|
84
104
|
end
|
85
105
|
end
|
86
106
|
private_class_method :__define_ruby_do_range
|
@@ -101,7 +121,6 @@ module Neovim
|
|
101
121
|
yield
|
102
122
|
end
|
103
123
|
end
|
104
|
-
nil
|
105
124
|
end
|
106
125
|
private_class_method :__wrap_client
|
107
126
|
|
@@ -120,10 +139,10 @@ module Neovim
|
|
120
139
|
$stdout, $stderr = StringIO.new, StringIO.new
|
121
140
|
|
122
141
|
begin
|
123
|
-
yield
|
124
|
-
|
125
|
-
|
126
|
-
|
142
|
+
yield.tap do
|
143
|
+
client.out_write($stdout.string + $/) if $stdout.size > 0
|
144
|
+
client.err_writeln($stderr.string) if $stderr.size > 0
|
145
|
+
end
|
127
146
|
ensure
|
128
147
|
$stdout = old_stdout
|
129
148
|
$stderr = old_stderr
|
@@ -134,9 +153,9 @@ module Neovim
|
|
134
153
|
def self.__update_lines_in_chunks(buffer, start, stop, size)
|
135
154
|
(start..stop).each_slice(size) do |linenos|
|
136
155
|
start, stop = linenos[0] - 1, linenos[-1]
|
137
|
-
lines = buffer.get_lines(start, stop,
|
156
|
+
lines = buffer.get_lines(start, stop, false)
|
138
157
|
|
139
|
-
buffer.set_lines(start, stop,
|
158
|
+
buffer.set_lines(start, stop, false, yield(lines))
|
140
159
|
end
|
141
160
|
end
|
142
161
|
private_class_method :__update_lines_in_chunks
|
data/lib/neovim/session.rb
CHANGED
@@ -11,6 +11,13 @@ module Neovim
|
|
11
11
|
|
12
12
|
attr_writer :request_id
|
13
13
|
|
14
|
+
# @api private
|
15
|
+
class Disconnected < RuntimeError
|
16
|
+
def initialize
|
17
|
+
super("Disconnected from nvim process")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
14
21
|
def initialize(event_loop)
|
15
22
|
@event_loop = event_loop
|
16
23
|
@main_thread = Thread.current
|
@@ -21,19 +28,21 @@ module Neovim
|
|
21
28
|
end
|
22
29
|
|
23
30
|
def run(&block)
|
24
|
-
@
|
31
|
+
block ||= ->(msg) { @pending_messages << msg }
|
25
32
|
|
26
|
-
|
27
|
-
Fiber.new { pending.received(@response_handlers, &block) }.resume
|
28
|
-
end
|
29
|
-
|
30
|
-
return unless @running
|
33
|
+
@running = true
|
31
34
|
|
32
35
|
@event_loop.run do |message|
|
33
36
|
Fiber.new { message.received(@response_handlers, &block) }.resume
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
40
|
+
def next
|
41
|
+
return @pending_messages.shift if @pending_messages.any?
|
42
|
+
|
43
|
+
run { |msg| stop; msg }
|
44
|
+
end
|
45
|
+
|
37
46
|
# Make an RPC request and return its response.
|
38
47
|
#
|
39
48
|
# If this method is called inside a callback, we are already inside a
|
@@ -60,7 +69,10 @@ module Neovim
|
|
60
69
|
|
61
70
|
@event_loop.request(@request_id, method, *args)
|
62
71
|
response = blocking ? blocking_response : yielding_response
|
63
|
-
|
72
|
+
|
73
|
+
raise(Disconnected) if response.nil?
|
74
|
+
raise(response.error) if response.error
|
75
|
+
response.value
|
64
76
|
end
|
65
77
|
end
|
66
78
|
|
@@ -85,15 +97,8 @@ module Neovim
|
|
85
97
|
private
|
86
98
|
|
87
99
|
def blocking_response
|
88
|
-
|
89
|
-
|
90
|
-
@response_handlers[@request_id] = lambda do |res|
|
91
|
-
response = res
|
92
|
-
stop
|
93
|
-
end
|
94
|
-
|
95
|
-
run { |message| @pending_messages << message }
|
96
|
-
response
|
100
|
+
@response_handlers[@request_id] = ->(res) { stop; res }
|
101
|
+
run
|
97
102
|
end
|
98
103
|
|
99
104
|
def yielding_response
|