use std::path::PathBuf; use clap::{value_parser, Parser, Subcommand}; use crate::error::Error; #[derive(Debug, Clone, PartialEq, Eq)] pub enum SortKey { Date, Sender, Subject, Size, } #[derive(PartialEq, Eq, Clone)] pub enum SortOrder { Ascending, Descending, } #[derive(PartialEq, Eq, Clone)] pub struct SortInfo { pub key: SortKey, pub order: SortOrder, } impl std::str::FromStr for SortInfo { type Err = Error; fn from_str(mut value: &str) -> Result { if value == "" { return Ok(SortInfo { key: SortKey::Date, order: SortOrder::Ascending, }); } let order = if value.starts_with('!') { value = &value[1..]; SortOrder::Descending } else { SortOrder::Ascending }; let key = match value.to_ascii_lowercase().as_str() { "date" => SortKey::Date, "sender" => SortKey::Sender, "subject" => SortKey::Subject, "size" => SortKey::Size, v => return Err(Error::SortOrder(format!("invalid sort order {:}", v))), }; Ok(SortInfo { key, order }) } } impl std::fmt::Debug for SortInfo { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { write!( f, "{}{:?}", match self.order { SortOrder::Descending => "!", SortOrder::Ascending => "", }, self.key ) } } #[derive(Subcommand)] pub enum Mode { List { subfolder: String, start: usize, end: usize, #[arg(value_parser = value_parser!(SortInfo))] sortby: SortInfo, }, Search { pattern: String, subfolder: String, }, Count { subfolder: String, }, Read { subfolder: String, mid: String, }, Raw { subfolder: String, mid: String, mime_path: String, }, Folders, Move { mid: String, from: String, to: String, }, } #[derive(Parser)] #[command(author, version, about, long_about = None)] pub struct Arguments { pub maildir_path: PathBuf, pub sys_user: String, pub mail_user: String, #[command(subcommand)] pub mode: Mode, } #[cfg(test)] mod tests { use super::*; #[test] fn sort_info() { assert_eq!( "!date".parse::().unwrap(), SortInfo { key: SortKey::Date, order: SortOrder::Descending } ); } }