wrapForScrollback hard-wraps every line of s to the terminal width before it goes to tea.Println. bubbletea's standard renderer dumps queued Println lines verbatim - unlike its View paint path it never truncates them - so a line wider than the terminal is soft-wrapped by the terminal into extra phys
(s string, width int)
| 46 | // frame's wrapped textarea rows survive un-erased: the duplicated prompt |
| 47 | // fragment seen when submitting a long prompt. Mirrors the ansi.Wrap the live |
| 48 | // streaming view already applies. width <= 0 (no WindowSizeMsg yet) is a no-op. |
| 49 | func wrapForScrollback(s string, width int) string { |
| 50 | if width <= 0 { |
| 51 | return s |
| 52 | } |
| 53 | // Terminals advance a literal tab to the next 8-column stop, but ansi.Wrap |
| 54 | // counts it as one cell, so a tab-bearing line (glamour preserves tabs |
| 55 | // inside code fences; a user echo can carry pasted ones) passes the width |
| 56 | // check yet physically overflows - the exact drift this wrap exists to |
| 57 | // prevent. Expand before counting; \t never occurs inside an ANSI escape |
| 58 | // sequence, so a plain replace is safe on styled strings. |
| 59 | s = strings.ReplaceAll(s, "\t", " ") |
| 60 | lines := strings.Split(s, "\n") |
| 61 | for i, line := range lines { |
| 62 | lines[i] = ansi.Wrap(line, width, "") |
| 63 | } |
| 64 | return strings.Join(lines, "\n") |
| 65 | } |
| 66 | |
| 67 | // flushStreaming ends the content phase: render the streaming buffer through |
no outgoing calls