UNPKG

@chemzqm/neovim

Version:

NodeJS client API for vim9 and neovim

122 lines (121 loc) 3.82 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const events_1 = __importDefault(require("events")); const logger_1 = require("../utils/logger"); const logger = (0, logger_1.createLogger)('connection'); const NR_CODE = 10; // vim connection by using channel feature class Connection extends events_1.default { constructor(readable, writeable) { super(); this.writeable = writeable; let cached = []; let hasCache = false; readable.once('data', buf => { if (!Buffer.isBuffer(buf)) throw new Error(`Vim connection expect Buffer from readable stream.`); }); // should be utf8 encoding. let onData = (buf) => { let start = 0; let len = buf.byteLength; for (let i = 0; i < len; i++) { if (buf[i] === NR_CODE) { // '\n' let b = buf.slice(start, i); if (hasCache) { cached.push(b); let concated = Buffer.concat(cached); hasCache = false; cached = []; this.parseData(concated.toString('utf8')); } else { this.parseData(b.toString('utf8')); } start = i + 1; } } if (start < len) { cached.push(start == 0 ? buf : buf.slice(start)); hasCache = true; } }; readable.on('data', onData); let onClose = () => { logger.warn('readable stream closed.'); }; readable.on('close', onClose); this.clean = () => { readable.off('data', onData); readable.off('close', onClose); }; } parseData(str) { if (str.length == 0) return; let arr; try { arr = JSON.parse(str); } catch (e) { logger.error(`Invalid data from vim: ${str}`); return; } // request, notification, response let [id, obj] = arr; if (id > 0) { logger.debug('received request:', id, obj); this.emit('request', id, obj); } else if (id == 0) { logger.debug('received notification:', obj); this.emit('notification', obj); } else { logger.debug('received response:', id, obj); // response for previous request this.emit('response', id, obj); } } response(requestId, data) { this.send([requestId, data || null]); } notify(event, data) { this.send([0, [event, data || null]]); } send(arr) { logger.debug('send to vim:', arr); this.writeable.write(JSON.stringify(arr) + '\n'); } redraw(force) { this.send(['redraw', force ? 'force' : '']); } ex(cmd) { this.send(['ex', cmd]); } expr(expr, requestId) { if (typeof requestId === 'number') { this.send(['expr', expr, requestId]); return; } this.send(['expr', expr]); } call(func, args, requestId) { if (typeof requestId === 'number') { this.send(['call', func, args, requestId]); return; } this.send(['call', func, args]); } dispose() { if (typeof this.clean === 'function') { this.clean(); this.clean = undefined; } this.removeAllListeners(); } } exports.default = Connection;