melib: add Folder operations in mail backends
Add following operations in mail backend: - Create, - Delete, - Subscribe, - Unsubscribe, - Renameembed
parent
8b0dff728d
commit
dc2184a9de
|
@ -143,6 +143,18 @@ impl NotifyFn {
|
||||||
self.0(f);
|
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 {
|
pub trait MailBackend: ::std::fmt::Debug {
|
||||||
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>;
|
fn get(&mut self, folder: &Folder) -> Async<Result<Vec<Envelope>>>;
|
||||||
fn watch(&self, sender: RefreshEventConsumer) -> Result<()>;
|
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 operation(&self, hash: EnvelopeHash, folder_hash: FolderHash) -> Box<BackendOp>;
|
||||||
|
|
||||||
fn save(&self, bytes: &[u8], folder: &str) -> Result<()>;
|
fn save(&self, bytes: &[u8], folder: &str) -> Result<()>;
|
||||||
|
fn folder_operation(&mut self, path: &str, op: FolderOperation) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
//login function
|
//login function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,3 +110,10 @@ impl From<str::Utf8Error> for MeliError {
|
||||||
// MeliError::new(format!("{:?}", kind))
|
// 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ use super::AccountConf;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus};
|
use melib::async_workers::{Async, AsyncBuilder, AsyncStatus};
|
||||||
use melib::backends::{
|
use melib::backends::{
|
||||||
BackendOp, Backends, Folder, FolderHash, MailBackend, NotifyFn, ReadOnlyOp, RefreshEvent,
|
BackendOp, Backends, Folder, FolderHash, FolderOperation, MailBackend, NotifyFn, ReadOnlyOp,
|
||||||
RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox,
|
RefreshEvent, RefreshEventConsumer, RefreshEventKind, SpecialUseMailbox,
|
||||||
};
|
};
|
||||||
use melib::error::{MeliError, Result};
|
use melib::error::{MeliError, Result};
|
||||||
use melib::mailbox::*;
|
use melib::mailbox::*;
|
||||||
|
@ -601,6 +601,10 @@ impl Account {
|
||||||
pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode {
|
pub fn thread(&self, h: ThreadHash, f: FolderHash) -> &ThreadNode {
|
||||||
&self.collection.threads[&f].thread_nodes()[&h]
|
&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 {
|
impl Index<FolderHash> for Account {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
/*! A parser module for user commands passed through the Ex mode.
|
/*! A parser module for user commands passed through the Ex mode.
|
||||||
*/
|
*/
|
||||||
|
use melib::backends::FolderOperation;
|
||||||
pub use melib::mailbox::{SortField, SortOrder};
|
pub use melib::mailbox::{SortField, SortOrder};
|
||||||
use nom::{digit, not_line_ending};
|
use nom::{digit, not_line_ending};
|
||||||
use std;
|
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>,
|
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)
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::components::Component;
|
use crate::components::Component;
|
||||||
|
use melib::backends::FolderOperation;
|
||||||
pub use melib::mailbox::{SortField, SortOrder};
|
pub use melib::mailbox::{SortField, SortOrder};
|
||||||
use melib::thread::ThreadHash;
|
use melib::thread::ThreadHash;
|
||||||
use melib::{Draft, EnvelopeHash};
|
use melib::{Draft, EnvelopeHash};
|
||||||
|
@ -83,4 +84,8 @@ pub enum Action {
|
||||||
SetEnv(String, String),
|
SetEnv(String, String),
|
||||||
PrintEnv(String),
|
PrintEnv(String),
|
||||||
Compose(ComposeAction),
|
Compose(ComposeAction),
|
||||||
|
Folder(AccountName, FolderPath, FolderOperation),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AccountName = String;
|
||||||
|
type FolderPath = String;
|
||||||
|
|
|
@ -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 => {
|
v => {
|
||||||
self.rcv_event(UIEvent::Action(v));
|
self.rcv_event(UIEvent::Action(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.context
|
||||||
|
.replies
|
||||||
|
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||||
|
"invalid command".to_string(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue