package main import ( "flag" "fmt" "net/url" "os/exec" "regexp" ) // MatchFunc is a signature for a function to match a URL type MatchFunc = func(url.URL) bool // A BrowserRule is a rule that will launch a browser, if matched type BrowserRule struct { matcher MatchFunc command string args []string } // IsMatched will check to see the rule matches the provied URL func (r BrowserRule) IsMatched(dest url.URL) bool { return r.matcher(dest) } // Launch will launch the browser with the provided URL func (r BrowserRule) Launch(dest url.URL) error { args := append(r.args, "--", dest.String()) cmd := exec.Command(r.command, args...) return cmd.Start() } // MaybeLaunch will lauch the browser with the provided URL if it matches the rule func (r BrowserRule) MaybeLaunch(dest url.URL) (bool, error) { if r.IsMatched(dest) { return true, r.Launch(dest) } return false, nil } func matchHostname(hostnames ...string) MatchFunc { return func(dest url.URL) bool { for _, host := range hostnames { if host == dest.Hostname() { return true } } return false } } func matchHostRegexp(hostRegexp ...string) MatchFunc { matchers := []*regexp.Regexp{} for _, s := range hostRegexp { matchers = append(matchers, regexp.MustCompile(s)) } return func(dest url.URL) bool { for _, matcher := range matchers { if matcher.MatchString(dest.Hostname()) { return true } } return false } } func matchRegexp(urlRegexp ...string) MatchFunc { matchers := []*regexp.Regexp{} for _, s := range urlRegexp { matchers = append(matchers, regexp.MustCompile(s)) } return func(dest url.URL) bool { for _, matcher := range matchers { if matcher.MatchString(dest.String()) { return true } } return false } } func matchAny(matchFuncs ...MatchFunc) MatchFunc { return func(dest url.URL) bool { for _, f := range matchFuncs { if f(dest) { return true } } return false } } // Always returns true func defaultBrowser(dest url.URL) bool { return true } // Never returns true func noop(dest url.URL) bool { return false } func handleURL(urlString string) error { dest, err := url.Parse(urlString) if err != nil { return fmt.Errorf("failed to parse url: %s, %w", urlString, err) } var matched bool for _, rule := range rules() { matched, err = rule.MaybeLaunch(*dest) if err != nil { return fmt.Errorf("failed launching browser: %w", err) } if matched { break } } return nil } func main() { flag.Parse() urls := flag.Args() for _, urlString := range urls { err := handleURL(urlString) if err != nil { panic(err) } } }