Skip to content

Bug: Arrow keys during tab completion break input (completion lost, raw escape codes inserted) #248

Description

@Avafly

Description

When using tab completion, if you press an arrow key to navigate, the current completion candidate is discarded, and the raw escape sequence characters (like [D, [C) are appended to the input buffer as literal text.

Steps to reproduce

// set completion callback
void CompletionTest(const char *, linenoiseCompletions *lc) {
  linenoiseAddCompletion(lc, "Text1");
}

int main() {
  linenoiseSetCompletionCallback(CompletionTest);
  /* ... loop ... */
}
  1. Pressing Tab to trigger completion, the prompt shows the candidate Text1.
  2. Pressing the Left Arrow key, the prompt becomes [D.
  3. Inspecting the input line reveals that the underlying buffer data has also been replaced by [D.
> Text1 <- Shows candidate after pressing Tab
> [D    <- Becomes [D after pressing Left Arrow

Expected behavior

Arrow keys should be handled correctly during completion:

  • The cursor should move in the specified direction.
  • It should accept the current completion candidate.

Cause analysis

In linenoise.c, the completeLine function handles case 27 (ESC) by immediately setting ls->in_completion = 0 and returning c = 0.

linenoise/linenoise.c

Lines 739 to 744 in 452e379

case 27: /* escape */
/* Re-show original buffer */
if (ls->completion_idx < lc.len) refreshLine(ls);
ls->in_completion = 0;
c = 0;
break;

It fails to check if the ESC character is the start of a multi-byte escape sequence. Consequently, the subsequent bytes (e.g., [D) are interpreted as user input in linenoiseEditFeed.

Proposed fix

Modify completeLine to check for escape sequences: When an ESC is received, attempt to read the next 2 bytes to determine if it is an arrow key sequence (similar to linenoiseEditFeed).

I think this modification wouldn't be too complicated. I'd be happy to submit a PR for this if the approach sounds good.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions