javascriptnode.jsemacsschemereadline

How to write Node.js REPL that works with GNU Emacs?


I have Scheme interpreter in JavaScript called LIPS. I have executable file, it works in terminal emulator but it's broken in GNU Emacs inferior mode (using run-scheme function).

I've reproduced the issue with this simple Node.js REPL using Readline:

var prompt = 'lips> ';
var continuePrompt = '... ';
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    prompt: prompt,
    terminal: !!process.stdin.isTTY // true in Emacs
});
if (process.stdin.isTTY) {
    rl.prompt();
}

rl.on('line', function(line) {
    if (process.stdin.isTTY) {
        rl.prompt();
    }
});

First issue was that when I type something the output is duplicated, it's literal command line echo:

lips> 10
10
10
lips> '(1 2 3)
'(1 2 3)
(1 2 3)
lips>

I've found solution, which:

(setq comint-process-echoes t)

But another issue is that on resize it keep appending prompt to prompt. so I have this:

lips> lips> lips> lips> lips>

This is prompt because if I set:

(setq comint-prompt-read-only t)

I can't delete that text.

EDIT:

The same happen if I call (read) that is also using readline to get input, it keep adding spaces.

I was reading Node.js source code and it also use readline and it works fine when run using run-js, Kawa Scheme Interpreter works correctly but it don't use readline:

 (setq inferior-js-program-command "node --interactive")
 (run-js)

This works, it's not run-scheme but it's same mode, I've also tried to run same run-js code but with my Scheme interpreter, and it also show same prompt duplication on resize.

 (setq inferior-js-program-command "/home/kuba/projects/jcubic/lips/bin/lips.js")
 (run-js)

Solution

  • Got answer in Emacs devel mailing list, the solution is to turn off readline when inside Emacs:

    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
        prompt: prompt,
        terminal: !!process.stdin.isTTY && !(process.env.EMACS || process.env.INSIDE_EMACS)
    });
    

    Lot of interpreters do the same thing. e.g: Bash.