1024 lines
39 KiB
Rust
1024 lines
39 KiB
Rust
/*
|
|
* meli
|
|
*
|
|
* Copyright 2017 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/>.
|
|
*/
|
|
|
|
//! Command parsing.
|
|
|
|
use super::*;
|
|
use crate::command::{argcheck::*, error::*};
|
|
|
|
macro_rules! command_err {
|
|
(nom $b:expr, $input: expr, $msg:literal) => {{
|
|
let evaluated: IResult<&'_ [u8], _> = { $b };
|
|
match evaluated {
|
|
Err(_) => {
|
|
let err = CommandError::BadValue { inner: $msg.into() };
|
|
return Ok(($input, Err(err)));
|
|
}
|
|
Ok(v) => v,
|
|
}
|
|
}};
|
|
($b:expr, $input: expr, $msg:literal) => {{
|
|
let evaluated = { $b };
|
|
match evaluated {
|
|
Err(_) => {
|
|
let err = CommandError::BadValue { inner: $msg.into() };
|
|
return Ok(($input, Err(err)));
|
|
}
|
|
Ok(v) => v,
|
|
}
|
|
}};
|
|
}
|
|
|
|
macro_rules! tag {
|
|
() => {{
|
|
tag::<&'_ str, &'_ [u8], melib::nom::error::Error<&[u8]>>
|
|
}};
|
|
}
|
|
|
|
pub fn usize_c(input: &[u8]) -> IResult<&[u8], usize> {
|
|
map_res(
|
|
map_res(digit1, std::str::from_utf8),
|
|
std::str::FromStr::from_str,
|
|
)(input.trim())
|
|
}
|
|
|
|
pub fn sortfield(input: &[u8]) -> IResult<&[u8], SortField> {
|
|
map_res(
|
|
map_res(take_until(" "), std::str::from_utf8),
|
|
std::str::FromStr::from_str,
|
|
)(input.trim())
|
|
}
|
|
|
|
pub fn sortorder(input: &[u8]) -> IResult<&[u8], SortOrder> {
|
|
map_res(
|
|
map_res(not_line_ending, std::str::from_utf8),
|
|
std::str::FromStr::from_str,
|
|
)(input)
|
|
}
|
|
|
|
pub fn threaded(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
map(tag("threaded"), |_| Ok(Listing(SetThreaded)))(input.trim())
|
|
}
|
|
|
|
pub fn plain(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
map(tag("plain"), |_| Ok(Listing(SetPlain)))(input.trim())
|
|
}
|
|
|
|
pub fn compact(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
map(tag("compact"), |_| Ok(Listing(SetCompact)))(input.trim())
|
|
}
|
|
|
|
pub fn conversations(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
map(tag("conversations"), |_| Ok(Listing(SetConversations)))(input.trim())
|
|
}
|
|
|
|
pub fn listing_action(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
alt((
|
|
set,
|
|
delete_message,
|
|
copymove,
|
|
import,
|
|
search,
|
|
select,
|
|
open_in_new_tab,
|
|
export_mbox,
|
|
_tag,
|
|
flag,
|
|
))(input)
|
|
}
|
|
|
|
pub fn compose_action(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
alt((add_attachment, mailto, remove_attachment, save_draft))(input)
|
|
}
|
|
|
|
pub fn account_action(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
alt((reindex, print_account_setting))(input)
|
|
}
|
|
|
|
pub fn view(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
alt((
|
|
filter,
|
|
pipe,
|
|
save_attachment,
|
|
export_mail,
|
|
add_addresses_to_contacts,
|
|
))(input)
|
|
}
|
|
|
|
pub fn new_tab(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
alt((manage_mailboxes, manage_jobs, compose_action))(input)
|
|
}
|
|
|
|
pub fn parse_command(input: &[u8]) -> Result<Action, CommandError> {
|
|
alt((
|
|
goto,
|
|
listing_action,
|
|
sort,
|
|
sort_column,
|
|
subsort,
|
|
close,
|
|
mailinglist,
|
|
setenv,
|
|
alt((printenv, currentdir, change_currentdir)),
|
|
view,
|
|
create_mailbox,
|
|
sub_mailbox,
|
|
unsub_mailbox,
|
|
delete_mailbox,
|
|
rename_mailbox,
|
|
new_tab,
|
|
account_action,
|
|
print_setting,
|
|
toggle,
|
|
reload_config,
|
|
quit,
|
|
))(input)
|
|
.map_err(|err| err.into())
|
|
.and_then(|(_, v)| v)
|
|
}
|
|
|
|
/// Set/unset a flag.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// # use meli::{melib::Flag, command::{Action,ListingAction, FlagAction, parser}};
|
|
///
|
|
/// let (rest, parsed) = parser::flag(b"flag set junk").unwrap();
|
|
/// assert_eq!(rest, b"");
|
|
/// assert!(
|
|
/// matches!(
|
|
/// parsed,
|
|
/// Ok(Action::Listing(ListingAction::Flag(FlagAction::Set(
|
|
/// Flag::TRASHED
|
|
/// ))))
|
|
/// ),
|
|
/// "{:?}",
|
|
/// parsed
|
|
/// );
|
|
///
|
|
/// let (rest, parsed) = parser::flag(b"flag unset junk").unwrap();
|
|
/// assert_eq!(rest, b"");
|
|
/// assert!(
|
|
/// matches!(
|
|
/// parsed,
|
|
/// Ok(Action::Listing(ListingAction::Flag(FlagAction::Unset(
|
|
/// Flag::TRASHED
|
|
/// ))))
|
|
/// ),
|
|
/// "{:?}",
|
|
/// parsed
|
|
/// );
|
|
///
|
|
/// let (rest, parsed) = parser::flag(b"flag set draft").unwrap();
|
|
/// assert_eq!(rest, b"");
|
|
/// assert!(
|
|
/// matches!(
|
|
/// parsed,
|
|
/// Ok(Action::Listing(ListingAction::Flag(FlagAction::Set(
|
|
/// Flag::DRAFT
|
|
/// ))))
|
|
/// ),
|
|
/// "{:?}",
|
|
/// parsed
|
|
/// );
|
|
///
|
|
/// let (rest, parsed) = parser::flag(b"flag set xunk").unwrap();
|
|
/// assert_eq!(rest, b"");
|
|
/// assert_eq!(
|
|
/// &parsed.unwrap_err().to_string(),
|
|
/// "Bad value/argument: xunk is not a valid flag name. Possible values are: passed, replied, \
|
|
/// seen or read, junk or trash or trashed, draft and flagged."
|
|
/// );
|
|
/// ```
|
|
pub fn flag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
use melib::Flag;
|
|
|
|
fn parse_flag(s: &str) -> Option<Flag> {
|
|
match s {
|
|
o if o.eq_ignore_ascii_case("passed") => Some(Flag::PASSED),
|
|
o if o.eq_ignore_ascii_case("replied") => Some(Flag::REPLIED),
|
|
o if o.eq_ignore_ascii_case("seen") => Some(Flag::SEEN),
|
|
o if o.eq_ignore_ascii_case("read") => Some(Flag::SEEN),
|
|
o if o.eq_ignore_ascii_case("junk") => Some(Flag::TRASHED),
|
|
o if o.eq_ignore_ascii_case("trash") => Some(Flag::TRASHED),
|
|
o if o.eq_ignore_ascii_case("trashed") => Some(Flag::TRASHED),
|
|
o if o.eq_ignore_ascii_case("draft") => Some(Flag::DRAFT),
|
|
o if o.eq_ignore_ascii_case("flagged") => Some(Flag::FLAGGED),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
preceded(
|
|
tag("flag"),
|
|
alt((
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, flag};
|
|
let (input, _) = tag("set")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, flag) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
let Some(flag) = parse_flag(flag) else {
|
|
return Ok((
|
|
b"",
|
|
Err(CommandError::BadValue {
|
|
inner: format!(
|
|
"{flag} is not a valid flag name. Possible values are: passed, \
|
|
replied, seen or read, junk or trash or trashed, draft and \
|
|
flagged."
|
|
)
|
|
.into(),
|
|
}),
|
|
));
|
|
};
|
|
Ok((input, Ok(Listing(Flag(FlagAction::Set(flag))))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, flag};
|
|
let (input, _) = tag("unset")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, flag) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
let Some(flag) = parse_flag(flag) else {
|
|
return Ok((
|
|
b"",
|
|
Err(CommandError::BadValue {
|
|
inner: format!(
|
|
"{flag} is not a valid flag name. Possible values are: passed, \
|
|
replied, seen or read, junk or trash or trashed, draft and \
|
|
flagged."
|
|
)
|
|
.into(),
|
|
}),
|
|
));
|
|
};
|
|
Ok((input, Ok(Listing(Flag(FlagAction::Unset(flag))))))
|
|
},
|
|
)),
|
|
)(input.trim())
|
|
}
|
|
|
|
pub fn set(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
fn toggle(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, set};
|
|
let (input, _) = tag("set")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, ret) = alt((threaded, plain, compact, conversations))(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, ret))
|
|
}
|
|
fn seen_flag(input: &'_ [u8]) -> IResult<&'_ [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, set_seen_flag};
|
|
let (input, _) = tag("set")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, ret) = command_err!(nom
|
|
alt((map(tag("seen"), |_| Listing(SetSeen)), map(tag("unseen"), |_| Listing(SetUnseen))))(input),
|
|
input,
|
|
"Bad argument for `set`. Accepted arguments are [seen, unseen, plain, threaded, compact, conversations].");
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(ret)))
|
|
}
|
|
if let val @ Ok((_, Ok(_))) = toggle(input) {
|
|
return val;
|
|
}
|
|
seen_flag(input)
|
|
}
|
|
|
|
pub fn delete_message(input: &'_ [u8]) -> IResult<&'_ [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, delete_message};
|
|
let (input, ret) = map(preceded(tag("delete"), eof), |_| Listing(Delete))(input)?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(ret)))
|
|
}
|
|
|
|
pub fn copymove<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
alt((
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, copymove};
|
|
let (input, _) = tag("copyto")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(inc check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(CopyTo(path.to_string())))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, copymove};
|
|
let (input, _) = tag("copyto")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Listing(CopyToOtherAccount(
|
|
account.to_string(),
|
|
path.to_string(),
|
|
))),
|
|
))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, moveto};
|
|
let (input, _) = tag("moveto")(input.trim())?;
|
|
println!("input len is {}", input.len());
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(MoveTo(path.to_string())))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, moveto};
|
|
let (input, _) = tag("moveto")(input.trim())?;
|
|
println!("input len is {}", input.len());
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Listing(MoveToOtherAccount(
|
|
account.to_string(),
|
|
path.to_string(),
|
|
))),
|
|
))
|
|
},
|
|
))(input)
|
|
}
|
|
pub fn close(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, close};
|
|
let (input, _) = tag("close")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Tab(Close))))
|
|
}
|
|
pub fn goto(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, goto};
|
|
let (input, _) = tag("go")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, nth) = command_err!(nom
|
|
usize_c(input),
|
|
input,
|
|
"Argument must be an integer.");
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Action::ViewMailbox(nth))))
|
|
}
|
|
pub fn subsort(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 2, subsort};
|
|
let (input, _) = tag("subsort")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, p) = pair(sortfield, sortorder)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(SubSort(p.0, p.1))))
|
|
}
|
|
pub fn sort(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 2, sort};
|
|
let (input, _) = tag("sort")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, p) = separated_pair(sortfield, tag(" "), sortorder)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Sort(p.0, p.1))))
|
|
}
|
|
pub fn sort_column(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, sort_column};
|
|
let (input, _) = tag("sort")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, i) = usize_c(input)?;
|
|
let (input, order) = if input.trim().is_empty() {
|
|
(input, SortOrder::Desc)
|
|
} else {
|
|
let (input, (_, order)) = pair(is_a(" "), sortorder)(input)?;
|
|
(input, order)
|
|
};
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(SortColumn(i, order))))
|
|
}
|
|
pub fn search(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg:{ u8::MAX}, search};
|
|
let (input, _) = tag("search")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, string) = map_res(not_line_ending, std::str::from_utf8)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(Search(String::from(string))))))
|
|
}
|
|
pub fn select(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
#[inline]
|
|
fn clear_selection(input: &[u8]) -> Option<IResult<&[u8], Result<Action, CommandError>>> {
|
|
if !input.trim().starts_with(b"clear-selection") {
|
|
return None;
|
|
}
|
|
#[inline]
|
|
fn inner(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, clear_selection};
|
|
let (input, _) = tag("clear-selection")(input.ltrim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(ListingAction::ClearSelection))))
|
|
}
|
|
Some(inner(input))
|
|
}
|
|
if let Some(retval) = clear_selection(input) {
|
|
return retval;
|
|
}
|
|
|
|
let mut check = arg_init! { min_arg:1, max_arg: {u8::MAX}, select};
|
|
let (input, _) = tag("select")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, string) = map_res(not_line_ending, std::str::from_utf8)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(Select(String::from(string))))))
|
|
}
|
|
pub fn export_mbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, export_mbox};
|
|
let (input, _) = tag("export-mbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Listing(ExportMbox(
|
|
Some(melib::mbox::MboxFormat::MboxCl2),
|
|
path.to_string().into(),
|
|
))),
|
|
))
|
|
}
|
|
pub fn mailinglist(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, mailinglist};
|
|
arg_chk!(start check, input);
|
|
let (input, ret) = alt((
|
|
map(tag("list-post"), |_| MailingListAction(ListPost)),
|
|
map(tag("list-unsubscribe"), |_| {
|
|
MailingListAction(ListUnsubscribe)
|
|
}),
|
|
map(tag("list-archive"), |_| MailingListAction(ListArchive)),
|
|
))(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(ret)))
|
|
}
|
|
pub fn setenv(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, setenv};
|
|
let (input, _) = tag("setenv")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
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)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(SetEnv(key.to_string(), val.to_string()))))
|
|
}
|
|
pub fn printenv(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, printenv};
|
|
let (input, _) = tag("printenv")(input.ltrim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, key) = map_res(not_line_ending, std::str::from_utf8)(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(PrintEnv(key.to_string()))))
|
|
}
|
|
pub fn currentdir(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, currentdir};
|
|
let (input, _) = tag("cwd")(input.ltrim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(CurrentDirectory)))
|
|
}
|
|
pub fn change_currentdir(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, change_currentdir};
|
|
let (input, _) = tag("cd")(input.ltrim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, d) = map_res(not_line_ending, std::str::from_utf8)(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(ChangeCurrentDirectory(d.into()))))
|
|
}
|
|
pub fn mailto(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, mailto};
|
|
use melib::email::parser::generic::mailto as parser;
|
|
let (input, _) = tag("mailto")(input.ltrim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, val) = map_res(not_line_ending, std::str::from_utf8)(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (_empty, _) = eof(input)?;
|
|
let (input, val) = command_err!(
|
|
parser(val.as_bytes()),
|
|
val.as_bytes(),
|
|
"Could not parse mailto value. If the value is valid, please report this bug."
|
|
);
|
|
Ok((input, Ok(Compose(Mailto(val)))))
|
|
}
|
|
pub fn pipe<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
alt((
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: { u8::MAX }, pipe};
|
|
let (input, _) = tag("pipe")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, bin) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, args) = separated_list1(is_a(" "), quoted_argument)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(View(Pipe(
|
|
bin.to_string(),
|
|
args.into_iter().map(String::from).collect::<Vec<String>>(),
|
|
))),
|
|
))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, pipe};
|
|
let (input, _) = tag("pipe")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, bin) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(View(Pipe(bin.to_string(), Vec::new())))))
|
|
},
|
|
))(input)
|
|
}
|
|
pub fn filter(input: &'_ [u8]) -> IResult<&'_ [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, filter};
|
|
let (input, _) = tag("filter")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, cmd) = map_res(not_line_ending, std::str::from_utf8)(input)?;
|
|
arg_chk!(finish check, input);
|
|
Ok((input, Ok(View(Filter(cmd.to_string())))))
|
|
}
|
|
pub fn add_attachment<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
alt((
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, add_attachment};
|
|
let (input, _) = tag("add-attachment")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
let (input, _) = tag("<")(input.trim())?;
|
|
arg_chk!(inc check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
let (input, cmd) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Compose(AddAttachmentPipe(cmd.to_string())))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, add_attachment};
|
|
let (input, _) = tag("add-attachment")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Compose(AddAttachment(path.to_string())))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, add_attachment};
|
|
let (input, _) = tag("add-attachment-file-picker")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Compose(AddAttachmentFilePicker(None)))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, add_attachment_file_picker};
|
|
let (input, _) = tag("add-attachment-file-picker")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
let (input, _) = tag("<")(input.trim())?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, shell) = map_res(not_line_ending, std::str::from_utf8)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Compose(AddAttachmentFilePicker(Some(shell.to_string())))),
|
|
))
|
|
},
|
|
))(input)
|
|
}
|
|
pub fn remove_attachment(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, remove_attachment};
|
|
let (input, _) = tag("remove-attachment")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, idx) = map_res(quoted_argument, usize::from_str)(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Compose(RemoveAttachment(idx)))))
|
|
}
|
|
pub fn save_draft(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, save_draft };
|
|
let (input, _) = tag("save-draft")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Compose(SaveDraft))))
|
|
}
|
|
pub fn create_mailbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, create_malbox};
|
|
let (input, _) = tag("create-mailbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Mailbox(
|
|
account.to_string(),
|
|
MailboxOperation::Create(path.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn sub_mailbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, sub_mailbox};
|
|
let (input, _) = tag("subscribe-mailbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Mailbox(
|
|
account.to_string(),
|
|
MailboxOperation::Subscribe(path.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn unsub_mailbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, unsub_mailbox};
|
|
let (input, _) = tag("unsubscribe-mailbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Mailbox(
|
|
account.to_string(),
|
|
MailboxOperation::Unsubscribe(path.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn rename_mailbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:3, max_arg: 3, rename_mailbox};
|
|
let (input, _) = tag("rename-mailbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, src) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, dest) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Mailbox(
|
|
account.to_string(),
|
|
MailboxOperation::Rename(src.to_string(), dest.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn delete_mailbox(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, delete_mailbox};
|
|
let (input, _) = tag("delete-mailbox")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(Mailbox(
|
|
account.to_string(),
|
|
MailboxOperation::Delete(path.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn reindex(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, reindex};
|
|
let (input, _) = tag("reindex")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(AccountAction(account.to_string(), ReIndex))))
|
|
}
|
|
pub fn open_in_new_tab(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, open_in_tab};
|
|
let (input, _) = tag("open-in-tab")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(OpenInNewTab))))
|
|
}
|
|
pub fn save_attachment(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, save_attachment};
|
|
let (input, _) = tag("save-attachment")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, idx) = map_res(quoted_argument, usize::from_str)(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(View(SaveAttachment(idx, path.to_string())))))
|
|
}
|
|
pub fn export_mail(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, export_mail};
|
|
let (input, _) = tag("export-mail")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, path) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(View(ExportMail(path.to_string())))))
|
|
}
|
|
pub fn add_addresses_to_contacts(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, add_addresses_to_contacts};
|
|
let (input, _) = tag("add-addresses-to-contacts")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(View(AddAddressesToContacts))))
|
|
}
|
|
|
|
/// Set/unset a tag.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// # use meli::command::{Action,ListingAction, TagAction, parser::_tag};
|
|
///
|
|
/// let (rest, parsed) = _tag(b"tag add newsletters").unwrap();
|
|
/// println!("parsed is {:?}", parsed);
|
|
/// assert_eq!(rest, b"");
|
|
/// assert!(matches!(parsed, Ok(Action::Listing(ListingAction::Tag(TagAction::Add(ref tagname)))) if tagname == "newsletters"), "{:?}", parsed);
|
|
/// ```
|
|
pub fn _tag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
preceded(
|
|
tag("tag"),
|
|
alt((
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, tag};
|
|
let (input, _) = tag("add")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, tag) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(Tag(TagAction::Add(tag.to_string()))))))
|
|
},
|
|
|input: &'a [u8]| -> IResult<&'a [u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, tag};
|
|
let (input, _) = tag("remove")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, tag) = quoted_argument(input.trim())?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Listing(Tag(TagAction::Remove(tag.to_string()))))))
|
|
},
|
|
)),
|
|
)(input.trim())
|
|
}
|
|
|
|
pub fn print_account_setting(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, print};
|
|
let (input, _) = tag("print")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, account) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, setting) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((
|
|
input,
|
|
Ok(AccountAction(
|
|
account.to_string(),
|
|
PrintAccountSetting(setting.to_string()),
|
|
)),
|
|
))
|
|
}
|
|
pub fn print_setting(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, print};
|
|
let (input, _) = tag("print")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, setting) = quoted_argument(input)?;
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(PrintSetting(setting.to_string()))))
|
|
}
|
|
pub fn toggle(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:1, max_arg: 1, toggle };
|
|
let (input, _) = tag("toggle")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (mut input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let mut retval = if tag!()("thread_snooze")(input.ltrim()).is_ok() {
|
|
Some(Listing(ToggleThreadSnooze))
|
|
} else {
|
|
None
|
|
};
|
|
for (tok, action) in [
|
|
("thread_snooze", Listing(ToggleThreadSnooze)),
|
|
("mouse", ToggleMouse),
|
|
("sign", Compose(ToggleSign)),
|
|
("encrypt", Compose(ToggleEncrypt)),
|
|
] {
|
|
if let Ok((inner_input, _)) = tag!()(tok)(input.trim()) {
|
|
input = inner_input;
|
|
retval = Some(action);
|
|
break;
|
|
}
|
|
}
|
|
let retval = match retval {
|
|
None => {
|
|
return Ok((
|
|
input,
|
|
Err(CommandError::BadValue {
|
|
inner: "Valid toggle values are thread_snooze, mouse, sign, encrypt.".into(),
|
|
}),
|
|
));
|
|
}
|
|
Some(v) => v,
|
|
};
|
|
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(retval)))
|
|
}
|
|
pub fn manage_mailboxes(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, manage_mailboxes};
|
|
let (input, _) = tag("manage-mailboxes")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Tab(ManageMailboxes))))
|
|
}
|
|
pub fn manage_jobs(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, manage_jobs};
|
|
let (input, _) = tag("manage-jobs")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input)?;
|
|
Ok((input, Ok(Tab(ManageJobs))))
|
|
}
|
|
pub fn quit(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, quit};
|
|
let (input, _) = tag("quit")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input.trim())?;
|
|
Ok((input, Ok(Quit)))
|
|
}
|
|
pub fn reload_config(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:0, max_arg: 0, reload_config};
|
|
let (input, _) = tag("reload-config")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
arg_chk!(finish check, input);
|
|
let (input, _) = eof(input.trim())?;
|
|
Ok((input, Ok(ReloadConfiguration)))
|
|
}
|
|
pub fn import(input: &[u8]) -> IResult<&[u8], Result<Action, CommandError>> {
|
|
let mut check = arg_init! { min_arg:2, max_arg: 2, import};
|
|
let (input, _) = tag("import")(input.trim())?;
|
|
arg_chk!(start check, input);
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, file) = quoted_argument(input)?;
|
|
let (input, _) = is_a(" ")(input)?;
|
|
arg_chk!(inc check, input);
|
|
let (input, mailbox_path) = quoted_argument(input)?;
|
|
let (input, _) = eof(input)?;
|
|
arg_chk!(finish check, input);
|
|
Ok((
|
|
input,
|
|
Ok(Listing(Import(
|
|
file.to_string().into(),
|
|
mailbox_path.to_string(),
|
|
))),
|
|
))
|
|
}
|