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
use std::collections::HashMap;
use std::env;
use std::path::PathBuf;

use anyhow::{Context, Result};

enum Collectible {
    Project(String),
    Lang,
}

fn dirs(c: Collectible) -> Result<Vec<PathBuf>> {
    let current_dir = env::current_dir()?;
    let dir = match c {
        Collectible::Lang => current_dir.join("../langs"),
        Collectible::Project(lang) => current_dir.join("../langs").join(lang),
    };
    let mut entries = vec![];

    for entry in dir
        .read_dir()
        .with_context(|| format!("read_dir call failed for dir {}", dir.display()))?
    {
        if let Ok(entry) = entry {
            entries.push(entry.path().to_path_buf())
        }
    }
    Ok(entries)
}

fn basename(p: PathBuf) -> Result<String> {
    Ok(p.file_name().unwrap().to_string_lossy().into_owned())
}

pub fn collect() -> Result<HashMap<String, Vec<PathBuf>>> {
    let mut map = HashMap::new();
    let langs = dirs(Collectible::Lang).context("failed to get available languages")?;
    for lang in langs {
        let projects = dirs(Collectible::Project(lang.to_str().unwrap().to_string())).with_context(|| {
            format!(
                "failed to get available projects for lang {}",
                &lang.display()
            )
        })?;
        map.insert(basename(lang)?, projects);
    }
    Ok(map)
}