use crate::core::*;
use std::collections::HashMap;
use std::fs;
use std::io::Write;
use std::path::Path;
pub fn edit(vault: &Vault, project: &String) -> Result<bool> {
let base = Path::new(&vault.tasks).join(project);
fs::create_dir_all(&base)?;
let path = base.join("tasks").with_extension("md");
let content_before = read_safe(&path);
editor::run(&path)?;
let content_after = read_safe(&path);
let saved = content_before != content_after;
if content_after == "" && path.exists() {
fs::remove_file(&path)?;
}
if content_after == "" && base.read_dir()?.count() == 0 {
fs::remove_dir_all(&base)?;
}
Ok(saved)
}
pub fn add_task(vault: &Vault, project: &String, task: &String) -> Result<()> {
let base = Path::new(&vault.tasks).join(project);
fs::create_dir_all(&base)?;
let path = base.join("tasks").with_extension("md");
if !path.exists() {
std::fs::File::create(&path)?;
}
let mut file = std::fs::OpenOptions::new().append(true).open(&path)?;
writeln!(file, "{} {}", vault.config.task_not_done_prefix, task)?;
Ok(())
}
pub fn rotate_state(vault: &Vault, project: &String, task: &String) -> Result<String> {
let base = Path::new(&vault.tasks).join(project);
let path = base.join("tasks").with_extension("md");
let mut ring: HashMap<String, String> = HashMap::new();
let not_done = vault.config.task_not_done_prefix.as_str();
let in_progress = vault.config.task_in_progress_prefix.as_str();
let done = vault.config.task_done_prefix.as_str();
ring.insert(
not_done.to_owned(),
in_progress.to_owned(),
);
ring.insert(
in_progress.to_owned(),
done.to_owned(),
);
ring.insert(
done.to_owned(),
not_done.to_owned(),
);
if path.exists() {
let content = fs::read_to_string(&path)?;
let t = task.as_str();
let new_task =
if t.starts_with(not_done) {
let new_prefix = ring.get(¬_done.to_owned()).unwrap();
let value = t.trim_start_matches(not_done).trim_start();
format!("{} {}", new_prefix, value)
} else if t.starts_with(in_progress) {
let new_prefix = ring.get(&in_progress.to_owned()).unwrap();
let value = t.trim_start_matches(in_progress).trim_start();
format!("{} {}", new_prefix, value)
} else if t.starts_with(done) {
let new_prefix = ring.get(&done.to_owned()).unwrap();
let value = t.trim_start_matches(done).trim_start();
format!("{} {}", new_prefix, value)
} else {
t.to_owned()
};
let new_content = content.as_str().replace(t, new_task.as_str());
std::fs::File::create(&path)?;
let mut file = std::fs::OpenOptions::new().append(true).open(&path)?;
write!(file, "{}", new_content)?;
return Ok(new_task);
}
Ok(task.to_owned())
}
pub fn remove(vault: &Vault, project: &String) -> Result<()> {
let base = Path::new(&vault.tasks).join(project);
let path = base.join("tasks").with_extension("md");
if path.exists() {
let question = format!("Are you sure you want to remove tasks for [{}]?", project);
match prompt_yes_no(question.as_str(), YesNo::No)? {
YesNo::Yes => {
fs::remove_file(&path)?;
if base.read_dir()?.count() == 0 {
fs::remove_dir_all(&base)?;
}
println!("Tasks for [{}] was successfully removed", project);
}
YesNo::No => println!("Nothing was removed"),
}
} else {
println!("Tasks for [{}] was not found", project);
}
Ok(())
}
pub fn remove_noprompt(vault: &Vault, project: &String, task: &String) -> Result<bool> {
let base = Path::new(&vault.tasks).join(project);
let path = base.join("tasks").with_extension("md");
if path.exists() {
let content = fs::read_to_string(&path)?;
let lines = content.as_str().lines();
let new_lines =
lines.into_iter()
.filter(|x| x.trim_start() != task.as_str())
.map(|x| x.to_owned())
.collect::<Vec<String>>();
if new_lines.len() == 0 {
fs::remove_file(&path)?;
if base.read_dir()?.count() == 0 {
fs::remove_dir_all(&base)?;
}
} else {
let mut new_content = String::from("");
for line in new_lines {
let line = format!("{}\n", line);
new_content.push_str(line.as_str());
fs::write(&path, &new_content)?;
}
}
Ok(true)
} else {
Ok(false)
}
}
pub fn list(vault: &Vault, show_tasks: bool, project: Option<String>) -> Result<()> {
let show_project = project.is_none();
for (project, tasks) in vault.list_tasks(show_tasks, &project)? {
if show_project {
println!("{}", project);
for note in tasks {
println!(" {}", note);
}
} else {
for note in tasks {
println!("{}", note);
}
}
}
Ok(())
}