Files
himalaya/src/imap/flag/command/set.rs
T
2026-05-20 00:51:45 +02:00

81 lines
2.6 KiB
Rust

use anyhow::{bail, Result};
use clap::Parser;
use io_imap::{
coroutines::{select::*, store::*},
types::{
flag::{Flag, StoreType},
IntoStatic,
},
};
use io_stream::runtimes::std::handle;
use pimalaya_toolbox::terminal::printer::{Message, Printer};
use crate::{config::ImapConfig, imap::mailbox::arg::name::MailboxNameOptionalFlag, imap::stream};
/// Set flags on messages (replacing existing flags).
///
/// This command replaces all existing flags on messages identified by
/// the given sequence set with the specified flags.
#[derive(Debug, Parser)]
pub struct SetFlagsCommand {
#[command(flatten)]
pub mailbox: MailboxNameOptionalFlag,
/// The sequence set of messages (e.g., "1", "1,2,3", "1:*").
#[arg(name = "sequence_set", value_name = "SEQUENCE")]
pub sequence_set: String,
/// The flags to set (e.g., "\\Seen", "\\Flagged").
#[arg(short, long, required = true, num_args = 1..)]
pub flags: Vec<String>,
/// Use sequence numbers instead of UIDs.
#[arg(long)]
pub seq: bool,
}
impl SetFlagsCommand {
pub fn execute(self, printer: &mut impl Printer, config: ImapConfig) -> Result<()> {
let (context, mut stream) = stream::connect(config)?;
let mailbox = self.mailbox.name.try_into()?;
// First, SELECT the mailbox
let mut arg = None;
let mut coroutine = ImapSelect::new(context, mailbox);
let context = loop {
match coroutine.resume(arg.take()) {
ImapSelectResult::Io { io } => arg = Some(handle(&mut stream, io)?),
ImapSelectResult::Ok { context, .. } => break context,
ImapSelectResult::Err { err, .. } => bail!(err),
}
};
// Parse flags
let flags: Vec<Flag<'static>> = self
.flags
.iter()
.map(|f| Flag::try_from(f.as_str()).map(|flag| flag.into_static()))
.collect::<Result<_, _>>()?;
// Parse sequence set
let sequence_set = self.sequence_set.as_str().try_into()?;
// Store flags
let mut arg = None;
let mut coroutine =
ImapStoreSilent::new(context, sequence_set, StoreType::Replace, flags, !self.seq);
loop {
match coroutine.resume(arg.take()) {
ImapStoreSilentResult::Io { io } => arg = Some(handle(&mut stream, io)?),
ImapStoreSilentResult::Ok { .. } => break,
ImapStoreSilentResult::Err { err, .. } => bail!(err),
}
}
printer.out(Message::new("Flag(s) successfully set"))
}
}