From 68007a084215e3ee9a1f3e6e1dd07c9b1df84e02 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 23 Feb 2020 10:42:29 +0200 Subject: [PATCH] View decoded email source by default Toggle between decoded/raw source with view_raw_source shortcut, default M-r --- melib/src/email/parser.rs | 2 +- src/components/mail/view.rs | 79 +++++++++++++++++++++++++++++++------ src/conf/shortcuts.rs | 2 +- 3 files changed, 68 insertions(+), 15 deletions(-) diff --git a/melib/src/email/parser.rs b/melib/src/email/parser.rs index c3b980aa..c8cf707b 100644 --- a/melib/src/email/parser.rs +++ b/melib/src/email/parser.rs @@ -913,10 +913,10 @@ pub fn phrase(input: &[u8]) -> IResult<&[u8], Vec> { ptr += 1; } - ascii_e = ptr; while ptr < input.len() && (is_whitespace!(input[ptr])) { ptr += 1; } + ascii_e = ptr; if ptr >= input.len() { acc.extend( ascii_token(&input[ascii_s..ascii_e]) diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs index 1364bf17..6c699835 100644 --- a/src/components/mail/view.rs +++ b/src/components/mail/view.rs @@ -38,12 +38,18 @@ pub use self::envelope::*; use linkify::{Link, LinkFinder}; use xdg_utils::query_default_app; +#[derive(PartialEq, Copy, Clone, Debug)] +enum Source { + Decoded, + Raw, +} + #[derive(PartialEq, Debug)] enum ViewMode { Normal, Url, Attachment(usize), - Raw, + Source(Source), Ansi(RawBuffer), Subview, ContactSelector(UIDialog), @@ -228,7 +234,10 @@ impl MailView { )) .into_owned(); match self.mode { - ViewMode::Normal | ViewMode::Subview | ViewMode::ContactSelector(_) => { + ViewMode::Normal + | ViewMode::Subview + | ViewMode::ContactSelector(_) + | ViewMode::Source(Source::Decoded) => { let mut t = body_text.to_string(); t.push('\n'); if body.count_attachments() > 1 { @@ -294,7 +303,7 @@ impl MailView { } t } - ViewMode::Raw => String::from_utf8_lossy(body.body()).into_owned(), + ViewMode::Source(Source::Raw) => String::from_utf8_lossy(body.body()).into_owned(), ViewMode::Url => { let mut t = body_text.to_string(); for (lidx, l) in finder.links(&body.text()).enumerate() { @@ -376,7 +385,7 @@ impl Component for MailView { let headers = crate::conf::value(context, "mail.view.headers"); - if self.mode == ViewMode::Raw { + if let ViewMode::Source(_) = self.mode { clear_area(grid, area, self.theme_default); context.dirty_areas.push_back(area); get_y(upper_left) @@ -652,14 +661,50 @@ impl Component for MailView { self.mode = ViewMode::Subview; } ViewMode::Subview | ViewMode::ContactSelector(_) => {} - ViewMode::Raw => { + ViewMode::Source(source) => { let text = { - let account = &mut context.accounts[self.coordinates.0]; + let account = &context.accounts[self.coordinates.0]; let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2); let mut op = account.operation(envelope.hash()); - op.as_bytes() - .map(|v| String::from_utf8_lossy(v).into_owned()) - .unwrap_or_else(|e| e.to_string()) + if source == Source::Raw { + op.as_bytes() + .map(|v| String::from_utf8_lossy(v).into_owned()) + .unwrap_or_else(|e| e.to_string()) + } else { + /* Decode each header value */ + let mut ret = op + .as_bytes() + .and_then(|b| { + melib::email::parser::headers(b) + .to_full_result() + .map_err(|err| err.into()) + }) + .and_then(|headers| { + Ok(headers + .into_iter() + .map(|(h, v)| { + melib::email::parser::phrase(v) + .to_full_result() + .map(|v| { + let mut h = h.to_vec(); + h.push(b':'); + h.push(b' '); + h.extend(v.into_iter()); + h + }) + .map_err(|err| err.into()) + }) + .collect::>>>()? + .join(&b"\n"[..])) + }) + .map(|v| String::from_utf8_lossy(&v).into_owned()) + .unwrap_or_else(|e| e.to_string()); + drop(envelope); + drop(account); + ret.push_str("\n\n"); + ret.extend(self.attachment_to_text(&body, context).chars()); + ret + } }; let colors = crate::conf::value(context, "mail.view.body"); self.pager = Pager::from_string(text, Some(context), None, None, colors); @@ -860,10 +905,16 @@ impl Component for MailView { return true; } UIEvent::Input(ref key) - if (self.mode == ViewMode::Normal || self.mode == ViewMode::Subview) + if (self.mode == ViewMode::Normal + || self.mode == ViewMode::Subview + || self.mode == ViewMode::Source(Source::Decoded) + || self.mode == ViewMode::Source(Source::Raw)) && shortcut!(key == shortcuts[MailView::DESCRIPTION]["view_raw_source"]) => { - self.mode = ViewMode::Raw; + self.mode = match self.mode { + ViewMode::Source(Source::Decoded) => ViewMode::Source(Source::Raw), + _ => ViewMode::Source(Source::Decoded), + }; self.set_dirty(true); return true; } @@ -872,7 +923,8 @@ impl Component for MailView { || self.mode.is_ansi() || self.mode == ViewMode::Subview || self.mode == ViewMode::Url - || self.mode == ViewMode::Raw) + || self.mode == ViewMode::Source(Source::Decoded) + || self.mode == ViewMode::Source(Source::Raw)) && shortcut!( key == shortcuts[MailView::DESCRIPTION]["return_to_normal_view"] ) => @@ -1448,7 +1500,8 @@ impl Component for MailView { if !(self.mode.is_attachment() || self.mode.is_ansi() || self.mode == ViewMode::Subview - || self.mode == ViewMode::Raw + || self.mode == ViewMode::Source(Source::Decoded) + || self.mode == ViewMode::Source(Source::Raw) || self.mode == ViewMode::Url) { our_map.remove("return_to_normal_view"); diff --git a/src/conf/shortcuts.rs b/src/conf/shortcuts.rs index 9e4b68e6..820bfa97 100644 --- a/src/conf/shortcuts.rs +++ b/src/conf/shortcuts.rs @@ -176,7 +176,7 @@ shortcut_key_values! { "envelope-view", return_to_normal_view |> "Return to envelope if viewing raw source or attachment." |> Key::Char('r'), toggle_expand_headers |> "Expand extra headers (References and others)." |> Key::Char('h'), toggle_url_mode |> "Toggles url open mode." |> Key::Char('u'), - view_raw_source |> "View raw envelope source in a pager." |> Key::Alt('r') + view_raw_source |> "View envelope source in a pager. (toggles between raw and decoded source)" |> Key::Alt('r') } }