use rayon::iter::{ParallelBridge, ParallelIterator};
use regex::Regex;
use crate::config::ConfigOptions;
use crate::io::*;
fn find_links(contents: &str) -> Vec<String>
{
let re = Regex::new(r#"\[\[(.*?)\]\]"#).unwrap();
re.captures_iter(contents).par_bridge()
.map(|cap| {
let title = cap.get(1).map_or("", |m| m.as_str()).to_string();
title
})
.collect()
}
fn find_tags(contents: &str) -> Vec<String>
{
let re = Regex::new(r"#([\w/_-]+?)\s+").unwrap();
re.captures_iter(contents).par_bridge()
.map(|cap| {
let tag = cap.get(1).map_or("", |m| m.as_str()).to_string();
tag
})
.collect()
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Zettel
{
pub title: String,
pub inbox: bool,
pub links: Vec<String>,
pub tags: Vec<String>,
}
impl Zettel
{
pub fn new(title: &str, inbox: bool) -> Self
{
Zettel
{
title: title.to_string(),
inbox,
links: vec![],
tags: vec![],
}
}
pub fn from_file(path: &str) -> Self
{
let title = basename(&replace_extension(path, ""));
let contents = file_to_string(path);
let mut is_inbox = false;
let pieces: Vec<_> = path.split('/').collect();
if pieces[pieces.len() - 2] == "inbox" {
is_inbox = true;
}
let mut zettel = Zettel::new(&title, is_inbox);
zettel.links = find_links(&contents);
zettel.tags = find_tags(&contents);
zettel
}
pub fn create(&self, cfg: &ConfigOptions)
{
if file_exists(&cfg.template) {
let template_contents = file_to_string(&cfg.template);
let new_zettel_contents = self.replace_template_placeholders(&template_contents);
write_to_file(&self.filename(cfg), &new_zettel_contents);
} else {
write_to_file(&self.filename(cfg), "");
}
}
pub fn filename(&self, cfg: &ConfigOptions) -> String
{
let dir;
if self.inbox {
dir = format!("{}/inbox", cfg.zettelkasten);
} else {
dir = cfg.zettelkasten.clone();
}
format!("{}/{}.md", dir, &self.title)
}
pub fn has_text(&self, cfg: &ConfigOptions, text: &str) -> bool
{
let contents = file_to_string(&self.filename(cfg));
let re = Regex::new(&format!(r"(?i){}", text)).unwrap();
re.is_match(&contents)
}
fn replace_template_placeholders(&self, contents: &str) -> String
{
let re_title = Regex::new(r"\$\{TITLE\}").unwrap();
re_title.replace_all(contents, &self.title).to_string()
}
}