1use failure::Error;
2use std::collections::HashMap;
3use std::fs::File;
4use std::io::prelude::*;
5use std::path::{Path, PathBuf};
6
7#[derive(Deserialize)]
8struct Cargo {
9 package: Package,
10}
11
12#[derive(Deserialize)]
13struct Package {
14 metadata: Option<Metadata>,
15}
16
17#[derive(Deserialize)]
18struct Metadata {
19 x: Option<Xconf>,
20}
21
22pub type Xconf = HashMap<String, String>;
23
24fn dotx() -> Result<Xconf, Error> {
25 let mut path = match dirs::home_dir() {
26 Some(p) => p,
27 _ => return Err(format_err!("cannot get home dir")),
28 };
29 path.push(".x.toml");
30
31 if !Path::new(&path).exists() {
32 return Ok(HashMap::new());
33 }
34
35 let mut conf_string = String::new();
36 File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
37
38 let xconf: Xconf = toml::from_str(&conf_string)?;
39
40 Ok(xconf)
41}
42
43fn x() -> Result<Xconf, Error> {
44 let mut path = PathBuf::new();
45 path.push(super::meta::root()?);
46 path.push("x.toml");
47
48 if !Path::new(&path).exists() {
49 return Ok(HashMap::new());
50 }
51
52 let mut conf_string = String::new();
53 File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
54
55 let xconf: Xconf = toml::from_str(&conf_string)?;
56
57 Ok(xconf)
58}
59
60fn cargo() -> Result<Xconf, Error> {
61 let mut path = PathBuf::new();
62 path.push(super::meta::root()?);
63 path.push("Cargo.toml");
64
65 if !Path::new(&path).exists() {
66 return Ok(HashMap::new());
67 }
68
69 let mut conf_string = String::new();
70 File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
71
72 let cargo_toml: Cargo = toml::from_str(&conf_string)?;
73
74 Ok(
75 if let Some(Metadata { x: Some(x) }) = cargo_toml.package.metadata {
76 x
77 } else {
78 HashMap::new()
79 },
80 )
81}
82
83pub fn get() -> Result<Xconf, Error> {
84 let x_conf: Xconf =
85 dotx()?.into_iter().chain(x()?).chain(cargo()?).collect();
86
87 for pair in x_conf.clone().into_iter() {
88 match pair {
89 (ref k, _) if k == "x" => {
90 return Err(format_err!("command key `x` is reserved"));
92 }
93 _ => {}
94 }
95 }
96
97 Ok(x_conf)
98}