diff --git a/textarea/textarea.go b/textarea/textarea.go index f0c0ca54..5d5da090 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -959,6 +959,9 @@ func (m *Model) wordLeft() { if m.col < len(m.value[m.row]) && !unicode.IsSpace(m.value[m.row][m.col]) { break } + if m.col == 0 && m.row == 0 { + break + } } for m.col > 0 { diff --git a/textarea/textarea_test.go b/textarea/textarea_test.go index 41d51f74..c575a1b9 100644 --- a/textarea/textarea_test.go +++ b/textarea/textarea_test.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" "testing" + "time" "unicode" tea "charm.land/bubbletea/v2" @@ -2429,3 +2430,24 @@ func stripString(str string) string { return strings.Join(lines, "\n") } + +func TestWordLeftInfiniteLoopRepro(t *testing.T) { + m := New() + m.SetValue(" hello") + m.col = 0 + m.row = 0 + + done := make(chan struct{}) + go func() { + m.wordLeft() + close(done) + }() + + select { + case <-done: + t.Log("wordLeft finished") + case <-time.After(2 * time.Second): + t.Fatal("wordLeft timed out (likely infinite loop)") + } +} +