neovim 0.4.0 → 0.5.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.gitmodules +1 -1
  4. data/.rspec +1 -0
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +8 -0
  7. data/README.md +5 -3
  8. data/Rakefile +14 -8
  9. data/lib/neovim/buffer.rb +86 -114
  10. data/lib/neovim/client.rb +105 -103
  11. data/lib/neovim/current.rb +8 -18
  12. data/lib/neovim/executable.rb +2 -2
  13. data/lib/neovim/line_range.rb +48 -59
  14. data/lib/neovim/plugin/dsl.rb +11 -3
  15. data/lib/neovim/remote_object.rb +3 -13
  16. data/lib/neovim/ruby_provider.rb +3 -3
  17. data/lib/neovim/ruby_provider/buffer_ext.rb +3 -3
  18. data/lib/neovim/ruby_provider/vim.rb +2 -2
  19. data/lib/neovim/ruby_provider/window_ext.rb +3 -3
  20. data/lib/neovim/session.rb +4 -4
  21. data/lib/neovim/session/api.rb +50 -22
  22. data/lib/neovim/tabpage.rb +29 -19
  23. data/lib/neovim/version.rb +1 -1
  24. data/lib/neovim/window.rb +60 -40
  25. data/script/dump_api +1 -1
  26. data/script/generate_docs +35 -22
  27. data/spec/helper.rb +3 -1
  28. data/spec/integration/rplugin_autocmd_spec.vim +18 -0
  29. data/spec/integration/rplugin_command_spec.vim +97 -0
  30. data/spec/integration/rplugin_function_spec.vim +26 -0
  31. data/spec/integration/ruby_buffer_spec.rb +151 -0
  32. data/spec/{acceptance → integration}/ruby_spec.vim +2 -22
  33. data/spec/integration/ruby_vim_spec.rb +27 -0
  34. data/spec/integration/ruby_window_spec.rb +56 -0
  35. data/spec/{acceptance → integration}/rubydo_spec.vim +27 -18
  36. data/spec/{acceptance → integration}/rubyfile/call_foo.rb +0 -0
  37. data/spec/{acceptance → integration}/rubyfile/curbuf_ivar_get.rb +0 -0
  38. data/spec/{acceptance → integration}/rubyfile/curbuf_ivar_set.rb +0 -0
  39. data/spec/{acceptance → integration}/rubyfile/define_foo.rb +0 -0
  40. data/spec/{acceptance → integration}/rubyfile/raise_standard_error.rb +0 -0
  41. data/spec/{acceptance → integration}/rubyfile/raise_syntax_error.rb +0 -0
  42. data/spec/{acceptance → integration}/rubyfile/set_pwd_after.rb +0 -0
  43. data/spec/{acceptance → integration}/rubyfile/set_pwd_before.rb +0 -0
  44. data/spec/{acceptance → integration}/rubyfile_spec.vim +12 -30
  45. data/spec/integration/runtime/init.vim +9 -0
  46. data/spec/integration/runtime/rplugin/ruby/autocmds.rb +9 -0
  47. data/spec/integration/runtime/rplugin/ruby/commands.rb +59 -0
  48. data/spec/integration/runtime/rplugin/ruby/functions.rb +17 -0
  49. data/spec/integration_spec.rb +119 -0
  50. data/spec/neovim/buffer_spec.rb +0 -167
  51. data/spec/neovim/client_spec.rb +1 -44
  52. data/spec/neovim/current_spec.rb +0 -8
  53. data/spec/neovim/line_range_spec.rb +92 -97
  54. data/spec/neovim/plugin_spec.rb +14 -2
  55. data/spec/neovim/remote_object_spec.rb +4 -4
  56. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +3 -3
  57. data/spec/neovim/ruby_provider/window_ext_spec.rb +1 -1
  58. data/spec/neovim/session/api_spec.rb +40 -35
  59. data/spec/neovim/session/event_loop_spec.rb +1 -1
  60. data/spec/neovim/session_spec.rb +15 -15
  61. metadata +49 -41
  62. data/script/acceptance_tests +0 -46
  63. data/spec/acceptance/rplugin_spec.vim +0 -19
  64. data/spec/acceptance/rubyfile/curbuf.rb +0 -1
  65. data/spec/acceptance/rubyfile/curwin.rb +0 -1
  66. data/spec/acceptance/rubyfile/vim_constants.rb +0 -2
  67. data/spec/acceptance/runtime/init.vim +0 -1
  68. data/spec/acceptance/runtime/rplugin/ruby/plugin.rb +0 -13
  69. data/spec/documentation_spec.rb +0 -24
  70. data/spec/neovim/window_spec.rb +0 -91
@@ -9,14 +9,13 @@ module Neovim
9
9
  class Current
10
10
  def initialize(session)
11
11
  @session = session
12
- @range = (0..-1)
13
12
  end
14
13
 
15
14
  # Get the line under the cursor.
16
15
  #
17
16
  # @return [String]
18
17
  def line
19
- @session.request(:vim_get_current_line)
18
+ @session.request(:nvim_get_current_line)
20
19
  end
21
20
 
22
21
  # Set the line under the cursor.
@@ -24,16 +23,14 @@ module Neovim
24
23
  # @param line [String] The target line contents.
25
24
  # @return [String]
26
25
  def line=(line)
27
- @session.request(:vim_set_current_line, line)
26
+ @session.request(:nvim_set_current_line, line)
28
27
  end
29
28
 
30
29
  # Get the active buffer.
31
30
  #
32
31
  # @return [Buffer]
33
32
  def buffer
34
- @session.request(:vim_get_current_buffer).tap do |buf|
35
- buf.range = @range
36
- end
33
+ @session.request(:nvim_get_current_buf)
37
34
  end
38
35
 
39
36
  # Set the active buffer.
@@ -41,14 +38,14 @@ module Neovim
41
38
  # @param buffer [Buffer, Integer] The target buffer or index.
42
39
  # @return [Buffer, Integer]
43
40
  def buffer=(buffer)
44
- @session.request(:vim_set_current_buffer, buffer)
41
+ @session.request(:nvim_set_current_buf, buffer)
45
42
  end
46
43
 
47
44
  # Get the active window.
48
45
  #
49
46
  # @return [Window]
50
47
  def window
51
- @session.request(:vim_get_current_window)
48
+ @session.request(:nvim_get_current_win)
52
49
  end
53
50
 
54
51
  # Set the active window.
@@ -56,14 +53,14 @@ module Neovim
56
53
  # @param window [Window, Integer] The target window or index.
57
54
  # @return [Window, Integer]
58
55
  def window=(window)
59
- @session.request(:vim_set_current_window, window)
56
+ @session.request(:nvim_set_current_win, window)
60
57
  end
61
58
 
62
59
  # Get the active tabpage.
63
60
  #
64
61
  # @return [Tabpage]
65
62
  def tabpage
66
- @session.request(:vim_get_current_tabpage)
63
+ @session.request(:nvim_get_current_tabpage)
67
64
  end
68
65
 
69
66
  # Set the active tabpage.
@@ -71,14 +68,7 @@ module Neovim
71
68
  # @param tabpage [Tabpage, Integer] The target tabpage or index.
72
69
  # @return [Tabpage, Integer]
73
70
  def tabpage=(tabpage)
74
- @session.request(:vim_set_current_tabpage, tabpage)
75
- end
76
-
77
- # Set the current line range of the current buffer.
78
- #
79
- # @param range [Range] The target range
80
- def range=(range)
81
- @range = range
71
+ @session.request(:nvim_set_current_tabpage, tabpage)
82
72
  end
83
73
  end
84
74
  end
@@ -23,11 +23,11 @@ module Neovim
23
23
  #
24
24
  # @return [String]
25
25
  def version
26
- @version ||= IO.popen([path, "--version"]) do |io|
26
+ @version ||= IO.popen([@path, "--version"]) do |io|
27
27
  io.gets[VERSION_PATTERN, 1]
28
28
  end
29
29
  rescue => e
30
- raise Error, "Couldn't load #{path}: #{e}"
30
+ raise Error, "Couldn't load #{@path}: #{e}"
31
31
  end
32
32
  end
33
33
  end
@@ -3,28 +3,35 @@ module Neovim
3
3
  class LineRange
4
4
  include Enumerable
5
5
 
6
- def initialize(buffer, _begin, _end)
6
+ def initialize(buffer)
7
7
  @buffer = buffer
8
- @begin = _begin
9
- @end = _end
8
+ end
9
+
10
+ # Satisfy the +Enumerable+ interface by yielding each line.
11
+ #
12
+ # @yieldparam line [String]
13
+ def each(&block)
14
+ (0...@buffer.count).each_slice(5000) do |linenos|
15
+ _start, _stop = linenos[0], linenos[-1] + 1
16
+ @buffer.get_lines(_start, _stop, true).each(&block)
17
+ end
10
18
  end
11
19
 
12
20
  # Resolve to an array of lines as strings.
13
21
  #
14
22
  # @return [Array<String>]
15
23
  def to_a
16
- @buffer.get_line_slice(@begin, @end, true, true)
24
+ map { |line| line }
17
25
  end
18
26
 
19
- # Yield each line in the range.
27
+ # Override +#==+ to compare contents of lines.
20
28
  #
21
- # @yield [String] The current line
22
- # @return [Array<String>]
23
- def each(&block)
24
- to_a.each(&block)
29
+ # @return Boolean
30
+ def ==(other)
31
+ to_a == other.to_a
25
32
  end
26
33
 
27
- # Access the line at the given index within the range.
34
+ # Access a line or line range.
28
35
  #
29
36
  # @overload [](index)
30
37
  # @param index [Integer]
@@ -43,28 +50,17 @@ module Neovim
43
50
  # @example Get the first two lines using an index and length
44
51
  # line_range[0, 2] # => ["first", "second"]
45
52
  def [](pos, len=nil)
46
- case pos
47
- when Range
48
- LineRange.new(
49
- @buffer,
50
- abs_line(pos.begin),
51
- abs_line(pos.exclude_end? ? pos.end - 1 : pos.end)
52
- )
53
+ if Range === pos
54
+ @buffer.get_lines(*range_indices(pos), true)
53
55
  else
54
- if len
55
- LineRange.new(
56
- @buffer,
57
- abs_line(pos),
58
- abs_line(pos + len - 1)
59
- )
60
- else
61
- @buffer.get_line(abs_line(pos))
62
- end
56
+ _begin, _end = length_indices(pos, len || 1)
57
+ lines = @buffer.get_lines(_begin, _end, true)
58
+ len ? lines : lines.first
63
59
  end
64
60
  end
65
61
  alias_method :slice, :[]
66
62
 
67
- # Set the line at the given index within the range.
63
+ # Set a line or line range.
68
64
  #
69
65
  # @overload []=(index, string)
70
66
  # @param index [Integer]
@@ -89,27 +85,11 @@ module Neovim
89
85
  *target, val = args
90
86
  pos, len = target
91
87
 
92
- case pos
93
- when Range
94
- @buffer.set_line_slice(
95
- abs_line(pos.begin),
96
- abs_line(pos.end),
97
- true,
98
- !pos.exclude_end?,
99
- val
100
- )
88
+ if Range === pos
89
+ @buffer.set_lines(*range_indices(pos), true, Array(val))
101
90
  else
102
- if len
103
- @buffer.set_line_slice(
104
- abs_line(pos),
105
- abs_line(pos + len),
106
- true,
107
- false,
108
- val
109
- )
110
- else
111
- @buffer.set_line(abs_line(pos), val)
112
- end
91
+ _begin, _end = length_indices(pos, len || 1)
92
+ @buffer.set_lines(_begin, _end, true, Array(val))
113
93
  end
114
94
  end
115
95
 
@@ -117,29 +97,38 @@ module Neovim
117
97
  #
118
98
  # @param other [Array] The replacement lines
119
99
  def replace(other)
120
- self[0..-1] = other
100
+ self[0..-1] = other.to_ary
121
101
  self
122
102
  end
123
103
 
124
- # Insert line(s) at the given index within the range.
125
- #
126
- # @param index [Integer]
127
- # @param lines [String]
128
- def insert(index, lines)
129
- @buffer.insert(index, Array(lines))
130
- end
131
-
132
104
  # Delete the line at the given index within the range.
133
105
  #
134
106
  # @param index [Integer]
135
107
  def delete(index)
136
- @buffer.del_line(abs_line(index))
108
+ i = Integer(index)
109
+ self[i].tap { self[i, 1] = [] }
110
+ rescue TypeError
137
111
  end
138
112
 
139
113
  private
140
114
 
141
- def abs_line(n)
142
- n < 0 ? (@end + n + 1) : @begin + n
115
+ def range_indices(range)
116
+ _begin = adjust_index(range.begin)
117
+ _end = adjust_index(range.end)
118
+ _end += 1 unless range.exclude_end?
119
+
120
+ [_begin, _end]
121
+ end
122
+
123
+ def length_indices(index, len)
124
+ _begin = adjust_index(index)
125
+ _end = _begin < 0 ? [_begin + len, -1].min : _begin + len
126
+
127
+ [_begin, _end]
128
+ end
129
+
130
+ def adjust_index(i)
131
+ i < 0 ? i - 1 : i
143
132
  end
144
133
  end
145
134
  end
@@ -43,7 +43,7 @@ module Neovim
43
43
  # @param &block [Proc, nil] The body of the function.
44
44
  #
45
45
  # @option options [String, Boolean] :range The range argument.
46
- # See +:h command-range+.
46
+ # See +:h func-range+.
47
47
  # @option options [String] :eval An +nvim+ expression. Gets evaluated and
48
48
  # passed as an argument to the block.
49
49
  # @option options [Boolean] :sync (false) Whether +nvim+ should receive
@@ -89,7 +89,7 @@ module Neovim
89
89
  if type == :autocmd
90
90
  options = _options.dup
91
91
  else
92
- options = standardize_range(_options.dup)
92
+ options = standardize(_options.dup)
93
93
  end
94
94
 
95
95
  sync = options.delete(:sync)
@@ -99,12 +99,20 @@ module Neovim
99
99
  )
100
100
  end
101
101
 
102
- def standardize_range(options)
102
+ def standardize(options)
103
103
  if options.key?(:range)
104
104
  options[:range] = "" if options[:range] == true
105
105
  options[:range] = ::Kernel.String(options[:range])
106
106
  end
107
107
 
108
+ [:bang, :register].each do |opt|
109
+ if options[opt]
110
+ options[opt] = ""
111
+ elsif options.key?(opt)
112
+ options.delete(opt)
113
+ end
114
+ end
115
+
108
116
  options
109
117
  end
110
118
  end
@@ -23,7 +23,7 @@ module Neovim
23
23
 
24
24
  # Intercept method calls and delegate to appropriate RPC methods.
25
25
  def method_missing(method_name, *args)
26
- if func = @api.function(qualify(method_name))
26
+ if func = @api.function_for_object_method(self, method_name)
27
27
  func.call(@session, @index, *args)
28
28
  else
29
29
  super
@@ -36,7 +36,7 @@ module Neovim
36
36
  end
37
37
 
38
38
  # Extend +methods+ to include RPC methods
39
- def methods
39
+ def methods(*args)
40
40
  super | rpc_methods
41
41
  end
42
42
 
@@ -48,17 +48,7 @@ module Neovim
48
48
  private
49
49
 
50
50
  def rpc_methods
51
- @api.functions_with_prefix(function_prefix).map do |func|
52
- func.name.sub(/\A#{function_prefix}/, "").to_sym
53
- end
54
- end
55
-
56
- def function_prefix
57
- "#{self.class.to_s.split("::").last.downcase}_"
58
- end
59
-
60
- def qualify(method_name)
61
- :"#{function_prefix}#{method_name}"
51
+ @api.functions_for_object(self).map(&:method_name)
62
52
  end
63
53
  end
64
54
  end
@@ -32,7 +32,7 @@ module Neovim
32
32
  end
33
33
 
34
34
  $stderr.define_singleton_method(:write) do |string|
35
- client.report_error(string)
35
+ client.err_writeln(string)
36
36
  end
37
37
 
38
38
  begin
@@ -81,7 +81,7 @@ module Neovim
81
81
  __plug.__send__(:rpc, :ruby_do_range) do |__nvim, *__args|
82
82
  __wrap_client(__nvim) do
83
83
  __start, __stop, __ruby = __args
84
- __buffer = __nvim.get_current_buffer
84
+ __buffer = __nvim.get_current_buf
85
85
 
86
86
  __update_lines_in_chunks(__buffer, __start, __stop, 5000) do |__lines|
87
87
  __lines.map do |__line|
@@ -118,7 +118,7 @@ module Neovim
118
118
  yield
119
119
  rescue SyntaxError, LoadError, StandardError => e
120
120
  msg = [e.class, e.message].join(": ")
121
- client.report_error(msg.lines.first.strip)
121
+ client.err_writeln(msg.lines.first.strip)
122
122
  end
123
123
  end
124
124
 
@@ -3,15 +3,15 @@ require "neovim/ruby_provider/vim"
3
3
  module Neovim
4
4
  class Buffer
5
5
  def self.current
6
- ::Vim.get_current_buffer
6
+ ::Vim.get_current_buf
7
7
  end
8
8
 
9
9
  def self.count
10
- ::Vim.get_buffers.size
10
+ ::Vim.list_bufs.size
11
11
  end
12
12
 
13
13
  def self.[](index)
14
- ::Vim.get_buffers[index]
14
+ ::Vim.list_bufs[index]
15
15
  end
16
16
  end
17
17
  end
@@ -24,10 +24,10 @@ module Vim
24
24
  bufnr = client.evaluate("bufnr('%')")
25
25
 
26
26
  $curbuf = @__buffer_cache.fetch(bufnr) do
27
- @__buffer_cache[bufnr] = client.get_current_buffer
27
+ @__buffer_cache[bufnr] = client.get_current_buf
28
28
  end
29
29
 
30
- $curwin = client.get_current_window
30
+ $curwin = client.get_current_win
31
31
  end
32
32
  end
33
33
 
@@ -3,15 +3,15 @@ require "neovim/ruby_provider/vim"
3
3
  module Neovim
4
4
  class Window
5
5
  def self.current
6
- ::Vim.get_current_window
6
+ ::Vim.get_current_win
7
7
  end
8
8
 
9
9
  def self.count
10
- ::Vim.get_current_tabpage.get_windows.size
10
+ ::Vim.get_current_tabpage.list_wins.size
11
11
  end
12
12
 
13
13
  def self.[](index)
14
- ::Vim.get_current_tabpage.get_windows[index]
14
+ ::Vim.get_current_tabpage.list_wins[index]
15
15
  end
16
16
  end
17
17
  end
@@ -48,16 +48,16 @@ module Neovim
48
48
  @running = false
49
49
  end
50
50
 
51
- # Return the +nvim+ API as described in the +vim_get_api_info+ call.
51
+ # Return the +nvim+ API as described in the +nvim_get_api_info+ call.
52
52
  # Defaults to empty API information.
53
53
  def api
54
54
  @api ||= API.null
55
55
  end
56
56
 
57
- # Discover the +nvim+ API as described in the +vim_get_api_info+ call,
57
+ # Discover the +nvim+ API as described in the +nvim_get_api_info+ call,
58
58
  # propagating it down to lower layers of the stack.
59
59
  def discover_api
60
- @api = API.new(request(:vim_get_api_info)).tap do |api|
60
+ @api = API.new(request(:nvim_get_api_info)).tap do |api|
61
61
  @rpc.serializer.register_types(api, self)
62
62
  end
63
63
  end
@@ -111,7 +111,7 @@ module Neovim
111
111
  end
112
112
  end
113
113
 
114
- # Return the channel ID if registered via +vim_get_api_info+.
114
+ # Return the channel ID if registered via +nvim_get_api_info+.
115
115
  def channel_id
116
116
  api.channel_id
117
117
  end
@@ -5,7 +5,7 @@ module Neovim
5
5
  attr_reader :channel_id
6
6
 
7
7
  # Represents an unknown API. Used as a stand-in when the API hasn't been
8
- # discovered yet via the +vim_get_api_info+ RPC call.
8
+ # discovered yet via the +nvim_get_api_info+ RPC call.
9
9
  def self.null
10
10
  new([nil, {"functions" => [], "types" => []}])
11
11
  end
@@ -17,8 +17,8 @@ module Neovim
17
17
  # Return all functions defined by the API.
18
18
  def functions
19
19
  @functions ||= @api_info.fetch("functions").inject({}) do |acc, func|
20
- name, async = func.values_at("name", "async")
21
- acc.merge(name => Function.new(name, async))
20
+ function = Function.new(func)
21
+ acc.merge(function.name => function)
22
22
  end
23
23
  end
24
24
 
@@ -28,38 +28,66 @@ module Neovim
28
28
  @types ||= @api_info.fetch("types")
29
29
  end
30
30
 
31
- # Return a list of functions with the given name prefix.
32
- def functions_with_prefix(prefix)
33
- functions.inject([]) do |acc, (name, function)|
34
- name =~ /\A#{prefix}/ ? acc.push(function) : acc
35
- end
31
+ def function_for_object_method(obj, method_name)
32
+ functions[function_name(obj, method_name)]
36
33
  end
37
34
 
38
- # Find a function with the given name.
39
- def function(name)
40
- functions[name.to_s]
35
+ def functions_for_object(obj)
36
+ pattern = function_pattern(obj)
37
+ functions.values.select { |func| func.name =~ pattern }
41
38
  end
42
39
 
43
40
  # Truncate the output of inspect so console sessions are more pleasant.
44
41
  def inspect
45
- "#<#{self.class}:0x%x @types={...} @functions={...}>" % (object_id << 1)
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
46
75
  end
47
76
 
48
77
  class Function
49
- attr_reader :name, :async
78
+ attr_reader :name
79
+
80
+ def initialize(attributes)
81
+ @name = attributes.fetch("name")
82
+ end
50
83
 
51
- def initialize(name, async)
52
- @name, @async = name, async
84
+ def method_name
85
+ @name.sub(/^nvim_(win_|buf_|tabpage_)?/, "").to_sym
53
86
  end
54
87
 
55
- # Apply this function to a running RPC session. Sends either a request if
56
- # +async+ is +false+ or a notification if +async+ is +true+.
88
+ # Apply this function to a running RPC session.
57
89
  def call(session, *args)
58
- if async
59
- session.notify(name, *args)
60
- else
61
- session.request(name, *args)
62
- end
90
+ session.request(name, *args)
63
91
  end
64
92
  end
65
93
  end