From ac2a5dcdd10d97f5ed9c8a8c83e1641b373dd31a Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 15 Nov 2023 12:52:23 +0200 Subject: [PATCH] melib: add display() method for Address Signed-off-by: Manos Pitsidianakis --- meli/src/mail/listing.rs | 5 ++-- melib/src/email/address.rs | 54 +++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/meli/src/mail/listing.rs b/meli/src/mail/listing.rs index 24f49dca..3775624f 100644 --- a/meli/src/mail/listing.rs +++ b/meli/src/mail/listing.rs @@ -405,14 +405,15 @@ pub struct EntryStrings { } #[macro_export] -/// Creates a comma separated list `String` out of an `Address` iterable. +/// Creates a comma separated list `String` out of an +/// [`Address`](melib::Address) iterable. macro_rules! address_list { (($name:expr) as comma_sep_list) => {{ let mut ret: String = $name .into_iter() .fold(String::new(), |mut s: String, n: &Address| { - s.extend(n.to_string().chars()); + s.extend(n.display().to_string().chars()); s.push_str(", "); s }); diff --git a/melib/src/email/address.rs b/melib/src/email/address.rs index 96b0e767..20d64715 100644 --- a/melib/src/email/address.rs +++ b/melib/src/email/address.rs @@ -306,6 +306,30 @@ impl Address { Self::Group(g) => g.display_name.display_bytes(&g.raw), } } + + /// Returns a type that prints addresses suitably for UI display, e.g. + /// without quotes. + /// + /// ## Example + /// + /// ```rust + /// # use melib::email::Address; + /// let addr = Address::new( + /// Some("Jörg T. Doe".to_string()), + /// "joerg@example.com".to_string(), + /// ); + /// assert_eq!( + /// addr.to_string().as_str(), + /// r#""Jörg T. Doe" "# + /// ); + /// assert_eq!( + /// addr.display().to_string().as_str(), + /// "Jörg T. Doe " + /// ); + /// ``` + pub fn display(&self) -> UIAddress { + UIAddress(self) + } } impl Eq for Address {} @@ -349,6 +373,7 @@ impl std::fmt::Display for Address { } d => write!(f, "{} <{}>", d, m.address_spec.display(&m.raw)), }, + Self::Mailbox(m) => write!(f, "{}", m.address_spec.display(&m.raw)), Self::Group(g) => { let attachment_strings: Vec = g.mailbox_list.iter().map(|a| format!("{}", a)).collect(); @@ -359,7 +384,6 @@ impl std::fmt::Display for Address { attachment_strings.join(", ") ) } - Self::Mailbox(m) => write!(f, "{}", m.address_spec.display(&m.raw)), } } } @@ -393,6 +417,34 @@ impl TryFrom<&str> for Address { } } +#[derive(Debug, Copy, Clone)] +#[repr(transparent)] +pub struct UIAddress<'a>(&'a Address); + +impl std::fmt::Display for UIAddress<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self.0 { + Address::Mailbox(m) if m.display_name.length > 0 => write!( + f, + "{} <{}>", + m.display_name.display(&m.raw), + m.address_spec.display(&m.raw) + ), + Address::Mailbox(m) => write!(f, "{}", m.address_spec.display(&m.raw)), + Address::Group(g) => { + let attachment_strings: Vec = + g.mailbox_list.iter().map(|a| format!("{}", a)).collect(); + write!( + f, + "{}: {}", + g.display_name.display(&g.raw), + attachment_strings.join(", ") + ) + } + } + } +} + /// Helper struct to return slices from a struct field on demand. #[derive(Clone, Debug, Serialize, Deserialize, Default, PartialEq, Eq, Copy, Hash)] pub struct StrBuilder {