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
@@ -1,95 +0,0 @@
1
- module Neovim
2
- class Session
3
- # @api private
4
- class API
5
- attr_reader :channel_id
6
-
7
- # Represents an unknown API. Used as a stand-in when the API hasn't been
8
- # discovered yet via the +nvim_get_api_info+ RPC call.
9
- def self.null
10
- new([nil, {"functions" => [], "types" => []}])
11
- end
12
-
13
- def initialize(payload)
14
- @channel_id, @api_info = payload
15
- end
16
-
17
- # Return all functions defined by the API.
18
- def functions
19
- @functions ||= @api_info.fetch("functions").inject({}) do |acc, func|
20
- function = Function.new(func)
21
- acc.merge(function.name => function)
22
- end
23
- end
24
-
25
- # Return information about +nvim+ types. Used for registering MessagePack
26
- # +ext+ types.
27
- def types
28
- @types ||= @api_info.fetch("types")
29
- end
30
-
31
- def function_for_object_method(obj, method_name)
32
- functions[function_name(obj, method_name)]
33
- end
34
-
35
- def functions_for_object(obj)
36
- pattern = function_pattern(obj)
37
- functions.values.select { |func| func.name =~ pattern }
38
- end
39
-
40
- # Truncate the output of inspect so console sessions are more pleasant.
41
- def inspect
42
- "#<#{self.class}:0x%x @channel_id=#{@channel_id.inspect} @types={...} @functions={...}>" % (object_id << 1)
43
- end
44
-
45
- private
46
-
47
- def function_name(obj, method_name)
48
- case obj
49
- when Client
50
- "nvim_#{method_name}"
51
- when Buffer
52
- "nvim_buf_#{method_name}"
53
- when Window
54
- "nvim_win_#{method_name}"
55
- when Tabpage
56
- "nvim_tabpage_#{method_name}"
57
- else
58
- raise "Unknown object #{obj.inspect}"
59
- end
60
- end
61
-
62
- def function_pattern(obj)
63
- case obj
64
- when Client
65
- /^nvim_(?!(buf|win|tabpage)_)/
66
- when Buffer
67
- /^nvim_buf_/
68
- when Window
69
- /^nvim_win_/
70
- when Tabpage
71
- /^nvim_tabpage_/
72
- else
73
- raise "Unknown object #{obj.inspect}"
74
- end
75
- end
76
-
77
- class Function
78
- attr_reader :name
79
-
80
- def initialize(attributes)
81
- @name = attributes.fetch("name")
82
- end
83
-
84
- def method_name
85
- @name.sub(/^nvim_(win_|buf_|tabpage_)?/, "").to_sym
86
- end
87
-
88
- # Apply this function to a running RPC session.
89
- def call(session, *args)
90
- session.request(name, *args)
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,100 +0,0 @@
1
- require "neovim/logging"
2
- require "socket"
3
-
4
- module Neovim
5
- class Session
6
- # The lowest level interface to reading from and writing to +nvim+.
7
- #
8
- # @api private
9
- class EventLoop
10
- include Logging
11
-
12
- # Connect to a TCP socket.
13
- def self.tcp(host, port)
14
- socket = Socket.tcp(host, port)
15
- new(socket)
16
- end
17
-
18
- # Connect to a UNIX domain socket.
19
- def self.unix(path)
20
- socket = Socket.unix(path)
21
- new(socket)
22
- end
23
-
24
- # Spawn and connect to a child +nvim+ process.
25
- def self.child(_argv)
26
- argv = _argv.include?("--embed") ? _argv : _argv + ["--embed"]
27
-
28
- io = IO.popen(argv, "rb+").tap do |_io|
29
- Process.detach(_io.pid)
30
- end
31
-
32
- new(io)
33
- end
34
-
35
- # Connect to the current process's standard streams. This is used to
36
- # promote the current process to a Ruby plugin host.
37
- def self.stdio
38
- new(STDIN, STDOUT)
39
- end
40
-
41
- def initialize(rd, wr=rd)
42
- @rd, @wr = rd, wr
43
- @running = false
44
- end
45
-
46
- # Write data to the underlying +IO+. This will block until all the
47
- # data has been written.
48
- def write(data)
49
- start = 0
50
- size = data.size
51
- debug("writing #{data.inspect}")
52
-
53
- begin
54
- while start < size
55
- start += @wr.write_nonblock(data[start..-1])
56
- end
57
- self
58
- rescue IO::WaitWritable
59
- IO.select(nil, [@wr], nil, 1)
60
- retry
61
- end
62
- end
63
-
64
- # Run the event loop, reading from the underlying +IO+ and yielding
65
- # received messages to the block.
66
- def run
67
- @running = true
68
-
69
- loop do
70
- break unless @running
71
- message = @rd.readpartial(1024 * 16)
72
- debug("received #{message.inspect}")
73
- yield message if block_given?
74
- end
75
- rescue EOFError
76
- info("got EOFError")
77
- rescue => e
78
- fatal("got unexpected error #{e.inspect}")
79
- debug(e.backtrace.join("\n"))
80
- end
81
-
82
- # Stop the event loop.
83
- def stop
84
- @running = false
85
- end
86
-
87
- # Stop the event loop and close underlying +IO+s.
88
- def shutdown
89
- stop
90
-
91
- [@rd, @wr].each do |io|
92
- begin
93
- io.close
94
- rescue IOError
95
- end
96
- end
97
- end
98
- end
99
- end
100
- end
@@ -1,19 +0,0 @@
1
- module Neovim
2
- class Session
3
- # An asynchronous message from +nvim+.
4
- #
5
- # @api private
6
- class Notification
7
- attr_reader :method_name, :arguments
8
-
9
- def initialize(method_name, args)
10
- @method_name = method_name.to_s
11
- @arguments = args
12
- end
13
-
14
- def sync?
15
- false
16
- end
17
- end
18
- end
19
- end
@@ -1,31 +0,0 @@
1
- module Neovim
2
- class Session
3
- # A synchronous message from +nvim+.
4
- #
5
- # @api private
6
- class Request
7
- attr_reader :method_name, :arguments
8
-
9
- def initialize(method_name, args, serializer, request_id)
10
- @method_name = method_name.to_s
11
- @arguments = args
12
- @serializer = serializer
13
- @request_id = request_id
14
- end
15
-
16
- def sync?
17
- true
18
- end
19
-
20
- def respond(value)
21
- @serializer.write([1, @request_id, nil, value])
22
- self
23
- end
24
-
25
- def error(message)
26
- @serializer.write([1, @request_id, message, nil])
27
- self
28
- end
29
- end
30
- end
31
- end
@@ -1,95 +0,0 @@
1
- require "neovim/logging"
2
- require "neovim/session/request"
3
- require "neovim/session/notification"
4
-
5
- module Neovim
6
- class Session
7
- # Handles formatting RPC requests and writing them to the +Serializer+.
8
- # This exposes an asynchronous API, in which responses are handled in
9
- # callbacks.
10
- #
11
- # @api private
12
- class RPC
13
- include Logging
14
-
15
- attr_reader :serializer
16
-
17
- def initialize(serializer)
18
- @serializer = serializer
19
- @request_id = 0
20
- @pending_requests = {}
21
- end
22
-
23
- # Send an RPC request and enqueue it's callback to be called when a
24
- # response is received.
25
- def request(method, *args, &response_cb)
26
- reqid = @request_id
27
- @request_id += 1
28
-
29
- @serializer.write([0, reqid, method, args])
30
- @pending_requests[reqid] = response_cb || Proc.new {}
31
- self
32
- end
33
-
34
- # Send an RPC notification. Notifications don't receive a response
35
- # from +nvim+.
36
- def notify(method, *args)
37
- @serializer.write([2, method, args])
38
- self
39
- end
40
-
41
- # Run the event loop, yielding received RPC messages to the block. RPC
42
- # requests and notifications from +nvim+ will be wrapped in +Request+
43
- # and +Notification+ objects, respectively, and responses will be
44
- # passed to their callbacks with optional errors.
45
- def run(&callback)
46
- @serializer.run do |msg|
47
- debug("received #{msg.inspect}")
48
- kind, *payload = msg
49
-
50
- case kind
51
- when 0
52
- handle_request(payload, callback)
53
- when 1
54
- handle_response(payload)
55
- when 2
56
- handle_notification(payload, callback)
57
- end
58
- end
59
- rescue => e
60
- fatal("got unexpected error #{e.inspect}")
61
- debug(e.backtrace.join("\n"))
62
- end
63
-
64
- # Stop the event loop.
65
- def stop
66
- @serializer.stop
67
- end
68
-
69
- # Shut down the event loop.
70
- def shutdown
71
- @serializer.shutdown
72
- end
73
-
74
- private
75
-
76
- def handle_request(payload, callback)
77
- callback ||= Proc.new {}
78
- reqid, method, args = payload
79
- callback.call(Request.new(method, args, @serializer, reqid))
80
- end
81
-
82
- def handle_response(payload)
83
- reqid, (_, error), result = payload
84
- callback = @pending_requests.delete(reqid) || Proc.new {}
85
- callback.call(error, result)
86
- end
87
-
88
- def handle_notification(payload, callback)
89
- callback ||= Proc.new {}
90
- method, args = payload
91
- callback.call(Notification.new(method, args))
92
- end
93
- end
94
- end
95
- end
@@ -1,62 +0,0 @@
1
- require "neovim/logging"
2
- require "msgpack"
3
-
4
- module Neovim
5
- class Session
6
- # Handles serializing RPC messages to MessagePack and passing them to
7
- # the event loop.
8
- #
9
- # @api private
10
- class Serializer
11
- include Logging
12
-
13
- def initialize(event_loop, unpacker=nil)
14
- @event_loop = event_loop
15
- @unpacker = unpacker || MessagePack::Unpacker.new
16
- end
17
-
18
- # Serialize an RPC message to and write it to the event loop.
19
- def write(msg)
20
- debug("writing #{msg.inspect}")
21
- @event_loop.write(MessagePack.pack(msg))
22
- self
23
- end
24
-
25
- # Run the event loop, yielding deserialized messages to the block.
26
- def run
27
- @event_loop.run do |data|
28
- @unpacker.feed_each(data) do |msg|
29
- debug("received #{msg.inspect}")
30
- yield msg if block_given?
31
- end
32
- end
33
- rescue => e
34
- fatal("got unexpected error #{e.inspect}")
35
- debug(e.backtrace.join("\n"))
36
- end
37
-
38
- # Stop the event loop.
39
- def stop
40
- @event_loop.stop
41
- end
42
-
43
- # Shut down the event loop.
44
- def shutdown
45
- @event_loop.shutdown
46
- end
47
-
48
- # Register msgpack ext types using the provided API and session
49
- def register_types(api, session)
50
- info("registering msgpack ext types")
51
- api.types.each do |type, info|
52
- klass = Neovim.const_get(type)
53
- id = info.fetch("id")
54
-
55
- @unpacker.register_type(id) do |data|
56
- klass.new(MessagePack.unpack(data), session)
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,151 +0,0 @@
1
- begin
2
- require "helper"
3
- rescue LoadError
4
- end
5
-
6
- RSpec.describe "Vim::Buffer", :embedded do
7
- before do
8
- $curbuf.set_lines(0, -1, true, ["one", "two", "three"])
9
- $curwin.set_cursor([1, 0])
10
- end
11
-
12
- specify "$curbuf" do
13
- expect($curbuf).to be_a(Vim::Buffer)
14
- end
15
-
16
- specify ".current" do
17
- expect(Vim::Buffer.current).to eq($curbuf)
18
- end
19
-
20
- specify ".[]" do
21
- expect(Vim::Buffer[0]).to eq($curbuf)
22
- end
23
-
24
- specify ".count" do
25
- expect(Vim::Buffer.count).to be > 0
26
- end
27
-
28
- specify "#name" do
29
- $curbuf.set_name("test_buf")
30
- expect($curbuf.name).to include("test_buf")
31
- end
32
-
33
- specify "#number" do
34
- expect($curbuf.number).to eq(1)
35
- end
36
-
37
- specify "#count" do
38
- expect($curbuf.count).to eq(3)
39
- end
40
-
41
- specify "#length" do
42
- expect($curbuf.length).to eq(3)
43
- end
44
-
45
- specify "#[]" do
46
- expect($curbuf[1]).to eq("one")
47
-
48
- expect do
49
- $curbuf[-1]
50
- end.to raise_error(/out of bounds/)
51
-
52
- expect do
53
- $curbuf[4]
54
- end.to raise_error(/out of bounds/)
55
- end
56
-
57
- specify "#[]=" do
58
- expect($curbuf[1] = "first").to eq("first")
59
- expect($curbuf[1]).to eq("first")
60
-
61
- expect do
62
- $curbuf[4] = "line"
63
- end.to raise_error(/out of bounds/)
64
-
65
- expect do
66
- $curbuf[-1] = "line"
67
- end.to raise_error(/out of bounds/)
68
- end
69
-
70
- specify "#delete" do
71
- expect($curbuf.delete(3)).to eq(nil)
72
- expect($curbuf.count).to eq(2)
73
-
74
- expect do
75
- $curbuf.delete(-1)
76
- end.to raise_error(/out of bounds/)
77
-
78
- expect do
79
- $curbuf.delete(4)
80
- end.to raise_error(/out of bounds/)
81
- end
82
-
83
- specify "#append" do
84
- expect($curbuf.append(2, "last")).to eq("last")
85
- expect($curbuf[3]).to eq("last")
86
-
87
- $curbuf.set_lines(0, -1, true, [])
88
- $curbuf.append(0, "one")
89
-
90
- expect($curbuf.lines.to_a).to eq(["one", ""])
91
-
92
- expect do
93
- $curbuf.append(0, "two")
94
- end.not_to change { $curwin.cursor }
95
-
96
- expect do
97
- $curbuf.append(-1, "line")
98
- end.to raise_error(/out of bounds/)
99
-
100
- expect do
101
- $curbuf.append(4, "line")
102
- end.to raise_error(/out of bounds/)
103
- end
104
-
105
- specify "#line_number" do
106
- expect do
107
- Vim.command("normal j")
108
- end.to change { $curbuf.line_number }.from(1).to(2)
109
-
110
- original = $curbuf
111
-
112
- begin
113
- Vim.command("new")
114
- expect(original.line_number).to eq(nil)
115
- ensure
116
- Vim.set_current_buf(original)
117
- end
118
- end
119
-
120
- specify "#line" do
121
- expect do
122
- Vim.command("normal j")
123
- end.to change { $curbuf.line }.from("one").to("two")
124
-
125
- original = $curbuf
126
-
127
- begin
128
- Vim.command("new")
129
- expect(original.line).to eq(nil)
130
- ensure
131
- Vim.set_current_buf(original)
132
- end
133
- end
134
-
135
- specify "#line=" do
136
- $curbuf.line = "first"
137
- expect($curbuf[1]).to eq("first")
138
-
139
- original = $curbuf
140
-
141
- begin
142
- Vim.command("new")
143
-
144
- expect do
145
- original.line = "line"
146
- end.not_to change { original.lines.to_a }
147
- ensure
148
- Vim.set_current_buf(original)
149
- end
150
- end
151
- end