summaryrefslogtreecommitdiff
path: root/melib/src/addressbook/mutt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'melib/src/addressbook/mutt.rs')
-rw-r--r--melib/src/addressbook/mutt.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/melib/src/addressbook/mutt.rs b/melib/src/addressbook/mutt.rs
new file mode 100644
index 00000000..805c3546
--- /dev/null
+++ b/melib/src/addressbook/mutt.rs
@@ -0,0 +1,106 @@
+/*
+ * meli - addressbook module
+ *
+ * Copyright 2019 Manos Pitsidianakis
+ *
+ * This file is part of meli.
+ *
+ * meli is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * meli is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with meli. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! # Mutt contact formats
+//!
+
+use super::*;
+use crate::parsec::{is_not, map_res, match_literal_anycase, prefix, Parser};
+use std::collections::VecDeque;
+
+//alias <nickname> [ <long name> ] <address>
+// From mutt doc:
+//
+// ```text
+// Since the name can consist of several whitespace-separated words, the
+// last word is considered the address, and it can be optionally enclosed
+// between angle brackets.
+// For example: alias mumon My dear pupil Mumon foobar@example.com
+// will be parsed in this way:
+//
+// alias mumon My dear pupil Mumon foobar@example.com
+// ^ ^ ^
+// nickname long name email address
+// The nickname (or alias) will be used to select a corresponding long name
+// and email address when specifying the To field of an outgoing message,
+// e.g. when using the function in the browser or index context.
+// The long name is optional, so you can specify an alias command in this
+// way:
+//
+// alias mumon foobar@example.com
+// ^ ^
+// nickname email address
+// ```
+pub fn parse_mutt_contact<'a>() -> impl Parser<'a, Card> {
+ move |input| {
+ map_res(
+ prefix(match_literal_anycase("alias "), is_not(b"\r\n")),
+ |l| {
+ let mut tokens = l.split_whitespace().collect::<VecDeque<&str>>();
+
+ let mut ret = Card::new();
+ let title = tokens.pop_front().ok_or(l)?.to_string();
+ let mut email = tokens.pop_back().ok_or(l)?.to_string();
+ if email.starts_with('<') && email.ends_with('>') {
+ email.pop();
+ email.remove(0);
+ }
+ let mut name = tokens.into_iter().fold(String::new(), |mut acc, el| {
+ acc.push_str(el);
+ acc.push(' ');
+ acc
+ });
+ name.pop();
+ if name.trim().is_empty() {
+ name = title.clone();
+ }
+ ret.set_title(title).set_email(email).set_name(name);
+ Ok::<Card, &'a str>(ret)
+ },
+ )
+ .parse(input)
+ }
+}
+
+#[test]
+fn test_mutt_contacts() {
+ let a = "alias mumon My dear pupil Mumon foobar@example.com";
+ let b = "alias mumon foobar@example.com";
+ let c = "alias <nickname> <long name> <address>";
+
+ let (other, a_card) = parse_mutt_contact().parse(a).unwrap();
+ assert!(other.is_empty());
+ assert_eq!(a_card.name(), "My dear pupil Mumon");
+ assert_eq!(a_card.title(), "mumon");
+ assert_eq!(a_card.email(), "foobar@example.com");
+
+ let (other, b_card) = parse_mutt_contact().parse(b).unwrap();
+ assert!(other.is_empty());
+ assert_eq!(b_card.name(), "mumon");
+ assert_eq!(b_card.title(), "mumon");
+ assert_eq!(b_card.email(), "foobar@example.com");
+
+ let (other, c_card) = parse_mutt_contact().parse(c).unwrap();
+ assert!(other.is_empty());
+ assert_eq!(c_card.name(), "<long name>");
+ assert_eq!(c_card.title(), "<nickname>");
+ assert_eq!(c_card.email(), "address");
+}