neovim 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +9 -3
  4. data/CODE_OF_CONDUCT.md +46 -0
  5. data/README.md +2 -2
  6. data/Rakefile +6 -6
  7. data/lib/neovim.rb +8 -7
  8. data/lib/neovim/api.rb +87 -0
  9. data/lib/neovim/buffer.rb +7 -1
  10. data/lib/neovim/client.rb +32 -6
  11. data/lib/neovim/event_loop.rb +114 -0
  12. data/lib/neovim/event_loop/connection.rb +78 -0
  13. data/lib/neovim/event_loop/message_builder.rb +127 -0
  14. data/lib/neovim/event_loop/serializer.rb +37 -0
  15. data/lib/neovim/host.rb +28 -28
  16. data/lib/neovim/logging.rb +41 -19
  17. data/lib/neovim/plugin/dsl.rb +6 -6
  18. data/lib/neovim/remote_object.rb +2 -2
  19. data/lib/neovim/ruby_provider.rb +8 -6
  20. data/lib/neovim/ruby_provider/vim.rb +2 -2
  21. data/lib/neovim/session.rb +42 -79
  22. data/lib/neovim/tabpage.rb +1 -1
  23. data/lib/neovim/version.rb +1 -1
  24. data/lib/neovim/window.rb +1 -1
  25. data/script/dump_api +4 -2
  26. data/script/generate_docs +2 -1
  27. data/spec/{integration → acceptance}/rplugin_autocmd_spec.vim +1 -1
  28. data/spec/{integration → acceptance}/rplugin_command_spec.vim +6 -2
  29. data/spec/{integration → acceptance}/rplugin_function_spec.vim +5 -2
  30. data/spec/{integration → acceptance}/ruby_spec.vim +18 -0
  31. data/spec/{integration → acceptance}/rubydo_spec.vim +0 -0
  32. data/spec/{integration → acceptance}/rubyfile/call_foo.rb +0 -0
  33. data/spec/{integration → acceptance}/rubyfile/curbuf_ivar_get.rb +0 -0
  34. data/spec/{integration → acceptance}/rubyfile/curbuf_ivar_set.rb +0 -0
  35. data/spec/{integration → acceptance}/rubyfile/define_foo.rb +0 -0
  36. data/spec/acceptance/rubyfile/nested.rb +1 -0
  37. data/spec/acceptance/rubyfile/nested_inner.rb +1 -0
  38. data/spec/{integration → acceptance}/rubyfile/raise_standard_error.rb +0 -0
  39. data/spec/{integration → acceptance}/rubyfile/raise_syntax_error.rb +0 -0
  40. data/spec/acceptance/rubyfile/ruby_interface.rb +8 -0
  41. data/spec/{integration → acceptance}/rubyfile/set_pwd_after.rb +0 -0
  42. data/spec/{integration → acceptance}/rubyfile/set_pwd_before.rb +0 -0
  43. data/spec/{integration → acceptance}/rubyfile_spec.vim +9 -0
  44. data/spec/acceptance/runtime/init.vim +8 -0
  45. data/spec/acceptance/runtime/rplugin.vim +37 -0
  46. data/spec/{integration → acceptance}/runtime/rplugin/ruby/autocmds.rb +1 -1
  47. data/spec/{integration → acceptance}/runtime/rplugin/ruby/commands.rb +9 -1
  48. data/spec/{integration → acceptance}/runtime/rplugin/ruby/functions.rb +9 -1
  49. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader.vim +0 -0
  50. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/assert.vim +0 -0
  51. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/helper.vim +0 -0
  52. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/parser.vim +0 -0
  53. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/syntax.vim +0 -0
  54. data/spec/{integration → acceptance}/runtime/vader.vim/autoload/vader/window.vim +0 -0
  55. data/spec/{integration → acceptance}/runtime/vader.vim/plugin/vader.vim +0 -0
  56. data/spec/acceptance_spec.rb +74 -0
  57. data/spec/helper.rb +2 -32
  58. data/spec/neovim/api_spec.rb +59 -0
  59. data/spec/neovim/buffer_spec.rb +161 -2
  60. data/spec/neovim/client_spec.rb +18 -4
  61. data/spec/neovim/event_loop/connection_spec.rb +63 -0
  62. data/spec/neovim/event_loop/message_builder_spec.rb +105 -0
  63. data/spec/neovim/event_loop/serializer_spec.rb +63 -0
  64. data/spec/neovim/event_loop_spec.rb +81 -0
  65. data/spec/neovim/host/loader_spec.rb +0 -1
  66. data/spec/neovim/host_spec.rb +130 -161
  67. data/spec/neovim/logging_spec.rb +77 -5
  68. data/spec/neovim/session_spec.rb +54 -127
  69. data/spec/neovim/window_spec.rb +46 -0
  70. metadata +81 -81
  71. data/lib/neovim/session/api.rb +0 -95
  72. data/lib/neovim/session/event_loop.rb +0 -100
  73. data/lib/neovim/session/notification.rb +0 -19
  74. data/lib/neovim/session/request.rb +0 -31
  75. data/lib/neovim/session/rpc.rb +0 -95
  76. data/lib/neovim/session/serializer.rb +0 -62
  77. data/spec/integration/ruby_buffer_spec.rb +0 -151
  78. data/spec/integration/ruby_vim_spec.rb +0 -27
  79. data/spec/integration/ruby_window_spec.rb +0 -56
  80. data/spec/integration/runtime/init.vim +0 -9
  81. data/spec/integration_spec.rb +0 -119
  82. data/spec/neovim/session/api_spec.rb +0 -70
  83. data/spec/neovim/session/event_loop_spec.rb +0 -152
  84. data/spec/neovim/session/notification_spec.rb +0 -20
  85. data/spec/neovim/session/request_spec.rb +0 -36
  86. data/spec/neovim/session/rpc_spec.rb +0 -120
  87. data/spec/neovim/session/serializer_spec.rb +0 -62
@@ -26,8 +26,8 @@ module Neovim
26
26
  # modifier. See +:h command-bang+.
27
27
  # @option options [Boolean] :register Whether the command can accept a
28
28
  # register name. See +:h command-register+.
29
- # @option options [Boolean] :complete Set the completion attributes of
30
- # the command. See +:h command-completion+.
29
+ # @option options [String] :complete Set the completion attributes of the
30
+ # command. See +:h command-completion+.
31
31
  # @option options [String] :eval An +nvim+ expression. Gets evaluated and
32
32
  # passed as an argument to the block.
33
33
  # @option options [Boolean] :sync (false) Whether +nvim+ should receive
@@ -71,16 +71,16 @@ module Neovim
71
71
  # Register a setup block to run once before the host starts. The block
72
72
  # should expect to receive a single argument, a +Neovim::Client+.
73
73
  #
74
- # This is used for bootstrapping the legacy ruby provider, and not meant
75
- # to be used publicly in plugin definitions.
74
+ # This is used for bootstrapping the ruby provider, and not meant to be
75
+ # used publicly in plugin definitions.
76
76
  def setup(&block)
77
77
  @plugin.setup_blocks << block
78
78
  end
79
79
 
80
80
  # Directly define a synchronous RPC call without a namespace.
81
81
  #
82
- # This is used for exposing legacy ruby provider calls, and not meant to
83
- # be used publicly in plugin definitions.
82
+ # This is used for exposing ruby provider calls, and not meant to be used
83
+ # publicly in plugin definitions.
84
84
  def rpc(name, &block)
85
85
  @plugin.handlers.push(Handler.unqualified(name, block))
86
86
  end
@@ -7,10 +7,10 @@ module Neovim
7
7
  class RemoteObject
8
8
  attr_reader :index
9
9
 
10
- def initialize(index, session)
10
+ def initialize(index, session, api)
11
11
  @index = index
12
12
  @session = session
13
- @api = session.api
13
+ @api = api
14
14
  end
15
15
 
16
16
  # Serialize object to MessagePack.
@@ -4,8 +4,8 @@ require "neovim/ruby_provider/window_ext"
4
4
 
5
5
  module Neovim
6
6
  # This class is used to define a +Neovim::Plugin+ to act as a backend for the
7
- # legacy +:ruby+, +:rubyfile+, and +:rubydo+ Vim commands. It is autoloaded
8
- # from +nvim+ and not intended to be required directly.
7
+ # +:ruby+, +:rubyfile+, and +:rubydo+ Vim commands. It is autoloaded from
8
+ # +nvim+ and not intended to be required directly.
9
9
  #
10
10
  # @api private
11
11
  module RubyProvider
@@ -28,7 +28,7 @@ module Neovim
28
28
  def self.__define_setup(plug)
29
29
  plug.__send__(:setup) do |client|
30
30
  $stdout.define_singleton_method(:write) do |string|
31
- client.out_write(string)
31
+ client.out_write(string + "\n")
32
32
  end
33
33
 
34
34
  $stderr.define_singleton_method(:write) do |string|
@@ -36,7 +36,7 @@ module Neovim
36
36
  end
37
37
 
38
38
  begin
39
- cid = client.channel_id
39
+ cid = client.api.channel_id
40
40
  client.command("au DirChanged * call rpcrequest(#{cid}, 'ruby_chdir', v:event)")
41
41
  rescue ArgumentError
42
42
  # Swallow this exception for now. This means the nvim installation is
@@ -116,8 +116,10 @@ module Neovim
116
116
  def self.__with_exception_handling(client)
117
117
  begin
118
118
  yield
119
- rescue SyntaxError, LoadError, StandardError => e
120
- msg = [e.class, e.message].join(": ")
119
+ rescue SignalException => sig
120
+ raise sig
121
+ rescue Exception => e
122
+ msg = [e.class, e.message.gsub("\n", " ")].join(": ")
121
123
  client.err_writeln(msg.lines.first.strip)
122
124
  end
123
125
  end
@@ -1,8 +1,8 @@
1
1
  require "neovim/buffer"
2
2
  require "neovim/window"
3
3
 
4
- # The VIM module provides backwards compatibility for the legacy +:ruby+,
5
- # +:rubyfile+, and +:rubydo+ +vim+ functions.
4
+ # The VIM module provides backwards compatibility for the +:ruby+, +:rubyfile+,
5
+ # and +:rubydo+ +vim+ functions.
6
6
  module Vim
7
7
  Buffer = ::Neovim::Buffer
8
8
  Window = ::Neovim::Window
@@ -1,65 +1,18 @@
1
1
  require "neovim/logging"
2
- require "neovim/session/api"
3
- require "neovim/session/event_loop"
4
- require "neovim/session/rpc"
5
- require "neovim/session/serializer"
6
2
  require "fiber"
7
3
 
8
4
  module Neovim
9
- # Wraps a +Session::RPC+ in a synchronous API using +Fiber+s.
5
+ # Wraps an event loop in a synchronous API using +Fiber+s.
10
6
  #
11
7
  # @api private
12
8
  class Session
13
9
  include Logging
14
10
 
15
- # Connect to a TCP socket.
16
- def self.tcp(host, port)
17
- from_event_loop(EventLoop.tcp(host, port))
18
- end
19
-
20
- # Connect to a UNIX domain socket.
21
- def self.unix(socket_path)
22
- from_event_loop(EventLoop.unix(socket_path))
23
- end
24
-
25
- # Spawn and connect to a child +nvim+ process.
26
- def self.child(argv)
27
- from_event_loop(EventLoop.child(argv))
28
- end
29
-
30
- # Connect to the current process's standard streams. This is used to
31
- # promote the current process to a Ruby plugin host.
32
- def self.stdio
33
- from_event_loop(EventLoop.stdio)
34
- end
35
-
36
- def self.from_event_loop(event_loop)
37
- serializer = Serializer.new(event_loop)
38
- rpc = RPC.new(serializer)
39
- new(rpc)
40
- end
41
- private_class_method :from_event_loop
42
-
43
- def initialize(rpc)
44
- @rpc = rpc
11
+ def initialize(event_loop)
12
+ @event_loop = event_loop
45
13
  @pending_messages = []
46
14
  @main_thread = Thread.current
47
15
  @main_fiber = Fiber.current
48
- @running = false
49
- end
50
-
51
- # Return the +nvim+ API as described in the +nvim_get_api_info+ call.
52
- # Defaults to empty API information.
53
- def api
54
- @api ||= API.null
55
- end
56
-
57
- # Discover the +nvim+ API as described in the +nvim_get_api_info+ call,
58
- # propagating it down to lower layers of the stack.
59
- def discover_api
60
- @api = API.new(request(:nvim_get_api_info)).tap do |api|
61
- @rpc.serializer.register_types(api, self)
62
- end
63
16
  end
64
17
 
65
18
  # Run the event loop, handling messages in a +Fiber+.
@@ -72,11 +25,11 @@ module Neovim
72
25
 
73
26
  return unless @running
74
27
 
75
- @rpc.run do |message|
28
+ @event_loop.run do |message|
76
29
  Fiber.new { yield message if block_given? }.resume
77
30
  end
78
31
  ensure
79
- shutdown
32
+ @event_loop.shutdown
80
33
  end
81
34
 
82
35
  # Make an RPC request and return its response.
@@ -92,61 +45,71 @@ module Neovim
92
45
  def request(method, *args)
93
46
  main_thread_only do
94
47
  if Fiber.current == @main_fiber
95
- debug("handling blocking request")
96
- err, res = stopped_request(method, *args)
48
+ response = blocking_request(method, *args)
97
49
  else
98
- debug("yielding request to fiber")
99
- err, res = running_request(method, *args)
50
+ response = yielding_request(method, *args)
100
51
  end
101
52
 
102
- err ? raise(ArgumentError, err) : res
53
+ response.value!
103
54
  end
104
55
  end
105
56
 
106
- # Make an RPC notification. +nvim+ will not block waiting for a response.
107
- def notify(method, *args)
108
- main_thread_only do
109
- @rpc.notify(method, *args)
110
- nil
111
- end
57
+ def respond(request_id, value, error=nil)
58
+ @event_loop.respond(request_id, value, error)
112
59
  end
113
60
 
114
- # Return the channel ID if registered via +nvim_get_api_info+.
115
- def channel_id
116
- api.channel_id
61
+ # Make an RPC notification. +nvim+ will not block waiting for a response.
62
+ def notify(method, *args)
63
+ @event_loop.notify(method, *args)
117
64
  end
118
65
 
119
- def stop
66
+ def shutdown
120
67
  @running = false
121
- @rpc.stop
68
+ @event_loop.shutdown
122
69
  end
123
70
 
124
- def shutdown
71
+ def stop
125
72
  @running = false
126
- @rpc.shutdown
73
+ @event_loop.stop
127
74
  end
128
75
 
129
76
  private
130
77
 
131
- def running_request(method, *args)
78
+ def yielding_request(method, *args)
79
+ log(:debug) do
80
+ {
81
+ :method_name => method,
82
+ :arguments => args,
83
+ }
84
+ end
85
+
132
86
  fiber = Fiber.current
133
- @rpc.request(method, *args) do |err, res|
134
- fiber.resume(err, res)
87
+ @event_loop.request(method, *args) do |response|
88
+ fiber.resume(response)
135
89
  end
136
90
  Fiber.yield
137
91
  end
138
92
 
139
- def stopped_request(method, *args)
140
- error, result = nil
93
+ def blocking_request(method, *args)
94
+ log(:debug) do
95
+ {
96
+ :method_name => method,
97
+ :arguments => args,
98
+ }
99
+ end
100
+
101
+ response = nil
141
102
 
142
- @rpc.request(method, *args) do |err, res|
143
- error, result = err, res
103
+ @event_loop.request(method, *args) do |res|
104
+ response = res
144
105
  stop
145
- end.run do |message|
106
+ end
107
+
108
+ @event_loop.run do |message|
146
109
  @pending_messages << message
147
110
  end
148
111
 
149
- [error, result]
112
+ response
150
113
  end
151
114
 
152
115
  def main_thread_only
@@ -3,7 +3,7 @@ require "neovim/remote_object"
3
3
  module Neovim
4
4
  # Class representing an +nvim+ tabpage.
5
5
  #
6
- # The methods documented here were generated using NVIM v0.2.0
6
+ # The methods documented here were generated using NVIM v0.2.1
7
7
  class Tabpage < RemoteObject
8
8
  # The following methods are dynamically generated.
9
9
  =begin
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.5.1")
2
+ VERSION = Gem::Version.new("0.6.0")
3
3
  end
@@ -3,7 +3,7 @@ require "neovim/remote_object"
3
3
  module Neovim
4
4
  # Class representing an +nvim+ window.
5
5
  #
6
- # The methods documented here were generated using NVIM v0.2.0
6
+ # The methods documented here were generated using NVIM v0.2.1
7
7
  class Window < RemoteObject
8
8
  # Get the buffer displayed in the window
9
9
  #
@@ -3,8 +3,10 @@
3
3
  $:.unshift File.expand_path("../../lib", __FILE__)
4
4
 
5
5
  require "neovim"
6
+ require "json"
6
7
  require "pp"
7
8
 
8
9
  nvim_exe = ENV.fetch("NVIM_EXECUTABLE", "nvim")
9
- session = Neovim::Session.child([nvim_exe, "-u", "NONE", "-n"])
10
- pp session.request(:nvim_get_api_info)
10
+ event_loop = Neovim::EventLoop.child([nvim_exe, "-u", "NONE", "-n"])
11
+ session = Neovim::Session.new(event_loop)
12
+ puts JSON.pretty_generate(session.request(:nvim_get_api_info))
@@ -12,7 +12,8 @@ tabpage_docs = []
12
12
  nvim_exe = ENV.fetch("NVIM_EXECUTABLE", "nvim")
13
13
  nvim_vrs = %x(#{nvim_exe} --version).split("\n").first
14
14
 
15
- session = Neovim::Session.child([nvim_exe, "-u", "NONE", "-n"])
15
+ event_loop = Neovim::EventLoop.child([nvim_exe, "-u", "NONE", "-n"])
16
+ session = Neovim::Session.new(event_loop)
16
17
  nvim_defs = Neovim::Client.instance_methods(false)
17
18
  buffer_defs = Neovim::Buffer.instance_methods(false)
18
19
  tabpage_defs = Neovim::Tabpage.instance_methods(false)
@@ -15,4 +15,4 @@ Execute (Trigger event with eval):
15
15
  let g:to_eval = {'a': 42}
16
16
  silent split file.c
17
17
  sleep 50m
18
- AssertEqual {'a': 42}, g:rplugin_autocmd_BufEnter_eval
18
+ AssertEqual {'a': 42, 'b': 43}, g:rplugin_autocmd_BufEnter_eval
@@ -87,11 +87,15 @@ Execute (Call rplugin commands with completion):
87
87
  AssertEqual "buffer", g:rplugin_command_completion
88
88
 
89
89
  Execute (Call rplugin commands with eval):
90
- let g:to_eval = {'n': 42}
90
+ let g:to_eval = {'a': 42}
91
91
  RPluginCommandEval
92
92
  sleep 50m
93
- AssertEqual {'n': 42}, g:rplugin_command_eval
93
+ AssertEqual {'a': 42, 'b': 43}, g:rplugin_command_eval
94
94
 
95
95
  Execute (Call synchronous rplugin commands):
96
96
  RPluginCommandSync
97
97
  AssertEqual v:true, g:rplugin_command_sync
98
+
99
+ Execute (Call recursive rplugin commands):
100
+ RPluginCommandRecursive 0
101
+ AssertEqual "10", g:rplugin_command_recursive
@@ -17,10 +17,13 @@ Execute (Call rplugin functions with a range):
17
17
  AssertEqual [1, 2], g:rplugin_function_range
18
18
 
19
19
  Execute (Call rplugin functions with eval):
20
- let g:to_eval = {'n': 42}
20
+ let g:to_eval = {'a': 42}
21
21
  call RPluginFunctionEval()
22
22
  sleep 50m
23
- AssertEqual {'n': 42}, g:rplugin_function_eval
23
+ AssertEqual {'a': 42, 'b': 43}, g:rplugin_function_eval
24
24
 
25
25
  Execute (Call synchronous rplugin functions):
26
26
  AssertEqual v:true, RPluginFunctionSync()
27
+
28
+ Execute (Call recursive rplugin functions):
29
+ AssertEqual 10, RPluginFunctionRecursive(0)
@@ -47,6 +47,12 @@ Then:
47
47
  AssertNotEqual g:before_pwd, g:after_pwd
48
48
  endif
49
49
 
50
+ Execute (Run nested Ruby commands):
51
+ ruby Vim.command("ruby Vim.command('let g:ruby_nested = 123')")
52
+
53
+ Then:
54
+ AssertEqual 123, g:ruby_nested
55
+
50
56
  Execute (Raise a Ruby standard error):
51
57
  try
52
58
  ruby raise "BOOM"
@@ -72,3 +78,15 @@ Execute (Raise a Ruby syntax error):
72
78
  Expect:
73
79
  still works
74
80
  two
81
+
82
+ Execute (Access Vim interface):
83
+ ruby expect(Vim).to eq(VIM)
84
+ ruby expect(Vim.strwidth("hi")).to eq(2)
85
+
86
+ Execute (Access Vim::Buffer interface):
87
+ ruby expect($curbuf).to be_a(Neovim::Buffer)
88
+ ruby expect(Vim::Buffer.current).to eq($curbuf)
89
+
90
+ Execute (Access Vim::Window interface):
91
+ ruby expect($curwin).to be_a(Neovim::Window)
92
+ ruby expect(Vim::Window.current).to eq($curwin)
@@ -0,0 +1 @@
1
+ Vim.command("rubyfile ./rubyfile/nested_inner.rb")
@@ -0,0 +1 @@
1
+ Vim.command("let g:ruby_nested = 123")
@@ -0,0 +1,8 @@
1
+ expect(Vim).to eq(VIM)
2
+ expect(Vim.strwidth("hi")).to eq(2)
3
+
4
+ expect($curbuf).to be_a(Neovim::Buffer)
5
+ expect(Vim::Buffer.current).to eq($curbuf)
6
+
7
+ expect($curwin).to be_a(Neovim::Window)
8
+ expect(Vim::Window.current).to eq($curwin)
@@ -53,6 +53,12 @@ Then:
53
53
  AssertNotEqual g:pwd_before, g:pwd_after
54
54
  endif
55
55
 
56
+ Execute (Run nested Ruby files):
57
+ rubyfile ./rubyfile/nested.rb
58
+
59
+ Then:
60
+ AssertEqual 123, g:ruby_nested
61
+
56
62
  Execute (Raise a Ruby load error):
57
63
  try
58
64
  rubyfile /foo/bar/baz
@@ -91,3 +97,6 @@ Execute (Raise a Ruby syntax error):
91
97
  Expect:
92
98
  still works
93
99
  two
100
+
101
+ Execute (Access ruby interface):
102
+ rubyfile ./rubyfile/ruby_interface.rb