libzettels 0.4.1

A library intended as a backend for applications which implement Niklas Luhmann's system of a 'Zettelkasten'.
Documentation
//Copyright (c) 2020 Stefan Thesing
//
//This file is part of libzettels.
//
//libzettels is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//libzettels is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with libzettels. If not, see http://www.gnu.org/licenses/.
// --------------------------------------------------------------------------

extern crate libzettels;
extern crate tempfile;
use self::tempfile::tempdir;

use libzettels::{Config, Index, IndexingMethod};
use libzettels::examples::*;
use std::path::PathBuf;

#[test]
fn test_full_run_from_scratch_grep() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_bare_examples(dir).expect("Failed to generate examples");
    
    // Paths
    let rootdir = dir.join("examples/Zettelkasten");
    let config_dir = dir.join("examples/config");
    let indexfile = config_dir.join("index.yaml"); //doesn't exist yet. Only
                                                   //entry in Config
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    
    // Make config and index
    let mut cfg = Config::new(&rootdir, &indexfile);
    cfg.indexingmethod = IndexingMethod::Grep;
    
    // Write config to file
    cfg.to_file(&cfg_file).expect("Failed to write config");
    
    // Index our example directory
    let index = Index::new(&cfg).expect("Failed to create index");
    
    // Write index to file
    index.save(&cfg).expect("Failed to save index");
    
    // Check to see if everything is correct
    // All zettels that we expected?
    assert_eq!(index.files.len(), 7);
    // With correct filenames?
    assert!(index.files.contains_key(&PathBuf::from("file1.md")));
    assert!(index.files.contains_key(&PathBuf::from("file2.md")));
    assert!(index.files.contains_key(&PathBuf::from("file3.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file4.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file5.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/markdown-only.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/pure-yaml.yaml")));
    
    // retrieve all the zettels and check their metadata
    // File 1
    let z = index.get_zettel("file1.md").unwrap();
    assert_eq!(z.title, "File 1");
    assert_eq!(z.links.len(), 2);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file2.md")));
    assert!(z.followups.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.keywords.len(), 3);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"first".to_string()));
    assert!(z.keywords.contains(&"test".to_string()));
    
    // File 2
    let z = index.get_zettel("file2.md").unwrap();
    assert_eq!(z.title, "File 2");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"second".to_string()));
    
    // File 3
    let z = index.get_zettel("file3.md").unwrap();
    assert_eq!(z.title, "File 3");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"third".to_string()));
    
    // Markdown Only
    let z = index.get_zettel("onlies/markdown-only.md").unwrap();
    assert_eq!(z.title, "untitled");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
    
    // Markdown Only
    let z = index.get_zettel("onlies/pure-yaml.yaml").unwrap();
    assert_eq!(z.title, "Pure Yaml");
    assert_eq!(z.links.len(), 0);
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"pureyaml".to_string()));
    
    // File 4
    let z = index.get_zettel("subdir/file4.md").unwrap();
    assert_eq!(z.title, "File 4");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file1.md")));
    assert!(z.followups.contains(&PathBuf::from("subdir/file5.md")));
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"fourth".to_string()));
    
    // File 5
    let z = index.get_zettel("subdir/file5.md").unwrap();
    assert_eq!(z.title, "File 5");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
}

#[test]
fn test_full_run_from_scratch_ripgrep() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_bare_examples(dir).expect("Failed to generate examples");
    
    // Paths
    let rootdir = dir.join("examples/Zettelkasten");
    let config_dir = dir.join("examples/config");
    let indexfile = config_dir.join("index.yaml"); //doesn't exist yet. Only
                                                   //entry in Config
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    
    // Make config and index
    let mut cfg = Config::new(&rootdir, &indexfile);
    cfg.indexingmethod = IndexingMethod::RipGrep;
    
    // Write config to file
    cfg.to_file(&cfg_file).expect("Failed to write config");
    
    // Index our example directory
    let index = Index::new(&cfg).expect("Failed to create index");
    
    // Write index to file
    index.save(&cfg).expect("Failed to save index");
    
    // Check to see if everything is correct
    // All zettels that we expected?
    assert_eq!(index.files.len(), 7);
    // With correct filenames?
    assert!(index.files.contains_key(&PathBuf::from("file1.md")));
    assert!(index.files.contains_key(&PathBuf::from("file2.md")));
    assert!(index.files.contains_key(&PathBuf::from("file3.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file4.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file5.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/markdown-only.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/pure-yaml.yaml")));
    
    // retrieve all the zettels and check their metadata
    // File 1
    let z = index.get_zettel("file1.md").unwrap();
    assert_eq!(z.title, "File 1");
    assert_eq!(z.links.len(), 2);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file2.md")));
    assert!(z.followups.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.keywords.len(), 3);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"first".to_string()));
    assert!(z.keywords.contains(&"test".to_string()));
    
    // File 2
    let z = index.get_zettel("file2.md").unwrap();
    assert_eq!(z.title, "File 2");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"second".to_string()));
    
    // File 3
    let z = index.get_zettel("file3.md").unwrap();
    assert_eq!(z.title, "File 3");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"third".to_string()));
    
    // Markdown Only
    let z = index.get_zettel("onlies/markdown-only.md").unwrap();
    assert_eq!(z.title, "untitled");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
    
    // Markdown Only
    let z = index.get_zettel("onlies/pure-yaml.yaml").unwrap();
    assert_eq!(z.title, "Pure Yaml");
    assert_eq!(z.links.len(), 0);
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"pureyaml".to_string()));
    
    // File 4
    let z = index.get_zettel("subdir/file4.md").unwrap();
    assert_eq!(z.title, "File 4");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file1.md")));
    assert!(z.followups.contains(&PathBuf::from("subdir/file5.md")));
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"fourth".to_string()));
    
    // File 5
    let z = index.get_zettel("subdir/file5.md").unwrap();
    assert_eq!(z.title, "File 5");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
}

#[test]
fn test_full_run_from_scratch_native() {
    let tmp_dir = tempdir().expect("Failed to setup temp dir");
    let dir = tmp_dir.path();
    generate_bare_examples(dir).expect("Failed to generate examples");
    
    // Paths
    let rootdir = dir.join("examples/Zettelkasten");
    let config_dir = dir.join("examples/config");
    let indexfile = config_dir.join("index.yaml"); //doesn't exist yet. Only
                                                   //entry in Config
    let cfg_file = config_dir.join("libzettels.cfg.yaml");
    
    // Make config and index
    let mut cfg = Config::new(&rootdir, &indexfile);
    cfg.indexingmethod = IndexingMethod::Native;
    
    // Write config to file
    cfg.to_file(&cfg_file).expect("Failed to write config");
    
    // Index our example directory
    let index = Index::new(&cfg).expect("Failed to create index");
    
    // Write index to file
    index.save(&cfg).expect("Failed to save index");
    
    // Check to see if everything is correct
    // All zettels that we expected?
    assert_eq!(index.files.len(), 7);
    // With correct filenames?
    assert!(index.files.contains_key(&PathBuf::from("file1.md")));
    assert!(index.files.contains_key(&PathBuf::from("file2.md")));
    assert!(index.files.contains_key(&PathBuf::from("file3.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file4.md")));
    assert!(index.files.contains_key(&PathBuf::from("subdir/file5.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/markdown-only.md")));
    assert!(index.files.contains_key(&PathBuf::from("onlies/pure-yaml.yaml")));
    
    // retrieve all the zettels and check their metadata
    // File 1
    let z = index.get_zettel("file1.md").unwrap();
    assert_eq!(z.title, "File 1");
    assert_eq!(z.links.len(), 2);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file2.md")));
    assert!(z.followups.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.keywords.len(), 3);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"first".to_string()));
    assert!(z.keywords.contains(&"test".to_string()));
    
    // File 2
    let z = index.get_zettel("file2.md").unwrap();
    assert_eq!(z.title, "File 2");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file3.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"second".to_string()));
    
    // File 3
    let z = index.get_zettel("file3.md").unwrap();
    assert_eq!(z.title, "File 3");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"third".to_string()));
    
    // Markdown Only
    let z = index.get_zettel("onlies/markdown-only.md").unwrap();
    assert_eq!(z.title, "untitled");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file2.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
    
    // Markdown Only
    let z = index.get_zettel("onlies/pure-yaml.yaml").unwrap();
    assert_eq!(z.title, "Pure Yaml");
    assert_eq!(z.links.len(), 0);
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"pureyaml".to_string()));
    
    // File 4
    let z = index.get_zettel("subdir/file4.md").unwrap();
    assert_eq!(z.title, "File 4");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 2);
    assert!(z.followups.contains(&PathBuf::from("file1.md")));
    assert!(z.followups.contains(&PathBuf::from("subdir/file5.md")));
    assert_eq!(z.keywords.len(), 2);
    assert!(z.keywords.contains(&"example".to_string()));
    assert!(z.keywords.contains(&"fourth".to_string()));
    
    // File 5
    let z = index.get_zettel("subdir/file5.md").unwrap();
    assert_eq!(z.title, "File 5");
    assert_eq!(z.links.len(), 1);
    assert!(z.links.contains(&PathBuf::from("file1.md")));
    assert_eq!(z.followups.len(), 0);
    assert_eq!(z.keywords.len(), 0);
}