1package app
2
3import (
4 "strings"
5
6 "github.com/charmbracelet/lipgloss"
7 "github.com/muesli/reflow/truncate"
8)
9
10func PlaceOverlay(x, y int, fg, bg string) string {
11 fgLines := strings.Split(fg, "\n")
12 bgLines := strings.Split(bg, "\n")
13 result := make([]string, len(bgLines))
14 copy(result, bgLines)
15
16 for i, fgLine := range fgLines {
17 bgY := y + i
18 if bgY < 0 || bgY >= len(bgLines) {
19 continue
20 }
21
22 fgW := uint(lipgloss.Width(fgLine))
23 bgLine := bgLines[bgY]
24 bgW := uint(lipgloss.Width(bgLine))
25
26 if uint(x) >= bgW {
27 continue
28 }
29
30 left := truncate.String(bgLine, uint(x))
31 right := ""
32 if end := uint(x) + fgW; end < bgW {
33 right = rightSlice(bgLine, int(end))
34 }
35
36 result[bgY] = left + fgLine + right
37 }
38
39 return strings.Join(result, "\n")
40}
41
42func rightSlice(s string, fromVisible int) string {
43 visible := 0
44 inEsc := false
45 runes := []rune(s)
46 for i, r := range runes {
47 if r == '\x1b' {
48 inEsc = true
49 }
50 if inEsc {
51 if r == 'm' {
52 inEsc = false
53 }
54 continue
55 }
56 if visible == fromVisible {
57 return string(runes[i:])
58 }
59 visible++
60 }
61 return ""
62}
63