fuzzy.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package fuzzy
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. /*
  7. fuzzy.go
  8. Author: tobychui
  9. This logic is designed to handle fuzzy logic change similar to Google search engine
  10. You can fill in string with fuzzy keywords.
  11. Assume there are two files:
  12. Hello World.txt
  13. Hello World not this.txt
  14. Use fuzzyInput of: World Hello -"not this" .txt
  15. will return "Hello World.txt" as match only
  16. */
  17. type Matcher struct {
  18. caseSensitive bool
  19. matchList []string
  20. excludeList []string
  21. }
  22. func NewFuzzyMatcher(fuzzyInput string, caseSensitive bool) *Matcher {
  23. m, e := buildFuzzyChunks(fuzzyInput, caseSensitive)
  24. return &Matcher{
  25. caseSensitive: caseSensitive,
  26. matchList: m,
  27. excludeList: e,
  28. }
  29. }
  30. func (m *Matcher) Match(filename string) bool {
  31. if !m.caseSensitive {
  32. filename = strings.ToLower(filename)
  33. }
  34. //All keyword in matchList must be satisfied
  35. for _, keyword := range m.matchList {
  36. if !strings.Contains(filename, keyword) {
  37. return false
  38. }
  39. }
  40. //Check if contain exclude words
  41. for _, exclude := range m.excludeList {
  42. if strings.Contains(filename, exclude) {
  43. return false
  44. }
  45. }
  46. return true
  47. }
  48. //Check if a fuzzyKey require precise searching
  49. func buildFuzzyChunks(fuzzyInput string, caseSensitive bool) ([]string, []string) {
  50. includeList := []string{}
  51. excludeList := []string{}
  52. preciseExclude := false //Exclude precise word from buffer
  53. preciseBuffer := []string{}
  54. fmt.Println(fuzzyInput)
  55. if !caseSensitive {
  56. fuzzyInput = strings.ToLower(fuzzyInput)
  57. }
  58. fmt.Println(fuzzyInput)
  59. fuzzyChunks := strings.Split(fuzzyInput, " ")
  60. for _, thisChunk := range fuzzyChunks {
  61. if len(thisChunk) > 0 && thisChunk[:1] == "\"" && thisChunk[len(thisChunk)-1:] == "\"" {
  62. //This chunk start and end with exact "", just trim the " away
  63. //Example: "asd"
  64. includeList = append(includeList, thisChunk[1:len(thisChunk)-1])
  65. } else if len(thisChunk) > 1 && thisChunk[:1] == "-" && thisChunk[1:2] == "\"" {
  66. // Example: -"asd
  67. if thisChunk[len(thisChunk)-1:] == "\"" {
  68. //-"asd", push directly into exclude list
  69. excludeList = append(excludeList, thisChunk[2:len(thisChunk)-1])
  70. } else {
  71. preciseExclude = true
  72. preciseBuffer = append(preciseBuffer, thisChunk[2:])
  73. }
  74. } else if len(thisChunk) > 0 && thisChunk[:1] == "\"" {
  75. //Starting of precise string
  76. //Example (start of): "asd asd"
  77. preciseBuffer = append(preciseBuffer, thisChunk[1:])
  78. } else if len(thisChunk) > 0 && thisChunk[len(thisChunk)-1:] == "\"" {
  79. //End of precise string
  80. //Example (end of): "asd asd"
  81. preciseBuffer = append(preciseBuffer, thisChunk[:len(thisChunk)-1])
  82. tmp := strings.Join(preciseBuffer, " ")
  83. if preciseExclude {
  84. excludeList = append(excludeList, tmp)
  85. } else {
  86. includeList = append(includeList, tmp)
  87. }
  88. //Reset precisebuf
  89. preciseExclude = false
  90. preciseBuffer = []string{}
  91. } else if len(thisChunk) > 0 && thisChunk[:1] == "-" {
  92. //Example: -asd
  93. excludeList = append(excludeList, thisChunk[1:])
  94. } else {
  95. includeList = append(includeList, thisChunk)
  96. }
  97. }
  98. return includeList, excludeList
  99. }