neovim 0.8.1 → 0.9.0.pre.1

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 (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