Skip to content

Replace raw stdin with rustyline in localgpt-gen interactive loop#51

Merged
yiwang merged 2 commits into
mainfrom
copilot/replace-stdin-with-rustyline
Feb 19, 2026
Merged

Replace raw stdin with rustyline in localgpt-gen interactive loop#51
yiwang merged 2 commits into
mainfrom
copilot/replace-stdin-with-rustyline

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 19, 2026

The localgpt-gen interactive loop uses raw stdin.read_line(), causing arrow keys to insert literal ANSI escape sequences (\x1b[D, \x1b[C) instead of moving the cursor. No command history or line editing available.

Changes

  • crates/gen/Cargo.toml: Add rustyline = "17.0.2" dependency
  • crates/gen/src/main.rs: Replace stdin loop with DefaultEditor, matching pattern from crates/cli/src/cli/chat.rs
    • Handle ReadlineError::Interrupted (Ctrl+C) and ReadlineError::Eof (Ctrl+D)
    • Add history support via add_history_entry()

Users now get proper cursor movement, command history navigation, and consistent UX with the main localgpt chat CLI.

// Before
let stdin = io::stdin();
loop {
    print!("> ");
    io::stdout().flush()?;
    let mut input = String::new();
    stdin.read_line(&mut input)?;
    // ...
}

// After
let mut rl = DefaultEditor::new()?;
loop {
    let input = match rl.readline("> ") {
        Ok(line) => line,
        Err(ReadlineError::Interrupted) => continue,
        Err(ReadlineError::Eof) => break,
        // ...
    };
    let _ = rl.add_history_entry(input.trim());
    // ...
}

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cdn.pyke.io
    • Triggering command: /home/REDACTED/work/localgpt/.codeql-scratch/dbs/rust/working/target/debug/build/ort-sys-af27879de92f8ade/build-script-main /home/REDACTED/work/localgpt/.codeql-scratch/dbs/rust/working/target/debug/build/ort-sys-af27879de92f8ade/build-script-main -I /home/REDACTED/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.3/home/REDACTED/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.37.1/aws-lc/third_party/jitterentropy/jitterentropy-library -I /home/REDACTED/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.3x86_64-linux-gnu 7.1/generated-include --64 7.1/include /home/REDACTED/work/localgpt/.codeql-scratch/dbs/rust/working/target/debug/build/a-D 7.1/aws-lc/include o 7.1/aws-lc/third_party/s2n-bignum/include o 7.1/aws-lc/third_party/s2n-bignum/s2n-bignum-imported/include f/aws-lc-sys-0.3-gdwarf-4 7.1/aws-lc/third_party/jitterentropy/jitterentropy-library f/aws-lc-sys-0.3as 1 -1949cf8c6b5b557/home/REDACTED/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.3-I ws-lc-sys-e0caf0de8a4e0289/out/7510312e0f5aa0be-p_hmac_asn1.o (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

Problem

The localgpt-gen CLI interactive input loop uses raw std::io::stdin().read_line() for user input (in crates/gen/src/main.rs, around lines 150-166). This does not handle terminal escape sequences, so pressing left/right arrow keys inserts literal ANSI escape characters (e.g., \x1b[D, \x1b[C) instead of moving the cursor. This makes the interactive experience significantly worse than the main localgpt chat CLI.

In contrast, the main localgpt chat CLI (in crates/cli/src/cli/chat.rs) uses rustyline for input, which properly handles arrow keys, cursor movement, and history.

Fix

Replace the raw stdin.read_line() interactive loop in crates/gen/src/main.rs with rustyline, matching the approach used in crates/cli/src/cli/chat.rs.

Current code in crates/gen/src/main.rs (lines ~150-166):

// Interactive loop
let stdin = io::stdin();
loop {
    print!("> ");
    io::stdout().flush()?;

    let mut input = String::new();
    if stdin.read_line(&mut input)? == 0 {
        break; // EOF
    }

    let input = input.trim();
    if input.is_empty() {
        continue;
    }
    if input == "/quit" || input == "/exit" || input == "/q" {
        break;
    }

    let response = agent.chat(input).await?;
    println!("\n{}\n", response);
}

What to do:

  1. Add rustyline as a dependency in crates/gen/Cargo.toml (it's already used by crates/cli).
  2. Replace the raw stdin.read_line() loop with rustyline's Editor, using rl.readline("> ") for input, handling ReadlineError::Interrupted (Ctrl+C) and ReadlineError::Eof (Ctrl+D) properly.
  3. Add history support with rl.add_history_entry() so users can use up/down arrow keys to recall previous prompts.
  4. This gives users proper left/right arrow cursor movement, up/down history navigation, and no more escape character artifacts.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…ve input

Co-authored-by: yiwang <142937+yiwang@users.noreply.github.com>
Copilot AI changed the title [WIP] Replace raw stdin input with rustyline for better interactive experience Replace raw stdin with rustyline in localgpt-gen interactive loop Feb 19, 2026
Copilot AI requested a review from yiwang February 19, 2026 13:08
@yiwang yiwang marked this pull request as ready for review February 19, 2026 13:27
@yiwang yiwang merged commit a2b4b93 into main Feb 19, 2026
5 checks passed
@yiwang yiwang deleted the copilot/replace-stdin-with-rustyline branch February 19, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants