package search import "strings" // Search represents a parsed search query with inclusions and exclusions. type Search struct { Includes []string Excludes []string } // ParseSearchString parses a user search query and supports "quoted phrases" and -negations. func ParseSearchString(input string) *Search { var result = new(Search) var ( negate bool phrase bool buf = []rune{} commit = func() { var text = strings.TrimSpace(string(buf)) if len(text) == 0 { return } if negate { result.Excludes = append(result.Excludes, text) negate = false } else { result.Includes = append(result.Includes, text) } buf = []rune{} } ) for _, char := range input { // Inside a quoted phrase? if phrase { if char == '"' { // End of quoted phrase. commit() phrase = false continue } buf = append(buf, char) continue } // Start a quoted phrase? if char == '"' { phrase = true continue } // Negation indicator? if len(buf) == 0 && char == '-' { negate = true continue } // End of a word? if char == ' ' { commit() continue } buf = append(buf, char) } // Last word? commit() return result }