package config import ( "errors" "fmt" "os" "path" "strings" "git.sr.ht/~rjarry/aerc/lib/xdg" "github.com/go-ini/ini" ) // Set at build time var ( shareDir string libexecDir string ) func buildDefaultDirs() []string { var defaultDirs []string prefixes := []string{ xdg.ConfigPath(), "~/.local/libexec", xdg.DataPath(), } // Add XDG_CONFIG_HOME and XDG_DATA_HOME for _, v := range prefixes { if v != "" { defaultDirs = append(defaultDirs, xdg.ExpandHome(v, "aerc")) } } // Add custom buildtime dirs if libexecDir != "" && libexecDir != "/usr/local/libexec/aerc" { defaultDirs = append(defaultDirs, xdg.ExpandHome(libexecDir)) } if shareDir != "" && shareDir != "/usr/local/share/aerc" { defaultDirs = append(defaultDirs, xdg.ExpandHome(shareDir)) } // Add fixed fallback locations defaultDirs = append(defaultDirs, "/usr/local/libexec/aerc") defaultDirs = append(defaultDirs, "/usr/local/share/aerc") defaultDirs = append(defaultDirs, "/usr/libexec/aerc") defaultDirs = append(defaultDirs, "/usr/share/aerc") return defaultDirs } var SearchDirs = buildDefaultDirs() func installTemplate(root, name string) error { var err error if _, err = os.Stat(root); os.IsNotExist(err) { err = os.MkdirAll(root, 0o755) if err != nil { return err } } var data []byte for _, dir := range SearchDirs { data, err = os.ReadFile(path.Join(dir, name)) if err == nil { break } } if err != nil { return err } err = os.WriteFile(path.Join(root, name), data, 0o644) if err != nil { return err } return nil } func parseConf(filename string) error { file, err := ini.LoadSources(ini.LoadOptions{ KeyValueDelimiters: "=", }, filename) if err != nil { return err } if err := parseGeneral(file); err != nil { return err } if err := parseFilters(file); err != nil { return err } if err := parseCompose(file); err != nil { return err } if err := parseConverters(file); err != nil { return err } if err := parseViewer(file); err != nil { return err } if err := parseStatusline(file); err != nil { return err } if err := parseOpeners(file); err != nil { return err } if err := parseHooks(file); err != nil { return err } if err := parseUi(file); err != nil { return err } if err := parseTemplates(file); err != nil { return err } return nil } func LoadConfigFromFile( root *string, accts []string, filename, bindPath, acctPath string, ) error { if root == nil { _root := xdg.ConfigPath("aerc") root = &_root } if filename == "" { filename = path.Join(*root, "aerc.conf") // if it doesn't exist copy over the template, then load if _, err := os.Stat(filename); errors.Is(err, os.ErrNotExist) { fmt.Printf("%s not found, installing the system default\n", filename) if err := installTemplate(*root, "aerc.conf"); err != nil { return err } } } SetConfFilename(filename) if err := parseConf(filename); err != nil { return fmt.Errorf("%s: %w", filename, err) } if err := parseAccounts(*root, accts, acctPath); err != nil { return err } if err := parseBinds(*root, bindPath); err != nil { return err } return nil } func parseLayout(layout string) [][]string { rows := strings.Split(layout, ",") l := make([][]string, len(rows)) for i, r := range rows { l[i] = strings.Split(r, "|") } return l } func contains(list []string, v string) bool { for _, item := range list { if item == v { return true } } return false } // warning message related to configuration (deprecation, etc.) type Warning struct { Title string Body string } var Warnings []Warning