search.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. /**
  2. * The functions in this module are from @codemirror/search (MIT license)
  3. * https://github.com/codemirror/search/blob/c1ee7d4b0babd0de0d1198a7c1ece2a387c97c0d/src/search.ts
  4. */
  5. import { CharCategory, findClusterBreak, Text } from '@codemirror/state'
  6. const charBefore = (str: string, index: number) =>
  7. str.slice(findClusterBreak(str, index, false), index)
  8. const charAfter = (str: string, index: number) =>
  9. str.slice(index, findClusterBreak(str, index))
  10. export const categorizer = (char: string) => {
  11. if (/\s/.test(char)) {
  12. return CharCategory.Space
  13. }
  14. if (/\w/.test(char)) {
  15. return CharCategory.Word
  16. }
  17. return CharCategory.Other
  18. }
  19. export const stringWordTest =
  20. (doc: Text, categorizer: (ch: string) => CharCategory) =>
  21. (from: number, to: number, buf: string, bufPos: number) => {
  22. if (bufPos > from || bufPos + buf.length < to) {
  23. bufPos = Math.max(0, from - 2)
  24. buf = doc.sliceString(bufPos, Math.min(doc.length, to + 2))
  25. }
  26. return (
  27. (categorizer(charBefore(buf, from - bufPos)) !== CharCategory.Word ||
  28. categorizer(charAfter(buf, from - bufPos)) !== CharCategory.Word) &&
  29. (categorizer(charAfter(buf, to - bufPos)) !== CharCategory.Word ||
  30. categorizer(charBefore(buf, to - bufPos)) !== CharCategory.Word)
  31. )
  32. }
  33. export const regexpWordTest =
  34. (categorizer: (ch: string) => CharCategory) =>
  35. (_from: number, _to: number, match: RegExpExecArray) =>
  36. !match[0].length ||
  37. ((categorizer(charBefore(match.input, match.index)) !== CharCategory.Word ||
  38. categorizer(charAfter(match.input, match.index)) !== CharCategory.Word) &&
  39. (categorizer(charAfter(match.input, match.index + match[0].length)) !==
  40. CharCategory.Word ||
  41. categorizer(charBefore(match.input, match.index + match[0].length)) !==
  42. CharCategory.Word))