prefixmatches.nim 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2017 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. from std/strutils import toLowerAscii
  10. type
  11. PrefixMatch* {.pure.} = enum
  12. None, ## no prefix detected
  13. Abbrev ## prefix is an abbreviation of the symbol
  14. Substr, ## prefix is a substring of the symbol
  15. Prefix, ## prefix does match the symbol
  16. proc prefixMatch*(p, s: string): PrefixMatch =
  17. template eq(a, b): bool = a.toLowerAscii == b.toLowerAscii
  18. if p.len > s.len: return PrefixMatch.None
  19. var i = 0
  20. # check for prefix/contains:
  21. while i < s.len:
  22. if s[i] == '_': inc i
  23. if i < s.len and eq(s[i], p[0]):
  24. var ii = i+1
  25. var jj = 1
  26. while ii < s.len and jj < p.len:
  27. if p[jj] == '_': inc jj
  28. if s[ii] == '_': inc ii
  29. if not eq(s[ii], p[jj]): break
  30. inc ii
  31. inc jj
  32. if jj >= p.len:
  33. if i == 0: return PrefixMatch.Prefix
  34. else: return PrefixMatch.Substr
  35. inc i
  36. # check for abbrev:
  37. if eq(s[0], p[0]):
  38. i = 1
  39. var j = 1
  40. while i < s.len:
  41. if i < s.len-1 and s[i] == '_':
  42. if j < p.len and eq(p[j], s[i+1]): inc j
  43. else: return PrefixMatch.None
  44. if i < s.len and s[i] in {'A'..'Z'} and s[i-1] notin {'A'..'Z'}:
  45. if j < p.len and eq(p[j], s[i]): inc j
  46. else: return PrefixMatch.None
  47. inc i
  48. if j >= p.len:
  49. return PrefixMatch.Abbrev
  50. else:
  51. return PrefixMatch.None
  52. return PrefixMatch.None