146 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package common
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| type Query struct {
 | |
| 	Search string
 | |
| 	Artist string
 | |
| 	Album  string
 | |
| 	Song   string
 | |
| }
 | |
| 
 | |
| const emptyChar = ' '
 | |
| const songChar = 's'
 | |
| const albumChar = 'r'
 | |
| const artistChar = 'a'
 | |
| 
 | |
| func NewQuery(search string) (Query, error) {
 | |
| 	search = strings.TrimSpace(search)
 | |
| 	query := Query{
 | |
| 		Search: search,
 | |
| 	}
 | |
| 	if search == "" {
 | |
| 		return query, errors.New("search should not be empty")
 | |
| 	}
 | |
| 
 | |
| 	parsed := make(map[rune]string)
 | |
| 	indexChar := emptyChar
 | |
| 	nextIsIndex := false
 | |
| 	ignoreNextIfSpace := false
 | |
| 
 | |
| 	for _, char := range search {
 | |
| 		// figuring out when the next char is an index char
 | |
| 		if char == '#' {
 | |
| 			// escape # => asserts previous char was also #
 | |
| 			if nextIsIndex {
 | |
| 				nextIsIndex = false
 | |
| 				parsed[indexChar] = parsed[indexChar] + "#"
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			nextIsIndex = true
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		// setting an index char
 | |
| 		if nextIsIndex {
 | |
| 			if char != songChar && char != albumChar && char != artistChar {
 | |
| 				return query, errors.New("the char after # has to be " + string(songChar) + ", " + string(albumChar) + " or " + string(artistChar) + " if it isn't escaped with another #")
 | |
| 			}
 | |
| 
 | |
| 			if _, ok := parsed[char]; ok {
 | |
| 				return query, errors.New("you can use #" + string(char) + " only once")
 | |
| 			}
 | |
| 
 | |
| 			indexChar = char
 | |
| 			nextIsIndex = false
 | |
| 			ignoreNextIfSpace = true
 | |
| 			parsed[char] = ""
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		if ignoreNextIfSpace {
 | |
| 			ignoreNextIfSpace = false
 | |
| 
 | |
| 			if char == ' ' {
 | |
| 				continue
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		parsed[indexChar] = parsed[indexChar] + string(char)
 | |
| 	}
 | |
| 
 | |
| 	if nextIsIndex {
 | |
| 		return query, errors.New("there cant be an unescaped # at the end, it has to be escaped with another #")
 | |
| 	}
 | |
| 
 | |
| 	if _, ok := parsed[emptyChar]; ok {
 | |
| 		// no other index char should be used
 | |
| 
 | |
| 		e := errors.New("if you use advanced search with # you cant put anything before the first #")
 | |
| 		if _, ok := parsed[songChar]; ok {
 | |
| 			return query, e
 | |
| 		}
 | |
| 		if _, ok := parsed[albumChar]; ok {
 | |
| 			return query, e
 | |
| 		}
 | |
| 		if _, ok := parsed[artistChar]; ok {
 | |
| 			return query, e
 | |
| 		}
 | |
| 
 | |
| 		query.Search = parsed[emptyChar]
 | |
| 	} else {
 | |
| 		query.Song = strings.TrimSpace(parsed[songChar])
 | |
| 		query.Album = strings.TrimSpace(parsed[albumChar])
 | |
| 		query.Artist = strings.TrimSpace(parsed[artistChar])
 | |
| 
 | |
| 		elements := []string{}
 | |
| 
 | |
| 		if query.Song != "" {
 | |
| 			elements = append(elements, query.Song)
 | |
| 		}
 | |
| 
 | |
| 		if query.Artist != "" {
 | |
| 			elements = append(elements, query.Artist)
 | |
| 		}
 | |
| 
 | |
| 		if query.Album != "" && len(elements) <= 1 {
 | |
| 			elements = append(elements, query.Album)
 | |
| 		}
 | |
| 
 | |
| 		query.Search = strings.Join(elements, " - ")
 | |
| 	}
 | |
| 
 | |
| 	return query, nil
 | |
| }
 | |
| 
 | |
| func TestQueryParsing() {
 | |
| 	for {
 | |
| 		fmt.Print("> ")
 | |
| 
 | |
| 		reader := bufio.NewReader(os.Stdin)
 | |
| 		line, err := reader.ReadString('\n')
 | |
| 		if err != nil {
 | |
| 			log.Fatal(err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		query, err := NewQuery(line)
 | |
| 		if err != nil {
 | |
| 			fmt.Println(err)
 | |
| 		}
 | |
| 		fmt.Println("search: '" + query.Search + "'")
 | |
| 		fmt.Println("artist: '" + query.Artist + "'")
 | |
| 		fmt.Println("album:  '" + query.Album + "'")
 | |
| 		fmt.Println("song:   '" + query.Song + "'")
 | |
| 		fmt.Println()
 | |
| 	}
 | |
| }
 |