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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -2
  3. data/CHANGELOG.md +11 -0
  4. data/README.md +15 -4
  5. data/Rakefile +64 -4
  6. data/bin/j2mp +8 -0
  7. data/bin/mp2j +8 -0
  8. data/lib/neovim.rb +100 -17
  9. data/lib/neovim/api.rb +84 -0
  10. data/lib/neovim/async_session.rb +74 -21
  11. data/lib/neovim/buffer.rb +111 -4
  12. data/lib/neovim/client.rb +175 -4
  13. data/lib/neovim/current.rb +19 -8
  14. data/lib/neovim/event_loop.rb +55 -10
  15. data/lib/neovim/host.rb +21 -8
  16. data/lib/neovim/line_range.rb +55 -15
  17. data/lib/neovim/logging.rb +4 -0
  18. data/lib/neovim/manifest.rb +11 -3
  19. data/lib/neovim/msgpack_stream.rb +53 -19
  20. data/lib/neovim/notification.rb +2 -0
  21. data/lib/neovim/plugin.rb +12 -87
  22. data/lib/neovim/plugin/dsl.rb +81 -0
  23. data/lib/neovim/plugin/handler.rb +43 -0
  24. data/lib/neovim/remote_object.rb +64 -0
  25. data/lib/neovim/request.rb +4 -2
  26. data/lib/neovim/session.rb +167 -16
  27. data/lib/neovim/tabpage.rb +24 -2
  28. data/lib/neovim/version.rb +1 -1
  29. data/lib/neovim/window.rb +92 -2
  30. data/neovim.gemspec +1 -1
  31. data/spec/acceptance/neovim-ruby-host_spec.rb +16 -8
  32. data/spec/helper.rb +11 -3
  33. data/spec/neovim/api_spec.rb +40 -0
  34. data/spec/neovim/async_session_spec.rb +19 -25
  35. data/spec/neovim/current_spec.rb +64 -4
  36. data/spec/neovim/event_loop_spec.rb +18 -27
  37. data/spec/neovim/host_spec.rb +20 -1
  38. data/spec/neovim/manifest_spec.rb +0 -2
  39. data/spec/neovim/msgpack_stream_spec.rb +5 -6
  40. data/spec/neovim/{object_spec.rb → remote_object_spec.rb} +1 -4
  41. data/spec/neovim/session_spec.rb +18 -26
  42. data/spec/neovim_spec.rb +2 -3
  43. data/spec/support.rb +5 -5
  44. metadata +13 -6
  45. data/lib/neovim/api_info.rb +0 -27
  46. data/lib/neovim/object.rb +0 -40
@@ -1,23 +1,130 @@
1
- require "neovim/object"
1
+ require "neovim/remote_object"
2
2
  require "neovim/line_range"
3
3
 
4
4
  module Neovim
5
- class Buffer < Neovim::Object
5
+ # Class representing an +nvim+ buffer.
6
+ class Buffer < RemoteObject
7
+ # A +LineRange+ object representing the buffer's lines.
8
+ #
9
+ # @return [LineRange]
10
+ # @see LineRange
6
11
  def lines
7
12
  @lines ||= LineRange.new(self, 0, -1)
8
13
  end
9
14
 
10
- def lines=(arr)
11
- lines[0..-1] = arr
15
+ # Replace all the lines of the buffer.
16
+ #
17
+ # @param strs [Array<String>] The replacement lines
18
+ # @return [Array<String>]
19
+ def lines=(strs)
20
+ lines[0..-1] = strs
12
21
  end
13
22
 
23
+ # A +LineRange+ object representing the buffer's selection range.
24
+ #
25
+ # @return [LineRange]
26
+ # @see LineRange
14
27
  def range
15
28
  @range ||= LineRange.new(self, 0, -1)
16
29
  end
17
30
 
31
+ # Set the buffer's current selection range.
32
+ #
33
+ # @param _range [Range] The replacement range
34
+ # @return [LineRange]
35
+ # @see LineRange
18
36
  def range=(_range)
19
37
  _end = _range.exclude_end? ? _range.end - 1 : _range.end
20
38
  @range = LineRange.new(self, _range.begin, _end)
21
39
  end
40
+
41
+ # The following methods are dynamically generated.
42
+ =begin
43
+ @method line_count
44
+ @return [Fixnum]
45
+
46
+ @method get_line(index)
47
+ @param [Fixnum] index
48
+ @return [String]
49
+
50
+ @method set_line(index, line)
51
+ @param [Fixnum] index
52
+ @param [String] line
53
+ @return [void]
54
+
55
+ @method del_line(index)
56
+ @param [Fixnum] index
57
+ @return [void]
58
+
59
+ @method get_line_slice(start, end, include_start, include_end)
60
+ @param [Fixnum] start
61
+ @param [Fixnum] end
62
+ @param [Boolean] include_start
63
+ @param [Boolean] include_end
64
+ @return [Array<String>]
65
+
66
+ @method set_line_slice(start, end, include_start, include_end, replacement)
67
+ @param [Fixnum] start
68
+ @param [Fixnum] end
69
+ @param [Boolean] include_start
70
+ @param [Boolean] include_end
71
+ @param [Array<String>] replacement
72
+ @return [void]
73
+
74
+ @method get_var(name)
75
+ @param [String] name
76
+ @return [Object]
77
+
78
+ @method set_var(name, value)
79
+ @param [String] name
80
+ @param [Object] value
81
+ @return [Object]
82
+
83
+ @method get_option(name)
84
+ @param [String] name
85
+ @return [Object]
86
+
87
+ @method set_option(name, value)
88
+ @param [String] name
89
+ @param [Object] value
90
+ @return [void]
91
+
92
+ @method get_number
93
+ @return [Fixnum]
94
+
95
+ @method get_name
96
+ @return [String]
97
+
98
+ @method set_name(name)
99
+ @param [String] name
100
+ @return [void]
101
+
102
+ @method is_valid
103
+ @return [Boolean]
104
+
105
+ @method insert(lnum, lines)
106
+ @param [Fixnum] lnum
107
+ @param [Array<String>] lines
108
+ @return [void]
109
+
110
+ @method get_mark(name)
111
+ @param [String] name
112
+ @return [Array<Fixnum>]
113
+
114
+ @method add_highlight(src_id, hl_group, line, col_start, col_end)
115
+ @param [Fixnum] src_id
116
+ @param [String] hl_group
117
+ @param [Fixnum] line
118
+ @param [Fixnum] col_start
119
+ @param [Fixnum] col_end
120
+ @return [Fixnum]
121
+
122
+ @method clear_highlight(src_id, line_start, line_end)
123
+ @param [Fixnum] src_id
124
+ @param [Fixnum] line_start
125
+ @param [Fixnum] line_end
126
+ @return [void]
127
+
128
+ =end
22
129
  end
23
130
  end
@@ -1,31 +1,202 @@
1
1
  require "neovim/current"
2
2
 
3
3
  module Neovim
4
+ # Client to a running +nvim+ instance. The interface is generated at
5
+ # runtime via the +vim_get_api_info+ RPC call. Some methods return
6
+ # +RemoteObject+ subclasses (i.e. +Buffer+, +Window+, or +Tabpage+),
7
+ # which similarly have dynamically generated interfaces.
8
+ #
9
+ # @see Buffer
10
+ # @see Window
11
+ # @see Tabpage
4
12
  class Client
5
13
  attr_reader :session
6
14
 
7
15
  def initialize(session)
8
16
  @session = session
17
+ @api = session.api
9
18
  end
10
19
 
20
+ # Intercept method calls and delegate to appropriate RPC methods.
11
21
  def method_missing(method_name, *args)
12
- if methods.include?(method_name)
13
- @session.request("vim_#{method_name}", *args)
22
+ if func = @api.function("vim_#{method_name}")
23
+ func.call(session, *args)
14
24
  else
15
25
  super
16
26
  end
17
27
  end
18
28
 
29
+ # Extend +respond_to?+ to support RPC methods.
19
30
  def respond_to?(method_name)
20
- super || methods.include?(method_name.to_sym)
31
+ super || rpc_methods.include?(method_name.to_sym)
21
32
  end
22
33
 
34
+ # Extend +methods+ to include RPC methods.
23
35
  def methods
24
- super | @session.api_methods_for_prefix("vim_")
36
+ super | rpc_methods
25
37
  end
26
38
 
39
+ # Access to objects belonging to the current +nvim+ context.
40
+ #
41
+ # @return [Current]
42
+ # @example Get the current buffer
43
+ # client.current.buffer
44
+ # @example Set the current line
45
+ # client.current.line = "New line"
46
+ # @see Current
27
47
  def current
28
48
  Current.new(@session)
29
49
  end
50
+
51
+ private
52
+
53
+ def rpc_methods
54
+ @api.functions_with_prefix("vim_").map do |func|
55
+ func.name.sub(/\Avim_/, "").to_sym
56
+ end
57
+ end
58
+
59
+ public
60
+
61
+ # The following methods are dynamically generated.
62
+ =begin
63
+ @method command(str)
64
+ @param [String] str
65
+ @return [void]
66
+
67
+ @method feedkeys(keys, mode, escape_csi)
68
+ @param [String] keys
69
+ @param [String] mode
70
+ @param [Boolean] escape_csi
71
+ @return [void]
72
+
73
+ @method input(keys)
74
+ @param [String] keys
75
+ @return [Fixnum]
76
+
77
+ @method replace_termcodes(str, from_part, do_lt, special)
78
+ @param [String] str
79
+ @param [Boolean] from_part
80
+ @param [Boolean] do_lt
81
+ @param [Boolean] special
82
+ @return [String]
83
+
84
+ @method command_output(str)
85
+ @param [String] str
86
+ @return [String]
87
+
88
+ @method eval(str)
89
+ @param [String] str
90
+ @return [Object]
91
+
92
+ @method call_function(fname, args)
93
+ @param [String] fname
94
+ @param [Array] args
95
+ @return [Object]
96
+
97
+ @method strwidth(str)
98
+ @param [String] str
99
+ @return [Fixnum]
100
+
101
+ @method list_runtime_paths
102
+ @return [Array<String>]
103
+
104
+ @method change_directory(dir)
105
+ @param [String] dir
106
+ @return [void]
107
+
108
+ @method get_current_line
109
+ @return [String]
110
+
111
+ @method set_current_line(line)
112
+ @param [String] line
113
+ @return [void]
114
+
115
+ @method del_current_line
116
+ @return [void]
117
+
118
+ @method get_var(name)
119
+ @param [String] name
120
+ @return [Object]
121
+
122
+ @method set_var(name, value)
123
+ @param [String] name
124
+ @param [Object] value
125
+ @return [Object]
126
+
127
+ @method get_vvar(name)
128
+ @param [String] name
129
+ @return [Object]
130
+
131
+ @method get_option(name)
132
+ @param [String] name
133
+ @return [Object]
134
+
135
+ @method set_option(name, value)
136
+ @param [String] name
137
+ @param [Object] value
138
+ @return [void]
139
+
140
+ @method out_write(str)
141
+ @param [String] str
142
+ @return [void]
143
+
144
+ @method err_write(str)
145
+ @param [String] str
146
+ @return [void]
147
+
148
+ @method report_error(str)
149
+ @param [String] str
150
+ @return [void]
151
+
152
+ @method get_buffers
153
+ @return [Array<Buffer>]
154
+
155
+ @method get_current_buffer
156
+ @return [Buffer]
157
+
158
+ @method set_current_buffer(buffer)
159
+ @param [Buffer] buffer
160
+ @return [void]
161
+
162
+ @method get_windows
163
+ @return [Array<Window>]
164
+
165
+ @method get_current_window
166
+ @return [Window]
167
+
168
+ @method set_current_window(window)
169
+ @param [Window] window
170
+ @return [void]
171
+
172
+ @method get_tabpages
173
+ @return [Array<Tabpage>]
174
+
175
+ @method get_current_tabpage
176
+ @return [Tabpage]
177
+
178
+ @method set_current_tabpage(tabpage)
179
+ @param [Tabpage] tabpage
180
+ @return [void]
181
+
182
+ @method subscribe(event)
183
+ @param [String] event
184
+ @return [void]
185
+
186
+ @method unsubscribe(event)
187
+ @param [String] event
188
+ @return [void]
189
+
190
+ @method name_to_color(name)
191
+ @param [String] name
192
+ @return [Fixnum]
193
+
194
+ @method get_color_map
195
+ @return [Dictionary]
196
+
197
+ @method get_api_info
198
+ @return [Array]
199
+
200
+ =end
30
201
  end
31
202
  end
@@ -3,43 +3,54 @@ require "neovim/tabpage"
3
3
  require "neovim/window"
4
4
 
5
5
  module Neovim
6
+ # Support for +client.current+ chaining.
7
+ # @see Client#current
6
8
  class Current
7
9
  def initialize(session)
8
10
  @session = session
9
11
  end
10
12
 
13
+ # @return [String]
11
14
  def line
12
15
  @session.request(:vim_get_current_line)
13
16
  end
14
17
 
15
- def line=(ln)
16
- @session.request(:vim_set_current_line, ln)
18
+ # @param line [String] The target line contents.
19
+ # @return [String]
20
+ def line=(line)
21
+ @session.request(:vim_set_current_line, line)
17
22
  end
18
23
 
24
+ # @return [Buffer]
19
25
  def buffer
20
26
  @session.request(:vim_get_current_buffer)
21
27
  end
22
28
 
23
- def buffer=(buffer_index)
24
- buffer = Buffer.new(buffer_index, @session)
29
+ # @param buffer [Buffer, Fixnum] The target buffer or index.
30
+ # @return [Buffer, Fixnum]
31
+ def buffer=(buffer)
25
32
  @session.request(:vim_set_current_buffer, buffer)
26
33
  end
27
34
 
35
+ # @return [Window]
28
36
  def window
29
37
  @session.request(:vim_get_current_window)
30
38
  end
31
39
 
32
- def window=(window_index)
33
- window = Window.new(window_index, @session)
40
+ # @param window [Window, Fixnum] The target window or index.
41
+ # @return [Window, Fixnum]
42
+ def window=(window)
34
43
  @session.request(:vim_set_current_window, window)
35
44
  end
36
45
 
46
+ # @return [Tabpage]
37
47
  def tabpage
38
48
  @session.request(:vim_get_current_tabpage)
39
49
  end
40
50
 
41
- def tabpage=(tabpage_index)
42
- tabpage = Tabpage.new(tabpage_index, @session)
51
+ # @param tabpage [Tabpage, Fixnum] The target tabpage or index.
52
+ # @return [Tabpage, Fixnum]
53
+ def tabpage=(tabpage)
43
54
  @session.request(:vim_set_current_tabpage, tabpage)
44
55
  end
45
56
  end
@@ -2,38 +2,63 @@ require "neovim/logging"
2
2
  require "socket"
3
3
 
4
4
  module Neovim
5
+ # The lowest level interface to reading from and writing to +nvim+.
5
6
  class EventLoop
6
7
  include Logging
7
8
 
9
+ private_class_method :new
10
+
11
+ # Connect to a TCP socket.
12
+ #
13
+ # @param host [String] The hostname or IP address
14
+ # @param port [Fixnum] The port
15
+ # @return [EventLoop]
8
16
  def self.tcp(host, port)
9
17
  socket = TCPSocket.new(host, port)
10
- new(socket, socket)
18
+ new(socket)
11
19
  end
12
20
 
21
+ # Connect to a UNIX domain socket.
22
+ #
23
+ # @param path [String] The socket path
24
+ # @return [EventLoop]
13
25
  def self.unix(path)
14
26
  socket = UNIXSocket.new(path)
15
- new(socket, socket)
27
+ new(socket)
16
28
  end
17
29
 
30
+ # Spawn and connect to a child +nvim+ process.
31
+ #
32
+ # @param argv [Array] The arguments to pass to the spawned process
33
+ # @return [EventLoop]
18
34
  def self.child(argv)
19
35
  argv = [ENV.fetch("NVIM_EXECUTABLE", "nvim"), "--embed"] | argv
20
36
  io = IO.popen(argv, "rb+")
21
- new(io, io)
37
+ new(io)
22
38
  end
23
39
 
40
+ # Connect to the current process's standard streams. This is used to
41
+ # promote the current process to a Ruby plugin host.
42
+ #
43
+ # @return [EventLoop]
24
44
  def self.stdio
25
45
  new(STDIN, STDOUT)
26
46
  end
27
47
 
28
- def initialize(rd, wr)
48
+ def initialize(rd, wr=rd)
29
49
  @rd, @wr = rd, wr
30
50
  @running = false
31
51
  end
32
52
 
33
- def send(data)
53
+ # Write data to the underlying +IO+. This will block until all the
54
+ # data has been written.
55
+ #
56
+ # @param data [String] The data to write (typically message-packed)
57
+ # @return [self]
58
+ def write(data)
34
59
  start = 0
35
60
  size = data.size
36
- debug("sending #{data.inspect}")
61
+ debug("writing #{data.inspect}")
37
62
 
38
63
  begin
39
64
  while start < size
@@ -41,20 +66,24 @@ module Neovim
41
66
  end
42
67
  self
43
68
  rescue IO::WaitWritable
44
- IO.select(nil, [@wr])
69
+ IO.select(nil, [@wr], nil, 1)
45
70
  retry
46
71
  end
47
72
  end
48
73
 
49
- def run(message_callback, setup_callback=nil)
74
+ # Run the event loop, reading from the underlying +IO+ and yielding
75
+ # received messages to the block.
76
+ #
77
+ # @yield [String]
78
+ # @return [void]
79
+ def run
50
80
  @running = true
51
- setup_callback.call if setup_callback.respond_to?(:call)
52
81
 
53
82
  loop do
54
83
  break unless @running
55
84
  message = @rd.readpartial(1024 * 16)
56
85
  debug("received #{message.inspect}")
57
- message_callback.call(message)
86
+ yield message if block_given?
58
87
  end
59
88
  rescue EOFError
60
89
  warn("got EOFError")
@@ -62,5 +91,21 @@ module Neovim
62
91
  fatal("got unexpected error #{e}")
63
92
  debug(e.backtrace.join("\n"))
64
93
  end
94
+
95
+ # Stop the event loop.
96
+ #
97
+ # @return [void]
98
+ def stop
99
+ @running = false
100
+ end
101
+
102
+ # Stop the event loop and close underlying +IO+s.
103
+ #
104
+ # @return [void]
105
+ def shutdown
106
+ stop
107
+ [@rd, @wr].each(&:close)
108
+ rescue IOError
109
+ end
65
110
  end
66
111
  end