Skip to content

fix(textarea): prevent infinite loop in wordLeft on empty/start-of-text input - #1019

Open
djedi-knight wants to merge 1 commit into
charmbracelet:mainfrom
djedi-knight:fix/textarea-wordleft-infinite-loop
Open

fix(textarea): prevent infinite loop in wordLeft on empty/start-of-text input#1019
djedi-knight wants to merge 1 commit into
charmbracelet:mainfrom
djedi-knight:fix/textarea-wordleft-infinite-loop

Conversation

@djedi-knight

Copy link
Copy Markdown

Suggested PR

Title: fix(textarea): prevent infinite loop in wordLeft on empty/start-of-text input

Description:

Summary

textarea's word-backward motion (alt+left / alt+b) could spin forever and freeze the event loop when the textarea was empty or the cursor was already at the start of the text.

wordLeft() used an unconditional for {} that only exits once it finds a non-space rune:

for {
    m.characterLeft(true /* insideLine */)
    if m.col < len(m.value[m.row]) && !unicode.IsSpace(m.value[m.row][m.col]) {
        break
    }
}

When the textarea is empty (m.value == [][]rune{{}}, cursor at row=0, col=0), characterLeft(true) is a no-op and the break condition m.col < len(m.value[m.row]) evaluates to 0 < 0 == false. The loop never terminates, hanging the program.

Fix

Add a start-of-text guard at the top of the loop, mirroring the end-of-text break that doWordRight() already has. Since characterLeft always makes progress (moving up a row and/or left a column) until it reaches row 0, col 0, returning at that point guarantees termination and makes the motion a no-op on empty input.

for {
    if m.row == 0 && m.col == 0 {
        // Start of text.
        return
    }
    m.characterLeft(true /* insideLine */)
    ...
}

Related helpers audited

  • deleteWordLeft / deleteWordRight — already guard m.col == 0 / len(m.value[m.row]) == 0; safe.
  • doWordRight (and its callers wordRight, uppercaseRight, lowercaseRight, capitalizeRight, deleteWordRight) — already break at end of text; safe.
  • wordLeft was the only word-motion helper missing the boundary guard.

Testing

Added TestWordBackwardEmptyTextareaTerminates, which drives an empty textarea with alt+left and alt+b. The update runs on a goroutine guarded by a 2s timeout, so a regression fails the test rather than hanging the suite, and asserts the motion is a no-op (cursor stays at row 0, col 0, value stays empty).

Verified the test fails against the unpatched code (times out) and passes with the fix. go test ./..., go vet ./..., and gofmt -l . are all clean.

Fixes charmbracelet/bubbletea#1652

wordLeft used an unconditional for{} that only exits on a non-space rune.
On empty input (row 0, col 0) characterLeft is a no-op and the break
condition 0 < 0 is never true, freezing the event loop on alt+left/alt+b.
Add a start-of-text guard mirroring doWordRight's end-of-text break.

Fixes charmbracelet/bubbletea#1652
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.

bug: textarea infinite loop when pressing alt+left on empty input

1 participant