@@ -1,16 +1,15 @@
11package layout
22
33import (
4− "bytes"
54 "strings"
65
76 "github.com/charmbracelet/lipgloss"
8− "github.com/opencode-ai/opencode/internal/tui/styles"
9− "github.com/opencode-ai/opencode/internal/tui/util"
10− "github.com/mattn/go-runewidth"
7+ chAnsi "github.com/charmbracelet/x/ansi"
118 "github.com/muesli/ansi"
129 "github.com/muesli/reflow/truncate"
1310 "github.com/muesli/termenv"
11+ "github.com/opencode-ai/opencode/internal/tui/styles"
12+ "github.com/opencode-ai/opencode/internal/tui/util"
1413)
1514
1615// Most of this code is borrowed from
@@ -117,42 +116,7 @@ func PlaceOverlay(
117116// cutLeft cuts printable characters from the left.
118117// This function is heavily based on muesli's ansi and truncate packages.
119118func cutLeft(s string, cutWidth int) string {
120− var (
121− pos int
122− isAnsi bool
123− ab bytes.Buffer
124− b bytes.Buffer
125− )
126− for _, c := range s {
127− var w int
128− if c == ansi.Marker || isAnsi {
129− isAnsi = true
130− ab.WriteRune(c)
131− if ansi.IsTerminator(c) {
132− isAnsi = false
133− if bytes.HasSuffix(ab.Bytes(), []byte("[0m")) {
134− ab.Reset()
135− }
136− }
137− } else {
138− w = runewidth.RuneWidth(c)
139− }
140−
141− if pos >= cutWidth {
142− if b.Len() == 0 {
143− if ab.Len() > 0 {
144− b.Write(ab.Bytes())
145− }
146− if pos-cutWidth > 1 {
147− b.WriteByte(' ')
148− continue
149− }
150− }
151− b.WriteRune(c)
152− }
153− pos += w
154− }
155− return b.String()
119+ return chAnsi.Cut(s, cutWidth, lipgloss.Width(s))
156120}
157121
158122func max(a, b int) int {