use std::path::{PathBuf, Path};
use backstage::index::Index;
use std::collections::HashSet;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum SequenceStart {
RootOnly,
Keyword,
Fork,
KeywordAndFork,
KeywordOrFork,
}
pub fn parents_of_scope(index: &Index,
scope: Vec<PathBuf>)
-> HashSet<PathBuf> {
let mut parents = HashSet::new();
for zettel in scope {
let mut zettel_parents = parents_of_zettel(&index, &zettel);
for zp in zettel_parents.drain() {
parents.insert(zp);
}
}
parents
}
fn parents_of_zettel<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let mut parents = HashSet::new();
let key = key.as_ref().to_path_buf();
for (path, zettel) in &index.files {
if zettel.followups.contains(&key) {
parents.insert(path.to_path_buf());
}
}
parents
}
pub fn sequence_tree(index: &Index,
scope: &HashSet<PathBuf>)
-> HashSet<PathBuf> {
let mut sequence_tree = HashSet::new();
for zettel in scope {
let stn_of_zettel = sequence_tree_of_zettel(&index, zettel);
for z in stn_of_zettel {
sequence_tree.insert(z);
}
}
sequence_tree
}
fn sequence_tree_of_zettel<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let key = key.as_ref();
let mut ad = ancestors_and_descendants(&index, &key);
ad.insert(key.to_path_buf());
ad
}
pub fn sequence_tree_whole(index: &Index, scope: &HashSet<PathBuf>)
-> HashSet<PathBuf> {
let mut sequence_tree = HashSet::new();
for zettel in scope {
let wst_of_zettel = sequence_tree_whole_of_zettel(&index, zettel);
for z in wst_of_zettel {
sequence_tree.insert(z);
}
}
sequence_tree
}
fn sequence_tree_whole_of_zettel<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let mut sequence_tree = HashSet::new();
let root_sequences = sequences_of_zettel(&index,
key,
&SequenceStart::RootOnly);
for sequence in root_sequences {
let sq_zettels = zettels_of_sequence(&index, sequence);
for z in sq_zettels {
sequence_tree.insert(z);
}
}
sequence_tree
}
pub fn sequences(index: &Index,
scope: &HashSet<PathBuf>,
cfg_sequence_start: &SequenceStart)
-> HashSet<PathBuf> {
let mut sequences = HashSet::new();
for zettel in scope {
let zettel_sequences = sequences_of_zettel(&index,
&zettel,
cfg_sequence_start);
for zs in zettel_sequences {
sequences.insert(zs);
}
}
sequences
}
fn sequences_of_zettel<P: AsRef<Path>>(index: &Index,
key: P,
cfg_sequence_start: &SequenceStart)
-> HashSet<PathBuf> {
let key = key.as_ref();
let mut sequences = HashSet::new();
let (check, parents) = check_sequence_start(&index,
&key,
&cfg_sequence_start);
if check {
sequences.insert(key.to_path_buf());
}
for parent in parents {
let parent_sequences = sequences_of_zettel(&index,
parent,
&cfg_sequence_start);
for parent_sequence in parent_sequences {
sequences.insert(parent_sequence);
}
}
sequences
}
pub fn zettels_of_sequence<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let key = key.as_ref().to_path_buf();
let mut zettels = HashSet::new();
zettels.insert(key.clone());
if let Some(z) = &index.get_zettel(&key) {
for f in &z.followups {
let rest_sequence = zettels_of_sequence(&index,
&f);
for rest in rest_sequence {
zettels.insert(rest);
}
}
}
zettels
}
fn ancestors_and_descendants<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let key = key.as_ref();
let mut ad = HashSet::new();
let ancestors = ancestors_of_zettel(&index, &key);
for a in ancestors {
ad.insert(a);
}
let descendants = descendants_of_zettel(&index, &key);
for d in descendants {
ad.insert(d);
}
ad
}
fn ancestors_of_zettel<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let key = key.as_ref();
let mut ancestors = HashSet::new();
let parents = parents_of_zettel(&index, key);
for parent in parents {
if ancestors.insert(parent.clone()) {
let parent_ancestors = ancestors_of_zettel(&index, parent);
for pa in parent_ancestors {
ancestors.insert(pa);
}
}
}
ancestors
}
fn descendants_of_zettel<P: AsRef<Path>>(index: &Index,
key: P)
-> HashSet<PathBuf> {
let key = key.as_ref();
let mut descendants = HashSet::new();
if let Some(zettel) = &index.get_zettel(&key) {
for followup in &zettel.followups {
if descendants.insert(followup.clone()) {
let followup_descendants = descendants_of_zettel(&index, followup);
for fd in followup_descendants {
descendants.insert(fd);
}
}
}
}
descendants
}
fn children_of_parents(index: &Index,
parents: &HashSet<PathBuf>)
-> HashSet<PathBuf> {
let mut children = HashSet::new();
for p in parents {
if let Some(parent) = &index.get_zettel(&p) {
for f in &parent.followups {
children.insert(f.clone());
}
}
}
children
}
fn parents_and_siblings<P: AsRef<Path>>(index: &Index,
key: P)
-> (HashSet<PathBuf>, HashSet<PathBuf>) {
let parents = parents_of_zettel(&index, &key);
let key = key.as_ref().to_path_buf();
if parents.is_empty() {
return (parents, HashSet::new()); } else {
let mut children = children_of_parents(index, &parents);
children.remove(&key);
return (parents, children);
}
}
fn check_sequence_start<P: AsRef<Path>>(index: &Index,
key: P,
cfg_sequence_start: &SequenceStart)
-> (bool, HashSet<PathBuf>) {
let (parents, siblings) = parents_and_siblings(&index, &key);
if parents.is_empty() {
return (true, parents);
} else {
if let Some(zettel) = index.get_zettel(key) {
match cfg_sequence_start {
SequenceStart::RootOnly => (), SequenceStart::Keyword => {
if !zettel.keywords.is_empty() {
return (true, parents);
}
},
SequenceStart::Fork => {
if !siblings.is_empty() {
return (true, parents);
}
},
SequenceStart::KeywordAndFork => {
if !zettel.keywords.is_empty() && !siblings.is_empty() {
return (true, parents);
}
},
SequenceStart::KeywordOrFork => {
if !zettel.keywords.is_empty() || !siblings.is_empty() {
return (true, parents);
}
},
}
}
}
(false, parents)
}
#[cfg(test)]
mod tests {
use super::*;
use Zettel;
#[test]
fn test_parents_of_zettel() {
let mut index = Index::empty();
let child = Zettel::new("Child");
index.add_zettel("child.md", child);
let mut parent = Zettel::new("Parent");
parent.add_followup("child.md");
index.add_zettel("parent.md", parent);
let mut parent2 = Zettel::new("Other Parent");
parent2.add_followup("child.md");
index.add_zettel("parent2.md", parent2);
let unrelated = Zettel::new("Unrelated");
index.add_zettel("unrelated.md", unrelated);
assert_eq!(parents_of_zettel(&index, "unrelated.md").len(), 0);
let parents = parents_of_zettel(&index, "child.md");
assert_eq!(parents.len(), 2);
assert!(parents.contains(&PathBuf::from("parent.md")));
assert!(parents.contains(&PathBuf::from("parent2.md")));
}
#[test]
fn test_parents_of_scope() {
let mut index = Index::empty();
let child = Zettel::new("Child");
index.add_zettel("child.md", child);
let mut parent = Zettel::new("Parent");
parent.add_followup("child.md");
index.add_zettel("parent.md", parent);
let mut parent2 = Zettel::new("Other Parent");
parent2.add_followup("child.md");
index.add_zettel("parent2.md", parent2);
let otherchild = Zettel::new("Other Child");
index.add_zettel("otherchild.md", otherchild);
let mut parent3 = Zettel::new("Parent3");
parent3.add_followup("otherchild.md");
index.add_zettel("parent3.md", parent3);
let unrelated = Zettel::new("Unrelated");
index.add_zettel("unrelated.md", unrelated);
let scope = vec![PathBuf::from("child.md"), PathBuf::from("otherchild.md")];
let parents = parents_of_scope(&index, scope);
assert!(parents.contains(&PathBuf::from("parent.md")));
assert!(parents.contains(&PathBuf::from("parent2.md")));
assert!(parents.contains(&PathBuf::from("parent3.md")));
}
#[test]
fn test_parents_and_siblings() {
let mut index = Index::empty();
let child_zettel = Zettel::new("A Child");
index.add_zettel("child.md", child_zettel);
let mut our_zettel = Zettel::new("Our Zettel");
our_zettel.add_followup("child.md");
index.add_zettel("our_zettel.md", our_zettel);
let s1 = Zettel::new("1st Sibling");
index.add_zettel("s1.md", s1);
let s2 = Zettel::new("2nd Sibling");
index.add_zettel("s2.md", s2);
let mut parent = Zettel::new("Parent");
parent.add_followup("our_zettel.md");
parent.add_followup("s1.md");
parent.add_followup("s2.md");
index.add_zettel("parent.md", parent);
let (p, s) = parents_and_siblings(&index, "our_zettel.md");
assert_eq!(p.len(), 1);
assert!(p.contains(&PathBuf::from("parent.md")));
assert_eq!(s.len(), 2);
assert!(s.contains(&PathBuf::from("s1.md")));
assert!(s.contains(&PathBuf::from("s2.md")));
let (p, s) = parents_and_siblings(&index, "parent.md");
assert!(p.is_empty());
assert!(s.is_empty());
let (p, s) = parents_and_siblings(&index, "child.md");
assert_eq!(p.len(), 1);
assert!(p.contains(&PathBuf::from("our_zettel.md")));
assert_eq!(s.len(), 0);
}
fn sequence_test_index() -> Index {
let mut index = Index::empty();
let mut f1 = Zettel::new("File 1");
let mut f2 = Zettel::new("File 2");
let mut f3 = Zettel::new("File 3");
let mut f4 = Zettel::new("File 4");
let f5 = Zettel::new("File 5");
let mut f6 = Zettel::new("File 6");
let mut f7 = Zettel::new("File 7");
f1.add_keyword("example");
f3.add_keyword("foo");
f4.add_keyword("bar");
f7.add_keyword("baz");
f1.add_followup("file2.md");
f2.add_followup("file3.md");
f2.add_followup("file4.md");
f3.add_followup("file5.md");
f4.add_followup("file5.md"); f4.add_followup("file6.md");
f6.add_followup("file7.md");
index.add_zettel("file1.md", f1);
index.add_zettel("file2.md", f2);
index.add_zettel("file3.md", f3);
index.add_zettel("file4.md", f4);
index.add_zettel("file5.md", f5);
index.add_zettel("file6.md", f6);
index.add_zettel("file7.md", f7);
index
}
#[test]
fn test_sequence_start_orphan_only() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::RootOnly;
let (check, parents) = check_sequence_start(&index, "file1.md", &cfg_ss);
assert_eq!(check, true);
assert!(parents.is_empty());
let (check, parents) = check_sequence_start(&index, "file2.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file1.md")));
let (check, parents) = check_sequence_start(&index, "file3.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file4.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file5.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 2); assert!(parents.contains(&PathBuf::from("file3.md")));
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file6.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file7.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_sequence_start_keyword() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::Keyword;
let (check, parents) = check_sequence_start(&index, "file1.md", &cfg_ss);
assert_eq!(check, true);
assert!(parents.is_empty());
let (check, parents) = check_sequence_start(&index, "file2.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file1.md")));
let (check, parents) = check_sequence_start(&index, "file3.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file4.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file5.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 2); assert!(parents.contains(&PathBuf::from("file3.md")));
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file6.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file7.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_sequence_start_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::Fork;
let (check, parents) = check_sequence_start(&index, "file1.md", &cfg_ss);
assert_eq!(check, true);
assert!(parents.is_empty());
let (check, parents) = check_sequence_start(&index, "file2.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file1.md")));
let (check, parents) = check_sequence_start(&index, "file3.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file4.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file5.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 2); assert!(parents.contains(&PathBuf::from("file3.md")));
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file6.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file7.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_sequence_start_keyword_and_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::KeywordAndFork;
let (check, parents) = check_sequence_start(&index, "file1.md", &cfg_ss);
assert_eq!(check, true);
assert!(parents.is_empty());
let (check, parents) = check_sequence_start(&index, "file2.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file1.md")));
let (check, parents) = check_sequence_start(&index, "file3.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file4.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file5.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 2); assert!(parents.contains(&PathBuf::from("file3.md")));
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file6.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file7.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_sequence_start_keyword_or_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::KeywordOrFork;
let (check, parents) = check_sequence_start(&index, "file1.md", &cfg_ss);
assert_eq!(check, true);
assert!(parents.is_empty());
let (check, parents) = check_sequence_start(&index, "file2.md", &cfg_ss);
assert_eq!(check, false);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file1.md")));
let (check, parents) = check_sequence_start(&index, "file3.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file4.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file2.md")));
let (check, parents) = check_sequence_start(&index, "file5.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 2); assert!(parents.contains(&PathBuf::from("file3.md")));
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file6.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file4.md")));
let (check, parents) = check_sequence_start(&index, "file7.md", &cfg_ss);
assert_eq!(check, true);
assert_eq!(parents.len(), 1);
assert!(parents.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_sequences_of_zettel_orphan_only() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::RootOnly;
let sequences = sequences_of_zettel(&index, "file7.md", &cfg_ss);
assert_eq!(sequences.len(), 1);
assert!(sequences.contains(&PathBuf::from("file1.md")));
let sequences = sequences_of_zettel(&index, "file5.md", &cfg_ss);
assert_eq!(sequences.len(), 1);
assert!(sequences.contains(&PathBuf::from("file1.md")));
}
#[test]
fn test_sequences_of_zettel_keyword() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::Keyword;
let sequences = sequences_of_zettel(&index, "file7.md", &cfg_ss);
assert_eq!(sequences.len(), 3);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
assert!(sequences.contains(&PathBuf::from("file7.md")));
let sequences = sequences_of_zettel(&index, "file5.md", &cfg_ss);
assert_eq!(sequences.len(), 3);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file3.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
}
#[test]
fn test_sequences_of_zettel_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::Fork;
let sequences = sequences_of_zettel(&index, "file7.md", &cfg_ss);
assert_eq!(sequences.len(), 3);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
assert!(sequences.contains(&PathBuf::from("file6.md")));
let sequences = sequences_of_zettel(&index, "file5.md", &cfg_ss);
assert_eq!(sequences.len(), 4);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file3.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
assert!(sequences.contains(&PathBuf::from("file5.md")));
}
#[test]
fn test_sequences_of_zettel_keyword_and_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::KeywordAndFork;
let sequences = sequences_of_zettel(&index, "file7.md", &cfg_ss);
assert_eq!(sequences.len(), 2);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
let sequences = sequences_of_zettel(&index, "file5.md", &cfg_ss);
assert_eq!(sequences.len(), 3);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file3.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
}
#[test]
fn test_sequences_of_zettel_keyword_or_fork() {
let index = sequence_test_index();
let cfg_ss = SequenceStart::KeywordOrFork;
let sequences = sequences_of_zettel(&index, "file7.md", &cfg_ss);
assert_eq!(sequences.len(), 4);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
assert!(sequences.contains(&PathBuf::from("file6.md")));
assert!(sequences.contains(&PathBuf::from("file7.md")));
let sequences = sequences_of_zettel(&index, "file5.md", &cfg_ss);
assert_eq!(sequences.len(), 4);
assert!(sequences.contains(&PathBuf::from("file1.md")));
assert!(sequences.contains(&PathBuf::from("file3.md")));
assert!(sequences.contains(&PathBuf::from("file4.md")));
assert!(sequences.contains(&PathBuf::from("file5.md")));
}
#[test]
fn test_zettels_of_sequence() {
let index = sequence_test_index();
let zettels = zettels_of_sequence(&index, "file1.md");
assert_eq!(zettels.len(), 7);
assert!(zettels.contains(&PathBuf::from("file1.md")));
assert!(zettels.contains(&PathBuf::from("file2.md")));
assert!(zettels.contains(&PathBuf::from("file3.md")));
assert!(zettels.contains(&PathBuf::from("file4.md")));
assert!(zettels.contains(&PathBuf::from("file5.md")));
assert!(zettels.contains(&PathBuf::from("file6.md")));
assert!(zettels.contains(&PathBuf::from("file7.md")));
let zettels = zettels_of_sequence(&index, "file2.md");
assert_eq!(zettels.len(), 6);
assert!(zettels.contains(&PathBuf::from("file2.md")));
assert!(zettels.contains(&PathBuf::from("file3.md")));
assert!(zettels.contains(&PathBuf::from("file4.md")));
assert!(zettels.contains(&PathBuf::from("file5.md")));
assert!(zettels.contains(&PathBuf::from("file6.md")));
assert!(zettels.contains(&PathBuf::from("file7.md")));
let zettels = zettels_of_sequence(&index, "file3.md");
assert_eq!(zettels.len(), 2);
assert!(zettels.contains(&PathBuf::from("file3.md")));
assert!(zettels.contains(&PathBuf::from("file5.md")));
let zettels = zettels_of_sequence(&index, "file4.md");
assert_eq!(zettels.len(), 4);
assert!(zettels.contains(&PathBuf::from("file4.md")));
assert!(zettels.contains(&PathBuf::from("file5.md")));
assert!(zettels.contains(&PathBuf::from("file6.md")));
assert!(zettels.contains(&PathBuf::from("file7.md")));
let zettels = zettels_of_sequence(&index, "file5.md");
assert_eq!(zettels.len(), 1);
assert!(zettels.contains(&PathBuf::from("file5.md")));
let zettels = zettels_of_sequence(&index, "file6.md");
assert_eq!(zettels.len(), 2);
assert!(zettels.contains(&PathBuf::from("file6.md")));
assert!(zettels.contains(&PathBuf::from("file7.md")));
let zettels = zettels_of_sequence(&index, "file7.md");
assert_eq!(zettels.len(), 1);
assert!(zettels.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_ancestors_of_zettel() {
let index = sequence_test_index();
let ancestors = ancestors_of_zettel(&index, "file4.md");
assert_eq!(ancestors.len(), 2);
assert!(ancestors.contains(&PathBuf::from("file1.md")));
assert!(ancestors.contains(&PathBuf::from("file2.md")));
let ancestors = ancestors_of_zettel(&index, "file5.md");
assert_eq!(ancestors.len(), 4);
assert!(ancestors.contains(&PathBuf::from("file1.md")));
assert!(ancestors.contains(&PathBuf::from("file2.md")));
assert!(ancestors.contains(&PathBuf::from("file3.md")));
assert!(ancestors.contains(&PathBuf::from("file4.md")));
let ancestors = ancestors_of_zettel(&index, "file7.md");
assert_eq!(ancestors.len(), 4);
assert!(ancestors.contains(&PathBuf::from("file1.md")));
assert!(ancestors.contains(&PathBuf::from("file2.md")));
assert!(ancestors.contains(&PathBuf::from("file4.md")));
assert!(ancestors.contains(&PathBuf::from("file6.md")));
}
#[test]
fn test_descendants_of_zettel() {
let index = sequence_test_index();
let descendants = descendants_of_zettel(&index, "file3.md");
assert_eq!(descendants.len(), 1);
assert!(descendants.contains(&PathBuf::from("file5.md")));
let descendants = descendants_of_zettel(&index, "file2.md");
assert_eq!(descendants.len(), 5);
assert!(descendants.contains(&PathBuf::from("file3.md")));
assert!(descendants.contains(&PathBuf::from("file4.md")));
assert!(descendants.contains(&PathBuf::from("file5.md")));
assert!(descendants.contains(&PathBuf::from("file6.md")));
assert!(descendants.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_ancestors_and_descendants() {
let index = sequence_test_index();
let ad = ancestors_and_descendants(&index, "file4.md");
assert_eq!(ad.len(), 5);
assert!(ad.contains(&PathBuf::from("file1.md")));
assert!(ad.contains(&PathBuf::from("file2.md")));
assert!(ad.contains(&PathBuf::from("file5.md")));
assert!(ad.contains(&PathBuf::from("file6.md")));
assert!(ad.contains(&PathBuf::from("file7.md")));
let ad = ancestors_and_descendants(&index, "file5.md");
assert_eq!(ad.len(), 4);
assert!(ad.contains(&PathBuf::from("file1.md")));
assert!(ad.contains(&PathBuf::from("file2.md")));
assert!(ad.contains(&PathBuf::from("file3.md")));
assert!(ad.contains(&PathBuf::from("file4.md")));
let ad = ancestors_and_descendants(&index, "file6.md");
assert_eq!(ad.len(), 4);
assert!(ad.contains(&PathBuf::from("file1.md")));
assert!(ad.contains(&PathBuf::from("file2.md")));
assert!(ad.contains(&PathBuf::from("file4.md")));
assert!(ad.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_sequence_tree_of_zettel() {
let index = sequence_test_index();
let stn = sequence_tree_of_zettel(&index, "file4.md");
assert_eq!(stn.len(), 6);
assert!(stn.contains(&PathBuf::from("file1.md")));
assert!(stn.contains(&PathBuf::from("file2.md")));
assert!(stn.contains(&PathBuf::from("file4.md")));
assert!(stn.contains(&PathBuf::from("file5.md")));
assert!(stn.contains(&PathBuf::from("file6.md")));
assert!(stn.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_sequence_tree() {
let index = sequence_test_index();
let mut scope = HashSet::new();
scope.insert(PathBuf::from("file4.md"));
scope.insert(PathBuf::from("file6.md"));
let stn = sequence_tree(&index, &scope);
assert_eq!(stn.len(), 6);
assert!(stn.contains(&PathBuf::from("file1.md")));
assert!(stn.contains(&PathBuf::from("file2.md")));
assert!(stn.contains(&PathBuf::from("file4.md")));
assert!(stn.contains(&PathBuf::from("file5.md")));
assert!(stn.contains(&PathBuf::from("file6.md")));
assert!(stn.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_sequence_tree_whole_of_zettel() {
let index = sequence_test_index();
let wst = sequence_tree_whole_of_zettel(&index, "file4.md");
println!("{:#?}", wst);
assert_eq!(wst.len(), 7);
assert!(wst.contains(&PathBuf::from("file1.md")));
assert!(wst.contains(&PathBuf::from("file2.md")));
assert!(wst.contains(&PathBuf::from("file3.md")));
assert!(wst.contains(&PathBuf::from("file4.md")));
assert!(wst.contains(&PathBuf::from("file5.md")));
assert!(wst.contains(&PathBuf::from("file6.md")));
assert!(wst.contains(&PathBuf::from("file7.md")));
}
#[test]
fn test_sequence_tree_whole() {
let index = sequence_test_index();
let mut scope = HashSet::new();
scope.insert(PathBuf::from("file4.md"));
scope.insert(PathBuf::from("file6.md"));
let wst = sequence_tree_whole(&index, &scope);
println!("{:#?}", wst);
assert_eq!(wst.len(), 7);
assert!(wst.contains(&PathBuf::from("file1.md")));
assert!(wst.contains(&PathBuf::from("file2.md")));
assert!(wst.contains(&PathBuf::from("file3.md")));
assert!(wst.contains(&PathBuf::from("file4.md")));
assert!(wst.contains(&PathBuf::from("file5.md")));
assert!(wst.contains(&PathBuf::from("file6.md")));
assert!(wst.contains(&PathBuf::from("file7.md")));
}
}