func ExpandTag(tag string) (string, error) {
	names := TagNames(false)
	r := regexp.MustCompile(`^` + tag)
	validTags := []string{}
	for _, n := range names {
		if n == tag {
			return n, nil
		}
		if r.Match([]byte(n)) {
			validTags = append(validTags, n)
		}
	}
	switch len(validTags) {
	case 0:
		return "", fmt.Errorf("No tag found for %q", tag)
	case 1:
		return validTags[0], nil
	default:
		return "", fmt.Errorf("Multiple tags matched %q: %v", tag, validTags)
	}
}
ExpandTag expands the passed in tag to the full value.
package providers
import (
	"fmt"
	"os"
	"regexp"
	"sort"
	"strings"
	"github.com/zquestz/s/launcher"
	"golang.org/x/text/language"
)
const (
	defaultLanguage = "en"
	defaultRegion   = "US"
)
var (
	enableBlacklist = false
	enableWhitelist = false
	clientLocale    = ""
	blacklist       = make(map[string]interface{})
	whitelist       = make(map[string]interface{})
)
type Provider interface {
	BuildURI(string) string
	Tags() []string
}
var Providers map[string]Provider
func init() {
	Providers = make(map[string]Provider)
}
func AddProvider(name string, provider Provider) {
	Providers[name] = provider
}
func SetBlacklist(b []string) {
	for _, v := range b {
		blacklist[v] = nil
	}
	if len(blacklist) > 0 {
		enableBlacklist = true
	}
}
func SetWhitelist(w []string) {
	for _, v := range w {
		whitelist[v] = nil
	}
	if len(whitelist) > 0 {
		enableWhitelist = true
	}
}
func Search(binary string, p string, t string, q string, userProvider bool, outputOnly bool, verbose bool) error {
	prov, err := ExpandProvider(p)
	if err != nil {
		return err
	}
	builders := []Provider{}
	if t == "" || userProvider {
		builders = append(builders, Providers[prov])
	}
	if t != "" {
		tag, err := ExpandTag(t)
		if err != nil {
			return err
		}
		builders = append(builders, GetProvidersByTag(tag)...)
	}
	var success bool
	for _, builder := range builders {
		if builder != nil {
			url := builder.BuildURI(q)
			if verbose || outputOnly {
				fmt.Printf("%s\n", url)
			}
			if !outputOnly {
				err = launcher.OpenURI(binary, url)
				if err != nil {
					return err
				}
			}
			success = true
		}
	}
	if !success {
		return fmt.Errorf("No providers found for tag %q.", t)
	}
	return nil
}
func GetProvidersByTag(tag string) []Provider {
	provs := []Provider{}
	for _, providerName := range ProviderNames(false) {
		provider := Providers[providerName]
		for _, providerTag := range provider.Tags() {
			if providerTag == tag {
				provs = append(provs, provider)
			}
		}
	}
	return provs
}
func DisplayProviders(verbose bool) string {
	names := ProviderNames(verbose)
	return fmt.Sprintf("%s\n", strings.Join(names, "\n"))
}
func DisplayTags(verbose bool) string {
	names := TagNames(verbose)
	return fmt.Sprintf("%s\n", strings.Join(names, "\n"))
}
func ExpandProvider(provider string) (string, error) {
	names := ProviderNames(false)
	r := regexp.MustCompile(`^` + provider)
	validProviders := []string{}
	for _, n := range names {
		if n == provider {
			return n, nil
		}
		if r.Match([]byte(n)) {
			validProviders = append(validProviders, n)
		}
	}
	switch len(validProviders) {
	case 0:
		return "", fmt.Errorf("No provider found for %q", provider)
	case 1:
		return validProviders[0], nil
	default:
		return "", fmt.Errorf("Multiple providers matched %q: %v", provider, validProviders)
	}
}