A printing issue in terminal when implementing repl

I'm implementing a simple repl, which prints a prompt, reads a line, evals it, prints result and loops. It works well except when pasting multiline texts from clipboard, in which case all the prompts are displayed after the input, like

> 1
2
3
4
5> > > > 

It's annoying. What I expect is

> 1
> 2
> 3
> 4
> 5

But someone tests my code in another computer, it works well. So I think maybe it has something to do with platform or os.

What have I tried:

  • cache Stdin, Stdout instances
  • lock stdin, stdout
  • call stdin(), stdout() everytime I use them
  • use print!
  • use write!
  • try three terminal emulators(idea, vscode, alacritty)

The minimal reproducable code is as below:

use std::io::Write;

pub(crate) fn repl() {
    let mut input_buffer = String::new();
    let mut i = std::io::stdin().lock();
    let mut o = std::io::stdout().lock();

    loop {
        write!(o,"> ").unwrap();
        o.flush().unwrap();

        i.read_line(&mut input_buffer).unwrap();

        input_buffer.clear();
    }
}

Someone helps me.

I think it has something to do with how your terminal emulator handles clipboard, it's not a problem with file io, you already called flush() in the loop and that's pretty much all you can do.

try a different terminal emulator or try find relevant settings of your terminal program.

2 Likes

Could it be possible that the text in the clipboard has some kind of weird newlines?

No, I copy ascii texts from vscode editor.

There is no way for the terminal to know when you're done printing. It must be a coincidence of timing that it works for someone.

If you want to control the display precisely and get a guarantee of clean prompts, you must disable local echo (usually done via "enabling raw mode", with a library such as crossterm), and print the input characters yourself as you read them. That way you can be assured they are printed only after a prompt.

Note that this will disable all line editing and control-character commands (such as backspace and ctrl-C) and you'll have to provide that, perhaps using a line editor library from crates.io (there are several).

While all of the needed components are available as libraries, this is still a fair amount of work and you probably shouldn't do it unless you really care about refining the interactive experience.

2 Likes

Thank you for your explanation. I'm searching for an explanation and/or a simple solution. If there is no simple solution, I will not solve it currently.