Added from:, in:, and channel: search modifiers

This commit is contained in:
hmhealey
2015-10-17 14:37:51 -04:00
parent 754f1721fe
commit 06fd374c19
8 changed files with 419 additions and 67 deletions

130
model/search_params.go Normal file
View File

@@ -0,0 +1,130 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"strings"
)
type SearchParams struct {
Terms string
IsHashtag bool
InChannel string
FromUser string
}
var searchFlags = [...]string{"from", "channel", "in"}
func splitWords(text string) []string {
words := []string{}
for _, word := range strings.Fields(text) {
word = puncStart.ReplaceAllString(word, "")
word = puncEnd.ReplaceAllString(word, "")
if len(word) != 0 {
words = append(words, word)
}
}
return words
}
func parseSearchFlags(input []string) ([]string, map[string]string) {
words := []string{}
flags := make(map[string]string)
skipNextWord := false
for i, word := range input {
if skipNextWord {
skipNextWord = false
continue
}
isFlag := false
if colon := strings.Index(word, ":"); colon != -1 {
flag := word[:colon]
value := word[colon+1:]
for _, searchFlag := range searchFlags {
// check for case insensitive equality
if strings.EqualFold(flag, searchFlag) {
if value != "" {
flags[searchFlag] = value
isFlag = true
} else if i < len(input)-1 {
flags[searchFlag] = input[i+1]
skipNextWord = true
isFlag = true
}
if isFlag {
break
}
}
}
}
if !isFlag {
words = append(words, word)
}
}
return words, flags
}
func ParseSearchParams(text string) (*SearchParams, *SearchParams) {
words, flags := parseSearchFlags(splitWords(text))
hashtagTerms := []string{}
plainTerms := []string{}
for _, word := range words {
if validHashtag.MatchString(word) {
hashtagTerms = append(hashtagTerms, word)
} else {
plainTerms = append(plainTerms, word)
}
}
inChannel := flags["channel"]
if inChannel == "" {
inChannel = flags["in"]
}
fromUser := flags["from"]
var plainParams *SearchParams
if len(plainTerms) > 0 {
plainParams = &SearchParams{
Terms: strings.Join(plainTerms, " "),
IsHashtag: false,
InChannel: inChannel,
FromUser: fromUser,
}
}
var hashtagParams *SearchParams
if len(hashtagTerms) > 0 {
hashtagParams = &SearchParams{
Terms: strings.Join(hashtagTerms, " "),
IsHashtag: true,
InChannel: inChannel,
FromUser: fromUser,
}
}
// special case for when no terms are specified but we still have a filter
if plainParams == nil && hashtagParams == nil && (inChannel != "" || fromUser != "") {
plainParams = &SearchParams{
Terms: "",
IsHashtag: false,
InChannel: inChannel,
FromUser: fromUser,
}
}
return plainParams, hashtagParams
}

View File

@@ -0,0 +1,70 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"testing"
)
func TestParseSearchFlags(t *testing.T) {
if words, flags := parseSearchFlags(splitWords("")); len(words) != 0 {
t.Fatal("got words from empty input")
} else if len(flags) != 0 {
t.Fatal("got flags from empty input")
}
if words, flags := parseSearchFlags(splitWords("word")); len(words) != 1 || words[0] != "word" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 0 {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("apple banana cherry")); len(words) != 3 || words[0] != "apple" || words[1] != "banana" || words[2] != "cherry" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 0 {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("apple banana from:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 1 || flags["from"] != "chan" {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("apple banana from: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 1 || flags["from"] != "chan" {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("apple banana in: chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 1 || flags["in"] != "chan" {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("apple banana channel:chan")); len(words) != 2 || words[0] != "apple" || words[1] != "banana" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 1 || flags["channel"] != "chan" {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("fruit: cherry")); len(words) != 2 || words[0] != "fruit:" || words[1] != "cherry" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 0 {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("channel:")); len(words) != 1 || words[0] != "channel:" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 0 {
t.Fatalf("got incorrect flags %v", flags)
}
if words, flags := parseSearchFlags(splitWords("channel: first in: second from:")); len(words) != 1 || words[0] != "from:" {
t.Fatalf("got incorrect words %v", words)
} else if len(flags) != 2 || flags["channel"] != "first" || flags["in"] != "second" {
t.Fatalf("got incorrect flags %v", flags)
}
}

View File

@@ -242,10 +242,10 @@ func Etag(parts ...interface{}) string {
var validHashtag = regexp.MustCompile(`^(#[A-Za-z]+[A-Za-z0-9_\-]*[A-Za-z0-9])$`)
var puncStart = regexp.MustCompile(`^[.,()&$!\[\]{}"':;\\]+`)
var puncEnd = regexp.MustCompile(`[.,()&$#!\[\]{}"':;\\]+$`)
var puncEnd = regexp.MustCompile(`[.,()&$#!\[\]{}"';\\]+$`)
func ParseHashtags(text string) (string, string) {
words := strings.Split(strings.Replace(text, "\n", " ", -1), " ")
words := strings.Fields(text)
hashtagString := ""
plainString := ""