use chrono::{Local, NaiveDate};
use regex::Regex;
use std::fs;
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
pub fn remove_consecutive_spaces(file_contents: String) -> anyhow::Result<String> {
let space_re = Regex::new(r" {2,}").unwrap();
let ends_with_linebreak = file_contents.ends_with('\n');
let result = file_contents
.lines()
.map(|line| {
if line.trim_start().starts_with('-') {
let first_non_space = line.find('-').unwrap_or(0);
let (leading_spaces, rest) = line.split_at(first_non_space);
format!("{}{}", leading_spaces, space_re.replace_all(rest, " "))
} else {
line.to_string()
}
})
.collect::<Vec<_>>()
.join("\n");
let final_result = if ends_with_linebreak {
format!("{}\n", result)
} else {
result
};
Ok(final_result)
}
pub struct Journal {
graph: PathBuf,
date: NaiveDate,
}
impl Journal {
pub fn new(graph: PathBuf, date: Option<NaiveDate>) -> Self {
let final_date = date.unwrap_or_else(|| Local::now().date_naive());
Journal {
graph,
date: final_date,
}
}
pub fn as_path(&self) -> PathBuf {
let journal_file_name = format!("journals/{}.md", self.date.format("%Y_%m_%d"));
self.graph.join(journal_file_name)
}
fn _append_or_prepend(&self, markdown: String, append: bool) -> anyhow::Result<()> {
let prepend: bool = !append;
let path = self.as_path();
eprint!("Journal {}: ", path.to_string_lossy());
if markdown.is_empty() {
eprintln!("no content provided");
return Ok(());
}
let empty: bool;
let content;
if let Ok(valid_content) = fs::read_to_string(&path) {
content = valid_content.clone();
let trimmed_content = valid_content
.trim_end()
.trim_start_matches('-')
.trim_start();
empty = trimmed_content.is_empty();
if empty {
eprintln!("truncated file");
}
} else {
empty = true;
content = String::new();
eprintln!("new file");
}
let mut file: File;
if empty || prepend {
file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&path)?;
} else {
file = OpenOptions::new().append(true).open(&path)?;
eprintln!("appending");
println!(); file.write_all(b"\n")?;
}
print!("{}", markdown);
file.write_all(markdown.as_bytes())?;
if prepend && !empty {
file.write_all(b"\n")?;
file.write_all(content.as_bytes())?;
}
file.flush()?;
Ok(())
}
pub fn append(&self, markdown: String) -> anyhow::Result<()> {
self._append_or_prepend(markdown, true)
}
pub fn prepend(&self, markdown: String) -> anyhow::Result<()> {
self._append_or_prepend(markdown, false)
}
}