| 270 | } |
| 271 | |
| 272 | func highlightMatch(s string, filter *regexp.Regexp, matched *bool, color, highlight func(string) string) (string, error) { |
| 273 | matches := filter.FindAllStringIndex(s, -1) |
| 274 | if matches == nil { |
| 275 | return color(s), nil |
| 276 | } |
| 277 | |
| 278 | out := strings.Builder{} |
| 279 | |
| 280 | // Color up to the first match. If an empty string, no ANSI color sequence is added. |
| 281 | if _, err := out.WriteString(color(s[:matches[0][0]])); err != nil { |
| 282 | return "", err |
| 283 | } |
| 284 | |
| 285 | // Highlight each match, then color the remaining text which, if an empty string, no ANSI color sequence is added. |
| 286 | for i, match := range matches { |
| 287 | if _, err := out.WriteString(highlight(s[match[0]:match[1]])); err != nil { |
| 288 | return "", err |
| 289 | } |
| 290 | |
| 291 | text := s[match[1]:] |
| 292 | if i+1 < len(matches) { |
| 293 | text = s[match[1]:matches[i+1][0]] |
| 294 | } |
| 295 | if _, err := out.WriteString(color(text)); err != nil { |
| 296 | return "", err |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | if matched != nil { |
| 301 | *matched = *matched || true |
| 302 | } |
| 303 | |
| 304 | return out.String(), nil |
| 305 | } |
| 306 | |
| 307 | func normal(s string) string { |
| 308 | return s |