109 lines
2.4 KiB
Go
109 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/antonmedv/expr"
|
|
"github.com/hashicorp/hcl/v2/hclsimple"
|
|
)
|
|
|
|
func fileExists(path string) bool {
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// Config is the full set of configuration required
|
|
type Config struct {
|
|
DefaultBrowserCommand []string `hcl:"default_browser_cmd"`
|
|
Rules []BrowserRuleConfig `hcl:"rule,block"`
|
|
}
|
|
|
|
// BrowserRuleConfig represents a BrowserRule
|
|
type BrowserRuleConfig struct {
|
|
Name string `hcl:"name,label"`
|
|
BrowserCommand []string `hcl:"browser_cmd"`
|
|
MatchExpr string `hcl:"match"`
|
|
}
|
|
|
|
func MakeMatchFunc(rule string) MatchFunc {
|
|
return func(dest url.URL) bool {
|
|
env := map[string]interface{}{
|
|
"matchHostname": matchHostname,
|
|
"matchHostRegexp": matchHostRegexp,
|
|
"matchRegexp": matchRegexp,
|
|
"matchAny": matchAny,
|
|
// Building custom matchers
|
|
"MatchFunc": func(foundMatch bool) MatchFunc {
|
|
return func(_ url.URL) bool {
|
|
return foundMatch
|
|
}
|
|
},
|
|
"hostname": dest.Hostname(),
|
|
"url": dest.String(),
|
|
}
|
|
matchFunc, err := expr.Eval(rule, env)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return matchFunc.(MatchFunc)(dest)
|
|
}
|
|
}
|
|
|
|
func LoadConfig(path string) ([]BrowserRule, error) {
|
|
rules := []BrowserRule{}
|
|
var config Config
|
|
err := hclsimple.DecodeFile(path, nil, &config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, rule := range config.Rules {
|
|
rules = append(rules, BrowserRule{
|
|
command: rule.BrowserCommand[0],
|
|
args: rule.BrowserCommand[1:],
|
|
matcher: MakeMatchFunc(rule.MatchExpr),
|
|
})
|
|
}
|
|
|
|
// Add default browser rule to the end
|
|
rules = append(rules, BrowserRule{
|
|
command: config.DefaultBrowserCommand[0],
|
|
args: config.DefaultBrowserCommand[1:],
|
|
matcher: defaultBrowser,
|
|
})
|
|
|
|
return rules, nil
|
|
}
|
|
|
|
func DefaultConfigPath() (string, error) {
|
|
appName := "browser-ruler"
|
|
|
|
// Check XDG_CONFIG_HOME
|
|
dir, err := os.UserConfigDir()
|
|
if err == nil {
|
|
configPath := filepath.Join(dir, appName, "config.hcl")
|
|
if fileExists(configPath) {
|
|
return configPath, nil
|
|
}
|
|
}
|
|
|
|
dir, err = os.UserHomeDir()
|
|
if err != nil {
|
|
return "", fmt.Errorf("Could not find a config dir or home dir to look for config file. Specify one with -config: %w", err)
|
|
}
|
|
|
|
configPath := filepath.Join(dir, "."+appName+".hcl")
|
|
if fileExists(configPath) {
|
|
return configPath, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("no config file found in config dir or home dir")
|
|
}
|