1package lipgloss
2
3import (
4 "strings"
5
6 "github.com/charmbracelet/x/ansi"
7)
8
9// StyleRanges applying styling to ranges in a string. Existing styles will be
10// taken into account. Ranges should not overlap.
11func StyleRanges(s string, ranges ...Range) string {
12 if len(ranges) == 0 {
13 return s
14 }
15
16 var buf strings.Builder
17 lastIdx := 0
18 stripped := ansi.Strip(s)
19
20 // Use Truncate and TruncateLeft to style match.MatchedIndexes without
21 // losing the original option style:
22 for _, rng := range ranges {
23 // Add the text before this match
24 if rng.Start > lastIdx {
25 buf.WriteString(ansi.Cut(s, lastIdx, rng.Start))
26 }
27 // Add the matched range with its highlight
28 buf.WriteString(rng.Style.Render(ansi.Cut(stripped, rng.Start, rng.End)))
29 lastIdx = rng.End
30 }
31
32 // Add any remaining text after the last match
33 buf.WriteString(ansi.TruncateLeft(s, lastIdx, ""))
34
35 return buf.String()
36}
37
38// NewRange returns a range and style that can be used with [StyleRanges].
39func NewRange(start, end int, style Style) Range {
40 return Range{start, end, style}
41}
42
43// Range is a range of text and associated styling to be used with
44// [StyleRanges].
45type Range struct {
46 Start, End int
47 Style Style
48}