SearchMatch returns true if the location `pos` is within a match of the last search for the buffer `b`. It is used for efficient highlighting of search matches (separately from the syntax highlighting). SearchMatch searches for the matches if it is called first time for the given line or if the line
(b *Buffer, pos Loc)
| 381 | // in different edit panes) which have distinct searches, so SearchMatch |
| 382 | // needs to know which search to match against. |
| 383 | func (la *LineArray) SearchMatch(b *Buffer, pos Loc) bool { |
| 384 | if b.LastSearch == "" { |
| 385 | return false |
| 386 | } |
| 387 | |
| 388 | lineN := pos.Y |
| 389 | if la.lines[lineN].search == nil { |
| 390 | la.lines[lineN].search = make(map[*Buffer]*searchState) |
| 391 | } |
| 392 | s, ok := la.lines[lineN].search[b] |
| 393 | if !ok { |
| 394 | // Note: here is a small harmless leak: when the buffer `b` is closed, |
| 395 | // `s` is not deleted from the map. It means that the buffer |
| 396 | // will not be garbage-collected until the line array is garbage-collected, |
| 397 | // i.e. until all the buffers sharing this file are closed. |
| 398 | s = new(searchState) |
| 399 | la.lines[lineN].search[b] = s |
| 400 | } |
| 401 | if !ok || s.search != b.LastSearch || s.useRegex != b.LastSearchRegex || |
| 402 | s.ignorecase != b.Settings["ignorecase"].(bool) { |
| 403 | s.search = b.LastSearch |
| 404 | s.useRegex = b.LastSearchRegex |
| 405 | s.ignorecase = b.Settings["ignorecase"].(bool) |
| 406 | s.done = false |
| 407 | } |
| 408 | |
| 409 | if !s.done { |
| 410 | s.match = nil |
| 411 | start := Loc{0, lineN} |
| 412 | end := Loc{util.CharacterCount(la.lines[lineN].data), lineN} |
| 413 | for start.X < end.X { |
| 414 | m, found, _ := b.FindNext(b.LastSearch, start, end, start, true, b.LastSearchRegex) |
| 415 | if !found { |
| 416 | break |
| 417 | } |
| 418 | s.match = append(s.match, [2]int{m[0].X, m[1].X}) |
| 419 | |
| 420 | start.X = m[1].X |
| 421 | if m[1].X == m[0].X { |
| 422 | start.X = m[1].X + 1 |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | s.done = true |
| 427 | } |
| 428 | |
| 429 | for _, m := range s.match { |
| 430 | if pos.X >= m[0] && pos.X < m[1] { |
| 431 | return true |
| 432 | } |
| 433 | } |
| 434 | return false |
| 435 | } |
| 436 | |
| 437 | // invalidateSearchMatches marks search matches for the given line as outdated. |
| 438 | // It is called when the line is modified. |
nothing calls this directly
no test coverage detected