neovim 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +18 -0
- data/.gitmodules +4 -0
- data/.travis.yml +30 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +26 -0
- data/lib/neovim.rb +31 -0
- data/lib/neovim/api_info.rb +27 -0
- data/lib/neovim/async_session.rb +75 -0
- data/lib/neovim/client.rb +29 -0
- data/lib/neovim/current.rb +44 -0
- data/lib/neovim/event_loop.rb +75 -0
- data/lib/neovim/msgpack_stream.rb +44 -0
- data/lib/neovim/object.rb +44 -0
- data/lib/neovim/session.rb +35 -0
- data/lib/neovim/version.rb +3 -0
- data/neovim.gemspec +27 -0
- data/spec/helper.rb +26 -0
- data/spec/neovim/async_session_spec.rb +96 -0
- data/spec/neovim/buffer_spec.rb +37 -0
- data/spec/neovim/client_spec.rb +57 -0
- data/spec/neovim/current_spec.rb +78 -0
- data/spec/neovim/event_loop_spec.rb +58 -0
- data/spec/neovim/msgpack_stream_spec.rb +29 -0
- data/spec/neovim/session_spec.rb +29 -0
- data/spec/neovim/tabpage_spec.rb +37 -0
- data/spec/neovim/window_spec.rb +37 -0
- data/spec/neovim_spec.rb +54 -0
- metadata +169 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c69f05bcd8852ed00d741fa9c86b4453a34acea8
|
4
|
+
data.tar.gz: fdf05283ab34d8f5692dc8cb95d3335d2b105bda
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3f6d303d8fd49a35c9ba809e0be985533a80e26a20940e565797821a3eefe968e3c579a3ae760f0f739eadf478ae7325e720553e60dcfd059bf470b82b2d0803
|
7
|
+
data.tar.gz: 14a9f4aa0be233fedac15c11e1064d8c54903fed3d868472c600063be30f7f8a692db1993da8ac0b77bc5622ccc848c99f39ac9a7d808cbd47b8c382d71f0929
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
|
4
|
+
branches:
|
5
|
+
only: master
|
6
|
+
|
7
|
+
rvm:
|
8
|
+
- 1.9.3
|
9
|
+
- 2.0.0
|
10
|
+
- 2.1.0
|
11
|
+
- 2.2.0
|
12
|
+
|
13
|
+
os:
|
14
|
+
- linux
|
15
|
+
- osx
|
16
|
+
|
17
|
+
addons:
|
18
|
+
apt:
|
19
|
+
packages:
|
20
|
+
- libtool
|
21
|
+
- autoconf
|
22
|
+
- automake
|
23
|
+
- cmake
|
24
|
+
- libncurses5-dev
|
25
|
+
- g++
|
26
|
+
- pkg-config
|
27
|
+
|
28
|
+
env: REPORT_COVERAGE=1
|
29
|
+
before_script: bundle exec rake neovim:install
|
30
|
+
script: travis_retry bundle exec rake
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Alex Genco
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# Neovim Ruby
|
2
|
+
|
3
|
+
[![Travis](https://travis-ci.org/alexgenco/neovim-ruby.svg?branch=master)](https://travis-ci.org/alexgenco/neovim-ruby)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/alexgenco/neovim-ruby/badge.png)](https://coveralls.io/r/alexgenco/neovim-ruby)
|
5
|
+
|
6
|
+
Ruby bindings for [Neovim](https://github.com/neovim/neovim).
|
7
|
+
|
8
|
+
*Warning*: This project is currently incomplete and unstable.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem "neovim"
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install neovim
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
You can control a running `nvim` process by connecting to `$NVIM_LISTEN_ADDRESS`. Start it up like this:
|
27
|
+
|
28
|
+
```shell
|
29
|
+
$ NVIM_LISTEN_ADDRESS=/tmp/nvim.sock nvim
|
30
|
+
```
|
31
|
+
|
32
|
+
You can then connect to that socket to get a `Neovim::Client`:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
require "neovim"
|
36
|
+
client = Neovim.attach_unix("/tmp/nvim.sock")
|
37
|
+
```
|
38
|
+
|
39
|
+
The interface of the client is generated at runtime from the `vim_get_api_info` RPC call. For now, you can refer to the Node client's auto-generated [API description](https://github.com/neovim/node-client/blob/master/index.d.ts). Note that methods will be in `snake_case` rather than `camelCase`.
|
40
|
+
|
41
|
+
## Contributing
|
42
|
+
|
43
|
+
1. Fork it (http://github.com/alexgenco/neovim-ruby/fork)
|
44
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
45
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
46
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
47
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
task :default => :spec
|
6
|
+
|
7
|
+
namespace :neovim do
|
8
|
+
vendor = File.expand_path("../vendor/neovim", __FILE__)
|
9
|
+
|
10
|
+
desc "Install Neovim"
|
11
|
+
task :install do
|
12
|
+
sh "git submodule update --init && " +
|
13
|
+
"cd #{vendor} && " +
|
14
|
+
"make distclean && " +
|
15
|
+
"make"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Update Neovim installation"
|
19
|
+
task :update do
|
20
|
+
sh "git submodule update --init && " +
|
21
|
+
"cd #{vendor} && " +
|
22
|
+
"make distclean && " +
|
23
|
+
"git pull origin master && " +
|
24
|
+
"make"
|
25
|
+
end
|
26
|
+
end
|
data/lib/neovim.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "neovim/async_session"
|
2
|
+
require "neovim/client"
|
3
|
+
require "neovim/event_loop"
|
4
|
+
require "neovim/msgpack_stream"
|
5
|
+
require "neovim/session"
|
6
|
+
|
7
|
+
module Neovim
|
8
|
+
def self.attach_tcp(host, port)
|
9
|
+
attach_event_loop(EventLoop.tcp(host, port))
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.attach_unix(socket_path)
|
13
|
+
attach_event_loop(EventLoop.unix(socket_path))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.attach_child(argv=[])
|
17
|
+
attach_event_loop(EventLoop.child(argv))
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
private
|
22
|
+
|
23
|
+
def attach_event_loop(event_loop)
|
24
|
+
msgpack_stream = MsgpackStream.new(event_loop)
|
25
|
+
async_session = AsyncSession.new(msgpack_stream)
|
26
|
+
session = Session.new(async_session)
|
27
|
+
|
28
|
+
Client.new(session)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "delegate"
|
2
|
+
|
3
|
+
module Neovim
|
4
|
+
class APIInfo < SimpleDelegator
|
5
|
+
def functions
|
6
|
+
@functions ||= fetch(1).fetch("functions")
|
7
|
+
end
|
8
|
+
|
9
|
+
def types
|
10
|
+
@types ||= fetch(1).fetch("types")
|
11
|
+
end
|
12
|
+
|
13
|
+
def channel_id
|
14
|
+
@channel_id ||= fetch(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
def defined?(function)
|
18
|
+
functions.any? do |func|
|
19
|
+
func["name"] == function.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
"#<#{self.class}:0x%x @channel_id=#{@channel_id.inspect} @types={...} @functions={...}>" % (object_id << 1)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Neovim
|
2
|
+
class AsyncSession
|
3
|
+
def initialize(msgpack_stream)
|
4
|
+
@msgpack_stream = msgpack_stream
|
5
|
+
@request_id = 0
|
6
|
+
@pending_requests = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def register_session(session)
|
10
|
+
@msgpack_stream.register_session(session)
|
11
|
+
end
|
12
|
+
|
13
|
+
def request(method, *args, &response_cb)
|
14
|
+
reqid = @request_id
|
15
|
+
@request_id += 1
|
16
|
+
|
17
|
+
@msgpack_stream.send([0, reqid, method, args])
|
18
|
+
@pending_requests[reqid] = response_cb || Proc.new {}
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def notify(method, *args)
|
23
|
+
@msgpack_stream.send([2, method, args])
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(request_cb=nil, notification_cb=nil)
|
28
|
+
request_cb ||= Proc.new {}
|
29
|
+
notification_cb ||= Proc.new {}
|
30
|
+
|
31
|
+
@msgpack_stream.run do |msg|
|
32
|
+
kind, *rest = msg
|
33
|
+
|
34
|
+
case kind
|
35
|
+
when 0
|
36
|
+
reqid, method, args = rest
|
37
|
+
request_cb.call(method, args, Responder.new(@msgpack_stream, reqid))
|
38
|
+
when 1
|
39
|
+
reqid, (_, error), result = rest
|
40
|
+
@pending_requests.fetch(reqid).call(error, result)
|
41
|
+
when 2
|
42
|
+
event, args = rest
|
43
|
+
notification_cb.call(event, args)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
@msgpack_stream.stop
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def shutdown
|
54
|
+
@msgpack_stream.shutdown
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
class Responder
|
59
|
+
def initialize(msgpack_stream, request_id)
|
60
|
+
@msgpack_stream = msgpack_stream
|
61
|
+
@request_id = request_id
|
62
|
+
end
|
63
|
+
|
64
|
+
def send(value)
|
65
|
+
@msgpack_stream.send([1, @request_id, nil, value])
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
def error(value)
|
70
|
+
@msgpack_stream.send([1, @request_id, value, nil])
|
71
|
+
self
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "neovim/current"
|
2
|
+
|
3
|
+
module Neovim
|
4
|
+
class Client
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(method_name, *args)
|
10
|
+
if methods.include?(method_name)
|
11
|
+
@session.request("vim_#{method_name}", *args)
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to?(method_name)
|
18
|
+
super || methods.include?(method_name.to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
def methods
|
22
|
+
super | @session.api_methods_for_prefix("vim_")
|
23
|
+
end
|
24
|
+
|
25
|
+
def current
|
26
|
+
Current.new(@session)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "neovim/object"
|
2
|
+
|
3
|
+
module Neovim
|
4
|
+
class Current
|
5
|
+
def initialize(session)
|
6
|
+
@session = session
|
7
|
+
end
|
8
|
+
|
9
|
+
def line
|
10
|
+
@session.request(:vim_get_current_line)
|
11
|
+
end
|
12
|
+
|
13
|
+
def line=(ln)
|
14
|
+
@session.request(:vim_set_current_line, ln)
|
15
|
+
end
|
16
|
+
|
17
|
+
def buffer
|
18
|
+
@session.request(:vim_get_current_buffer)
|
19
|
+
end
|
20
|
+
|
21
|
+
def buffer=(buffer_index)
|
22
|
+
buffer = Buffer.new(buffer_index, @session)
|
23
|
+
@session.request(:vim_set_current_buffer, buffer)
|
24
|
+
end
|
25
|
+
|
26
|
+
def window
|
27
|
+
@session.request(:vim_get_current_window)
|
28
|
+
end
|
29
|
+
|
30
|
+
def window=(window_index)
|
31
|
+
window = Window.new(window_index, @session)
|
32
|
+
@session.request(:vim_set_current_window, window)
|
33
|
+
end
|
34
|
+
|
35
|
+
def tabpage
|
36
|
+
@session.request(:vim_get_current_tabpage)
|
37
|
+
end
|
38
|
+
|
39
|
+
def tabpage=(tabpage_index)
|
40
|
+
tabpage = Tabpage.new(tabpage_index, @session)
|
41
|
+
@session.request(:vim_set_current_tabpage, tabpage)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
require "socket"
|
3
|
+
|
4
|
+
module Neovim
|
5
|
+
class EventLoop
|
6
|
+
def self.tcp(host, port)
|
7
|
+
socket = TCPSocket.new(host, port)
|
8
|
+
new(socket, socket)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.unix(path)
|
12
|
+
socket = UNIXSocket.new(path)
|
13
|
+
new(socket, socket)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.child(argv)
|
17
|
+
argv = [ENV.fetch("NVIM_EXECUTABLE", "nvim"), "--embed"] | argv.to_ary
|
18
|
+
io = IO.popen(argv, "rb+")
|
19
|
+
new(io, io)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.stdio
|
23
|
+
new(STDIN, STDOUT)
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(rd, wr)
|
27
|
+
@read_stream, @write_stream = rd, wr
|
28
|
+
end
|
29
|
+
|
30
|
+
def send(data)
|
31
|
+
EM.schedule do
|
32
|
+
@write_conn.send_data(data)
|
33
|
+
end
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def run(&message_callback)
|
38
|
+
message_callback ||= Proc.new {}
|
39
|
+
|
40
|
+
EM.run do
|
41
|
+
@read_conn = EM.watch(@read_stream, Connection)
|
42
|
+
@write_conn = EM.watch(@write_stream, Connection) unless @write_stream == @read_stream
|
43
|
+
@write_conn ||= @read_conn
|
44
|
+
|
45
|
+
@read_conn.notify_readable = true
|
46
|
+
@read_conn.message_callback = message_callback
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def stop
|
51
|
+
EM.stop_event_loop
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def shutdown
|
56
|
+
stop
|
57
|
+
self
|
58
|
+
ensure
|
59
|
+
@read_conn.close if @read_conn.respond_to?(:close)
|
60
|
+
@write_conn.close if @write_conn.respond_to?(:close)
|
61
|
+
end
|
62
|
+
|
63
|
+
class Connection < EM::Connection
|
64
|
+
attr_writer :message_callback
|
65
|
+
|
66
|
+
def send_data(data)
|
67
|
+
@io.write_nonblock(data)
|
68
|
+
end
|
69
|
+
|
70
|
+
def notify_readable
|
71
|
+
@message_callback.call(@io.readpartial(1024 * 16))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|