neovim 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile +1 -0
  4. data/README.md +6 -2
  5. data/Rakefile +4 -72
  6. data/bin/neovim-ruby-host +3 -2
  7. data/lib/neovim.rb +4 -16
  8. data/lib/neovim/buffer.rb +21 -0
  9. data/lib/neovim/client.rb +35 -0
  10. data/lib/neovim/host.rb +6 -4
  11. data/lib/neovim/host/loader.rb +2 -0
  12. data/lib/neovim/line_range.rb +1 -1
  13. data/lib/neovim/logging.rb +8 -7
  14. data/lib/neovim/plugin/dsl.rb +1 -1
  15. data/lib/neovim/ruby_provider.rb +7 -10
  16. data/lib/neovim/ruby_provider/buffer_ext.rb +3 -3
  17. data/lib/neovim/ruby_provider/vim.rb +6 -1
  18. data/lib/neovim/ruby_provider/window_ext.rb +3 -3
  19. data/lib/neovim/session.rb +2 -2
  20. data/lib/neovim/session/api.rb +7 -1
  21. data/lib/neovim/session/event_loop.rb +4 -12
  22. data/lib/neovim/session/serializer.rb +2 -2
  23. data/lib/neovim/tabpage.rb +6 -0
  24. data/lib/neovim/version.rb +1 -1
  25. data/lib/neovim/window.rb +19 -1
  26. data/script/generate_docs +71 -0
  27. data/{bin → script}/j2mp +0 -0
  28. data/{bin → script}/mp2j +0 -0
  29. data/spec/acceptance/neovim-ruby-host_spec.rb +1 -6
  30. data/spec/acceptance/ruby_provider_spec.rb +17 -33
  31. data/spec/helper.rb +42 -37
  32. data/spec/neovim/buffer_spec.rb +1 -1
  33. data/spec/neovim/client_spec.rb +1 -1
  34. data/spec/neovim/current_spec.rb +1 -1
  35. data/spec/neovim/host/loader_spec.rb +2 -0
  36. data/spec/neovim/host_spec.rb +25 -5
  37. data/spec/neovim/line_range_spec.rb +2 -2
  38. data/spec/neovim/logging_spec.rb +56 -0
  39. data/spec/neovim/plugin_spec.rb +9 -0
  40. data/spec/neovim/remote_object_spec.rb +5 -1
  41. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +5 -5
  42. data/spec/neovim/ruby_provider/vim_spec.rb +32 -0
  43. data/spec/neovim/ruby_provider/window_ext_spec.rb +22 -8
  44. data/spec/neovim/session/api_spec.rb +24 -5
  45. data/spec/neovim/session/event_loop_spec.rb +54 -1
  46. data/spec/neovim/session/notification_spec.rb +20 -0
  47. data/spec/neovim/session/request_spec.rb +36 -0
  48. data/spec/neovim/session/rpc_spec.rb +12 -0
  49. data/spec/neovim/session/serializer_spec.rb +14 -0
  50. data/spec/neovim/session_spec.rb +4 -4
  51. data/spec/neovim/window_spec.rb +17 -1
  52. data/spec/neovim_spec.rb +4 -20
  53. metadata +13 -4
@@ -1,4 +1,4 @@
1
- require "neovim/logging"
1
+ require "neovim"
2
2
  require "neovim/host/loader"
3
3
 
4
4
  module Neovim
@@ -8,14 +8,16 @@ module Neovim
8
8
 
9
9
  attr_reader :handlers, :specs
10
10
 
11
- # Initialize and populate a +Host+ from a list of plugin paths.
12
- def self.load_from_files(rplugin_paths, options={})
11
+ # Start a plugin host. This is called by the +nvim-ruby-host+ executable,
12
+ # which is spawned by +nvim+ to discover and run Ruby plugins, and acts as
13
+ # the bridge between +nvim+ and the plugin.
14
+ def self.run(rplugin_paths, options={})
13
15
  session = options.fetch(:session) { Session.stdio }
14
16
  client = options.fetch(:client) { Client.new(session) }
15
17
 
16
18
  new(session, client).tap do |host|
17
19
  Loader.new(host).load(rplugin_paths)
18
- end
20
+ end.run
19
21
  end
20
22
 
21
23
  def initialize(session, client)
@@ -1,3 +1,5 @@
1
+ require "neovim/plugin"
2
+
1
3
  module Neovim
2
4
  class Host
3
5
  # @api private
@@ -55,7 +55,7 @@ module Neovim
55
55
  LineRange.new(
56
56
  @buffer,
57
57
  abs_line(pos),
58
- abs_line(pos + len -1)
58
+ abs_line(pos + len - 1)
59
59
  )
60
60
  else
61
61
  @buffer.get_line(abs_line(pos))
@@ -2,6 +2,7 @@ require "logger"
2
2
 
3
3
  module Neovim
4
4
  # Mixed into classes for unified logging helper methods.
5
+ #
5
6
  # @api private
6
7
  module Logging
7
8
  class << self
@@ -9,22 +10,22 @@ module Neovim
9
10
  end
10
11
 
11
12
  # Return the value of @logger, or construct it from the environment.
12
- # $NVIM_RUBY_LOG_FILE specifies a file to log to (default +STDOUT+), while
13
+ # $NVIM_RUBY_LOG_FILE specifies a file to log to (default +STDERR+), while
13
14
  # NVIM_RUBY_LOG_LEVEL specifies the level (default +WARN+)
14
- def self.logger
15
+ def self.logger(env=ENV)
15
16
  return @logger if instance_variable_defined?(:@logger)
16
17
 
17
- if env_file = ENV["NVIM_RUBY_LOG_FILE"]
18
+ if env_file = env["NVIM_RUBY_LOG_FILE"]
18
19
  @logger = Logger.new(env_file)
19
20
  else
20
21
  @logger = Logger.new(STDERR)
21
22
  end
22
23
 
23
- if env_level = ENV["NVIM_RUBY_LOG_LEVEL"]
24
- if Logger.const_defined?(env_level.upcase)
25
- @logger.level = Logger.const_get(env_level.upcase)
26
- else
24
+ if env_level = env["NVIM_RUBY_LOG_LEVEL"]
25
+ begin
27
26
  @logger.level = Integer(env_level)
27
+ rescue ArgumentError
28
+ @logger.level = Logger.const_get(env_level.upcase)
28
29
  end
29
30
  else
30
31
  @logger.level = Logger::WARN
@@ -42,7 +42,7 @@ module Neovim
42
42
  # @param options [Hash] Function options.
43
43
  # @param &block [Proc, nil] The body of the function.
44
44
  #
45
- # @option options [String, Boolean] :range The range argument.
45
+ # @option options [String, Boolean] :range The range argument.
46
46
  # See +:h command-range+.
47
47
  # @option options [String] :eval An +nvim+ expression. Gets evaluated and
48
48
  # passed as an argument to the block.
@@ -9,6 +9,8 @@ module Neovim
9
9
  #
10
10
  # @api private
11
11
  module RubyProvider
12
+ @__buffer_cache = {}
13
+
12
14
  def self.__define_plugin!
13
15
  Thread.abort_on_exception = true
14
16
 
@@ -19,7 +21,7 @@ module Neovim
19
21
  end
20
22
  end
21
23
 
22
- # Evaluate the provided Ruby code, exposing the +VIM+ constant for
24
+ # Evaluate the provided Ruby code, exposing the +Vim+ constant for
23
25
  # interactions with the editor.
24
26
  #
25
27
  # This is used by the +:ruby+ command.
@@ -32,7 +34,7 @@ module Neovim
32
34
  end
33
35
  private_class_method :__define_ruby_execute
34
36
 
35
- # Evaluate the provided Ruby file, exposing the +VIM+ constant for
37
+ # Evaluate the provided Ruby file, exposing the +Vim+ constant for
36
38
  # interactions with the editor.
37
39
  #
38
40
  # This is used by the +:rubyfile+ command.
@@ -82,25 +84,20 @@ module Neovim
82
84
  private_class_method :__wrap_client
83
85
 
84
86
  def self.__with_globals(client)
85
- @__buffer_cache ||= {}
86
- @__window_cache ||= {}
87
-
88
- bufnr, winnr = client.evaluate("[bufnr('%'), winnr()]")
87
+ bufnr = client.evaluate("bufnr('%')")
89
88
 
90
89
  $curbuf = @__buffer_cache.fetch(bufnr) do
91
90
  @__buffer_cache[bufnr] = client.get_current_buffer
92
91
  end
93
92
 
94
- $curwin = @__window_cache.fetch(winnr) do
95
- @__window_cache[winnr] = client.get_current_window
96
- end
93
+ $curwin = client.get_current_window
97
94
 
98
95
  yield
99
96
  end
100
97
  private_class_method :__with_globals
101
98
 
102
99
  def self.__with_vim_constant(client)
103
- ::VIM.__client = client
100
+ ::Vim.__client = client
104
101
  yield
105
102
  end
106
103
  private_class_method :__with_vim_constant
@@ -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_buffer
7
7
  end
8
8
 
9
9
  def self.count
10
- ::VIM.get_buffers.size
10
+ ::Vim.get_buffers.size
11
11
  end
12
12
 
13
13
  def self.[](index)
14
- ::VIM.get_buffers[index]
14
+ ::Vim.get_buffers[index]
15
15
  end
16
16
  end
17
17
  end
@@ -1,7 +1,9 @@
1
1
  require "neovim/buffer"
2
2
  require "neovim/window"
3
3
 
4
- module VIM
4
+ # The VIM module provides backwards compatibility for the legacy +:ruby+,
5
+ # +:rubyfile+, and +:rubydo+ +vim+ functions.
6
+ module Vim
5
7
  Buffer = ::Neovim::Buffer
6
8
  Window = ::Neovim::Window
7
9
 
@@ -9,7 +11,10 @@ module VIM
9
11
  @__client = client
10
12
  end
11
13
 
14
+ # Delegate all method calls to the underlying +Neovim::Client+ object.
12
15
  def self.method_missing(method, *args, &block)
13
16
  @__client.public_send(method, *args, &block)
14
17
  end
15
18
  end
19
+
20
+ VIM = Vim
@@ -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_window
7
7
  end
8
8
 
9
9
  def self.count
10
- ::VIM.get_windows.size
10
+ ::Vim.get_current_tabpage.get_windows.size
11
11
  end
12
12
 
13
13
  def self.[](index)
14
- ::VIM.get_windows[index]
14
+ ::Vim.get_current_tabpage.get_windows[index]
15
15
  end
16
16
  end
17
17
  end
@@ -66,8 +66,8 @@ module Neovim
66
66
  def run
67
67
  @running = true
68
68
 
69
- while message = @pending_messages.shift
70
- Fiber.new { yield message if block_given? }.resume
69
+ while pending = @pending_messages.shift
70
+ Fiber.new { yield pending if block_given? }.resume
71
71
  end
72
72
 
73
73
  return unless @running
@@ -45,7 +45,13 @@ module Neovim
45
45
  "#<#{self.class}:0x%x @types={...} @functions={...}>" % (object_id << 1)
46
46
  end
47
47
 
48
- class Function < Struct.new(:name, :async)
48
+ class Function
49
+ attr_reader :name, :async
50
+
51
+ def initialize(name, async)
52
+ @name, @async = name, async
53
+ end
54
+
49
55
  # Apply this function to a running RPC session. Sends either a request if
50
56
  # +async+ is +false+ or a notification if +async+ is +true+.
51
57
  def call(session, *args)
@@ -9,8 +9,6 @@ module Neovim
9
9
  class EventLoop
10
10
  include Logging
11
11
 
12
- private_class_method :new
13
-
14
12
  # Connect to a TCP socket.
15
13
  def self.tcp(host, port)
16
14
  socket = TCPSocket.new(host, port)
@@ -24,8 +22,10 @@ module Neovim
24
22
  end
25
23
 
26
24
  # Spawn and connect to a child +nvim+ process.
27
- def self.child(argv)
28
- io = IO.popen(argv | ["--embed"], "rb+").tap do |_io|
25
+ def self.child(_argv)
26
+ argv = _argv.include?("--embed") ? _argv : _argv + ["--embed"]
27
+
28
+ io = IO.popen(argv, "rb+").tap do |_io|
29
29
  Process.detach(_io.pid)
30
30
  end
31
31
 
@@ -93,14 +93,6 @@ module Neovim
93
93
  io.close
94
94
  rescue IOError
95
95
  end
96
-
97
- begin
98
- if pid = io.pid
99
- Process.kill(:TERM, pid)
100
- Process.waitpid(pid)
101
- end
102
- rescue IOError, Errno::ESRCH, Errno::ECHILD
103
- end
104
96
  end
105
97
  end
106
98
  end
@@ -10,9 +10,9 @@ module Neovim
10
10
  class Serializer
11
11
  include Logging
12
12
 
13
- def initialize(event_loop)
13
+ def initialize(event_loop, unpacker=nil)
14
14
  @event_loop = event_loop
15
- @unpacker = MessagePack::Unpacker.new
15
+ @unpacker = unpacker || MessagePack::Unpacker.new
16
16
  end
17
17
 
18
18
  # Serialize an RPC message to and write it to the event loop.
@@ -6,25 +6,31 @@ module Neovim
6
6
  # The following methods are dynamically generated.
7
7
  =begin
8
8
  @method get_windows
9
+ Send the +tabpage_get_windows+ RPC to +nvim+
9
10
  @return [Array<Window>]
10
11
 
11
12
  @method get_var(name)
13
+ Send the +tabpage_get_var+ RPC to +nvim+
12
14
  @param [String] name
13
15
  @return [Object]
14
16
 
15
17
  @method set_var(name, value)
18
+ Send the +tabpage_set_var+ RPC to +nvim+
16
19
  @param [String] name
17
20
  @param [Object] value
18
21
  @return [Object]
19
22
 
20
23
  @method del_var(name)
24
+ Send the +tabpage_del_var+ RPC to +nvim+
21
25
  @param [String] name
22
26
  @return [Object]
23
27
 
24
28
  @method get_window
29
+ Send the +tabpage_get_window+ RPC to +nvim+
25
30
  @return [Window]
26
31
 
27
32
  @method is_valid
33
+ Send the +tabpage_is_valid+ RPC to +nvim+
28
34
  @return [Boolean]
29
35
 
30
36
  =end
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.3.0")
2
+ VERSION = Gem::Version.new("0.3.1")
3
3
  end
@@ -53,64 +53,82 @@ module Neovim
53
53
  # @param coords [Array(Fixnum, Fixnum)]
54
54
  # @return [Array(Fixnum, Fixnum)]
55
55
  def cursor=(coords)
56
- set_cursor(coords)
56
+ _x, _y = coords
57
+ x = [_x, 1].max
58
+ y = [_y, 0].max + 1
59
+ @session.request(:vim_eval, "cursor(#{x}, #{y})")
57
60
  end
58
61
 
59
62
  # The following methods are dynamically generated.
60
63
  =begin
61
64
  @method get_buffer
65
+ Send the +window_get_buffer+ RPC to +nvim+
62
66
  @return [Buffer]
63
67
 
64
68
  @method get_cursor
69
+ Send the +window_get_cursor+ RPC to +nvim+
65
70
  @return [Array<Fixnum>]
66
71
 
67
72
  @method set_cursor(pos)
73
+ Send the +window_set_cursor+ RPC to +nvim+
68
74
  @param [Array<Fixnum>] pos
69
75
  @return [void]
70
76
 
71
77
  @method get_height
78
+ Send the +window_get_height+ RPC to +nvim+
72
79
  @return [Fixnum]
73
80
 
74
81
  @method set_height(height)
82
+ Send the +window_set_height+ RPC to +nvim+
75
83
  @param [Fixnum] height
76
84
  @return [void]
77
85
 
78
86
  @method get_width
87
+ Send the +window_get_width+ RPC to +nvim+
79
88
  @return [Fixnum]
80
89
 
81
90
  @method set_width(width)
91
+ Send the +window_set_width+ RPC to +nvim+
82
92
  @param [Fixnum] width
83
93
  @return [void]
84
94
 
85
95
  @method get_var(name)
96
+ Send the +window_get_var+ RPC to +nvim+
86
97
  @param [String] name
87
98
  @return [Object]
88
99
 
89
100
  @method set_var(name, value)
101
+ Send the +window_set_var+ RPC to +nvim+
90
102
  @param [String] name
91
103
  @param [Object] value
92
104
  @return [Object]
93
105
 
94
106
  @method del_var(name)
107
+ Send the +window_del_var+ RPC to +nvim+
95
108
  @param [String] name
96
109
  @return [Object]
97
110
 
98
111
  @method get_option(name)
112
+ Send the +window_get_option+ RPC to +nvim+
99
113
  @param [String] name
100
114
  @return [Object]
101
115
 
102
116
  @method set_option(name, value)
117
+ Send the +window_set_option+ RPC to +nvim+
103
118
  @param [String] name
104
119
  @param [Object] value
105
120
  @return [void]
106
121
 
107
122
  @method get_position
123
+ Send the +window_get_position+ RPC to +nvim+
108
124
  @return [Array<Fixnum>]
109
125
 
110
126
  @method get_tabpage
127
+ Send the +window_get_tabpage+ RPC to +nvim+
111
128
  @return [Tabpage]
112
129
 
113
130
  @method is_valid
131
+ Send the +window_is_valid+ RPC to +nvim+
114
132
  @return [Boolean]
115
133
 
116
134
  =end
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+
5
+ require "neovim"
6
+ require "pathname"
7
+
8
+ vim_docs = []
9
+ buffer_docs = []
10
+ window_docs = []
11
+ tabpage_docs = []
12
+ session = Neovim::Session.child(%w(nvim -u NONE -n))
13
+ vim_defs = Neovim::Client.instance_methods(false)
14
+ buffer_defs = Neovim::Buffer.instance_methods(false)
15
+ tabpage_defs = Neovim::Tabpage.instance_methods(false)
16
+ window_defs = Neovim::Window.instance_methods(false)
17
+
18
+ session.request(:vim_get_api_info)[1]["functions"].each do |func|
19
+ prefix, method_name = func["name"].split("_", 2)
20
+
21
+ case prefix
22
+ when "vim"
23
+ next if vim_defs.include?(method_name.to_sym)
24
+ when "buffer"
25
+ next if buffer_defs.include?(method_name.to_sym)
26
+ when "tabpage"
27
+ next if tabpage_defs.include?(method_name.to_sym)
28
+ when "window"
29
+ next if window_defs.include?(method_name.to_sym)
30
+ end
31
+
32
+ return_type = func["return_type"]
33
+ params = func["parameters"]
34
+ params.shift unless prefix == "vim"
35
+ param_names = params.map(&:last)
36
+ param_str = params.empty? ? "" : "(#{param_names.join(", ")})"
37
+ method_decl = "@method #{method_name}#{param_str}"
38
+ method_desc = " Send the +#{prefix}_#{method_name}+ RPC to +nvim+"
39
+ param_docs = params.map do |type, name|
40
+ " @param [#{type}] #{name}"
41
+ end
42
+ return_doc = " @return [#{return_type}]\n"
43
+ method_doc = [method_decl, method_desc, *param_docs, return_doc].join("\n")
44
+ method_doc.gsub!(/ArrayOf\((\w+)[^)]*\)/, 'Array<\1>')
45
+ method_doc.gsub!(/Integer/, "Fixnum")
46
+
47
+ case prefix
48
+ when "vim"
49
+ vim_docs << method_doc
50
+ when "buffer"
51
+ buffer_docs << method_doc
52
+ when "tabpage"
53
+ tabpage_docs << method_doc
54
+ when "window"
55
+ window_docs << method_doc
56
+ end
57
+ end
58
+
59
+ lib_dir = Pathname.new(File.expand_path("../../lib/neovim", __FILE__))
60
+ {
61
+ "client.rb" => vim_docs,
62
+ "buffer.rb" => buffer_docs,
63
+ "tabpage.rb" => tabpage_docs,
64
+ "window.rb" => window_docs,
65
+ }.each do |filename, docs|
66
+ path = lib_dir.join(filename)
67
+ contents = File.read(path)
68
+ doc_str = ["=begin", *docs, "=end"].join("\n")
69
+
70
+ File.write(path, contents.sub(/=begin.+=end/m, doc_str))
71
+ end