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.
- checksums.yaml +4 -4
- data/.travis.yml +5 -2
- data/CHANGELOG.md +11 -0
- data/README.md +15 -4
- data/Rakefile +64 -4
- data/bin/j2mp +8 -0
- data/bin/mp2j +8 -0
- data/lib/neovim.rb +100 -17
- data/lib/neovim/api.rb +84 -0
- data/lib/neovim/async_session.rb +74 -21
- data/lib/neovim/buffer.rb +111 -4
- data/lib/neovim/client.rb +175 -4
- data/lib/neovim/current.rb +19 -8
- data/lib/neovim/event_loop.rb +55 -10
- data/lib/neovim/host.rb +21 -8
- data/lib/neovim/line_range.rb +55 -15
- data/lib/neovim/logging.rb +4 -0
- data/lib/neovim/manifest.rb +11 -3
- data/lib/neovim/msgpack_stream.rb +53 -19
- data/lib/neovim/notification.rb +2 -0
- data/lib/neovim/plugin.rb +12 -87
- data/lib/neovim/plugin/dsl.rb +81 -0
- data/lib/neovim/plugin/handler.rb +43 -0
- data/lib/neovim/remote_object.rb +64 -0
- data/lib/neovim/request.rb +4 -2
- data/lib/neovim/session.rb +167 -16
- data/lib/neovim/tabpage.rb +24 -2
- data/lib/neovim/version.rb +1 -1
- data/lib/neovim/window.rb +92 -2
- data/neovim.gemspec +1 -1
- data/spec/acceptance/neovim-ruby-host_spec.rb +16 -8
- data/spec/helper.rb +11 -3
- data/spec/neovim/api_spec.rb +40 -0
- data/spec/neovim/async_session_spec.rb +19 -25
- data/spec/neovim/current_spec.rb +64 -4
- data/spec/neovim/event_loop_spec.rb +18 -27
- data/spec/neovim/host_spec.rb +20 -1
- data/spec/neovim/manifest_spec.rb +0 -2
- data/spec/neovim/msgpack_stream_spec.rb +5 -6
- data/spec/neovim/{object_spec.rb → remote_object_spec.rb} +1 -4
- data/spec/neovim/session_spec.rb +18 -26
- data/spec/neovim_spec.rb +2 -3
- data/spec/support.rb +5 -5
- metadata +13 -6
- data/lib/neovim/api_info.rb +0 -27
- data/lib/neovim/object.rb +0 -40
data/lib/neovim/host.rb
CHANGED
@@ -7,6 +7,20 @@ module Neovim
|
|
7
7
|
|
8
8
|
attr_reader :manifest
|
9
9
|
|
10
|
+
# Load plugin definitions and instantiate a new +Host+. This temporarily
|
11
|
+
# mutates global state on the +Neovim+ module so that +Neovim.plugin+ calls
|
12
|
+
# will be registered correctly with the provided +Manifest+.
|
13
|
+
#
|
14
|
+
# @overload load_from_files(rplugin_paths)
|
15
|
+
# @param rplugin_paths [Array<String>] The remote plugin paths.
|
16
|
+
#
|
17
|
+
# @overload load_from_files(rplugin_paths, target_manifest)
|
18
|
+
# @param rplugin_paths [Array<String>] The remote plugin paths.
|
19
|
+
# @param target_manifest [Manifest] The plugin manifest.
|
20
|
+
#
|
21
|
+
# @return [Host]
|
22
|
+
# @see Neovim.start_host
|
23
|
+
# @see Neovim.plugin
|
10
24
|
def self.load_from_files(rplugin_paths, target_manifest=Manifest.new)
|
11
25
|
old_manifest = Neovim.__configured_plugin_manifest
|
12
26
|
old_path = Neovim.__configured_plugin_path
|
@@ -26,20 +40,19 @@ module Neovim
|
|
26
40
|
end
|
27
41
|
end
|
28
42
|
|
29
|
-
def initialize(manifest)
|
43
|
+
def initialize(manifest, session=nil)
|
44
|
+
@session = session || Session.stdio
|
30
45
|
@manifest = manifest
|
31
|
-
@event_loop = EventLoop.stdio
|
32
|
-
@msgpack_stream = MsgpackStream.new(@event_loop)
|
33
|
-
@async_session = AsyncSession.new(@msgpack_stream)
|
34
46
|
end
|
35
47
|
|
48
|
+
# Run the event loop, passing received messages to the manifest.
|
49
|
+
#
|
50
|
+
# @return [void]
|
36
51
|
def run
|
37
|
-
|
52
|
+
@session.run do |msg|
|
38
53
|
debug("received #{msg.inspect}")
|
39
54
|
@manifest.handle(msg, client)
|
40
55
|
end
|
41
|
-
|
42
|
-
@async_session.run(callback, callback)
|
43
56
|
rescue => e
|
44
57
|
fatal("got unexpected error #{e}")
|
45
58
|
debug(e.backtrace.join("\n"))
|
@@ -48,7 +61,7 @@ module Neovim
|
|
48
61
|
private
|
49
62
|
|
50
63
|
def client
|
51
|
-
@client ||= Client.new(
|
64
|
+
@client ||= Client.new(@session.discover_api)
|
52
65
|
end
|
53
66
|
end
|
54
67
|
end
|
data/lib/neovim/line_range.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Neovim
|
2
|
+
# Provide an enumerable interface for dealing with ranges of lines.
|
2
3
|
class LineRange
|
3
4
|
include Enumerable
|
4
5
|
|
@@ -8,53 +9,92 @@ module Neovim
|
|
8
9
|
@end = _end
|
9
10
|
end
|
10
11
|
|
12
|
+
# @return [Array<String>]
|
11
13
|
def to_a
|
12
14
|
@buffer.get_line_slice(@begin, @end, true, true)
|
13
15
|
end
|
14
16
|
|
17
|
+
# @yield [String] The current line
|
18
|
+
# @return [Array<String>]
|
15
19
|
def each(&block)
|
16
20
|
to_a.each(&block)
|
17
21
|
end
|
18
22
|
|
19
|
-
|
20
|
-
|
23
|
+
# @overload [](index)
|
24
|
+
# @param index [Fixnum]
|
25
|
+
#
|
26
|
+
# @overload [](range)
|
27
|
+
# @param range [Range]
|
28
|
+
#
|
29
|
+
# @overload [](index, length)
|
30
|
+
# @param index [Fixnum]
|
31
|
+
# @param length [Fixnum]
|
32
|
+
#
|
33
|
+
# @example Get the first line using an index
|
34
|
+
# line_range[0] # => "first"
|
35
|
+
# @example Get the first two lines using a +Range+
|
36
|
+
# line_range[0..1] # => ["first", "second"]
|
37
|
+
# @example Get the first two lines using an index and length
|
38
|
+
# line_range[0, 2] # => ["first", "second"]
|
39
|
+
def [](pos, len=nil)
|
40
|
+
case pos
|
21
41
|
when ::Range
|
22
|
-
_end =
|
23
|
-
LineRange.new(@buffer,
|
42
|
+
_end = pos.exclude_end? ? pos.end - 1 : pos.end
|
43
|
+
LineRange.new(@buffer, pos.begin, _end)
|
24
44
|
else
|
25
45
|
if len
|
26
|
-
LineRange.new(@buffer,
|
46
|
+
LineRange.new(@buffer, pos, pos + len - 1)
|
27
47
|
else
|
28
|
-
@buffer.get_line(
|
48
|
+
@buffer.get_line(pos)
|
29
49
|
end
|
30
50
|
end
|
31
51
|
end
|
32
52
|
alias_method :slice, :[]
|
33
53
|
|
54
|
+
# @overload []=(index, string)
|
55
|
+
# @param index [Fixnum]
|
56
|
+
# @param string [String]
|
57
|
+
#
|
58
|
+
# @overload []=(index, length, strings)
|
59
|
+
# @param index [Fixnum]
|
60
|
+
# @param length [Fixnum]
|
61
|
+
# @param strings [Array<String>]
|
62
|
+
#
|
63
|
+
# @overload []=(range, strings)
|
64
|
+
# @param range [Range]
|
65
|
+
# @param strings [Array<String>]
|
66
|
+
#
|
67
|
+
# @example Replace the first line using an index
|
68
|
+
# line_range[0] = "first"
|
69
|
+
# @example Replace the first two lines using a +Range+
|
70
|
+
# line_range[0..1] = ["first", "second"]
|
71
|
+
# @example Replace the first two lines using an index and length
|
72
|
+
# line_range[0, 2] = ["first", "second"]
|
34
73
|
def []=(*args)
|
35
74
|
*target, val = args
|
36
|
-
|
75
|
+
pos, len = target
|
37
76
|
|
38
|
-
case
|
77
|
+
case pos
|
39
78
|
when ::Range
|
40
79
|
@buffer.set_line_slice(
|
41
|
-
|
42
|
-
|
80
|
+
pos.begin,
|
81
|
+
pos.end,
|
43
82
|
true,
|
44
|
-
!
|
83
|
+
!pos.exclude_end?,
|
45
84
|
val
|
46
85
|
)
|
47
86
|
else
|
48
87
|
if len
|
49
|
-
@buffer.set_line_slice(
|
88
|
+
@buffer.set_line_slice(pos, pos + len, true, false, val)
|
50
89
|
else
|
51
|
-
@buffer.set_line(
|
90
|
+
@buffer.set_line(pos, val)
|
52
91
|
end
|
53
92
|
end
|
54
93
|
end
|
55
94
|
|
56
|
-
|
57
|
-
|
95
|
+
# @param other [Array] The replacement lines
|
96
|
+
def replace(other)
|
97
|
+
self[0..-1] = other
|
58
98
|
self
|
59
99
|
end
|
60
100
|
end
|
data/lib/neovim/logging.rb
CHANGED
@@ -2,11 +2,15 @@ require "logger"
|
|
2
2
|
require "stringio"
|
3
3
|
|
4
4
|
module Neovim
|
5
|
+
# Mixed into classes for unified logging helper methods.
|
5
6
|
module Logging
|
6
7
|
class << self
|
7
8
|
attr_writer :logger
|
8
9
|
end
|
9
10
|
|
11
|
+
# Return the value of @logger, or construct it from the environment.
|
12
|
+
# $NVIM_RUBY_LOG_FILE specifies a file to log to (default +STDOUT+), while
|
13
|
+
# NVIM_RUBY_LOG_LEVEL specifies the level (default +WARN+)
|
10
14
|
def self.logger
|
11
15
|
return @logger if instance_variable_defined?(:@logger)
|
12
16
|
|
data/lib/neovim/manifest.rb
CHANGED
@@ -11,6 +11,9 @@ module Neovim
|
|
11
11
|
@specs = {}
|
12
12
|
end
|
13
13
|
|
14
|
+
# Register a +Plugin+ to receive +Host+ messages.
|
15
|
+
#
|
16
|
+
# @param plugin [Plugin]
|
14
17
|
def register(plugin)
|
15
18
|
plugin.handlers.each do |handler|
|
16
19
|
wrapped_handler = handler.sync? ? wrap_sync(handler) : wrap_async(handler)
|
@@ -20,9 +23,14 @@ module Neovim
|
|
20
23
|
@specs[plugin.source] = plugin.specs
|
21
24
|
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
+
# Handle messages received from the host. Sends a +Neovim::Client+ along
|
27
|
+
# with the message to be used in plugin callbacks.
|
28
|
+
#
|
29
|
+
# @param message [Neovim::Request, Neovim::Notification]
|
30
|
+
# @param client [Neovim::Client]
|
31
|
+
def handle(message, client)
|
32
|
+
default_handler = message.sync? ? default_sync_handler : default_async_handler
|
33
|
+
@handlers.fetch(message.method_name, default_handler).call(client, message)
|
26
34
|
rescue => e
|
27
35
|
fatal("got unexpected error #{e}")
|
28
36
|
debug(e.backtrace.join("\n"))
|
@@ -2,6 +2,8 @@ require "neovim/logging"
|
|
2
2
|
require "msgpack"
|
3
3
|
|
4
4
|
module Neovim
|
5
|
+
# Handles serializing RPC messages to MessagePack and passing them to
|
6
|
+
# the event loop
|
5
7
|
class MsgpackStream
|
6
8
|
include Logging
|
7
9
|
|
@@ -10,35 +12,67 @@ module Neovim
|
|
10
12
|
@unpacker = MessagePack::Unpacker.new
|
11
13
|
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
def send(msg)
|
25
|
-
debug("sending #{msg.inspect}")
|
26
|
-
@event_loop.send(MessagePack.pack(msg))
|
15
|
+
# Serialize an RPC message to and write it to the event loop.
|
16
|
+
#
|
17
|
+
# @param msg [Array] The RPC message
|
18
|
+
# @return [self]
|
19
|
+
# @example Write an RPC request
|
20
|
+
# msgpack_stream.write([0, 1, :vim_strwidth, ["foobar"]])
|
21
|
+
def write(msg)
|
22
|
+
debug("writing #{msg.inspect}")
|
23
|
+
@event_loop.write(MessagePack.pack(msg))
|
27
24
|
self
|
28
25
|
end
|
29
26
|
|
30
|
-
|
31
|
-
|
27
|
+
# Run the event loop, yielding deserialized messages to the block.
|
28
|
+
#
|
29
|
+
# @param session [Session] Used for registering msgpack +ext+ types as
|
30
|
+
# described by the +vim_get_api_info+ call
|
31
|
+
# @return [void]
|
32
|
+
# @see EventLoop#run
|
33
|
+
def run(session=nil)
|
34
|
+
register_types(session)
|
35
|
+
|
36
|
+
@event_loop.run do |data|
|
32
37
|
@unpacker.feed_each(data) do |msg|
|
33
38
|
debug("received #{msg.inspect}")
|
34
|
-
|
39
|
+
yield msg if block_given?
|
35
40
|
end
|
36
41
|
end
|
37
|
-
|
38
|
-
@event_loop.run(data_cb, setup_cb)
|
39
42
|
rescue => e
|
40
43
|
fatal("got unexpected error #{e}")
|
41
44
|
debug(e.backtrace.join("\n"))
|
42
45
|
end
|
46
|
+
|
47
|
+
# Stop the event loop.
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
# @see EventLoop#stop
|
51
|
+
def stop
|
52
|
+
@event_loop.stop
|
53
|
+
end
|
54
|
+
|
55
|
+
# Shut down the event loop.
|
56
|
+
#
|
57
|
+
# @return [void]
|
58
|
+
# @see EventLoop#shutdown
|
59
|
+
def shutdown
|
60
|
+
@event_loop.shutdown
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def register_types(session)
|
66
|
+
return unless session && session.api
|
67
|
+
|
68
|
+
session.api.types.each do |type, info|
|
69
|
+
klass = Neovim.const_get(type)
|
70
|
+
id = info.fetch("id")
|
71
|
+
|
72
|
+
@unpacker.register_type(id) do |data|
|
73
|
+
klass.new(MessagePack.unpack(data), session)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
43
77
|
end
|
44
78
|
end
|
data/lib/neovim/notification.rb
CHANGED
data/lib/neovim/plugin.rb
CHANGED
@@ -1,103 +1,28 @@
|
|
1
|
+
require "neovim/plugin/dsl"
|
2
|
+
|
1
3
|
module Neovim
|
2
4
|
class Plugin
|
3
|
-
|
5
|
+
attr_accessor :handlers
|
6
|
+
attr_reader :source
|
7
|
+
|
8
|
+
# Entrypoint to the +Neovim.plugin+ DSL.
|
9
|
+
#
|
10
|
+
# @param source [String] The path of the plugin file.
|
11
|
+
# @yield [DSL] The receiver of DSL methods.
|
12
|
+
def self.from_config_block(source)
|
4
13
|
new(source).tap do |instance|
|
5
|
-
|
14
|
+
yield DSL.new(instance) if block_given?
|
6
15
|
end
|
7
16
|
end
|
8
17
|
|
9
|
-
attr_accessor :handlers
|
10
|
-
attr_reader :source
|
11
|
-
|
12
18
|
def initialize(source)
|
13
19
|
@handlers = []
|
14
20
|
@source = source
|
15
21
|
end
|
16
22
|
|
23
|
+
# @return [Array] Handler specs used by +nvim+ to register plugins.
|
17
24
|
def specs
|
18
25
|
@handlers.map(&:to_spec)
|
19
26
|
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
|
58
|
-
end
|
59
|
-
|
60
|
-
class DSL < BasicObject
|
61
|
-
def initialize(plugin)
|
62
|
-
@plugin = plugin
|
63
|
-
end
|
64
|
-
|
65
|
-
def command(name, options={}, &block)
|
66
|
-
register_handler(:command, name, options, block)
|
67
|
-
end
|
68
|
-
|
69
|
-
def function(name, options={}, &block)
|
70
|
-
register_handler(:function, name, options, block)
|
71
|
-
end
|
72
|
-
|
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
|
85
|
-
|
86
|
-
sync = options.delete(:sync)
|
87
|
-
|
88
|
-
@plugin.handlers.push(
|
89
|
-
Handler.new(@plugin.source, type, name, sync, options, block)
|
90
|
-
)
|
91
|
-
end
|
92
|
-
|
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
|
98
|
-
|
99
|
-
options
|
100
|
-
end
|
101
|
-
end
|
102
27
|
end
|
103
28
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "neovim/plugin/handler"
|
2
|
+
|
3
|
+
module Neovim
|
4
|
+
class Plugin
|
5
|
+
# The DSL exposed in +Neovim.plugin+ blocks.
|
6
|
+
class DSL < BasicObject
|
7
|
+
def initialize(plugin)
|
8
|
+
@plugin = plugin
|
9
|
+
end
|
10
|
+
|
11
|
+
# Register an +nvim+ command.
|
12
|
+
#
|
13
|
+
# @param name [String]
|
14
|
+
# @param options [Hash]
|
15
|
+
# @param &block [Proc, nil]
|
16
|
+
#
|
17
|
+
# @option options [Fixnum] :nargs
|
18
|
+
# @option options [Fixnum] :count
|
19
|
+
# @option options [String] :eval
|
20
|
+
# @option options [Boolean] :sync (false)
|
21
|
+
# @option options [Boolean] :bang
|
22
|
+
# @option options [Boolean] :register
|
23
|
+
# @option options [Boolean] :complete
|
24
|
+
# @option options [String, Boolean] :range
|
25
|
+
def command(name, options={}, &block)
|
26
|
+
register_handler(:command, name, options, block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Register an +nvim+ function.
|
30
|
+
#
|
31
|
+
# @param name [String]
|
32
|
+
# @param options [Hash]
|
33
|
+
# @param &block [Proc, nil]
|
34
|
+
#
|
35
|
+
# @option options [String] :eval
|
36
|
+
# @option options [Boolean] :sync (false)
|
37
|
+
# @option options [String, Boolean] :range
|
38
|
+
def function(name, options={}, &block)
|
39
|
+
register_handler(:function, name, options, block)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Register an +nvim+ autocmd.
|
43
|
+
#
|
44
|
+
# @param event [String]
|
45
|
+
# @param options [Hash]
|
46
|
+
# @param &block [Proc, nil]
|
47
|
+
#
|
48
|
+
# @option options [String] :pattern
|
49
|
+
# @option options [String] :eval
|
50
|
+
# @option options [Boolean] :sync (false)
|
51
|
+
def autocmd(event, options={}, &block)
|
52
|
+
register_handler(:autocmd, event, options, block)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def register_handler(type, name, _options, block)
|
58
|
+
if type == :autocmd
|
59
|
+
options = _options.dup
|
60
|
+
else
|
61
|
+
options = standardize_range(_options.dup)
|
62
|
+
end
|
63
|
+
|
64
|
+
sync = options.delete(:sync)
|
65
|
+
|
66
|
+
@plugin.handlers.push(
|
67
|
+
Handler.new(@plugin.source, type, name, sync, options, block)
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def standardize_range(options)
|
72
|
+
if options.key?(:range)
|
73
|
+
options[:range] = "" if options[:range] == true
|
74
|
+
options[:range] = ::Kernel.String(options[:range])
|
75
|
+
end
|
76
|
+
|
77
|
+
options
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|