#![allow(clippy::single_call_fn)]
use crate::db::Orm;
use crate::fs::File;
use crate::traits::Persister;
use super::cli::{arguments as args, subcommands as sub};
use super::{Action, Cli, Command};
use crate::config::Config;
use crate::docs;
use crate::models::{Task, Todo};
#[non_exhaustive]
pub struct Postit;
impl Postit {
#[inline]
pub fn run(cli: Cli) -> super::Result<()> {
match cli.command {
Command::Docs(args) => {
Self::docs(&args);
Ok(())
}
Command::Flag(args) => {
Self::flag(&args);
Ok(())
}
Command::Config(args) => Self::config(args),
Command::View(args) => Self::view(args),
Command::Add(args) => Self::add(args),
Command::Set(args) => Self::set(args),
Command::Check(args) => Self::edit(args, &Action::Check),
Command::Uncheck(args) => Self::edit(args, &Action::Uncheck),
Command::Drop(args) => Self::edit(args, &Action::Drop),
Command::Sample(args) => Self::sample(args),
Command::Copy(args) => Self::copy(&args),
Command::Clean(args) => Self::clean(args),
Command::Remove(args) => Self::remove(args),
}
}
#[inline]
pub fn get_persister<T>(persister: Option<T>) -> crate::Result<Box<dyn Persister>>
where
T: AsRef<str>,
{
let path_or_conn = match persister {
Some(v) => v.as_ref().to_owned(),
None => Config::load()?.persister,
};
let persister = if path_or_conn.contains("://") || Orm::is_sqlite(&path_or_conn) {
Orm::from(path_or_conn)?.boxed()
} else {
File::from(path_or_conn)?.boxed()
};
Ok(persister)
}
fn docs(args: &args::Docs) {
docs::Command::run(&args.subcommand);
}
fn flag(args: &args::Flag) {
docs::Flag::run(&args.subcommand);
}
fn view(args: args::Persister) -> super::Result<()> {
Self::get_persister(args.persister)?.view()
}
fn add(args: args::Add) -> super::Result<()> {
let persister = Self::get_persister(args.persister)?;
if !persister.exists()? {
persister.create()?;
}
let mut todo = Todo::from(persister.as_ref())?;
let id = todo.tasks.last().map_or(1, |last| last.id + 1);
let task = Task::new(id, args.content, args.priority, false);
todo.add(task);
persister.save(&todo)?;
persister.view()
}
fn set(args: args::Set) -> super::Result<()> {
let persister = Self::get_persister(args.persister)?;
if !persister.exists()? {
let msg = "The persister doesn't exist; add a task first to use this command";
return Err(super::Error::wrap(msg));
}
let mut todo = Todo::from(persister.as_ref())?;
todo.set(&args.subcommand)?;
let (ids, action) = match args.subcommand {
sub::Set::Content(args) => (args.ids, Action::SetContent),
sub::Set::Priority(args) => (args.ids, Action::SetPriority),
};
persister.edit(&todo, &ids, &action)?;
persister.view()
}
fn edit(args: args::Edit, action: &Action) -> super::Result<()> {
let persister = Self::get_persister(args.persister)?;
if !persister.exists()? {
let msg = "The persister doesn't exist; add a task first to use this command";
return Err(super::Error::wrap(msg));
}
let mut todo = Todo::from(persister.as_ref())?;
let changed_ids = match action {
Action::Check => todo.check(&args.ids),
Action::Uncheck => todo.uncheck(&args.ids),
Action::Drop => todo.drop(&args.ids),
Action::SetContent | Action::SetPriority => unreachable!(),
}?;
persister.edit(&todo, &changed_ids, action)?;
persister.view()
}
fn copy(args: &args::Copy) -> super::Result<()> {
let config = Config::load()?;
let (left_path, right_path) = match args.left.as_ref() {
"from" => (&args.right, &config.persister),
"to" => (&config.persister, &args.right),
_ => (&args.left, &args.right),
};
if left_path == right_path {
let msg = "Both persisters are the same";
return Err(super::Error::wrap(msg));
}
let left = Self::get_persister(Some(left_path))?;
if left.tasks()?.is_empty() {
let msg = format!("The persister '{}' has no tasks to copy", left.to_string());
return Err(super::Error::wrap(msg));
}
let right = Self::get_persister(Some(right_path))?;
if !right.exists()? {
right.create()?;
}
if !config.force_copy && right.tasks()? != Vec::new() {
let msg = format!(
"The persister '{}' already has tasks.\nSet 'force_copy' to 'true' to overwrite them.",
right.to_string()
);
return Err(super::Error::wrap(msg));
}
right.replace(&Todo::from(left.as_ref())?)?;
if config.drop_after_copy {
left.remove()?;
}
println!("The tasks of '{left_path}' have been copied to '{right_path}'");
right.view()
}
fn sample(args: args::Persister) -> super::Result<()> {
let persister = Self::get_persister(args.persister)?;
if !persister.exists()? {
persister.create()?;
}
persister.replace(&Todo::sample())?;
println!("Sample generated at '{}'", persister.to_string());
persister.view()
}
fn clean(args: args::Persister) -> super::Result<()> {
Self::get_persister(args.persister)?.clean()
}
fn remove(args: args::Persister) -> super::Result<()> {
Self::get_persister(args.persister)?.remove()
}
fn config(args: args::Config) -> super::Result<()> {
Config::manage(args.subcommand)?;
Ok(())
}
}