From 8e597f7e5dee86f1da0432f90dbc442bb99205ee Mon Sep 17 00:00:00 2001 From: realrasengan Date: Wed, 1 Apr 2026 18:22:18 -0700 Subject: [PATCH] fix prediction: confirm space characters instead of stalling --- predict.go | 3 ++- predict_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/predict.go b/predict.go index 3740ab1..c827ebd 100644 --- a/predict.go +++ b/predict.go @@ -149,8 +149,9 @@ func (p *Predictor) Confirm(fb *Framebuffer) { if cell.Rune == pred.r { // Server confirmed this prediction. confirmed++ - } else if cell.Rune == ' ' || cell.Rune == 0 { + } else if (cell.Rune == ' ' || cell.Rune == 0) && pred.r != ' ' { // Server hasn't caught up yet — stop checking. + // (But if we predicted a space, a space cell is a match, handled above.) break } else { // Server diverged — something unexpected happened diff --git a/predict_test.go b/predict_test.go index 410ae2c..04c288f 100644 --- a/predict_test.go +++ b/predict_test.go @@ -162,6 +162,32 @@ func TestPredictorExpireStale(t *testing.T) { } } +func TestPredictorSpaceConfirm(t *testing.T) { + p := NewPredictor() + p.SetCursor(0, 0) + p.Keystroke([]byte("hi there")) + + if len(p.pending) != 8 { + t.Fatalf("expected 8 predictions, got %d", len(p.pending)) + } + + // Server shows "hi " — space at position 2 should confirm, not stall + fb := NewFramebuffer(80, 24) + fb.CellAt(0, 0).Rune = 'h' + fb.CellAt(1, 0).Rune = 'i' + fb.CellAt(2, 0).Rune = ' ' + fb.CurX = 3 + fb.CurY = 0 + + p.Confirm(fb) + if len(p.pending) != 5 { + t.Fatalf("expected 5 pending after confirming 'hi ', got %d", len(p.pending)) + } + if p.pending[0].r != 't' { + t.Fatalf("first remaining should be 't', got %c", p.pending[0].r) + } +} + func TestPredictorNoActivityNoCursorOverride(t *testing.T) { p := NewPredictor()