@@ -19,7 +19,7 @@ import (
19
19
"github.com/charmbracelet/bubbles/viewport"
20
20
tea "github.com/charmbracelet/bubbletea"
21
21
"github.com/charmbracelet/lipgloss"
22
- "github.com/charmbracelet/x/ansi "
22
+ "github.com/rivo/uniseg "
23
23
"github.com/sahilm/fuzzy"
24
24
)
25
25
@@ -211,28 +211,16 @@ func (m model) View() string {
211
211
continue
212
212
}
213
213
214
- var buf strings.Builder
215
- lastIdx := 0
216
-
217
- // Use ansi.Truncate and ansi.TruncateLeft and ansi.StringWidth to
218
- // style match.MatchedIndexes without losing the original option style:
214
+ var ranges []lipgloss.Range
219
215
for _ , rng := range matchedRanges (match .MatchedIndexes ) {
220
- // fmt.Print("here ", lastIdx, rng, " - ", match.Str[rng[0]:rng[1]+1], "\r\n")
221
- // Add the text before this match
222
- if rng [0 ] > lastIdx {
223
- buf .WriteString (ansi .Cut (styledOption , lastIdx , rng [0 ]))
224
- }
225
-
226
- // Add the matched character with highlight
227
- buf .WriteString (m .matchStyle .Render (ansi .Cut (match .Str , rng [0 ], rng [1 ]+ 1 )))
228
- lastIdx = rng [1 ] + 1
216
+ // ansi.Cut is grapheme and ansi sequence aware, we match against a ansi.Stripped string, but we might still have graphemes.
217
+ // all that to say that rng is byte positions, but we need to pass it down to ansi.Cut as char positions.
218
+ // so we need to adjust it here:
219
+ start , stop := bytePosToVisibleCharPos (match .Str , rng )
220
+ ranges = append (ranges , lipgloss .NewRange (start , stop + 1 , m .matchStyle ))
229
221
}
230
222
231
- // Add any remaining text after the last match
232
- buf .WriteString (ansi .TruncateLeft (styledOption , lastIdx , "" ))
233
-
234
- // Flush text buffer.
235
- s .WriteString (lineTextStyle .Render (buf .String ()))
223
+ s .WriteString (lineTextStyle .Render (lipgloss .StyleRanges (styledOption , ranges ... )))
236
224
237
225
// We have finished displaying the match with all of it's matched
238
226
// characters highlighted and the rest filled in.
@@ -540,3 +528,26 @@ func matchedRanges(in []int) [][2]int {
540
528
out = append (out , current )
541
529
return out
542
530
}
531
+
532
+ func bytePosToVisibleCharPos (str string , rng [2 ]int ) (int , int ) {
533
+ bytePos , byteStart , byteStop := 0 , rng [0 ], rng [1 ]
534
+ pos , start , stop := 0 , 0 , 0
535
+ gr := uniseg .NewGraphemes (str )
536
+ for byteStart > bytePos {
537
+ if ! gr .Next () {
538
+ break
539
+ }
540
+ bytePos += len (gr .Str ())
541
+ pos += max (1 , gr .Width ())
542
+ }
543
+ start = pos
544
+ for byteStop > bytePos {
545
+ if ! gr .Next () {
546
+ break
547
+ }
548
+ bytePos += len (gr .Str ())
549
+ pos += max (1 , gr .Width ())
550
+ }
551
+ stop = pos
552
+ return start , stop
553
+ }
0 commit comments