forked from toolshed/abra
build: go 1.24
We were running behind and there were quite some deprecations to update. This was mostly in the upstream copy/pasta package but seems quite minimal.
This commit is contained in:
185
vendor/github.com/charmbracelet/x/cellbuf/wrap.go
generated
vendored
Normal file
185
vendor/github.com/charmbracelet/x/cellbuf/wrap.go
generated
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
package cellbuf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
)
|
||||
|
||||
const nbsp = '\u00a0'
|
||||
|
||||
// Wrap returns a string that is wrapped to the specified limit applying any
|
||||
// ANSI escape sequences in the string. It tries to wrap the string at word
|
||||
// boundaries, but will break words if necessary.
|
||||
//
|
||||
// The breakpoints string is a list of characters that are considered
|
||||
// breakpoints for word wrapping. A hyphen (-) is always considered a
|
||||
// breakpoint.
|
||||
//
|
||||
// Note: breakpoints must be a string of 1-cell wide rune characters.
|
||||
func Wrap(s string, limit int, breakpoints string) string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if limit < 1 {
|
||||
return s
|
||||
}
|
||||
|
||||
p := ansi.GetParser()
|
||||
defer ansi.PutParser(p)
|
||||
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
word bytes.Buffer
|
||||
space bytes.Buffer
|
||||
style, curStyle Style
|
||||
link, curLink Link
|
||||
curWidth int
|
||||
wordLen int
|
||||
)
|
||||
|
||||
hasBlankStyle := func() bool {
|
||||
// Only follow reverse attribute, bg color and underline style
|
||||
return !style.Attrs.Contains(ReverseAttr) && style.Bg == nil && style.UlStyle == NoUnderline
|
||||
}
|
||||
|
||||
addSpace := func() {
|
||||
curWidth += space.Len()
|
||||
buf.Write(space.Bytes())
|
||||
space.Reset()
|
||||
}
|
||||
|
||||
addWord := func() {
|
||||
if word.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
curLink = link
|
||||
curStyle = style
|
||||
|
||||
addSpace()
|
||||
curWidth += wordLen
|
||||
buf.Write(word.Bytes())
|
||||
word.Reset()
|
||||
wordLen = 0
|
||||
}
|
||||
|
||||
addNewline := func() {
|
||||
if !curStyle.Empty() {
|
||||
buf.WriteString(ansi.ResetStyle)
|
||||
}
|
||||
if !curLink.Empty() {
|
||||
buf.WriteString(ansi.ResetHyperlink())
|
||||
}
|
||||
buf.WriteByte('\n')
|
||||
if !curLink.Empty() {
|
||||
buf.WriteString(ansi.SetHyperlink(curLink.URL, curLink.Params))
|
||||
}
|
||||
if !curStyle.Empty() {
|
||||
buf.WriteString(curStyle.Sequence())
|
||||
}
|
||||
curWidth = 0
|
||||
space.Reset()
|
||||
}
|
||||
|
||||
var state byte
|
||||
for len(s) > 0 {
|
||||
seq, width, n, newState := ansi.DecodeSequence(s, state, p)
|
||||
switch width {
|
||||
case 0:
|
||||
if ansi.Equal(seq, "\t") {
|
||||
addWord()
|
||||
space.WriteString(seq)
|
||||
break
|
||||
} else if ansi.Equal(seq, "\n") {
|
||||
if wordLen == 0 {
|
||||
if curWidth+space.Len() > limit {
|
||||
curWidth = 0
|
||||
} else {
|
||||
// preserve whitespaces
|
||||
buf.Write(space.Bytes())
|
||||
}
|
||||
space.Reset()
|
||||
}
|
||||
|
||||
addWord()
|
||||
addNewline()
|
||||
break
|
||||
} else if ansi.HasCsiPrefix(seq) && p.Command() == 'm' {
|
||||
// SGR style sequence [ansi.SGR]
|
||||
ReadStyle(p.Params(), &style)
|
||||
} else if ansi.HasOscPrefix(seq) && p.Command() == 8 {
|
||||
// Hyperlink sequence [ansi.SetHyperlink]
|
||||
ReadLink(p.Data(), &link)
|
||||
}
|
||||
|
||||
word.WriteString(seq)
|
||||
default:
|
||||
if len(seq) == 1 {
|
||||
// ASCII
|
||||
r, _ := utf8.DecodeRuneInString(seq)
|
||||
if r != nbsp && unicode.IsSpace(r) && hasBlankStyle() {
|
||||
addWord()
|
||||
space.WriteRune(r)
|
||||
break
|
||||
} else if r == '-' || runeContainsAny(r, breakpoints) {
|
||||
addSpace()
|
||||
if curWidth+wordLen+width <= limit {
|
||||
addWord()
|
||||
buf.WriteString(seq)
|
||||
curWidth += width
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if wordLen+width > limit {
|
||||
// Hardwrap the word if it's too long
|
||||
addWord()
|
||||
}
|
||||
|
||||
word.WriteString(seq)
|
||||
wordLen += width
|
||||
|
||||
if curWidth+wordLen+space.Len() > limit {
|
||||
addNewline()
|
||||
}
|
||||
}
|
||||
|
||||
s = s[n:]
|
||||
state = newState
|
||||
}
|
||||
|
||||
if wordLen == 0 {
|
||||
if curWidth+space.Len() > limit {
|
||||
curWidth = 0
|
||||
} else {
|
||||
// preserve whitespaces
|
||||
buf.Write(space.Bytes())
|
||||
}
|
||||
space.Reset()
|
||||
}
|
||||
|
||||
addWord()
|
||||
|
||||
if !curLink.Empty() {
|
||||
buf.WriteString(ansi.ResetHyperlink())
|
||||
}
|
||||
if !curStyle.Empty() {
|
||||
buf.WriteString(ansi.ResetStyle)
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func runeContainsAny[T string | []rune](r rune, s T) bool {
|
||||
for _, c := range []rune(s) {
|
||||
if c == r {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
Reference in New Issue
Block a user