diff --git a/Cargo.lock b/Cargo.lock index 8ee11e505..08d59a401 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "arc-swap" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b585a98a234c46fc563103e9278c9391fde1f4e6850334da895d27edb9580f62" +checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" [[package]] name = "arrayref" @@ -80,9 +80,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bumpalo" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "byteorder" @@ -453,7 +453,7 @@ dependencies = [ "futures-core", "futures-io", "futures-task", - "memchr 2.3.3", + "memchr", "pin-project", "pin-utils", "slab", @@ -527,9 +527,9 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "hyper" -version = "0.13.5" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96816e1d921eca64d208a85aab4f7798455a8e34229ee5a88c935bdee1b78b14" +checksum = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" dependencies = [ "bytes", "futures-channel", @@ -541,8 +541,8 @@ dependencies = [ "httparse", "itoa", "log", - "net2", "pin-project", + "socket2", "time", "tokio", "tower-service", @@ -575,18 +575,18 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" dependencies = [ "autocfg", ] [[package]] name = "inotify" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" dependencies = [ "bitflags", "inotify-sys", @@ -707,7 +707,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03951527dd24d2c59f407502e7d88e0948ef06fac23335b556a4c2bc03c22096" dependencies = [ - "memchr 2.3.3", + "memchr", ] [[package]] @@ -772,7 +772,6 @@ dependencies = [ "linkify", "melib", "nix", - "nom 3.2.1", "notify", "notify-rust", "pcre2", @@ -807,7 +806,7 @@ dependencies = [ "memmap", "native-tls", "nix", - "nom 5.1.1", + "nom", "notify", "notify-rust", "reqwest", @@ -822,15 +821,6 @@ dependencies = [ "xdg", ] -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -dependencies = [ - "libc", -] - [[package]] name = "memchr" version = "2.3.3" @@ -965,15 +955,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -[[package]] -name = "nom" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" -dependencies = [ - "memchr 1.0.2", -] - [[package]] name = "nom" version = "5.1.1" @@ -981,7 +962,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6" dependencies = [ "lexical-core", - "memchr 2.3.3", + "memchr", "version_check", ] @@ -1105,9 +1086,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.57" +version = "0.9.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7410fef80af8ac071d4f63755c0ab89ac3df0fd1ea91f1d1f37cf5cec4395990" +checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" dependencies = [ "autocfg", "cc", @@ -1147,18 +1128,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791" +checksum = "e75373ff9037d112bb19bc61333a06a159eaeb217660dcfbea7d88e1db823919" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40" +checksum = "10b4b44893d3c370407a1d6a5cfde7c41ae0478e31c516c85f67eb3adc51be6d" dependencies = [ "proc-macro2", "quote", @@ -1167,9 +1148,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7505eeebd78492e0f6108f7171c4948dbb120ee8119d9d77d0afa5469bef67f" +checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" [[package]] name = "pin-utils" @@ -1191,9 +1172,9 @@ checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" [[package]] name = "proc-macro2" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" +checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" dependencies = [ "unicode-xid", ] @@ -1285,9 +1266,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be79e8610ce0c2d646aa03bff67653f76d394c4e0a5e7bc255007008fcc6ba8" +checksum = "3b82c9238b305f26f53443e3a4bc8528d64b8d0bee408ec949eb7bf5635ec680" dependencies = [ "base64 0.12.1", "bytes", @@ -1362,7 +1343,7 @@ dependencies = [ "fallible-streaming-iterator", "libsqlite3-sys", "lru-cache", - "memchr 2.3.3", + "memchr", "time", ] @@ -1389,9 +1370,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "same-file" @@ -1458,9 +1439,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" +checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" dependencies = [ "serde_derive", ] @@ -1476,9 +1457,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" dependencies = [ "proc-macro2", "quote", @@ -1543,6 +1524,18 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", +] + [[package]] name = "static_assertions" version = "0.3.4" @@ -1551,9 +1544,9 @@ checksum = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" [[package]] name = "syn" -version = "1.0.27" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef781e621ee763a2a40721a8861ec519cb76966aee03bb5d00adb6a31dc1c1de" +checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2" dependencies = [ "proc-macro2", "quote", @@ -1623,7 +1616,7 @@ dependencies = [ "futures-core", "iovec", "lazy_static", - "memchr 2.3.3", + "memchr", "mio", "num_cpus", "pin-project-lite", @@ -1737,9 +1730,9 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +checksum = "55d1e41d56121e07f1e223db0a4def204e45c85425f6a16d462fd07c8d10d74c" [[package]] name = "version_check" diff --git a/Cargo.toml b/Cargo.toml index a7cec1e1c..33da999e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ serde_json = "1.0" toml = "0.5.3" linkify = "0.4.0" xdg-utils = "0.3.0" -nom = "3.2.0" notify = "4.0.1" # >:c notify-rust = "^3" # >:c termion = "1.5.1" diff --git a/src/bin.rs b/src/bin.rs index a3bce4c85..c69949f22 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -37,14 +37,10 @@ extern crate serde_derive; extern crate linkify; extern crate uuid; -extern crate termion; - -#[macro_use] -extern crate nom; - extern crate bitflags; extern crate serde_json; extern crate smallvec; +extern crate termion; #[global_allocator] static GLOBAL: System = System; diff --git a/src/components/utilities.rs b/src/components/utilities.rs index ef3de95fa..aff984a61 100644 --- a/src/components/utilities.rs +++ b/src/components/utilities.rs @@ -238,7 +238,7 @@ impl Component for VSplit { } fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { - (self.left.process_event(event, context) || self.right.process_event(event, context)) + self.left.process_event(event, context) || self.right.process_event(event, context) } fn is_dirty(&self) -> bool { @@ -566,10 +566,9 @@ impl Component for Pager { Pager::print_string(&mut content, &lines, self.colors); #[cfg(feature = "regexp")] { - for text_formatter in crate::conf::text_format_regexps( - context, - "pager.envelope.body" - ) { + for text_formatter in + crate::conf::text_format_regexps(context, "pager.envelope.body") + { let t = content.insert_tag(text_formatter.tag); for (i, l) in lines.iter().enumerate() { for _match in text_formatter.regexp.0.find_iter(l.as_bytes()) { @@ -1247,9 +1246,7 @@ impl Component for StatusBar { .replies .push_back(UIEvent::Command(self.ex_buffer.as_str().to_string())); } - if parse_command(&self.ex_buffer.as_str().as_bytes()) - .to_full_result() - .is_ok() + if parse_command(&self.ex_buffer.as_str().as_bytes()).is_ok() && self.cmd_history.last().map(String::as_str) != Some(self.ex_buffer.as_str()) { diff --git a/src/execute.rs b/src/execute.rs index b167a53a9..32b928e83 100644 --- a/src/execute.rs +++ b/src/execute.rs @@ -21,8 +21,19 @@ /*! A parser module for user commands passed through the Execute mode. */ +use crate::melib::parser::BytesExt; +use melib::nom::{ + self, + branch::alt, + bytes::complete::{is_a, is_not, tag, take_until}, + character::complete::{digit1, not_line_ending}, + combinator::{map, map_res}, + multi::separated_list, + sequence::{pair, preceded, separated_pair}, + IResult, +}; pub use melib::thread::{SortField, SortOrder}; -use nom::{digit, not_line_ending, IResult}; +use melib::MeliError; use std; pub mod actions; use actions::MailboxOperation; @@ -62,22 +73,22 @@ macro_rules! define_commands { pub fn quoted_argument(input: &[u8]) -> IResult<&[u8], &str> { if input.is_empty() { - return IResult::Error(nom::ErrorKind::Custom(0)); + return Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))); } if input[0] == b'"' { let mut i = 1; while i < input.len() { if input[i] == b'\"' && input[i - 1] != b'\\' { - return IResult::Done(&input[i + 1..], unsafe { + return Ok((&input[i + 1..], unsafe { std::str::from_utf8_unchecked(&input[1..i]) - }); + })); } i += 1; } - return IResult::Error(nom::ErrorKind::Custom(0)); + Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))) } else { - return map_res!(input, is_not!(" "), std::str::from_utf8); + map_res(is_not(" "), std::str::from_utf8)(input) } } @@ -212,143 +223,143 @@ pub enum Token { IndexValue, } +fn eof(input: &[u8]) -> IResult<&[u8], ()> { + if input.is_empty() { + Ok((input, ())) + } else { + Err(nom::Err::Error((input, nom::error::ErrorKind::Tag))) + } +} + define_commands!([ { tags: ["set"], desc: "set [seen/unseen], toggles message's Seen flag.", tokens: &[One(Literal("set")), One(Alternatives(&[to_stream!(One(Literal("seen"))), to_stream!(One(Literal("unseen")))]))], parser: - ( named!( - envelope_action, - alt_complete!( - preceded!( - ws!(tag!("set")), - alt_complete!( - map!(ws!(tag!("seen")), |_| Listing(SetSeen)) - | map!(ws!(tag!("unseen")), |_| Listing(SetUnseen)) - ) - ) | map!(preceded!(tag!("delete"), eof!()), |_| Listing(Delete)) - | do_parse!(tag!("copyto") - >> is_a!(" ") - >> path: quoted_argument - >> ({ Listing(CopyTo(path.to_string())) })) - ) - ); ) + (fn envelope_action<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> { + alt(( + preceded( + tag("set"), + alt(( + map(tag("seen"), |_| Listing(SetSeen)) + , map(tag("unseen"), |_| Listing(SetUnseen)) + )) + ) , map(preceded(tag("delete"), eof), |_| Listing(Delete)) + , |input: &'a [u8]| -> IResult<&'a [u8], Action> { + let (input, _) = tag("copyto")(input.trim())?; + let (input, _) = is_a(" ")(input)?; + let (input,path) = quoted_argument(input)?; + Ok( (input, { Listing(CopyTo(path.to_string())) })) } + ))(input) + }) }, { tags: ["close"], desc: "close non-sticky tabs", tokens: &[One(Literal("close"))], parser: ( - named!(close, map!(ws!(tag!("close")), |_| Tab(Close))); + fn close(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("close"), |_| Tab(Close))(input.trim()) + } ) }, { tags: ["go"], desc: "go [n], switch to nth mailbox in this account", tokens: &[One(Literal("goto")), One(IndexValue)], parser: ( - named!( - goto, - preceded!(tag!("go "), map!(call!(usize_c), Action::ViewMailbox)) - ); + fn goto(input: &[u8]) -> IResult<&[u8], Action> { + preceded(tag("go "), map(usize_c, Action::ViewMailbox))(input) + } ) }, { tags: ["subsort"], desc: "subsort [date/subject] [asc/desc], sorts first level replies in threads.", tokens: &[One(Literal("subsort")), One(Alternatives(&[to_stream!(One(Literal("date"))), to_stream!(One(Literal("subject")))])), One(Alternatives(&[to_stream!(One(Literal("asc"))), to_stream!(One(Literal("desc")))])) ], parser: ( - named!( - subsort, - do_parse!(tag!("subsort ") >> p: pair!(sortfield, sortorder) >> (SubSort(p.0, p.1))) - ); + fn subsort(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("subsort ")(input)?; + let (input, p)=pair(sortfield, sortorder)(input)?; + Ok((input, SubSort(p.0, p.1))) + } ) }, { tags: ["sort"], desc: "sort [date/subject] [asc/desc], sorts threads.", tokens: &[One(Literal("sort")), One(Alternatives(&[to_stream!(One(Literal("date"))), to_stream!(One(Literal("subject")))])), One(Alternatives(&[to_stream!(One(Literal("asc"))), to_stream!(One(Literal("desc")))])) ], parser: ( - named!( - sort, - do_parse!( - tag!("sort ") >> p: separated_pair!(sortfield, tag!(" "), sortorder) >> (Sort(p.0, p.1)) - ) - ); - ) - }, + fn sort(input: &[u8]) -> IResult<&[u8], Action> { + let (input,_) = tag("sort ")(input)?; + let (input, p)= separated_pair(sortfield, tag(" "), sortorder)(input)?; + Ok((input, (Sort(p.0, p.1)))) + } + )}, { tags: ["set", "set plain", "set threaded", "set compact"], desc: "set [plain/threaded/compact/conversations], changes the mail listing view", tokens: &[One(Literal("set")), One(Alternatives(&[to_stream!(One(Literal("plain"))), to_stream!(One(Literal("threaded"))), to_stream!(One(Literal("compact"))), to_stream!(One(Literal("conversations")))]))], parser: ( - named!( - toggle, - preceded!(tag!("set "), alt_complete!(threaded | plain | compact | conversations)) - ); + fn toggle(input: &[u8]) -> IResult<&[u8], Action> { + preceded(tag("set "), alt((threaded , plain , compact , conversations)))(input) + } ) }, { tags: ["toggle_thread_snooze"], desc: "turn off new notifications for this thread", tokens: &[One(Literal("toggle_thread_snooze"))], parser: ( - named!(toggle_thread_snooze, - map!(ws!(tag!("toggle_thread_snooze")), |_| ToggleThreadSnooze) - ); + fn toggle_thread_snooze(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("toggle_thread_snooze"), |_| ToggleThreadSnooze)(input.trim()) + } ) }, { tags: ["search"], desc: "search , searches list with given term", tokens: &[One(Literal("search")), One(RestOfStringValue)], parser:( - named!(search, - do_parse!( - ws!(tag!("search")) - >> string: map_res!(call!(not_line_ending), std::str::from_utf8) - >> (Listing(Search(String::from(string)))) - ) - ); + fn search(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("search")(input.trim())?; + let (input, string) = map_res(not_line_ending, std::str::from_utf8)(input)?; + Ok((input, Listing(Search(String::from(string))))) + } ) }, { tags: ["list-archive", "list-post", "list-unsubscribe", "list-"], desc: "list-[unsubscribe/post/archive]", tokens: &[One(Alternatives(&[to_stream!(One(Literal("list-archive"))), to_stream!(One(Literal("list-post"))), to_stream!(One(Literal("list-unsubscribe")))]))], parser: ( - named!( - mailinglist, - alt_complete!( - map!(ws!(tag!("list-post")), |_| MailingListAction(ListPost)) - | map!(ws!(tag!("list-unsubscribe")), |_| MailingListAction( + fn mailinglist(input: &[u8]) -> IResult<&[u8], Action> { + alt(( + map(tag("list-post"), |_| MailingListAction(ListPost)) + , map(tag("list-unsubscribe"), |_| MailingListAction( ListUnsubscribe )) - | map!(ws!(tag!("list-archive")), |_| MailingListAction( + , map(tag("list-archive"), |_| MailingListAction( ListArchive )) - ) - ); + ))(input.trim()) + } ) }, { tags: ["setenv "], desc: "setenv VAR=VALUE", tokens: &[One(Literal("setenv")), OneOrMore(Seq(&[One(AlphanumericStringValue), One(Literal("=")), One(QuotedStringValue)]))], parser: ( - named!( setenv, - do_parse!( - ws!(tag!("setenv")) - >> key: map_res!(take_until1!("="), std::str::from_utf8) - >> ws!(tag!("=")) - >> val: map_res!(call!(not_line_ending), std::str::from_utf8) - >> (SetEnv(key.to_string(), val.to_string())) - ) - ); + fn setenv(input: &[u8]) -> IResult<&[u8], Action> { + let (input,_ ) = tag("setenv")(input.trim())?; + let (input, key) = map_res(take_until("="), std::str::from_utf8)(input)?; + let (input, _) = tag("=")(input.trim())?; + let (input, val)= map_res(not_line_ending, std::str::from_utf8)(input)?; + Ok((input, SetEnv(key.to_string(), val.to_string()))) + } ) }, { tags: ["printenv "], desc: "printenv VAR", tokens: &[], parser:( - named!( printenv, - do_parse!( - ws!(tag!("env")) - >> key: map_res!(call!(not_line_ending), std::str::from_utf8) - >> (PrintEnv(key.to_string())) - ) - ); + fn printenv(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("env")(input.ltrim())?; + let (input, key) = map_res(not_line_ending, std::str::from_utf8)(input.trim())?; + Ok((input, PrintEnv(key.to_string()))) + } ) }, /* Pipe pager contents to binary */ @@ -356,270 +367,276 @@ define_commands!([ desc: "pipe EXECUTABLE ARGS", tokens: &[One(Literal("pipe")), One(Filepath), ZeroOrMore(QuotedStringValue)], parser:( - named!( pipe, - alt_complete!( - do_parse!( - ws!(tag!("pipe")) - >> bin: quoted_argument - >> is_a!(" ") - >> args: separated_list!(is_a!(" "), quoted_argument) - >> ({ - View(Pipe(bin.to_string(), args.into_iter().map(String::from).collect::>())) - })) | do_parse!( - ws!(tag!("pipe")) - >> bin: ws!(quoted_argument) - >> ({ + fn pipe<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> { + alt(( + |input: &'a [u8]| -> IResult<&'a [u8], Action> { + let (input, _ ) = tag("pipe")(input.trim())?; + let (input, bin) = quoted_argument(input)?; + let (input, _)= is_a(" ")(input)?; + let(input, args)= separated_list(is_a(" "), quoted_argument)(input)?; + Ok( (input, { + View(Pipe(bin.to_string(), args.into_iter().map(String::from).collect::>())) + })) + }, + |input: &'a [u8]| -> IResult<&'a [u8], Action> { + let (input, _) = tag("pipe")(input.trim())?; + let (input, bin) = quoted_argument(input.trim())?; + Ok( (input, { View(Pipe(bin.to_string(), Vec::new())) - }) - )) - ); + })) + } + ))(input) + } ) }, { tags: ["add-attachment "], desc: "add-attachment PATH", tokens: &[One(Literal("add-attachment")), One(Filepath)], parser:( - named!( add_attachment, - alt_complete!( - do_parse!( - ws!(tag!("add-attachment")) - >> ws!(tag!("<")) - >> cmd: quoted_argument - >> (Compose(AddAttachmentPipe(cmd.to_string())))) - | do_parse!( - ws!(tag!("add-attachment")) - >> path: quoted_argument - >> (Compose(AddAttachment(path.to_string())))) - ) - ); + fn add_attachment<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> { + alt(( + |input: &'a [u8]| -> IResult<&'a [u8], Action>{ + let (input,_) = tag("add-attachment")(input.trim())?; + let (input, _) = tag("<")(input.trim())?; + let (input, cmd) = quoted_argument(input)?; + Ok( (input, Compose(AddAttachmentPipe(cmd.to_string()))))} + , |input: &'a [u8]| -> IResult<&'a [u8], Action>{ + let (input,_) = tag("add-attachment")(input.trim())?; + let (input, path) = quoted_argument(input)?; + Ok( (input, Compose(AddAttachment(path.to_string()))))} + ))(input) + } ) }, { tags: ["remove-attachment "], desc: "remove-attachment INDEX", tokens: &[One(Literal("remove-attachment")), One(IndexValue)], parser:( - named!( remove_attachment, - do_parse!( - ws!(tag!("remove-attachment")) - >> idx: map_res!(quoted_argument, usize::from_str) - >> (Compose(RemoveAttachment(idx))) - ) - ); + fn remove_attachment(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("remove-attachment")(input.trim())?; + let (input, idx) = map_res(quoted_argument, usize::from_str)(input)?; + Ok( (input, Compose(RemoveAttachment(idx)))) + } ) }, { tags: ["toggle sign "], desc: "switch between sign/unsign for this draft", tokens: &[One(Literal("toggle")), One(Literal("sign"))], parser:( - named!( toggle_sign, - do_parse!( - ws!(tag!("toggle sign")) - >> (Compose(ToggleSign)) - ) - ); + fn toggle_sign(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("toggle sign")(input.trim())?; + Ok((input, Compose(ToggleSign))) + } ) }, { tags: ["create-mailbox "], desc: "create-mailbox ACCOUNT MAILBOX_PATH", tokens: &[One(Literal("create-mailbox")), One(AccountName), One(MailboxPath)], parser:( - named!( create_mailbox, - do_parse!( - ws!(tag!("create-mailbox")) - >> account: quoted_argument - >> is_a!(" ") - >> path: quoted_argument - >> (Mailbox(account.to_string(), MailboxOperation::Create(path.to_string()))) - ) - ); + fn create_mailbox(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("create-mailbox")(input.trim())?; + let (input, account) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, path) = quoted_argument(input)?; + Ok( (input,Mailbox(account.to_string(), MailboxOperation::Create(path.to_string())))) + } ) }, { tags: ["subscribe-mailbox "], desc: "subscribe-mailbox ACCOUNT MAILBOX_PATH", tokens: &[One(Literal("subscribe-mailbox")), One(AccountName), One(MailboxPath)], parser:( - named!( sub_mailbox, - do_parse!( - ws!(tag!("subscribe-mailbox")) - >> account: quoted_argument - >> is_a!(" ") - >> path: quoted_argument - >> (Mailbox(account.to_string(), MailboxOperation::Subscribe(path.to_string()))) - ) - ); + fn sub_mailbox(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("subscribe-mailbox")(input.trim())?; + let (input, account) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, path) = quoted_argument(input)?; + Ok((input,Mailbox(account.to_string(), MailboxOperation::Subscribe(path.to_string())))) + } ) }, { tags: ["unsubscribe-mailbox "], desc: "unsubscribe-mailbox ACCOUNT MAILBOX_PATH", tokens: &[One(Literal("unsubscribe-mailbox")), One(AccountName), One(MailboxPath)], parser:( - named!( unsub_mailbox, - do_parse!( - ws!(tag!("unsubscribe-mailbox")) - >> account: quoted_argument - >> is_a!(" ") - >> path: quoted_argument - >> (Mailbox(account.to_string(), MailboxOperation::Unsubscribe(path.to_string()))) - ) - ); + fn unsub_mailbox(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("unsubscribe-mailbox")(input.trim())?; + let (input, account) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, path) = quoted_argument(input)?; + Ok((input, Mailbox(account.to_string(), MailboxOperation::Unsubscribe(path.to_string())))) + } ) }, { tags: ["rename-mailbox "], desc: "rename-mailbox ACCOUNT MAILBOX_PATH_SRC MAILBOX_PATH_DEST", tokens: &[One(Literal("rename-mailbox")), One(AccountName), One(MailboxPath), One(MailboxPath)], parser:( - named!( rename_mailbox, - do_parse!( - ws!(tag!("rename-mailbox")) - >> account: quoted_argument - >> is_a!(" ") - >> src: quoted_argument - >> is_a!(" ") - >> dest: quoted_argument - >> (Mailbox(account.to_string(), MailboxOperation::Rename(src.to_string(), dest.to_string()))) - ) - ); + fn rename_mailbox(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("rename-mailbox")(input.trim())?; + let (input, account) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, src) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, dest) = quoted_argument(input)?; + Ok((input, Mailbox(account.to_string(), MailboxOperation::Rename(src.to_string(), dest.to_string())))) + } ) }, { tags: ["delete-mailbox "], desc: "delete-mailbox ACCOUNT MAILBOX_PATH", tokens: &[One(Literal("delete-mailbox")), One(AccountName), One(MailboxPath)], parser:( - named!( delete_mailbox, - do_parse!( - ws!(tag!("delete-mailbox")) - >> account: quoted_argument - >> is_a!(" ") - >> path: quoted_argument - >> (Mailbox(account.to_string(), MailboxOperation::Delete(path.to_string()))) - ) - ); + fn delete_mailbox(input: &[u8]) -> IResult<&[u8], Action> { + let(input, _) = tag("delete-mailbox")(input.trim())?; + let (input, account) = quoted_argument(input)?; + let (input, _) = is_a(" ")(input)?; + let (input, path) = quoted_argument(input)?; + Ok ((input, Mailbox(account.to_string(), MailboxOperation::Delete(path.to_string())))) + } ) }, { tags: ["reindex "], desc: "reindex ACCOUNT, rebuild account cache in the background", tokens: &[One(Literal("reindex")), One(AccountName)], parser:( - named!( reindex, - do_parse!( - ws!(tag!("reindex")) - >> account: quoted_argument - >> (AccountAction(account.to_string(), ReIndex)) - ) - ); + fn reindex(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("reindex")(input.trim())?; + let (input, account) = quoted_argument(input)?; + Ok( (input, AccountAction(account.to_string(), ReIndex))) + } ) }, { tags: ["open-in-tab"], desc: "opens envelope view in new tab", tokens: &[One(Literal("open-in-tab"))], parser:( - named!( open_in_new_tab, - do_parse!( - ws!(tag!("open-in-tab")) - >> (Listing(OpenInNewTab)) - ) - ); + fn open_in_new_tab(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("open-in-tab")(input.trim())?; + Ok((input, Listing(OpenInNewTab))) + } ) }, { tags: ["save-attachment "], desc: "save-attachment INDEX PATH", tokens: &[One(Literal("save-attachment")), One(IndexValue), One(Filepath)], parser:( - named!( save_attachment, - do_parse!( - ws!(tag!("save-attachment")) - >> idx: map_res!(quoted_argument, usize::from_str) - >> path: ws!(quoted_argument) - >> (View(SaveAttachment(idx, path.to_string()))) - ) - ); + fn save_attachment(input: &[u8]) -> IResult<&[u8], Action> { + let (input, _) = tag("save-attachment")(input.trim())?; + let (input, idx) = map_res(quoted_argument, usize::from_str)(input)?; + let (input, path) = quoted_argument(input.trim())?; + Ok((input, View(SaveAttachment(idx, path.to_string())))) + } ) }, { tags: ["tag", "tag add", "tag remove"], desc: "tag [add/remove], edits message's tags.", tokens: &[One(Literal("tag")), One(Alternatives(&[to_stream!(One(Literal("add"))), to_stream!(One(Literal("remove")))]))], parser: - ( named!( - tag, - preceded!( - ws!(tag!("tag")), - alt_complete!( - do_parse!( - ws!(tag!("add")) - >> tag: ws!(quoted_argument) - >> (Listing(Tag(Add(tag.to_string()))))) - | do_parse!( - ws!(tag!("remove")) - >> tag: ws!(quoted_argument) - >> (Listing(Tag(Remove(tag.to_string()))))) + ( fn _tag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> { + preceded( + tag("tag"), + alt(( + |input: &'a [u8]| -> IResult<&'a [u8], Action> { + let (input, _) = tag("add")(input.trim())?; + let (input, tag) = quoted_argument(input.trim())?; + Ok( (input, Listing(Tag(Add(tag.to_string()))))) + } + , + |input: &'a [u8]| -> IResult<&'a [u8], Action> { + let (input, _) = tag("remove")(input.trim())?; + let (input, tag) = quoted_argument(input.trim())?; + Ok( (input, Listing(Tag(Remove(tag.to_string()))))) + } - ) - ) - ); ) + )) + )(input.trim()) + }) } ]); -named!( - usize_c, - map_res!( - map_res!(ws!(digit), std::str::from_utf8), - std::str::FromStr::from_str - ) -); +fn usize_c(input: &[u8]) -> IResult<&[u8], usize> { + map_res( + map_res(digit1, std::str::from_utf8), + std::str::FromStr::from_str, + )(input.trim()) +} -named!( - sortfield, - map_res!( - map_res!(take_until_s!(" "), std::str::from_utf8), - std::str::FromStr::from_str - ) -); +fn sortfield(input: &[u8]) -> IResult<&[u8], SortField> { + map_res( + map_res(take_until(" "), std::str::from_utf8), + std::str::FromStr::from_str, + )(input.trim()) +} -named!( - sortorder, - map_res!( - map_res!(call!(not_line_ending), std::str::from_utf8), - std::str::FromStr::from_str - ) -); +fn sortorder(input: &[u8]) -> IResult<&[u8], SortOrder> { + map_res( + map_res(not_line_ending, std::str::from_utf8), + std::str::FromStr::from_str, + )(input) +} -named!( - threaded, - map!(ws!(tag!("threaded")), |_| Listing(SetThreaded)) -); +fn threaded(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("threaded"), |_| Listing(SetThreaded))(input.trim()) +} -named!( - plain, - map!(ws!(tag!("plain")), |_| Listing(SetPlain)) -); +fn plain(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("plain"), |_| Listing(SetPlain))(input.trim()) +} -named!( - compact, - map!(ws!(tag!("compact")), |_| Listing(SetCompact)) -); +fn compact(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("compact"), |_| Listing(SetCompact))(input.trim()) +} -named!( - conversations, - map!(ws!(tag!("conversations")), |_| Listing(SetConversations)) -); +fn conversations(input: &[u8]) -> IResult<&[u8], Action> { + map(tag("conversations"), |_| Listing(SetConversations))(input.trim()) +} -named!( - listing_action, - alt_complete!(toggle | envelope_action | search | toggle_thread_snooze | open_in_new_tab | tag) -); +fn listing_action(input: &[u8]) -> IResult<&[u8], Action> { + alt(( + toggle, + envelope_action, + search, + toggle_thread_snooze, + open_in_new_tab, + _tag, + ))(input) +} -named!( - compose_action, - alt_complete!(add_attachment | remove_attachment | toggle_sign) -); +fn compose_action(input: &[u8]) -> IResult<&[u8], Action> { + alt((add_attachment, remove_attachment, toggle_sign))(input) +} -named!(account_action, alt_complete!(reindex)); +fn account_action(input: &[u8]) -> IResult<&[u8], Action> { + reindex(input) +} -named!(view, alt_complete!(pipe | save_attachment)); +fn view(input: &[u8]) -> IResult<&[u8], Action> { + alt((pipe, save_attachment))(input) +} -named!(pub parse_command, - alt_complete!( goto | listing_action | sort | subsort | close | mailinglist | setenv | printenv | view | compose_action | create_mailbox | sub_mailbox | unsub_mailbox | delete_mailbox | rename_mailbox | account_action ) -); +pub fn parse_command(input: &[u8]) -> Result { + alt(( + goto, + listing_action, + sort, + subsort, + close, + mailinglist, + setenv, + printenv, + view, + compose_action, + create_mailbox, + sub_mailbox, + unsub_mailbox, + delete_mailbox, + rename_mailbox, + account_action, + ))(input) + .map(|(_, v)| v) + .map_err(|err| err.into()) +} #[test] #[ignore] diff --git a/src/managesieve.rs b/src/managesieve.rs index 84e6a91fe..6b4a54ee6 100644 --- a/src/managesieve.rs +++ b/src/managesieve.rs @@ -31,13 +31,9 @@ extern crate serde_derive; extern crate linkify; extern crate uuid; -extern crate termion; - -#[macro_use] -extern crate nom; - extern crate serde_json; extern crate smallvec; +extern crate termion; use melib::backends::imap::managesieve::new_managesieve_connection; use melib::Result; diff --git a/src/state.rs b/src/state.rs index 08740708e..6eae7bd03 100644 --- a/src/state.rs +++ b/src/state.rs @@ -871,7 +871,7 @@ impl State { match event { // Command type is handled only by State. UIEvent::Command(cmd) => { - if let Ok(action) = parse_command(&cmd.as_bytes()).to_full_result() { + if let Ok(action) = parse_command(&cmd.as_bytes()) { if action.needs_confirmation() { self.overlay.push(Box::new(UIConfirmationDialog::new( "You sure?",