Don't hardcode config file path
1 files changed, 32 insertions(+), 1 deletions(-)

M src/main.rs
M src/main.rs +32 -1
@@ 9,6 9,7 @@ extern crate toml;
 // use serde::de::Deserialize;
 use std::collections::HashMap;
 use std::io;
+use std::path::PathBuf;
 
 #[derive(Deserialize, Debug)]
 struct Config {

          
@@ 18,6 19,35 @@ struct Config {
 }
 
 impl Config {
+    fn locate() -> io::Result<PathBuf> {
+        use std::env;
+
+        // first priority: if a config file exists in the same directory
+        let mut paths = vec![PathBuf::from(".")];
+
+        // second priority: in the user's config dir
+        match env::var("XDG_CONFIG_HOME") {
+            Ok(confdir) => paths.push(PathBuf::from(&confdir).join("choosier")),
+            Err(_) => {
+                match env::var("HOME") {
+                    Ok(homedir) => paths.push(PathBuf::from(&homedir).join(".config").join("choosier")),
+                    Err(_) => (),
+                }
+            }
+        }
+
+        // third priority: in /etc
+        paths.push(PathBuf::from("/etc/choosier"));
+
+        for p in paths {
+            let cfg_path = p.join("choosier.toml");
+            if cfg_path.exists() {
+                return Ok(cfg_path.to_owned());
+            }
+        }
+        Err(io::Error::new(io::ErrorKind::NotFound, "configuration file not found"))
+    }
+
     fn parse(config_str: &str) -> Result<Config, io::Error> {
         let config: Config = toml::from_str(&config_str)?;
         Ok(config)

          
@@ 28,7 58,8 @@ fn read_config() -> Result<String, io::E
     use std::fs::File;
     use std::io::prelude::*;
 
-    let mut file = File::open("choosier.toml")?;
+    let cfg_path = Config::locate()?;
+    let mut file = File::open(cfg_path)?;
     let mut contents = String::new();
     file.read_to_string(&mut contents)?;
     Ok(contents)