melib: add Folder operations in mail backends

Add following operations in mail backend:
- Create,
- Delete,
- Subscribe,
- Unsubscribe,
- Rename
embed
Manos Pitsidianakis 2019-08-26 19:44:05 +03:00
parent 8b0dff728d
commit dc2184a9de
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
6 changed files with 134 additions and 3 deletions

View File

@ -143,6 +143,18 @@ impl NotifyFn {
self.0(f);
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub enum FolderOperation {
Create,
Delete,
Subscribe,
Unsubscribe,
Rename(NewFolderName),
}
type NewFolderName = String;
pub trait MailBackend: ::std::fmt::Debug {
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>;
fn watch(&self, sender: RefreshEventConsumer) -> Result<()>;
@ -150,6 +162,9 @@ pub trait MailBackend: ::std::fmt::Debug {
fn operation(&self, hash: EnvelopeHash, folder_hash: FolderHash) -> Box<BackendOp>;
fn save(&self, bytes: &[u8], folder: &str) -> Result<()>;
fn folder_operation(&mut self, path: &str, op: FolderOperation) -> Result<()> {
Ok(())
}
//login function
}

View File

@ -110,3 +110,10 @@ impl From<str::Utf8Error> for MeliError {
// MeliError::new(format!("{:?}", kind))
// }
//}
impl<T> From<std::sync::PoisonError<T>> for MeliError {
#[inline]
fn from(kind: std::sync::PoisonError<T>) -> MeliError {
MeliError::new(format!("{}", kind))
}
}

View File

@ -27,8 +27,8 @@ use super::AccountConf;
use fnv::FnvHashMap;
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus};
use melib::backends::{
BackendOp, Backends, Folder, FolderHash, MailBackend, NotifyFn, ReadOnlyOp, RefreshEvent,
RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox,
BackendOp, Backends, Folder, FolderHash, FolderOperation, MailBackend, NotifyFn, ReadOnlyOp,
RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox,
};
use melib::error::{MeliError, Result};
use melib::mailbox::*;
@ -601,6 +601,10 @@ impl Account {
pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode {
&self.collection.threads[&f].thread_nodes()[&h]
}
pub fn folder_operation(&mut self, path: &str, op: FolderOperation) -> Result<()> {
self.backend.folder_operation(path, op)
}
}
impl Index<FolderHash> for Account {

View File

@ -21,6 +21,7 @@
/*! A parser module for user commands passed through the Ex mode.
*/
use melib::backends::FolderOperation;
pub use melib::mailbox::{SortField, SortOrder};
use nom::{digit, not_line_ending};
use std;
@ -211,6 +212,78 @@ define_commands!([
)
);
)
},
{ tags: ["create-folder "],
desc: "create-folder ACCOUNT FOLDER_PATH",
parser:(
named!( create_folder<Action>,
do_parse!(
ws!(tag!("create-folder"))
>> account: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> path: map_res!(call!(not_line_ending), std::str::from_utf8)
>> (Folder(account.to_string(), path.to_string(), FolderOperation::Create))
)
);
)
},
{ tags: ["subscribe-folder "],
desc: "subscribe-folder ACCOUNT FOLDER_PATH",
parser:(
named!( sub_folder<Action>,
do_parse!(
ws!(tag!("subscribe-folder"))
>> account: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> path: map_res!(call!(not_line_ending), std::str::from_utf8)
>> (Folder(account.to_string(), path.to_string(), FolderOperation::Subscribe))
)
);
)
},
{ tags: ["unsubscribe-folder "],
desc: "unsubscribe-folder ACCOUNT FOLDER_PATH",
parser:(
named!( unsub_folder<Action>,
do_parse!(
ws!(tag!("unsubscribe-folder"))
>> account: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> path: map_res!(call!(not_line_ending), std::str::from_utf8)
>> (Folder(account.to_string(), path.to_string(), FolderOperation::Unsubscribe))
)
);
)
},
{ tags: ["rename-folder "],
desc: "rename-folder ACCOUNT FOLDER_PATH_SRC FOLDER_PATH_DEST",
parser:(
named!( rename_folder<Action>,
do_parse!(
ws!(tag!("rename-folder"))
>> account: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> src: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> dest: map_res!(call!(not_line_ending), std::str::from_utf8)
>> (Folder(account.to_string(), src.to_string(), FolderOperation::Rename(dest.to_string())))
)
);
)
},
{ tags: ["delete-folder "],
desc: "delete-folder ACCOUNT FOLDER_PATH",
parser:(
named!( delete_folder<Action>,
do_parse!(
ws!(tag!("delete-folder"))
>> account: map_res!(is_not!(" "), std::str::from_utf8)
>> is_a!(" ")
>> path: map_res!(call!(not_line_ending), std::str::from_utf8)
>> (Folder(account.to_string(), path.to_string(), FolderOperation::Delete))
)
);
)
}
]);
@ -263,5 +336,5 @@ named!(
);
named!(pub parse_command<Action>,
alt_complete!( goto | listing_action | sort | subsort | close | mailinglist | setenv | printenv | pipe | compose_action)
alt_complete!( goto | listing_action | sort | subsort | close | mailinglist | setenv | printenv | pipe | compose_action | create_folder | sub_folder | unsub_folder | delete_folder | rename_folder)
);

View File

@ -24,6 +24,7 @@
*/
use crate::components::Component;
use melib::backends::FolderOperation;
pub use melib::mailbox::{SortField, SortOrder};
use melib::thread::ThreadHash;
use melib::{Draft, EnvelopeHash};
@ -83,4 +84,8 @@ pub enum Action {
SetEnv(String, String),
PrintEnv(String),
Compose(ComposeAction),
Folder(AccountName, FolderPath, FolderOperation),
}
type AccountName = String;
type FolderPath = String;

View File

@ -494,10 +494,37 @@ impl State {
),
));
}
Folder(account_name, path, op) => {
if let Some(account) = self
.context
.accounts
.iter_mut()
.find(|a| a.name() == account_name)
{
if let Err(e) = account.folder_operation(&path, op) {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(e.to_string()),
));
}
} else {
self.context.replies.push_back(UIEvent::StatusEvent(
StatusEvent::DisplayMessage(format!(
"Account with name `{}` not found.",
account_name
)),
));
}
}
v => {
self.rcv_event(UIEvent::Action(v));
}
}
} else {
self.context
.replies
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
"invalid command".to_string(),
)));
}
}