github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/utils/spellcheck/highlight.go (about) 1 package spellcheck 2 3 import ( 4 "unicode" 5 6 "github.com/lmorg/murex/utils/ansi" 7 "github.com/lmorg/murex/utils/inject" 8 ) 9 10 type highlightT struct { 11 start string 12 end string 13 } 14 15 func (hl *highlightT) Start() []rune { return []rune(ansi.ExpandConsts(hl.start)) } 16 func (hl *highlightT) End() []rune { return []rune(ansi.ExpandConsts(hl.end)) } 17 18 var highlight *highlightT 19 20 func init() { 21 highlight = &highlightT{ 22 start: "{UNDERLINE}", 23 end: "{UNDEROFF}", 24 } 25 } 26 27 func highlighter(line *string, word []rune, highlight *highlightT) { 28 var ( 29 i int 30 rLast rune 31 r = []rune(*line) 32 ) 33 34 defer func() { *line = string(r) }() 35 36 for ; i < len(r); i++ { 37 if r[i] == word[0] { 38 if r[i] == word[0] && 39 !(unicode.IsLetter(rLast) || 40 unicode.IsDigit(rLast) || 41 unicode.IsMark(rLast)) { 42 43 // first character of word found 44 45 rStart := i 46 for j := 1; j < len(word); j++ { 47 i++ 48 49 switch { 50 case i == len(r): 51 // end of line reached 52 return 53 54 case r[i] != word[j]: 55 // word not matched 56 goto breakfor 57 58 case j+1 == len(word): 59 // entire word match found 60 if i+1 < len(r) && (unicode.IsLetter(r[i+1]) || unicode.IsMark(r[i+1]) || unicode.IsDigit(r[i+1])) { 61 // word is substring of a larger word 62 63 } else { 64 // add highlight 65 var err error 66 r, err = inject.Rune(r, highlight.End(), i+1) 67 if err != nil { 68 return 69 } 70 r, err = inject.Rune(r, highlight.Start(), rStart) 71 if err != nil { 72 return 73 } 74 75 } 76 77 default: 78 continue 79 } 80 } 81 breakfor: 82 } 83 } 84 rLast = r[i] 85 } 86 }