Render renders only the visible portion of the log viewer.
()
| 282 | |
| 283 | // Render renders only the visible portion of the log viewer. |
| 284 | func (l *LogViewer) Render() string { |
| 285 | if len(l.entries) == 0 { |
| 286 | emptyStyle := lipgloss.NewStyle(). |
| 287 | Foreground(MutedColor). |
| 288 | Padding(1, 2) |
| 289 | return emptyStyle.Render("No log entries yet. Start the loop to see Claude's activity.") |
| 290 | } |
| 291 | |
| 292 | // Calculate visible range |
| 293 | startLine := l.scrollPos |
| 294 | if startLine < 0 { |
| 295 | startLine = 0 |
| 296 | } |
| 297 | if startLine >= l.totalLineCount { |
| 298 | startLine = l.totalLineCount - 1 |
| 299 | if startLine < 0 { |
| 300 | startLine = 0 |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | endLine := startLine + l.height |
| 305 | if endLine > l.totalLineCount { |
| 306 | endLine = l.totalLineCount |
| 307 | } |
| 308 | |
| 309 | // Collect only visible lines by scanning cached entries |
| 310 | currentLine := 0 |
| 311 | var visibleLines []string |
| 312 | |
| 313 | for i := range l.entries { |
| 314 | lines := l.entries[i].cachedLines |
| 315 | entryEnd := currentLine + len(lines) |
| 316 | |
| 317 | // Skip entries entirely before the viewport |
| 318 | if entryEnd <= startLine { |
| 319 | currentLine = entryEnd |
| 320 | continue |
| 321 | } |
| 322 | // Stop once we're past the viewport |
| 323 | if currentLine >= endLine { |
| 324 | break |
| 325 | } |
| 326 | |
| 327 | // This entry has some visible lines |
| 328 | for j, line := range lines { |
| 329 | lineNum := currentLine + j |
| 330 | if lineNum >= startLine && lineNum < endLine { |
| 331 | visibleLines = append(visibleLines, line) |
| 332 | } |
| 333 | } |
| 334 | currentLine = entryEnd |
| 335 | } |
| 336 | |
| 337 | // Add cursor indicator at bottom if streaming |
| 338 | content := strings.Join(visibleLines, "\n") |
| 339 | if l.autoScroll && len(l.entries) > 0 { |
| 340 | lastEntry := l.entries[len(l.entries)-1] |
| 341 | if lastEntry.Type == loop.EventAssistantText || lastEntry.Type == loop.EventToolStart { |
no outgoing calls