Files
patterm/internal/app/screen_renderer.go
2026-05-14 13:37:20 +01:00

87 lines
1.9 KiB
Go

package app
import (
"fmt"
"strings"
"github.com/harrybrwn/patterm/internal/vt"
)
func renderScreenSnapshot(text string, cursor vt.CursorState, layout terminalLayout) []byte {
lines := strings.Split(strings.ReplaceAll(text, "\r\n", "\n"), "\n")
cols := int(layout.childCols())
rows := int(layout.childRows())
var b strings.Builder
b.WriteString("\x1b[?25l")
for r := 0; r < rows; r++ {
line := ""
if r < len(lines) {
line = truncateCells(lines[r], cols)
}
fmt.Fprintf(&b, "\x1b[%d;%dH%s", int(layout.mainTop)+r, int(layout.mainLeft), padRight(line, cols))
}
if cursor.Visible {
row := int(layout.mainTop) + int(cursor.Row)
col := int(layout.mainLeft) + int(cursor.Col)
if row < int(layout.mainTop) {
row = int(layout.mainTop)
}
maxRow := int(layout.mainTop) + rows - 1
if row > maxRow {
row = maxRow
}
if col < int(layout.mainLeft) {
col = int(layout.mainLeft)
}
maxCol := int(layout.mainLeft) + cols - 1
if col > maxCol {
col = maxCol
}
fmt.Fprintf(&b, "\x1b[?25h\x1b[%d;%dH", row, col)
}
return []byte(b.String())
}
func renderCursor(cursor vt.CursorState, layout terminalLayout) []byte {
cols := int(layout.childCols())
rows := int(layout.childRows())
row := int(layout.mainTop) + int(cursor.Row)
col := int(layout.mainLeft) + int(cursor.Col)
if row < int(layout.mainTop) {
row = int(layout.mainTop)
}
maxRow := int(layout.mainTop) + rows - 1
if row > maxRow {
row = maxRow
}
if col < int(layout.mainLeft) {
col = int(layout.mainLeft)
}
maxCol := int(layout.mainLeft) + cols - 1
if col > maxCol {
col = maxCol
}
return []byte(fmt.Sprintf("\x1b[?25h\x1b[%d;%dH", row, col))
}
func truncateCells(s string, width int) string {
if width <= 0 {
return ""
}
if visibleLen(s) <= width {
return s
}
var b strings.Builder
n := 0
for _, r := range s {
if n >= width {
break
}
b.WriteRune(r)
n++
}
return b.String()
}