stash: consolidate confirmation prompts; install color_eyre hook

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I7fb4ba67098f897849fc9b317c7fde646a6a6964
This commit is contained in:
raf 2026-03-31 12:47:31 +03:00
commit d9bee33aba
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -1,3 +1,9 @@
mod clipboard;
mod commands;
mod db;
mod mime;
mod multicall;
use std::{ use std::{
env, env,
io::{self, IsTerminal}, io::{self, IsTerminal},
@ -6,14 +12,14 @@ use std::{
}; };
use clap::{CommandFactory, Parser, Subcommand}; use clap::{CommandFactory, Parser, Subcommand};
use color_eyre::eyre;
use humantime::parse_duration; use humantime::parse_duration;
use inquire::Confirm; use inquire::Confirm;
mod clipboard; // While the module is named "wayland", the Wayland module is *strictly* for the
mod commands; // use-toplevel feature as it requires some low-level wayland crates that are
pub(crate) mod db; // not required *by default*. The module is named that way because "toplevel"
pub(crate) mod mime; // sounded too silly. Stash is strictly a Wayland clipboard manager.
mod multicall;
#[cfg(feature = "use-toplevel")] mod wayland; #[cfg(feature = "use-toplevel")] mod wayland;
use crate::{ use crate::{
@ -189,8 +195,20 @@ fn report_error<T>(
} }
} }
fn confirm(prompt: &str) -> bool {
Confirm::new(prompt)
.with_default(false)
.prompt()
.unwrap_or_else(|e| {
log::error!("Confirmation prompt failed: {e}");
false
})
}
#[allow(clippy::too_many_lines)] // whatever #[allow(clippy::too_many_lines)] // whatever
fn main() -> color_eyre::eyre::Result<()> { fn main() -> eyre::Result<()> {
color_eyre::install()?;
// Check if we're being called as a multicall binary // Check if we're being called as a multicall binary
let program_name = env::args().next().map(|s| { let program_name = env::args().next().map(|s| {
PathBuf::from(s) PathBuf::from(s)
@ -217,12 +235,18 @@ fn main() -> color_eyre::eyre::Result<()> {
.filter_level(cli.verbosity.into()) .filter_level(cli.verbosity.into())
.init(); .init();
let db_path = cli.db_path.unwrap_or_else(|| { let db_path = match cli.db_path {
dirs::cache_dir() Some(path) => path,
.unwrap_or_else(|| PathBuf::from("/tmp")) None => {
.join("stash") let cache_dir = dirs::cache_dir().ok_or_else(|| {
.join("db") eyre::eyre!(
}); "Could not determine cache directory. Set --db-path or \
$STASH_DB_PATH explicitly."
)
})?;
cache_dir.join("stash").join("db")
},
};
if let Some(parent) = db_path.parent() { if let Some(parent) = db_path.parent() {
std::fs::create_dir_all(parent)?; std::fs::create_dir_all(parent)?;
@ -300,10 +324,7 @@ fn main() -> color_eyre::eyre::Result<()> {
let mut should_proceed = true; let mut should_proceed = true;
if ask { if ask {
should_proceed = should_proceed =
Confirm::new("Are you sure you want to delete clipboard entries?") confirm("Are you sure you want to delete clipboard entries?");
.with_default(false)
.prompt()
.unwrap_or(false);
if !should_proceed { if !should_proceed {
log::info!("aborted by user."); log::info!("aborted by user.");
@ -361,12 +382,8 @@ fn main() -> color_eyre::eyre::Result<()> {
); );
let mut should_proceed = true; let mut should_proceed = true;
if ask { if ask {
should_proceed = Confirm::new( should_proceed =
"Are you sure you want to wipe all clipboard history?", confirm("Are you sure you want to wipe all clipboard history?");
)
.with_default(false)
.prompt()
.unwrap_or(false);
if !should_proceed { if !should_proceed {
log::info!("wipe command aborted by user."); log::info!("wipe command aborted by user.");
} }
@ -386,10 +403,7 @@ fn main() -> color_eyre::eyre::Result<()> {
} else { } else {
"Are you sure you want to wipe ALL clipboard history?" "Are you sure you want to wipe ALL clipboard history?"
}; };
should_proceed = Confirm::new(message) should_proceed = confirm(message);
.with_default(false)
.prompt()
.unwrap_or(false);
if !should_proceed { if !should_proceed {
log::info!("db wipe command aborted by user."); log::info!("db wipe command aborted by user.");
} }
@ -398,7 +412,7 @@ fn main() -> color_eyre::eyre::Result<()> {
if expired { if expired {
match db.cleanup_expired() { match db.cleanup_expired() {
Ok(count) => { Ok(count) => {
log::info!("Wiped {count} expired entries"); log::info!("wiped {count} expired entries");
}, },
Err(e) => { Err(e) => {
log::error!("failed to wipe expired entries: {e}"); log::error!("failed to wipe expired entries: {e}");
@ -412,7 +426,7 @@ fn main() -> color_eyre::eyre::Result<()> {
DbAction::Vacuum => { DbAction::Vacuum => {
match db.vacuum() { match db.vacuum() {
Ok(()) => { Ok(()) => {
log::info!("Database optimized successfully"); log::info!("database optimized successfully");
}, },
Err(e) => { Err(e) => {
log::error!("failed to vacuum database: {e}"); log::error!("failed to vacuum database: {e}");
@ -435,13 +449,10 @@ fn main() -> color_eyre::eyre::Result<()> {
Some(Command::Import { r#type, ask }) => { Some(Command::Import { r#type, ask }) => {
let mut should_proceed = true; let mut should_proceed = true;
if ask { if ask {
should_proceed = Confirm::new( should_proceed = confirm(
"Are you sure you want to import clipboard data? This may \ "Are you sure you want to import clipboard data? This may \
overwrite existing entries.", overwrite existing entries.",
) );
.with_default(false)
.prompt()
.unwrap_or(false);
if !should_proceed { if !should_proceed {
log::info!("import command aborted by user."); log::info!("import command aborted by user.");
} }