package main import ( "encoding/json" "errors" "os" "path" "slices" "strings" "github.com/charmbracelet/log" ) type Config struct { UserName string UserID string ClientID string ClientSecret string } // Finds a valid configuration file if it exists. If nil is returned one // should be created. func find_config() (string, error) { // Paths where a tremble.conf file might reside // TODO: Check XDG_CONFIG_DIRS last in case XDG_CONFIG_HOME isn't set. var paths []string = []string{ ".", "$XDG_CONFIG_HOME/tremble", "$HOME/.tremble", "$HOME/.config/tremble", } if configDirs, isSet := os.LookupEnv("XDG_CONFIG_DIRS"); isSet { paths = slices.Concat(paths, strings.Split(configDirs, ":")) } for _, p := range paths { dir := os.ExpandEnv(p) pstr := path.Join(dir, "tremble.conf") _, err := os.Lstat(pstr) if err != nil { continue } return pstr, nil } return "", errors.New("No config file found.") } // Finds a configuration file and processes it if one exists. func read_config() (*Config, error) { pstr, err := find_config() if err != nil { log.Info(err) return nil, err } cdata, err := os.ReadFile(pstr) if err != nil { log.Info(err) return nil, err } // Parse the file and return. var confOut Config err = json.Unmarshal(cdata, &confOut) if err != nil { return nil, err } return &confOut, nil } // Writes configuration to the tremble config file. Currently this overwrites // the entire thing if found, or creates a new one if not. func write_config(config *Config) error { var pstr string // XXX: Maybe check to make sure this isn't some substantial error. // XXX: Some duplication here. pstr, err := find_config() if err != nil { // Get XDG_CONFIG_HOME, fallback to $HOME/.config configHome := os.Getenv("XDG_CONFIG_HOME") if configHome == "" { home := os.Getenv("HOME") if home == "" { log.Fatal("Cannot determine config directory: HOME not set") } configHome = path.Join(home, ".config") } dir := path.Join(configHome, "tremble") if err := os.MkdirAll(dir, 0755); err != nil { log.Fatalf("Couldnt create directory '%v': %v\n", dir, err) } pstr = path.Join(dir, "tremble.conf") } // TODO: Make this fatal in the caller, or... not. Just not here. cdata, err := json.Marshal(config) if err != nil { log.Fatalf("Couldn't write config %v: %v\n", config, err) } err = os.WriteFile(pstr, cdata, 0755) if err != nil { log.Fatalf("Couldn't write config %v: %v\n", config, err) } return nil }