├── .gitignore ├── README.md ├── example.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .*.swp 3 | .*.swo 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Neovim Node RPC/Plugin Library 2 | 3 | ### Install 4 | `npm install neovim` 5 | 6 | ### Usage 7 | 8 | Types and functions are registered under the plugin RPC 9 | 10 | ```javascript 11 | var VimPlugin = require('neovim'); 12 | var util = require('util'); 13 | var async = require('async'); 14 | 15 | var UNIX = '/tmp/neovim1' 16 | 17 | var vim = new VimPlugin(UNIX, function () { 18 | async.series([ 19 | function (scb) { 20 | vim.rpc.command('au VimResized call rpcnotify(0, "resized")', scb); 21 | }, 22 | function (scb) { 23 | vim.rpc.subscribe("resized", scb); 24 | }, 25 | function (scb) { 26 | vim.on('resized', function () { 27 | vim.rpc.get_current_window(function (window) { 28 | window.get_height(function (height) { 29 | window.get_width(function (width) { 30 | console.log(util.format("size changed to: %dx%d", height, width)); 31 | }); 32 | }); 33 | }); 34 | }); 35 | scb(); 36 | }], 37 | function () { 38 | console.log("go ahead and resize the neovim window"); 39 | } 40 | ); 41 | }); 42 | ``` 43 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var VimPlugin = require('./index'); 2 | var util = require('util'); 3 | var async = require('async'); 4 | 5 | var UNIX = '/tmp/neovim1' 6 | 7 | var vim = new VimPlugin(UNIX, function () { 8 | async.series([ 9 | function (scb) { 10 | vim.rpc.command('au VimResized call rpcnotify(0, "resized")', scb); 11 | }, 12 | function (scb) { 13 | vim.rpc.subscribe("resized", scb); 14 | }, 15 | function (scb) { 16 | vim.on('resized', function () { 17 | vim.rpc.get_current_window(function (window) { 18 | window.get_height(function (height) { 19 | window.get_width(function (width) { 20 | console.log(util.format("size changed to: %dx%d", height, width)); 21 | }); 22 | }); 23 | }); 24 | }); 25 | scb(); 26 | }], 27 | function () { 28 | console.log("go ahead and resize the neovim window"); 29 | } 30 | ); 31 | }); 32 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var net = require('net'); 2 | var msgpack5 = require('msgpack5'); 3 | var util = require('util'); 4 | var EventEmitter = require('events').EventEmitter; 5 | 6 | function TypeBase(id) { 7 | this.id = id; 8 | } 9 | 10 | function VimPlugin(path, cb) { 11 | EventEmitter.call(this); 12 | if (typeof cb === 'function') { 13 | this.once('ready', cb); 14 | } 15 | this.id = 1; 16 | this.rpc = {}; 17 | 18 | this.decoder = msgpack5(); 19 | this.decode = this.decoder.decoder({header: false}) 20 | this.decode.on('data', function (data) { 21 | if (data[0] == 1) { 22 | this.emit('reply:' + data[1], data[3]); 23 | } else if (data[0] == 2) { 24 | console.log(data[1].toString('utf8'), data[2]); 25 | this.emit(data[1].toString('utf8'), data[2]); 26 | } 27 | }.bind(this)); 28 | 29 | this.conn = net.connect({path: path}, function () { 30 | this.conn.pipe(this.decode); 31 | this.getAPI(function (result) { 32 | var api = result[1]; 33 | Object.keys(api.types).forEach(function (typen) { 34 | var name = typen.toString(); 35 | var typeId = api.types[typen].id; 36 | this.rpc[name] = function (id) { 37 | this.id = id; 38 | this.typeId = typeId; 39 | } 40 | var ObjType = this.rpc[name]; 41 | if (typeId !== 35) { 42 | this.decoder.register(typeId, this.rpc[name], function (obj) { 43 | return obj.id; 44 | }, 45 | function (buff) { 46 | return new ObjType(buff); 47 | }); 48 | } 49 | }.bind(this)); 50 | api.functions.forEach(function (func) { 51 | var params = []; 52 | func.parameters.forEach(function (p) { 53 | params.push(p[0].toString()); 54 | }); 55 | var fname = func.name.toString().split('_').slice(1).join('_'); 56 | if (this.rpc.hasOwnProperty(params[0])) { 57 | this.rpc[params[0]].prototype[fname] = this.generateMethod(func.name.toString()); 58 | console.log(util.format("registering %s.%s(%s) -> %s", params[0], fname, params.slice(1).join(', '), func.return_type.toString())); 59 | } else { 60 | this.rpc[fname] = this.generateFunction(func.name.toString()); 61 | console.log(util.format("registering %s(%s) -> %s", fname, params.join(', '), func.return_type.toString())); 62 | } 63 | }.bind(this)); 64 | this.emit('ready'); 65 | }.bind(this)); 66 | }.bind(this)); 67 | 68 | this.getAPI = this.generateFunction('vim_get_api_info', 'get_api'); 69 | } 70 | 71 | VimPlugin.prototype = Object.create(EventEmitter.prototype); 72 | 73 | (function () { 74 | 75 | this.generateFunction = function (name) { 76 | var self = this; 77 | return function () { 78 | var args = Array.prototype.slice.call(arguments, 0); 79 | var cb = args[args.length - 1]; 80 | var args = args.slice(0, args.length - 1); 81 | self.send(name, args, cb); 82 | }; 83 | }; 84 | 85 | this.generateMethod = function (name) { 86 | var self = this; 87 | return function () { 88 | var args = Array.prototype.slice.call(arguments, 0); 89 | var cb = args[args.length - 1]; 90 | var args = args.slice(0, args.length - 1); 91 | args.unshift(this); 92 | self.send(name, args, cb); 93 | }; 94 | }; 95 | 96 | 97 | this.send = function (cmdid, args, cb) { 98 | this.once('reply:' + this.id, cb); 99 | var out = this.decoder.encode([0, this.id, cmdid, args]); 100 | var out2 = Buffer.concat(out._bufs); 101 | this.conn.write(out2); 102 | 103 | this.id++; 104 | }; 105 | 106 | }).apply(VimPlugin.prototype); 107 | 108 | module.exports = VimPlugin; 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "neovim", 3 | "version": "0.0.1", 4 | "description": "Plugin Framework for NeoVIM", 5 | "main": "index.js", 6 | "dependencies": { 7 | "msgpack5": "~1.3.2", 8 | "async": "^0.9.0" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "author": "Nathan Fritz", 15 | "license": "MIT" 16 | } 17 | --------------------------------------------------------------------------------