neovim 0.0.6 → 0.1.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 +4 -4
- data/.travis.yml +4 -19
- data/CHANGELOG.md +9 -0
- data/README.md +2 -2
- data/Rakefile +1 -25
- data/bin/j2mp +1 -1
- data/bin/mp2j +1 -1
- data/bin/neovim-ruby-host +9 -0
- data/lib/neovim.rb +5 -7
- data/lib/neovim/async_session.rb +2 -1
- data/lib/neovim/buffer.rb +112 -0
- data/lib/neovim/client.rb +4 -2
- data/lib/neovim/current.rb +9 -1
- data/lib/neovim/event_loop.rb +8 -4
- data/lib/neovim/host.rb +3 -1
- data/lib/neovim/line_range.rb +34 -10
- data/lib/neovim/logging.rb +29 -20
- data/lib/neovim/manifest.rb +9 -3
- data/lib/neovim/plugin.rb +3 -1
- data/lib/neovim/plugin/dsl.rb +14 -0
- data/lib/neovim/plugin/handler.rb +24 -5
- data/lib/neovim/ruby_provider.rb +138 -0
- data/lib/neovim/session.rb +14 -5
- data/lib/neovim/version.rb +1 -1
- data/lib/neovim/window.rb +52 -59
- data/spec/acceptance/neovim-ruby-host_spec.rb +6 -1
- data/spec/acceptance/ruby_provider_spec.rb +76 -0
- data/spec/helper.rb +13 -19
- data/spec/neovim/async_session_spec.rb +19 -15
- data/spec/neovim/buffer_spec.rb +127 -1
- data/spec/neovim/client_spec.rb +1 -1
- data/spec/neovim/current_spec.rb +9 -1
- data/spec/neovim/event_loop_spec.rb +20 -21
- data/spec/neovim/host_spec.rb +1 -1
- data/spec/neovim/line_range_spec.rb +73 -9
- data/spec/neovim/manifest_spec.rb +26 -0
- data/spec/neovim/msgpack_stream_spec.rb +8 -8
- data/spec/neovim/plugin_spec.rb +41 -0
- data/spec/neovim/remote_object_spec.rb +3 -3
- data/spec/neovim/session_spec.rb +68 -29
- data/spec/neovim/window_spec.rb +47 -24
- data/spec/neovim_spec.rb +3 -5
- data/spec/support.rb +1 -2
- metadata +5 -3
- data/.gitmodules +0 -4
data/lib/neovim/logging.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "logger"
|
2
|
-
require "stringio"
|
3
2
|
|
4
3
|
module Neovim
|
5
4
|
# Mixed into classes for unified logging helper methods.
|
@@ -14,14 +13,18 @@ module Neovim
|
|
14
13
|
def self.logger
|
15
14
|
return @logger if instance_variable_defined?(:@logger)
|
16
15
|
|
17
|
-
if ENV["NVIM_RUBY_LOG_FILE"]
|
18
|
-
@logger = Logger.new(
|
16
|
+
if env_file = ENV["NVIM_RUBY_LOG_FILE"]
|
17
|
+
@logger = Logger.new(env_file)
|
19
18
|
else
|
20
19
|
@logger = Logger.new(STDERR)
|
21
20
|
end
|
22
21
|
|
23
|
-
if ENV["NVIM_RUBY_LOG_LEVEL"]
|
24
|
-
|
22
|
+
if env_level = ENV["NVIM_RUBY_LOG_LEVEL"]
|
23
|
+
if Logger.const_defined?(env_level.upcase)
|
24
|
+
@logger.level = Logger.const_get(env_level.upcase)
|
25
|
+
else
|
26
|
+
@logger.level = Integer(env_level)
|
27
|
+
end
|
25
28
|
else
|
26
29
|
@logger.level = Logger::WARN
|
27
30
|
end
|
@@ -29,26 +32,32 @@ module Neovim
|
|
29
32
|
@logger
|
30
33
|
end
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
def fatal(msg)
|
35
|
-
logger.fatal(self.class) { msg }
|
35
|
+
def self.included(base)
|
36
|
+
base.send(:include, Helpers)
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
39
|
+
module Helpers
|
40
|
+
private
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
def fatal(msg)
|
43
|
+
logger.fatal(self.class) { msg }
|
44
|
+
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def warn(msg)
|
47
|
+
logger.warn(self.class) { msg }
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
50
|
+
def info(msg)
|
51
|
+
logger.info(self.class) { msg }
|
52
|
+
end
|
53
|
+
|
54
|
+
def debug(msg)
|
55
|
+
logger.debug(self.class) { msg }
|
56
|
+
end
|
57
|
+
|
58
|
+
def logger
|
59
|
+
Logging.logger
|
60
|
+
end
|
52
61
|
end
|
53
62
|
end
|
54
63
|
end
|
data/lib/neovim/manifest.rb
CHANGED
@@ -68,15 +68,21 @@ module Neovim
|
|
68
68
|
|
69
69
|
def wrap_sync(handler)
|
70
70
|
Proc.new do |client, request|
|
71
|
-
|
72
|
-
|
71
|
+
begin
|
72
|
+
debug("received #{request.inspect}")
|
73
|
+
args = request.arguments.flatten(1)
|
74
|
+
request.respond(handler.call(client, *args))
|
75
|
+
rescue => e
|
76
|
+
request.error(e.message)
|
77
|
+
end
|
73
78
|
end
|
74
79
|
end
|
75
80
|
|
76
81
|
def wrap_async(handler)
|
77
82
|
Proc.new do |client, notification|
|
78
83
|
debug("received #{notification.inspect}")
|
79
|
-
|
84
|
+
args = notification.arguments.flatten(1)
|
85
|
+
handler.call(client, *args)
|
80
86
|
end
|
81
87
|
end
|
82
88
|
end
|
data/lib/neovim/plugin.rb
CHANGED
data/lib/neovim/plugin/dsl.rb
CHANGED
@@ -52,6 +52,20 @@ module Neovim
|
|
52
52
|
register_handler(:autocmd, event, options, block)
|
53
53
|
end
|
54
54
|
|
55
|
+
# Register a top-level remote procedure call (RPC).
|
56
|
+
#
|
57
|
+
# This can be used to directly expose an RPC call without a namespace.
|
58
|
+
# This is used primarily for exposing legacy ruby provider calls.
|
59
|
+
#
|
60
|
+
# @option options [Boolean] :sync (false)
|
61
|
+
def rpc(name, options={}, &block)
|
62
|
+
sync = options.delete(:sync)
|
63
|
+
|
64
|
+
@plugin.handlers.push(
|
65
|
+
Handler.unqualified(name, sync, options, block)
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
55
69
|
private
|
56
70
|
|
57
71
|
def register_handler(type, name, _options, block)
|
@@ -4,16 +4,39 @@ module Neovim
|
|
4
4
|
class Handler
|
5
5
|
attr_reader :block
|
6
6
|
|
7
|
+
def self.unqualified(name, sync, options, block)
|
8
|
+
new(
|
9
|
+
nil,
|
10
|
+
nil,
|
11
|
+
name,
|
12
|
+
sync,
|
13
|
+
options.merge(:qualified => false),
|
14
|
+
block
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
7
18
|
def initialize(source, type, name, sync, options, block)
|
8
19
|
@source = source
|
9
|
-
@type = type.to_sym
|
20
|
+
@type = type.to_sym if type.respond_to?(:to_sym)
|
10
21
|
@name = name.to_s
|
11
22
|
@sync = !!sync
|
12
23
|
@options = options
|
13
24
|
@block = block || Proc.new {}
|
25
|
+
@qualified =
|
26
|
+
options.key?(:qualified) ? options.delete(:qualified) : true
|
27
|
+
end
|
28
|
+
|
29
|
+
def sync?
|
30
|
+
@sync
|
31
|
+
end
|
32
|
+
|
33
|
+
def qualified?
|
34
|
+
@qualified
|
14
35
|
end
|
15
36
|
|
16
37
|
def qualified_name
|
38
|
+
return @name unless qualified?
|
39
|
+
|
17
40
|
if @type == :autocmd
|
18
41
|
pattern = @options.fetch(:pattern, "*")
|
19
42
|
"#{@source}:#{@type}:#{@name}:#{pattern}"
|
@@ -22,10 +45,6 @@ module Neovim
|
|
22
45
|
end
|
23
46
|
end
|
24
47
|
|
25
|
-
def sync?
|
26
|
-
@sync
|
27
|
-
end
|
28
|
-
|
29
48
|
def to_spec
|
30
49
|
{
|
31
50
|
:type => @type,
|
@@ -0,0 +1,138 @@
|
|
1
|
+
class VIM < BasicObject
|
2
|
+
class << self
|
3
|
+
attr_accessor :__client
|
4
|
+
end
|
5
|
+
|
6
|
+
Buffer = ::Neovim::Buffer
|
7
|
+
Window = ::Neovim::Window
|
8
|
+
|
9
|
+
def self.method_missing(method, *args, &block)
|
10
|
+
@__client.public_send(method, *args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Neovim
|
15
|
+
# Make +VIM::Buffer.current+ return the current buffer.
|
16
|
+
class Buffer
|
17
|
+
def self.current
|
18
|
+
::VIM.current.buffer
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Make +VIM::Window.current+ return the current buffer.
|
23
|
+
class Window
|
24
|
+
def self.current
|
25
|
+
::VIM.current.window
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module RubyProvider
|
30
|
+
def self.define_plugin!
|
31
|
+
Neovim.plugin do |plug|
|
32
|
+
define_ruby_execute(plug)
|
33
|
+
define_ruby_execute_file(plug)
|
34
|
+
define_ruby_do_range(plug)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.define_ruby_execute(plug)
|
39
|
+
plug.rpc(:ruby_execute, sync: true) do |nvim, ruby|
|
40
|
+
wrap_client(nvim) do
|
41
|
+
eval(ruby, binding, __FILE__, __LINE__)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
private_class_method :define_ruby_execute
|
46
|
+
|
47
|
+
def self.define_ruby_execute_file(plug)
|
48
|
+
plug.rpc(:ruby_execute_file, sync: true) do |nvim, path|
|
49
|
+
wrap_client(nvim) do
|
50
|
+
eval(File.read(path), binding, __FILE__, __LINE__)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
private_class_method :define_ruby_execute_file
|
55
|
+
|
56
|
+
def self.define_ruby_do_range(plug)
|
57
|
+
plug.rpc(:ruby_do_range, sync: true) do |nvim, *args|
|
58
|
+
begin
|
59
|
+
start, stop, ruby = args
|
60
|
+
buffer = nvim.current.buffer
|
61
|
+
|
62
|
+
(start..stop).each_slice(5000) do |linenos|
|
63
|
+
_start, _stop = linenos[0]-1, linenos[-1]
|
64
|
+
lines = buffer.get_lines(_start, _stop, true)
|
65
|
+
|
66
|
+
lines.map! do |line|
|
67
|
+
$_ = line
|
68
|
+
eval(ruby, binding, __FILE__, __LINE__)
|
69
|
+
String($_)
|
70
|
+
end
|
71
|
+
|
72
|
+
buffer.set_lines(_start, _stop, true, lines)
|
73
|
+
end
|
74
|
+
ensure
|
75
|
+
$_ = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
private_class_method :define_ruby_do_range
|
80
|
+
|
81
|
+
def self.wrap_client(client)
|
82
|
+
with_globals(client) do
|
83
|
+
with_vim_constant(client) do
|
84
|
+
with_redirect_streams(client) do
|
85
|
+
yield
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
private_class_method :wrap_client
|
91
|
+
|
92
|
+
def self.with_globals(client)
|
93
|
+
$curwin = client.current.window
|
94
|
+
$curbuf = client.current.buffer
|
95
|
+
|
96
|
+
begin
|
97
|
+
yield
|
98
|
+
ensure
|
99
|
+
$curwin = $curbuf = nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
private_class_method :with_globals
|
103
|
+
|
104
|
+
def self.with_vim_constant(client)
|
105
|
+
::VIM.__client = client
|
106
|
+
|
107
|
+
begin
|
108
|
+
yield
|
109
|
+
ensure
|
110
|
+
::VIM.__client = nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
private_class_method :with_vim_constant
|
114
|
+
|
115
|
+
def self.with_redirect_streams(client)
|
116
|
+
old_out_write = $stdout.method(:write)
|
117
|
+
old_err_write = $stderr.method(:write)
|
118
|
+
|
119
|
+
$stdout.define_singleton_method(:write) do |string|
|
120
|
+
client.out_write(string)
|
121
|
+
end
|
122
|
+
|
123
|
+
$stderr.define_singleton_method(:write) do |string|
|
124
|
+
client.err_write(string)
|
125
|
+
end
|
126
|
+
|
127
|
+
begin
|
128
|
+
yield
|
129
|
+
ensure
|
130
|
+
$stdout.define_singleton_method(:write, &old_out_write)
|
131
|
+
$stderr.define_singleton_method(:write, &old_err_write)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
private_class_method :with_redirect_streams
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
Neovim::RubyProvider.define_plugin!
|
data/lib/neovim/session.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require "neovim/api"
|
2
|
+
require "neovim/async_session"
|
3
|
+
require "neovim/event_loop"
|
4
|
+
require "neovim/msgpack_stream"
|
2
5
|
require "fiber"
|
3
6
|
|
4
7
|
module Neovim
|
@@ -66,11 +69,10 @@ module Neovim
|
|
66
69
|
|
67
70
|
# Discover the +nvim+ API as described in the +vim_get_api_info+ call.
|
68
71
|
#
|
69
|
-
# @return [
|
72
|
+
# @return [API]
|
70
73
|
# @see API
|
71
74
|
def discover_api
|
72
75
|
@api = API.new(request(:vim_get_api_info))
|
73
|
-
self
|
74
76
|
end
|
75
77
|
|
76
78
|
# Run the event loop, handling messages in a +Fiber+.
|
@@ -121,7 +123,7 @@ module Neovim
|
|
121
123
|
err ? raise(ArgumentError, err) : res
|
122
124
|
end
|
123
125
|
|
124
|
-
# Make an RPC notification
|
126
|
+
# Make an RPC notification.
|
125
127
|
#
|
126
128
|
# @param method [String, Symbol] The RPC method name
|
127
129
|
# @param *args [Array] The RPC method arguments
|
@@ -131,7 +133,7 @@ module Neovim
|
|
131
133
|
nil
|
132
134
|
end
|
133
135
|
|
134
|
-
# Stop the event loop
|
136
|
+
# Stop the event loop.
|
135
137
|
#
|
136
138
|
# @return [void]
|
137
139
|
# @see EventLoop#stop
|
@@ -140,7 +142,7 @@ module Neovim
|
|
140
142
|
@async_session.stop
|
141
143
|
end
|
142
144
|
|
143
|
-
# Shut down the event loop
|
145
|
+
# Shut down the event loop.
|
144
146
|
#
|
145
147
|
# @return [void]
|
146
148
|
# @see EventLoop#shutdown
|
@@ -149,6 +151,13 @@ module Neovim
|
|
149
151
|
@async_session.shutdown
|
150
152
|
end
|
151
153
|
|
154
|
+
# Return the channel ID if registered via +vim_get_api_info+.
|
155
|
+
#
|
156
|
+
# @return [Fixnum, nil]
|
157
|
+
def channel_id
|
158
|
+
api.channel_id
|
159
|
+
end
|
160
|
+
|
152
161
|
private
|
153
162
|
|
154
163
|
def in_handler_fiber(&block)
|
data/lib/neovim/version.rb
CHANGED
data/lib/neovim/window.rb
CHANGED
@@ -10,65 +10,58 @@ module Neovim
|
|
10
10
|
@cursor ||= Cursor.new(self)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
# @param n [Fixnum]
|
66
|
-
# @return [Fixnum]
|
67
|
-
# @note Column numbers are 1-indexed
|
68
|
-
def column=(n)
|
69
|
-
self.coordinates = [line, n]
|
70
|
-
n
|
71
|
-
end
|
13
|
+
# Get the buffer displayed in the window
|
14
|
+
#
|
15
|
+
# @return [Buffer]
|
16
|
+
def buffer
|
17
|
+
get_buffer
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get the height of the window
|
21
|
+
#
|
22
|
+
# @return [Fixnum]
|
23
|
+
def height
|
24
|
+
get_height
|
25
|
+
end
|
26
|
+
|
27
|
+
# Set the height of the window
|
28
|
+
#
|
29
|
+
# @param height [Fixnum]
|
30
|
+
# @return [Fixnum]
|
31
|
+
def height=(height)
|
32
|
+
set_height(height)
|
33
|
+
height
|
34
|
+
end
|
35
|
+
|
36
|
+
# Get the width of the window
|
37
|
+
#
|
38
|
+
# @return [Fixnum]
|
39
|
+
def width
|
40
|
+
get_width
|
41
|
+
end
|
42
|
+
|
43
|
+
# Set the width of the window
|
44
|
+
#
|
45
|
+
# @param width [Fixnum]
|
46
|
+
# @return [Fixnum]
|
47
|
+
def width=(width)
|
48
|
+
set_width(width)
|
49
|
+
width
|
50
|
+
end
|
51
|
+
|
52
|
+
# Get the cursor coordinates
|
53
|
+
#
|
54
|
+
# @return [Array(Fixnum, Fixnum)]
|
55
|
+
def cursor
|
56
|
+
get_cursor
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the cursor coodinates
|
60
|
+
#
|
61
|
+
# @param coords [Array(Fixnum, Fixnum)]
|
62
|
+
# @return [Array(Fixnum, Fixnum)]
|
63
|
+
def cursor=(coords)
|
64
|
+
set_cursor(coords)
|
72
65
|
end
|
73
66
|
|
74
67
|
# The following methods are dynamically generated.
|