1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use serde::{Deserialize, Serialize};

const CONFIG_FILE: &str = "fus.toml";

pub fn read() -> crate::Result<Config> {
    let toml = std::fs::read(CONFIG_FILE)?;
    Ok(toml::from_slice(&toml)?)
}
pub fn init() -> crate::Result<()> {
    let mut modules = Vec::new();
    for result in ignore::WalkBuilder::new("./")
        .max_depth(Some(1))
        .build()
        .filter_map(|entry| {
            entry
                .map(|entry| {
                    if matches!(entry.file_type(), Some(x) if x.is_dir()) {
                        Some(entry)
                    } else {
                        None
                    }
                })
                .transpose()
        })
    {
        let entry = result?;
        let path = entry.path();
        if let (Some(module_name), Some(path)) = (
            path.file_name().and_then(|file_name| file_name.to_str()),
            path.to_str(),
        ) {
            modules.push(Module {
                name: module_name.to_string(),
                includes: vec![Include {
                    glob: path.to_string(),
                    prefix_strip: None,
                }],
                destination: format!("$CONFIG_DIR/{}", module_name),
            })
        }
    }
    let toml = toml::to_string_pretty(&Config {
        module: modules,
        vars: toml::Value::Table(toml::map::Map::new()),
    })?;
    Ok(std::fs::write(CONFIG_FILE, toml)?)
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
    pub module: Vec<Module>,
    pub vars: toml::Value,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Module {
    pub name: String,
    pub destination: String,
    pub includes: Vec<Include>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Include {
    pub glob: String,
    pub prefix_strip: Option<usize>,
}