neovim 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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