feat: add initial cli implementation

This commit is contained in:
2026-02-28 12:57:19 +01:00
parent c75ba9b21f
commit 1618e00383
7 changed files with 359 additions and 12 deletions

111
src/commands.rs Normal file
View File

@@ -0,0 +1,111 @@
use anyhow::Result;
use colored::Colorize;
use crate::cli::{AddArgs, Command, DoneArgs, EditArgs, ListArgs, RemoveArgs};
use crate::db::{self, ListFilters, Pool};
use crate::display::{print_todo, print_todo_list};
pub struct Ctx<'a> {
pub pool: &'a Pool,
}
pub async fn run(cmd: Command, ctx: &Ctx<'_>) -> Result<()> {
match cmd {
Command::Add(args) => add(ctx, args).await,
Command::List(args) => list(ctx, args).await,
Command::Done(args) => done(ctx, args).await,
Command::Edit(args) => edit(ctx, args).await,
Command::Remove(args) => remove(ctx, args).await,
Command::Tags => tags(ctx).await,
Command::Purge => purge(ctx).await,
}
}
async fn add(ctx: &Ctx<'_>, args: AddArgs) -> Result<()> {
let project = if args.no_project {
None
} else {
db::detect_project()
};
let todo =
db::insert_todo(ctx.pool, &args.text, &args.priority, project.as_deref(), &args.tag)
.await?;
print!("{} ", "added:".green().bold());
print_todo(&todo);
Ok(())
}
async fn list(ctx: &Ctx<'_>, args: ListArgs) -> Result<()> {
let project = if args.here {
db::detect_project()
} else {
None
};
let todos = db::list_todos(
ctx.pool,
ListFilters {
tags: &args.tag,
priority: args.priority.as_ref(),
search: args.search.as_deref(),
project: project.as_deref(),
include_done: args.all,
},
)
.await?;
if args.json {
println!("{}", serde_json::to_string(&todos)?);
} else {
print_todo_list(&todos);
}
Ok(())
}
async fn done(ctx: &Ctx<'_>, args: DoneArgs) -> Result<()> {
let todo = db::complete_todo(ctx.pool, args.id).await?;
print!("{} ", "done:".green().bold());
print_todo(&todo);
Ok(())
}
async fn tags(ctx: &Ctx<'_>) -> Result<()> {
let tags = db::list_tags(ctx.pool).await?;
if tags.is_empty() {
println!("{}", "no tags".dimmed());
} else {
for tag in &tags {
println!(" {}", format!("#{tag}").blue());
}
}
Ok(())
}
async fn edit(ctx: &Ctx<'_>, args: EditArgs) -> Result<()> {
let todo = db::update_todo(
ctx.pool,
args.id,
args.text.as_deref(),
args.priority.as_ref(),
&args.tag,
&args.untag,
)
.await?;
print!("{} ", "edited:".green().bold());
print_todo(&todo);
Ok(())
}
async fn remove(ctx: &Ctx<'_>, args: RemoveArgs) -> Result<()> {
let todo = db::delete_todo(ctx.pool, args.id).await?;
print!("{} ", "removed:".red().bold());
print_todo(&todo);
Ok(())
}
async fn purge(ctx: &Ctx<'_>) -> Result<()> {
let count = db::purge_completed(ctx.pool).await?;
println!("{}", format!("purged {count} completed todo(s)").dimmed());
Ok(())
}