0
votes

I wrote a small REPL server and client for debugging the application I'm writing. When I input enough text to make it wrap to the next line in the terminal and press backspace though, it will display all the lines, not just the one that updated. I also can't move back to previous lines once I no longer have any characters to delete. There has to be a way to do this if node is reasonably sane, but I'm at a complete loss as to what to change. How can I make this work?

Edit: tab complete does not display until after hitting enter. Lines from history doesn't display in process.stdin at all, but will still be evaluated after sending them

repl-client.js

'use strict';

const net = require('net');

const socket = net.connect(8001, '0.0.0.0');
process.stdin.pipe(socket);
socket.pipe(process.stdout);

process.stdin.on('finish', () => {
    socket.destroy('');
});

repl-server.js

import * as babel from 'babel-core';
import net from 'net';
import repl from 'repl';
import vm from 'vm';

function extendContext(context) {
    // add vars I need to context
    return context;
}

function babelEval(input, filename) {
    let sanitizedInput = (input.startsWith('(') && input.endsWith(')'))
        ? input.slice(1, -1)
        : input;
    let code = babel.transform(sanitizedInput).code;
    return vm.runInThisContext(code, {filename});
}

export default function createREPLServer(port, hostname) {
    return net.createServer((socket) => {
        const _repl = repl.start({
            prompt: 'test> ',
            input: socket,
            output: socket,
            terminal: true,
            useColors: true,
            useGlobal: true,
            replMode: repl.REPL_MODE_STRICT,
            eval(input, context, filename, cb) {
                let err;
                let code;
                try {
                    code = babelEval(input.trim(), filename);
                } catch (e) {
                    err = e;
                }

                cb(err, code);
            }
        });
        _repl.on('reset', (context) => extendContext(context));
        _repl.on('exit', () => socket.end());

        extendContext(_repl.context);
    }).listen(8001, '0.0.0.0');
}
1
Likely some kind of line buffering involved. Try switching the program/terminal to raw mode? The alternative would be forgoing tab complete and rlwraping a nc instance小太郎
Running process.stdin.setRawMode(true) fixes most of this, but now pressing backspace when the input overlaps displays the entire input again with each press, rather than updating what's already there. Using rlwrap makes the output even worse.kpimov

1 Answers

0
votes

I managed to fix this in part with help of 小太郎 and by adding a readable event handler to repl-server.js:

socket.on('readable', (chunk) => {
    socket.read(chunk);
});