use anyhow::{Result, anyhow};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use crate::{get_module_paths, get_root_paths, read_yaml};
pub fn search_modules(s: &str, precision: f64) -> Result<Vec<PathBuf>> {
let module_paths = get_module_paths()?;
let mut matches = search_by_tag(s)?;
let mut other_matches = module_paths
.clone()
.into_iter()
.filter(|p| {
let p_str = p.file_name().unwrap().to_str().unwrap().to_string();
let mut hit: bool = strsim::jaro(&p_str, s) > precision || p_str.contains(s);
if matches.contains(p) {
hit = false;
}
hit
})
.collect();
matches.append(&mut other_matches);
Ok(matches)
}
pub fn find_module(s: &str) -> Result<Option<PathBuf>> {
if let Some(result) = get_module_paths()?
.into_iter()
.find(|p| p.file_name().unwrap().to_str().unwrap() == s)
{
return Ok(Some(result));
};
let substring_matches = get_module_paths()?
.into_iter()
.filter(|p| p.file_name().unwrap().to_str().unwrap().contains(s))
.collect::<Vec<PathBuf>>();
if substring_matches.len() == 1 {
return Ok(Some(substring_matches.first().unwrap().clone()));
}
Ok(None)
}
pub fn find_root(s: &str) -> Result<Option<PathBuf>> {
Ok(get_root_paths()?
.into_iter()
.find(|p| p.file_name().unwrap().to_str().unwrap() == s))
}
pub fn list_rooted_modules(root: &str) -> Result<Vec<PathBuf>> {
let root_paths = get_root_paths()?;
let root_paths: Vec<&PathBuf> = root_paths
.iter()
.filter(|r| {
let r = &r.file_name().unwrap().to_str().unwrap().to_string();
r == root
})
.collect();
if root_paths.is_empty() {
return Err(anyhow!("{}: {}", "invalid root", root));
}
let root_path = root_paths[0];
let modules = get_module_paths()?
.into_iter()
.filter(|p| p.ancestors().nth(1).unwrap() == root_path)
.collect();
Ok(modules)
}
pub fn search_by_tag(tag: &str) -> Result<Vec<PathBuf>> {
let mut modules: Vec<PathBuf> = vec![];
for module in get_module_paths()? {
if let Some(yaml) = read_yaml(&module)?
&& let Some(tags) = yaml["tags"].as_sequence()
&& tags
.iter()
.filter_map(|x| x.as_str())
.collect::<Vec<&str>>()
.contains(&tag)
{
modules.push(module);
}
}
Ok(modules)
}
pub fn get_module_tags(module: &Path) -> Result<Vec<String>> {
let mut module_tags = vec![];
if let Some(yaml) = read_yaml(module)?
&& let Some(tags) = yaml["tags"].as_sequence()
{
for tag in tags {
if let Some(t) = tag.as_str().map(|x| x.to_string()) {
module_tags.push(t)
}
}
}
Ok(module_tags)
}
pub fn get_all_tags() -> Result<Vec<(String, u32)>> {
let mut tags_count: HashMap<String, u32> = HashMap::new();
for module in &get_module_paths()? {
for tag in get_module_tags(module)? {
tags_count.entry(tag).and_modify(|c| *c += 1).or_insert(1);
}
}
Ok(tags_count.into_iter().collect::<Vec<(String, u32)>>())
}