cli: add --expire-after flag to watch and --expired flag to list

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I833e7bfaecb5e3254d2ea16f2b880e246a6a6964
This commit is contained in:
raf 2026-01-22 15:14:16 +03:00
commit f4936e56ff
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -2,9 +2,11 @@ use std::{
env, env,
io::{self, IsTerminal}, io::{self, IsTerminal},
path::PathBuf, path::PathBuf,
time::Duration,
}; };
use clap::{CommandFactory, Parser, Subcommand}; use clap::{CommandFactory, Parser, Subcommand};
use humantime::parse_duration;
use inquire::Confirm; use inquire::Confirm;
mod commands; mod commands;
@ -71,6 +73,10 @@ enum Command {
/// Output format: "tsv" (default) or "json" /// Output format: "tsv" (default) or "json"
#[arg(long, value_parser = ["tsv", "json"])] #[arg(long, value_parser = ["tsv", "json"])]
format: Option<String>, format: Option<String>,
/// Show only expired entries (diagnostic, does not remove them)
#[arg(long)]
expired: bool,
}, },
/// Decode and output clipboard entry by id /// Decode and output clipboard entry by id
@ -111,7 +117,11 @@ enum Command {
}, },
/// Start a process to watch clipboard for changes and store automatically. /// Start a process to watch clipboard for changes and store automatically.
Watch, Watch {
/// Expire new entries after duration (e.g., "3s", "500ms", "1h30m").
#[arg(long, value_parser = parse_duration)]
expire_after: Option<Duration>,
},
} }
fn report_error<T>( fn report_error<T>(
@ -186,7 +196,33 @@ fn main() -> color_eyre::eyre::Result<()> {
"failed to store entry", "failed to store entry",
); );
}, },
Some(Command::List { format }) => { Some(Command::List { format, expired }) => {
if expired {
// Diagnostic mode: show expired entries only (does not cleanup)
match db.get_expired_entries() {
Ok(entries) => {
for (id, contents, mime) in entries {
let preview = db::preview_entry(
&contents,
mime.as_deref(),
cli.preview_width,
);
println!("{id}\t{preview}");
}
},
Err(e) => {
log::error!("failed to list expired entries: {e}");
},
}
} else {
// Normal list mode
// Cleanup expired entries when daemon is not running
if let Ok(count) = db.cleanup_expired() {
if count > 0 {
log::info!("Cleaned up {} expired entries", count);
}
}
match format.as_deref() { match format.as_deref() {
Some("tsv") => { Some("tsv") => {
report_error( report_error(
@ -221,6 +257,7 @@ fn main() -> color_eyre::eyre::Result<()> {
} }
}, },
} }
}
}, },
Some(Command::Decode { input }) => { Some(Command::Decode { input }) => {
report_error( report_error(
@ -334,7 +371,7 @@ fn main() -> color_eyre::eyre::Result<()> {
} }
} }
}, },
Some(Command::Watch) => { Some(Command::Watch { expire_after }) => {
db.watch( db.watch(
cli.max_dedupe_search, cli.max_dedupe_search,
cli.max_items, cli.max_items,
@ -342,6 +379,7 @@ fn main() -> color_eyre::eyre::Result<()> {
&cli.excluded_apps, &cli.excluded_apps,
#[cfg(not(feature = "use-toplevel"))] #[cfg(not(feature = "use-toplevel"))]
&[], &[],
expire_after,
); );
}, },