neovim 0.8.1 → 0.9.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +36 -0
  3. data/.github/workflows/linter.yml +32 -0
  4. data/.github/workflows/tests.yml +62 -0
  5. data/.rubocop.yml +19 -2
  6. data/CHANGELOG.md +6 -0
  7. data/CODE_OF_CONDUCT.md +3 -3
  8. data/README.md +19 -17
  9. data/Rakefile +28 -24
  10. data/exe/neovim-ruby-host +2 -15
  11. data/lib/neovim/buffer.rb +15 -1
  12. data/lib/neovim/client.rb +89 -1
  13. data/lib/neovim/connection.rb +0 -1
  14. data/lib/neovim/event_loop.rb +6 -3
  15. data/lib/neovim/host/cli.rb +41 -0
  16. data/lib/neovim/logging.rb +1 -1
  17. data/lib/neovim/ruby_provider.rb +25 -8
  18. data/lib/neovim/ruby_provider/object_ext.rb +5 -0
  19. data/lib/neovim/session.rb +13 -18
  20. data/lib/neovim/tabpage.rb +1 -1
  21. data/lib/neovim/version.rb +1 -1
  22. data/lib/neovim/window.rb +15 -1
  23. data/neovim.gemspec +1 -1
  24. data/script/ci/download_nvim.sh +40 -0
  25. data/script/run_acceptance.rb +15 -11
  26. data/spec/acceptance/ruby_spec.vim +6 -1
  27. data/spec/acceptance/rubyeval_spec.vim +22 -0
  28. data/spec/acceptance/rubyfile/set_pwd_before.rb +1 -1
  29. data/spec/acceptance/rubyfile_spec.vim +4 -6
  30. data/spec/helper.rb +20 -1
  31. data/spec/neovim/api_spec.rb +1 -1
  32. data/spec/neovim/buffer_spec.rb +4 -6
  33. data/spec/neovim/client_spec.rb +3 -3
  34. data/spec/neovim/current_spec.rb +1 -2
  35. data/spec/neovim/event_loop_spec.rb +10 -0
  36. data/spec/neovim/host/cli_spec.rb +94 -0
  37. data/spec/neovim/host_spec.rb +2 -7
  38. data/spec/neovim/line_range_spec.rb +1 -3
  39. data/spec/neovim/remote_object_spec.rb +1 -2
  40. data/spec/neovim/ruby_provider/buffer_ext_spec.rb +6 -7
  41. data/spec/neovim/ruby_provider/object_ext_spec.rb +10 -0
  42. data/spec/neovim/ruby_provider/vim_spec.rb +1 -1
  43. data/spec/neovim/ruby_provider/window_ext_spec.rb +7 -10
  44. data/spec/neovim/session_spec.rb +13 -46
  45. data/spec/neovim/window_spec.rb +1 -1
  46. data/spec/neovim_spec.rb +10 -63
  47. data/spec/support.rb +25 -0
  48. metadata +21 -12
  49. data/.travis.yml +0 -25
  50. data/appveyor.yml +0 -35
  51. data/script/validate_docs.rb +0 -29
@@ -35,7 +35,6 @@ module Neovim
35
35
 
36
36
  @unpacker = MessagePack::Unpacker.new(@rd)
37
37
  @packer = MessagePack::Packer.new(@wr)
38
- @running = false
39
38
  end
40
39
 
41
40
  def write(object)
@@ -36,7 +36,7 @@ module Neovim
36
36
  def shutdown
37
37
  @running = false
38
38
  @shutdown = true
39
- run
39
+ @connection.close
40
40
  end
41
41
 
42
42
  def request(request_id, method, *args)
@@ -70,20 +70,23 @@ module Neovim
70
70
 
71
71
  def run
72
72
  @running = true
73
+ last_value = nil
73
74
 
74
75
  loop do
75
76
  break unless @running
76
77
  break if @shutdown
77
78
 
78
79
  begin
79
- yield read
80
- rescue EOFError => e
80
+ last_value = yield(read)
81
+ rescue EOFError, Errno::EPIPE => e
81
82
  log_exception(:debug, e, __method__)
82
83
  shutdown
83
84
  rescue => e
84
85
  log_exception(:error, e, __method__)
85
86
  end
86
87
  end
88
+
89
+ last_value
87
90
  ensure
88
91
  @connection.close if @shutdown
89
92
  end
@@ -0,0 +1,41 @@
1
+ require "neovim/connection"
2
+ require "neovim/event_loop"
3
+ require "neovim/host"
4
+ require "neovim/version"
5
+ require "optparse"
6
+
7
+ module Neovim
8
+ class Host
9
+ # @api private
10
+ class CLI
11
+ def self.run(path, argv, inn, out, err)
12
+ cmd = File.basename(path)
13
+
14
+ OptionParser.new do |opts|
15
+ opts.on("-V", "--version") do
16
+ out.puts Neovim::VERSION
17
+ exit(0)
18
+ end
19
+
20
+ opts.on("-h", "--help") do
21
+ out.puts "Usage: #{cmd} [-hV] rplugin_path ..."
22
+ exit(0)
23
+ end
24
+ end.order!(argv)
25
+
26
+ if inn.tty?
27
+ err.puts("Can't run #{cmd} interactively.")
28
+ exit(1)
29
+ else
30
+ conn = Connection.new(inn, out)
31
+ event_loop = EventLoop.new(conn)
32
+
33
+ Host.run(argv, event_loop)
34
+ end
35
+ rescue OptionParser::InvalidOption => e
36
+ err.puts(e.message)
37
+ exit(1)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -18,7 +18,7 @@ module Neovim
18
18
 
19
19
  @logger = Logger.new(env_file || STDERR)
20
20
 
21
- if env_level
21
+ if /\S+/.match?(env_level)
22
22
  begin
23
23
  @logger.level = Integer(env_level)
24
24
  rescue ArgumentError
@@ -1,4 +1,5 @@
1
1
  require "neovim/ruby_provider/vim"
2
+ require "neovim/ruby_provider/object_ext"
2
3
  require "neovim/ruby_provider/buffer_ext"
3
4
  require "neovim/ruby_provider/window_ext"
4
5
  require "stringio"
@@ -18,6 +19,7 @@ module Neovim
18
19
 
19
20
  __define_setup(plug)
20
21
  __define_ruby_execute(plug)
22
+ __define_ruby_eval(plug)
21
23
  __define_ruby_execute_file(plug)
22
24
  __define_ruby_do_range(plug)
23
25
  __define_ruby_chdir(plug)
@@ -44,12 +46,26 @@ module Neovim
44
46
  def self.__define_ruby_execute(plug)
45
47
  plug.__send__(:rpc, :ruby_execute) do |nvim, ruby|
46
48
  __wrap_client(nvim) do
47
- eval(ruby, TOPLEVEL_BINDING, "eval")
49
+ eval(ruby, TOPLEVEL_BINDING, "ruby_execute")
48
50
  end
51
+ nil
49
52
  end
50
53
  end
51
54
  private_class_method :__define_ruby_execute
52
55
 
56
+ # Evaluate the provided Ruby code, exposing the +Vim+ constant for
57
+ # interactions with the editor and returning the value.
58
+ #
59
+ # This is used by the +:rubyeval+ command.
60
+ def self.__define_ruby_eval(plug)
61
+ plug.__send__(:rpc, :ruby_eval) do |nvim, ruby|
62
+ __wrap_client(nvim) do
63
+ eval(ruby, TOPLEVEL_BINDING, "ruby_eval")
64
+ end
65
+ end
66
+ end
67
+ private_class_method :__define_ruby_eval
68
+
53
69
  # Evaluate the provided Ruby file, exposing the +Vim+ constant for
54
70
  # interactions with the editor.
55
71
  #
@@ -57,6 +73,7 @@ module Neovim
57
73
  def self.__define_ruby_execute_file(plug)
58
74
  plug.__send__(:rpc, :ruby_execute_file) do |nvim, path|
59
75
  __wrap_client(nvim) { load(path) }
76
+ nil
60
77
  end
61
78
  end
62
79
  private_class_method :__define_ruby_execute_file
@@ -75,14 +92,15 @@ module Neovim
75
92
  __start, __stop, __ruby = __args
76
93
  __buffer = __nvim.get_current_buf
77
94
 
78
- __update_lines_in_chunks(__buffer, __start, __stop, 5000) do |__lines|
95
+ __update_lines_in_chunks(__buffer, __start, __stop, 1_000) do |__lines|
79
96
  __lines.map do |__line|
80
97
  $_ = __line
81
- eval(__ruby, binding, "eval")
98
+ eval(__ruby, binding, "ruby_do_range")
82
99
  $_
83
100
  end
84
101
  end
85
102
  end
103
+ nil
86
104
  end
87
105
  end
88
106
  private_class_method :__define_ruby_do_range
@@ -103,7 +121,6 @@ module Neovim
103
121
  yield
104
122
  end
105
123
  end
106
- nil
107
124
  end
108
125
  private_class_method :__wrap_client
109
126
 
@@ -122,10 +139,10 @@ module Neovim
122
139
  $stdout, $stderr = StringIO.new, StringIO.new
123
140
 
124
141
  begin
125
- yield
126
-
127
- client.out_write($stdout.string + $/) if $stdout.size > 0
128
- client.err_writeln($stderr.string) if $stderr.size > 0
142
+ yield.tap do
143
+ client.out_write($stdout.string + $/) if $stdout.size > 0
144
+ client.err_writeln($stderr.string) if $stderr.size > 0
145
+ end
129
146
  ensure
130
147
  $stdout = old_stdout
131
148
  $stderr = old_stderr
@@ -0,0 +1,5 @@
1
+ class Object
2
+ def to_msgpack(packer)
3
+ packer.pack(to_s)
4
+ end
5
+ end
@@ -12,9 +12,9 @@ module Neovim
12
12
  attr_writer :request_id
13
13
 
14
14
  # @api private
15
- class Exited < RuntimeError
15
+ class Disconnected < RuntimeError
16
16
  def initialize
17
- super("nvim process exited")
17
+ super("Disconnected from nvim process")
18
18
  end
19
19
  end
20
20
 
@@ -28,19 +28,21 @@ module Neovim
28
28
  end
29
29
 
30
30
  def run(&block)
31
- @running = true
32
-
33
- while (pending = @pending_messages.shift)
34
- Fiber.new { pending.received(@response_handlers, &block) }.resume
35
- end
31
+ block ||= ->(msg) { @pending_messages << msg }
36
32
 
37
- return unless @running
33
+ @running = true
38
34
 
39
35
  @event_loop.run do |message|
40
36
  Fiber.new { message.received(@response_handlers, &block) }.resume
41
37
  end
42
38
  end
43
39
 
40
+ def next
41
+ return @pending_messages.shift if @pending_messages.any?
42
+
43
+ run { |msg| stop; msg }
44
+ end
45
+
44
46
  # Make an RPC request and return its response.
45
47
  #
46
48
  # If this method is called inside a callback, we are already inside a
@@ -68,7 +70,7 @@ module Neovim
68
70
  @event_loop.request(@request_id, method, *args)
69
71
  response = blocking ? blocking_response : yielding_response
70
72
 
71
- raise(Exited) if response.nil?
73
+ raise(Disconnected) if response.nil?
72
74
  raise(response.error) if response.error
73
75
  response.value
74
76
  end
@@ -95,15 +97,8 @@ module Neovim
95
97
  private
96
98
 
97
99
  def blocking_response
98
- response = nil
99
-
100
- @response_handlers[@request_id] = lambda do |res|
101
- response = res
102
- stop
103
- end
104
-
105
- run { |message| @pending_messages << message }
106
- response
100
+ @response_handlers[@request_id] = ->(res) { stop; res }
101
+ run
107
102
  end
108
103
 
109
104
  def yielding_response
@@ -3,7 +3,7 @@ require "neovim/remote_object"
3
3
  module Neovim
4
4
  # Class representing an +nvim+ tabpage.
5
5
  #
6
- # The methods documented here were generated using NVIM v0.3.7
6
+ # The methods documented here were generated using NVIM v0.4.4
7
7
  class Tabpage < RemoteObject
8
8
  # The following methods are dynamically generated.
9
9
  =begin
@@ -1,3 +1,3 @@
1
1
  module Neovim
2
- VERSION = Gem::Version.new("0.8.1")
2
+ VERSION = Gem::Version.new("0.9.0.pre.1")
3
3
  end
@@ -3,7 +3,7 @@ require "neovim/remote_object"
3
3
  module Neovim
4
4
  # Class representing an +nvim+ window.
5
5
  #
6
- # The methods documented here were generated using NVIM v0.3.7
6
+ # The methods documented here were generated using NVIM v0.4.4
7
7
  class Window < RemoteObject
8
8
  # Get the buffer displayed in the window
9
9
  #
@@ -143,6 +143,20 @@ module Neovim
143
143
  See +:h nvim_win_is_valid()+
144
144
  @return [Boolean]
145
145
 
146
+ @method set_config(config)
147
+ See +:h nvim_win_set_config()+
148
+ @param [Hash] config
149
+ @return [void]
150
+
151
+ @method get_config
152
+ See +:h nvim_win_get_config()+
153
+ @return [Hash]
154
+
155
+ @method close(force)
156
+ See +:h nvim_win_close()+
157
+ @param [Boolean] force
158
+ @return [void]
159
+
146
160
  =end
147
161
  end
148
162
  end
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "msgpack", "~> 1.1"
23
23
  spec.add_dependency "multi_json", "~> 1.0"
24
24
 
25
- spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
26
  spec.add_development_dependency "pry"
27
27
  spec.add_development_dependency "pry-byebug"
28
28
  spec.add_development_dependency "rake"
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -eu
4
+
5
+ : ${RUNNER_OS:?} ${BUILD:?}
6
+
7
+ case "$BUILD" in
8
+ latest)
9
+ URL_PART="latest/download"
10
+ ;;
11
+ nightly)
12
+ URL_PART="download/nightly"
13
+ ;;
14
+ *)
15
+ echo "BUILD must be 'latest' or 'nightly'." >&2
16
+ exit 1
17
+ ;;
18
+ esac
19
+
20
+ case "$(echo "$RUNNER_OS" | tr "[:upper:]" "[:lower:]")" in
21
+ macos)
22
+ wget -nv -P /tmp \
23
+ "https://github.com/neovim/neovim/releases/$URL_PART/nvim-macos.tar.gz"
24
+ tar -C /tmp -xzf /tmp/nvim-macos.tar.gz
25
+ mv /tmp/nvim-osx64 ./_nvim
26
+ ;;
27
+ linux)
28
+ mkdir -p _nvim/bin
29
+ wget -nv -O _nvim/bin/nvim \
30
+ "https://github.com/neovim/neovim/releases/$URL_PART/nvim.appimage"
31
+ ;;
32
+ *)
33
+ echo "Unrecognized \$RUNNER_OS" >&2
34
+ exit 1
35
+ ;;
36
+ esac
37
+
38
+ chmod u+x _nvim/bin/nvim
39
+
40
+ _nvim/bin/nvim --version
@@ -5,11 +5,13 @@ require "fileutils"
5
5
  ENV.delete("VIM")
6
6
  ENV.delete("VIMRUNTIME")
7
7
 
8
- acceptance_root = File.expand_path("../spec/acceptance", __dir__)
8
+ root = File.expand_path("..", __dir__)
9
+ acceptance_root = File.join(root, "spec/acceptance")
9
10
  themis_rtp = File.join(acceptance_root, "runtime")
10
11
  themis_home = File.join(themis_rtp, "flavors/thinca_vim-themis")
11
12
  manifest = File.join(themis_rtp, "rplugin_manifest.vim")
12
13
  vimrc = File.join(themis_rtp, "init.vim")
14
+ nvim = ENV.fetch("NVIM_EXECUTABLE", "nvim")
13
15
 
14
16
  themis_exe = Gem.win_platform? ?
15
17
  File.join(themis_home, "bin/themis.bat") :
@@ -17,19 +19,21 @@ themis_exe = Gem.win_platform? ?
17
19
 
18
20
  env = {
19
21
  "NVIM_RPLUGIN_MANIFEST" => manifest,
20
- "THEMIS_VIM" => "nvim",
22
+ "THEMIS_VIM" => nvim,
21
23
  "THEMIS_HOME" => themis_home,
22
24
  "THEMIS_ARGS" => "-e -s --headless -u #{vimrc}"
23
25
  }
24
26
 
25
27
  FileUtils.rm_f(manifest)
26
28
 
27
- system(
28
- env,
29
- "nvim",
30
- "-e", "-s", "--headless",
31
- "-u", vimrc,
32
- "+UpdateRemotePlugins", "+qa!"
33
- )
34
-
35
- exec(env, themis_exe, *ARGV)
29
+ Dir.chdir(root) do
30
+ system(
31
+ env,
32
+ nvim,
33
+ "-e", "-s", "--headless",
34
+ "-u", vimrc,
35
+ "+UpdateRemotePlugins", "+qa!"
36
+ )
37
+
38
+ exec(env, themis_exe, *ARGV)
39
+ end
@@ -2,11 +2,16 @@ let s:suite = themis#suite(":ruby")
2
2
  let s:expect = themis#helper("expect")
3
3
 
4
4
  function! s:suite.before_each() abort
5
+ let s:pwd = getcwd()
5
6
  1,$delete
6
7
  call append(0, ["one", "two"])
7
8
  unlet! s:var
8
9
  endfunction
9
10
 
11
+ function! s:suite.after_each() abort
12
+ execute("cd " . s:pwd)
13
+ endfunction
14
+
10
15
  function! s:suite.has_nvim() abort
11
16
  call s:expect(has("nvim")).to_equal(1)
12
17
  endfunction
@@ -27,7 +32,7 @@ endfunction
27
32
 
28
33
  function! s:suite.updates_working_directory() abort
29
34
  cd /
30
- ruby Vim.command("let s:var = '#{Dir.pwd.sub(/^C:/, "")}'")
35
+ ruby Vim.command("let s:var = '#{Dir.pwd.sub(/^[A-Z]:/, "")}'")
31
36
  cd -
32
37
 
33
38
  call s:expect(s:var).to_equal("/")
@@ -0,0 +1,22 @@
1
+ let s:suite = themis#suite(":rubyeval")
2
+ let s:expect = themis#helper("expect")
3
+
4
+ function! s:suite.evaluates_ruby_objects() abort
5
+ call s:expect(rubyeval("123")).to_equal(123)
6
+ call s:expect(rubyeval("1.2")).to_equal(1.2)
7
+ call s:expect(rubyeval("'test'")).to_equal("test")
8
+ call s:expect(rubyeval("nil")).to_equal(v:null)
9
+ call s:expect(rubyeval("true")).to_equal(v:true)
10
+ call s:expect(rubyeval("false")).to_equal(v:false)
11
+ call s:expect(rubyeval("{x: 1}")).to_equal({"x": 1})
12
+ call s:expect(rubyeval(":test")).to_equal("test")
13
+ call s:expect(rubyeval(":test.class")).to_equal("Symbol")
14
+ endfunction
15
+
16
+ function! s:suite.propagates_exceptions() abort
17
+ try
18
+ rubyeval("raise 'BOOM'")
19
+ throw "Nothing raised"
20
+ catch /BOOM/
21
+ endtry
22
+ endfunction