@chemzqm/neovim
Version:
NodeJS client API for vim9 and neovim
122 lines (121 loc) • 3.82 kB
JavaScript
;
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;