From 377d73355b1cebaf09dda7ec2962a6f149c7032c Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 19 Apr 2026 22:20:26 -0400 Subject: [PATCH] feat(cli): relicario list with --type/--group/--tag/--trashed filters Co-Authored-By: Claude Sonnet 4.6 --- crates/relicario-cli/src/main.rs | 49 +++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/crates/relicario-cli/src/main.rs b/crates/relicario-cli/src/main.rs index a54b7cd..f7a8bea 100644 --- a/crates/relicario-cli/src/main.rs +++ b/crates/relicario-cli/src/main.rs @@ -770,7 +770,54 @@ fn copy_to_clipboard_then_clear(secret: &zeroize::Zeroizing) -> Result<( }); Ok(()) } -fn cmd_list(_t: Option, _g: Option, _tag: Option, _trashed: bool) -> Result<()> { bail!("not yet implemented"); } +fn cmd_list( + type_filter: Option, + group_filter: Option, + tag_filter: Option, + trashed: bool, +) -> Result<()> { + use relicario_core::ItemType; + + let vault = crate::session::UnlockedVault::unlock_interactive()?; + let manifest = vault.load_manifest()?; + + let parsed_type: Option = match type_filter.as_deref() { + None => None, + Some("login") => Some(ItemType::Login), + Some("secure_note") | Some("note") => Some(ItemType::SecureNote), + Some("identity") => Some(ItemType::Identity), + Some("card") => Some(ItemType::Card), + Some("key") => Some(ItemType::Key), + Some("document") => Some(ItemType::Document), + Some("totp") => Some(ItemType::Totp), + Some(other) => anyhow::bail!("unknown type filter: {other}"), + }; + + let mut entries: Vec<_> = manifest.items.values() + .filter(|e| { + if trashed { e.trashed_at.is_some() } else { e.trashed_at.is_none() } + }) + .filter(|e| match parsed_type { + Some(t) => e.r#type == t, + None => true, + }) + .filter(|e| group_filter.as_ref().map_or(true, |g| e.group.as_deref() == Some(g.as_str()))) + .filter(|e| tag_filter.as_ref().map_or(true, |t| e.tags.iter().any(|x| x == t))) + .collect(); + entries.sort_by(|a, b| a.title.to_lowercase().cmp(&b.title.to_lowercase())); + + if entries.is_empty() { + eprintln!("(no items match)"); + return Ok(()); + } + + println!("{:<16} {:<14} {:<6} {}", "ID", "TYPE", "FAV", "TITLE"); + for e in entries { + let fav = if e.favorite { " *" } else { "" }; + println!("{:<16} {:<14} {:<6} {}", e.id.as_str(), format!("{:?}", e.r#type), fav, e.title); + } + Ok(()) +} fn cmd_edit(_query: String) -> Result<()> { bail!("not yet implemented"); } fn cmd_rm(_query: String) -> Result<()> { bail!("not yet implemented"); } fn cmd_restore(_query: String) -> Result<()> { bail!("not yet implemented"); }