neovim 0.7.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|