use std::path::{PathBuf};
use std::collections::{HashSet, BTreeMap};
use backstage::index::Index;
use backstage::zettel::Zettel;
pub mod sequences;
pub fn get_keywords(index: &Index) -> HashSet<String> {
let mut keywords = HashSet::new();
for (_, zettel) in &index.files {
for keyword in &zettel.keywords {
keywords.insert(keyword.to_string());
}
}
keywords
}
pub fn count_keywords(index: &Index) -> BTreeMap<String, u32> {
let mut counted_keywords = BTreeMap::new();
for (_, zettel) in &index.files {
for keyword in &zettel.keywords {
if let Some(count) = counted_keywords.get(keyword) {
let new_count = count + 1;
counted_keywords.insert(keyword.to_string(), new_count);
} else {
counted_keywords.insert(keyword.to_string(), 1);
}
}
}
counted_keywords
}
pub fn search_index_for_keywords(index: &Index,
searched_keywords: Vec<String>,
all: bool) -> HashSet<PathBuf> {
let mut matching_zettels = HashSet::new();
for (key, zettel) in &index.files {
if search_zettel_for_keywords(&zettel, &searched_keywords, all) {
matching_zettels.insert(key.to_path_buf());
}
}
matching_zettels
}
fn search_zettel_for_keywords(zettel: &Zettel,
searched_keywords: &Vec<String>,
all: bool) -> bool {
if all {
for keyword in searched_keywords {
if !zettel.keywords.contains(&keyword) {
return false;
}
}
return true;
} else {
for keyword in searched_keywords {
if zettel.keywords.contains(&keyword) {
return true;
}
}
return false;
}
}
pub fn search_index_for_title<T: AsRef<str>>(index: &Index,
search_term: T,
exact: bool) -> HashSet<PathBuf> {
let mut matching_zettels = HashSet::new();
for (key, zettel) in &index.files {
if search_zettel_title(&zettel, &search_term, exact) {
matching_zettels.insert(key.to_path_buf());
}
}
matching_zettels
}
fn search_zettel_title<T: AsRef<str>>(zettel: &Zettel,
search_term: T,
exact: bool) -> bool {
let search_term = search_term.as_ref();
let qs = search_term;
let zt = zettel.title.as_str();
if exact {
trace!("exact. Returning {:?}", zt==qs);
zt == qs
} else {
let qs = qs.to_ascii_lowercase();
let zt = zt.to_ascii_lowercase();
zt.contains(&qs)
}
}
pub fn combi_search<T: AsRef<str>>(index: &Index,
searched_keywords: Vec<String>,
all: bool,
search_term: T,
exact: bool)
-> HashSet<PathBuf> {
let mut k_result = search_index_for_keywords(&index,
searched_keywords,
all);
let t_result = search_index_for_title(&index, search_term, exact);
if all {
let mut temp = HashSet::new();
for r in k_result {
if t_result.contains(&r) {
temp.insert(r);
}
}
k_result = temp;
} else {
for r in t_result {
k_result.insert(r);
}
}
k_result
}
pub fn inspect_incoming(index: &Index,
inspected_zettels: &HashSet<PathBuf>,
all: bool)
-> HashSet<PathBuf> {
let mut incoming = HashSet::new();
for (other_key, other_zettel) in &index.files {
if other_zettel.links_to(&inspected_zettels, all) {
incoming.insert(other_key.to_path_buf());
}
}
incoming
}
#[cfg(test)]
mod tests {
use super::*;
extern crate tempfile;
use self::tempfile::tempdir;
use examples::*;
use std::path::Path;
fn setup() -> Index {
let tmp_dir = tempdir().expect("Failed setting up temp directory.");
let dir = tmp_dir.path();
generate_examples_with_index(dir)
.expect("Failed to generate examples");
let file_path = dir.join("examples/config/index.yaml");
let index = Index::from_file(&file_path).unwrap();
index
}
#[test]
fn test_search_zettel_for_keywords() {
let index = setup();
let z1 = index.get_zettel(Path::new("file1.md"));
assert!(z1.is_some());
let z1 = z1.unwrap();
let searched_keywords = vec!["example".to_string()];
assert!(search_zettel_for_keywords(&z1, &searched_keywords, false));
let searched_keywords = vec!["foo".to_string()];
assert!(!search_zettel_for_keywords(&z1, &searched_keywords, false));
let searched_keywords = vec!["example".to_string(),
"foo".to_string()];
assert!(search_zettel_for_keywords(&z1, &searched_keywords, false));
let searched_keywords = vec!["foo".to_string(),
"bar".to_string()];
assert!(!search_zettel_for_keywords(&z1, &searched_keywords, false));
let searched_keywords = vec!["example".to_string(),
"foo".to_string()];
assert!(!search_zettel_for_keywords(&z1, &searched_keywords, true));
let searched_keywords = vec!["example".to_string(),
"first".to_string()];
assert!(search_zettel_for_keywords(&z1, &searched_keywords, true));
let searched_keywords = vec!["example".to_string(),
"first".to_string(),
"foo".to_string()];
assert!(search_zettel_for_keywords(&z1, &searched_keywords, false));
let searched_keywords = vec!["example".to_string(),
"first".to_string(),
"foo".to_string()];
assert!(!search_zettel_for_keywords(&z1, &searched_keywords, true));
}
#[test]
fn test_get_keywords() {
let index = setup();
let keywords = get_keywords(&index);
assert_eq!(keywords.len(), 7);
assert!(keywords.contains("example"));
assert!(keywords.contains("test"));
assert!(keywords.contains("first"));
assert!(keywords.contains("second"));
assert!(keywords.contains("third"));
assert!(keywords.contains("fourth"));
assert!(keywords.contains("pureyaml"));
}
#[test]
fn test_count_keywords() {
let index = setup();
let keyword_count = count_keywords(&index);
assert_eq!(Some(&5), keyword_count.get("example"));
assert_eq!(Some(&1), keyword_count.get("test"));
assert_eq!(Some(&1), keyword_count.get("first"));
assert_eq!(Some(&1), keyword_count.get("second"));
assert_eq!(Some(&1), keyword_count.get("third"));
assert_eq!(Some(&1), keyword_count.get("fourth"));
assert_eq!(Some(&1), keyword_count.get("pureyaml"));
}
#[test]
fn test_search_index_for_keywords() {
let index = setup();
let searched_keywords = vec!["first".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
false);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let searched_keywords = vec!["first".to_string(),
"foo".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
false);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let searched_keywords = vec!["first".to_string(),
"foo".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
true);
assert_eq!(matching_zettels.len(), 0);
let searched_keywords = vec!["first".to_string(),
"second".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
false);
assert_eq!(matching_zettels.len(), 2);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
assert!(matching_zettels.contains(&PathBuf::from("file2.md")));
let searched_keywords = vec!["first".to_string(),
"second".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
true);
assert_eq!(matching_zettels.len(), 0);
let searched_keywords = vec!["first".to_string(),
"example".to_string()];
let matching_zettels = search_index_for_keywords(&index,
searched_keywords,
true);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
}
#[test]
fn test_search_zettel_title() {
let index = setup();
let z1 = index.get_zettel(Path::new("file1.md"));
assert!(z1.is_some());
let z1 = z1.unwrap();
assert!(search_zettel_title(&z1, "File 1", false));
assert!(search_zettel_title(&z1, "File 1", true));
assert!(search_zettel_title(&z1, "File", false));
assert!(!search_zettel_title(&z1, "File", true));
assert!(!search_zettel_title(&z1, "foo", false));
assert!(!search_zettel_title(&z1, "foo", true));
}
#[test]
fn test_search_index_for_title() {
let index = setup();
let matching_zettels = search_index_for_title(&index, "File 1", false);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let matching_zettels = search_index_for_title(&index, "File 1", true);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let matching_zettels = search_index_for_title(&index, "File", false);
assert_eq!(matching_zettels.len(), 5);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
assert!(matching_zettels.contains(&PathBuf::from("file2.md")));
assert!(matching_zettels.contains(&PathBuf::from("file3.md")));
assert!(matching_zettels.contains(&PathBuf::from("subdir/file4.md")));
assert!(matching_zettels.contains(&PathBuf::from("subdir/file5.md")));
let matching_zettels = search_index_for_title(&index, "File", true);
assert_eq!(matching_zettels.len(), 0);
let matching_zettels = search_index_for_title(&index, "foo", false);
assert_eq!(matching_zettels.len(), 0);
let matching_zettels = search_index_for_title(&index, "foo", true);
assert_eq!(matching_zettels.len(), 0);
}
#[test]
fn test_combi_search() {
let index = setup();
let searched_keywords = vec!["first".to_string()];
let matching_zettels = combi_search(&index,
searched_keywords.clone(),
true,
"File",
true);
assert_eq!(matching_zettels.len(), 0);
let matching_zettels = combi_search(&index,
searched_keywords.clone(),
true,
"File",
false);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let matching_zettels = combi_search(&index,
searched_keywords,
true,
"File 1",
true);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let searched_keywords = vec!["example".to_string()];
let matching_zettels = combi_search(&index,
searched_keywords.clone(),
true,
"File 1",
true);
assert_eq!(matching_zettels.len(), 1);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
let matching_zettels = combi_search(&index,
searched_keywords,
false,
"File 1",
true);
assert_eq!(matching_zettels.len(), 5);
assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
assert!(matching_zettels.contains(&PathBuf::from("file2.md")));
assert!(matching_zettels.contains(&PathBuf::from("file3.md")));
assert!(matching_zettels.contains(&PathBuf::from("subdir/file4.md")));
assert!(matching_zettels.contains(&PathBuf::from("onlies/pure-yaml.yaml")));
}
#[test]
fn test_inspect_incoming() {
let index = setup();
let mut inspected_zettels = HashSet::new();
inspected_zettels.insert(PathBuf::from("file2.md"));
inspected_zettels.insert(PathBuf::from("file3.md"));
let incoming = inspect_incoming(&index, &inspected_zettels, false);
assert_eq!(incoming.len(), 3);
assert!(incoming.contains(&PathBuf::from("file1.md")));
assert!(incoming.contains(&PathBuf::from("file2.md")));
assert!(incoming.contains(&PathBuf::from("onlies/markdown-only.md")));
let incoming = inspect_incoming(&index, &inspected_zettels, true);
assert_eq!(incoming.len(), 1);
assert!(incoming.contains(&PathBuf::from("file1.md")));
let mut inspected_zettels = HashSet::new();
inspected_zettels.insert(PathBuf::from("file2.md"));
inspected_zettels.insert(PathBuf::from("file42.md"));
let incoming = inspect_incoming(&index, &inspected_zettels, false);
assert_eq!(incoming.len(), 2);
assert!(incoming.contains(&PathBuf::from("file1.md")));
assert!(incoming.contains(&PathBuf::from("onlies/markdown-only.md")));
let incoming = inspect_incoming(&index, &inspected_zettels, true);
assert_eq!(incoming.len(), 0);
}
}