Add some documentation
parent
c32c6b82c8
commit
8a7dfcd4ee
|
@ -1,13 +1,28 @@
|
||||||
|
/*!
|
||||||
|
* Primitive Async/Wait implementation.
|
||||||
|
*
|
||||||
|
* To create an Async promise, create an AsyncBuilder. Ask for its channel receiver/sender with
|
||||||
|
* `tx` and `rx` methods to pass them in your worker's closure. Build an `Async<T>` with your
|
||||||
|
* `JoinHandle<T>`. The thread must communicate with the `Async<T>` object via `AsyncStatus`
|
||||||
|
* messages.
|
||||||
|
*
|
||||||
|
* When `Async<T>` receives `AsyncStatus::Finished` it joins the thread and takes its value which
|
||||||
|
* can be extracted with `extract`.
|
||||||
|
*/
|
||||||
|
|
||||||
use chan;
|
use chan;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
/// Messages to pass between `Async<T>` owner and its worker thread.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AsyncStatus {
|
pub enum AsyncStatus {
|
||||||
NoUpdate,
|
NoUpdate,
|
||||||
Finished,
|
Finished,
|
||||||
|
///The number may hold whatever meaning the user chooses.
|
||||||
ProgressReport(usize),
|
ProgressReport(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A builder object for `Async<T>`
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AsyncBuilder {
|
pub struct AsyncBuilder {
|
||||||
tx: chan::Sender<AsyncStatus>,
|
tx: chan::Sender<AsyncStatus>,
|
||||||
|
@ -22,8 +37,6 @@ pub struct Async<T> {
|
||||||
rx: chan::Receiver<AsyncStatus>,
|
rx: chan::Receiver<AsyncStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl AsyncBuilder {
|
impl AsyncBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (sender, receiver) = chan::sync(::std::mem::size_of::<AsyncStatus>());
|
let (sender, receiver) = chan::sync(::std::mem::size_of::<AsyncStatus>());
|
||||||
|
@ -32,12 +45,15 @@ impl AsyncBuilder {
|
||||||
rx: receiver,
|
rx: receiver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Returns the sender object of the promise's channel.
|
||||||
pub fn tx(&mut self) -> chan::Sender<AsyncStatus> {
|
pub fn tx(&mut self) -> chan::Sender<AsyncStatus> {
|
||||||
self.tx.clone()
|
self.tx.clone()
|
||||||
}
|
}
|
||||||
|
/// Returns the receiver object of the promise's channel.
|
||||||
pub fn rx(&mut self) -> chan::Receiver<AsyncStatus> {
|
pub fn rx(&mut self) -> chan::Receiver<AsyncStatus> {
|
||||||
self.rx.clone()
|
self.rx.clone()
|
||||||
}
|
}
|
||||||
|
/// Returns an `Async<T>` object that contains a `Thread` join handle that returns a `T`
|
||||||
pub fn build<T: Clone>(self, worker: thread::JoinHandle<T>) -> Async<T> {
|
pub fn build<T: Clone>(self, worker: thread::JoinHandle<T>) -> Async<T> {
|
||||||
Async {
|
Async {
|
||||||
worker: Some(worker),
|
worker: Some(worker),
|
||||||
|
@ -49,9 +65,11 @@ impl AsyncBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Async<T> {
|
impl<T> Async<T> {
|
||||||
|
/// Consumes `self` and returns the computed value. Will panic if computation hasn't finished.
|
||||||
pub fn extract(self) -> T {
|
pub fn extract(self) -> T {
|
||||||
self.value.unwrap()
|
self.value.unwrap()
|
||||||
}
|
}
|
||||||
|
/// Polls worker thread and returns result.
|
||||||
pub fn poll(&mut self) -> Result<AsyncStatus, ()> {
|
pub fn poll(&mut self) -> Result<AsyncStatus, ()> {
|
||||||
if self.value.is_some() {
|
if self.value.is_some() {
|
||||||
return Ok(AsyncStatus::Finished);
|
return Ok(AsyncStatus::Finished);
|
||||||
|
|
|
@ -18,6 +18,11 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* An error object for `melib`
|
||||||
|
*/
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
pub mod conf;
|
pub mod conf;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod mailbox;
|
pub mod mailbox;
|
||||||
pub mod utilities;
|
|
||||||
pub mod async;
|
pub mod async;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -45,4 +44,3 @@ pub use mailbox::*;
|
||||||
pub use error::{MeliError, Result};
|
pub use error::{MeliError, Result};
|
||||||
pub use mailbox::backends::{Backends, RefreshEvent, RefreshEventConsumer};
|
pub use mailbox::backends::{Backends, RefreshEvent, RefreshEventConsumer};
|
||||||
pub use mailbox::email::{Envelope, Flag};
|
pub use mailbox::email::{Envelope, Flag};
|
||||||
pub use utilities::*;
|
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Account management from user configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
use conf::{AccountSettings, Folder};
|
use conf::{AccountSettings, Folder};
|
||||||
use mailbox::backends::{Backends, RefreshEventConsumer};
|
use mailbox::backends::{Backends, RefreshEventConsumer};
|
||||||
use mailbox::*;
|
use mailbox::*;
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Email parsing, handling, sending etc.
|
||||||
|
*/
|
||||||
pub mod attachments;
|
pub mod attachments;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Mail related code.
|
||||||
|
*
|
||||||
|
* This module handles reading emails from various backends, handling account data etc
|
||||||
|
*/
|
||||||
|
|
||||||
pub mod email;
|
pub mod email;
|
||||||
pub use self::email::*;
|
pub use self::email::*;
|
||||||
/* Mail backends. Currently only maildir is supported */
|
/* Mail backends. Currently only maildir is supported */
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Threading algorithm
|
||||||
|
*/
|
||||||
|
|
||||||
use error::Result;
|
use error::Result;
|
||||||
use mailbox::email::*;
|
use mailbox::email::*;
|
||||||
use mailbox::Mailbox;
|
use mailbox::Mailbox;
|
||||||
|
@ -262,6 +266,7 @@ pub fn build_threads(
|
||||||
|
|
||||||
for x in &sent_mailbox.collection {
|
for x in &sent_mailbox.collection {
|
||||||
let m_id = x.message_id_raw();
|
let m_id = x.message_id_raw();
|
||||||
|
let x_r_id = x.in_reply_to_raw();
|
||||||
if id_table.contains_key(&m_id)
|
if id_table.contains_key(&m_id)
|
||||||
|| (!x.in_reply_to_raw().is_empty()
|
|| (!x.in_reply_to_raw().is_empty()
|
||||||
&& id_table.contains_key(&x.in_reply_to_raw()))
|
&& id_table.contains_key(&x.in_reply_to_raw()))
|
||||||
|
@ -280,7 +285,7 @@ pub fn build_threads(
|
||||||
} else if !x.in_reply_to_raw().is_empty()
|
} else if !x.in_reply_to_raw().is_empty()
|
||||||
&& id_table.contains_key(&x.in_reply_to_raw())
|
&& id_table.contains_key(&x.in_reply_to_raw())
|
||||||
{
|
{
|
||||||
let p = id_table[&m_id];
|
let p = id_table[&x_r_id];
|
||||||
let c = if id_table.contains_key(&m_id) {
|
let c = if id_table.contains_key(&m_id) {
|
||||||
id_table[&m_id]
|
id_table[&m_id]
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
pub trait ProgressTracker {
|
|
||||||
fn new(s: String, total_work: usize) -> Self;
|
|
||||||
|
|
||||||
fn add_work(&mut self, n: usize) -> ();
|
|
||||||
fn set_work(&mut self, n: usize) -> ();
|
|
||||||
fn work(&mut self, n: usize) -> ();
|
|
||||||
|
|
||||||
fn percentage(&self) -> usize;
|
|
||||||
fn description(&self) -> &str;
|
|
||||||
}
|
|
10
src/bin.rs
10
src/bin.rs
|
@ -33,7 +33,7 @@ extern crate melib;
|
||||||
extern crate ui;
|
extern crate ui;
|
||||||
|
|
||||||
pub use melib::*;
|
pub use melib::*;
|
||||||
use ui::*;
|
pub use ui::*;
|
||||||
|
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
|
@ -206,10 +206,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !flag {
|
if !flag {
|
||||||
state.finish_startup();
|
state.finish_startup();
|
||||||
}
|
}
|
||||||
|
state.render();
|
||||||
}
|
}
|
||||||
ThreadEvent::UIEvent(e) => {
|
ThreadEvent::UIEvent(e) => {
|
||||||
state.rcv_event(UIEvent { id: 0, event_type: e});
|
state.rcv_event(UIEvent { id: 0, event_type: e});
|
||||||
|
|
|
@ -14,6 +14,7 @@ struct AccountMenuEntry {
|
||||||
entries: Vec<(usize, Folder)>,
|
entries: Vec<(usize, Folder)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The account sidebar.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AccountMenu {
|
pub struct AccountMenu {
|
||||||
accounts: Vec<AccountMenuEntry>,
|
accounts: Vec<AccountMenuEntry>,
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/*!
|
||||||
|
* User actions that need to be handled by the UI
|
||||||
|
*/
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MailListingAction {
|
pub enum MailListingAction {
|
||||||
ToggleThreaded,
|
ToggleThreaded,
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This library exports the public types and methods of its modules
|
||||||
|
*/
|
||||||
|
|
||||||
extern crate melib;
|
extern crate melib;
|
||||||
extern crate mime_apps;
|
extern crate mime_apps;
|
||||||
extern crate notify_rust;
|
extern crate notify_rust;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/*!
|
/*! The application's state.
|
||||||
|
|
||||||
The UI crate has an Entity-Component-System design. The System part, is also the application's state, so they're both merged in the `State` struct.
|
The UI crate has an Entity-Component-System design. The System part, is also the application's state, so they're both merged in the `State` struct.
|
||||||
|
|
||||||
`State` owns all the Entities of the UI, which are currently plain Containers for `Component`s. In the application's main event loop, input is handed to the state in the form of `UIEvent` objects which traverse the entity graph. Components decide to handle each input or not.
|
`State` owns all the Entities of the UI, which are currently plain Containers for `Component`s. In the application's main event loop, input is handed to the state in the form of `UIEvent` objects which traverse the entity graph. Components decide to handle each input or not.
|
||||||
|
@ -158,11 +159,15 @@ impl State<std::io::Stdout> {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If an owned thread returns a `ThreadEvent::ThreadJoin` event to `State` then it must remove
|
||||||
|
/// the thread from its list and `join` it.
|
||||||
pub fn join(&mut self, id: thread::ThreadId) {
|
pub fn join(&mut self, id: thread::ThreadId) {
|
||||||
let handle = self.threads.remove(&id).unwrap();
|
let handle = self.threads.remove(&id).unwrap();
|
||||||
handle.join().unwrap();
|
handle.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If startup has finished, inform startup thread that it doesn't need to tick us with startup
|
||||||
|
/// check reminders and let it die.
|
||||||
pub fn finish_startup(&mut self) {
|
pub fn finish_startup(&mut self) {
|
||||||
// TODO: Encode startup process with the type system if possible
|
// TODO: Encode startup process with the type system if possible
|
||||||
if self.startup_thread.is_none() {
|
if self.startup_thread.is_none() {
|
||||||
|
@ -173,6 +178,9 @@ impl State<std::io::Stdout> {
|
||||||
tx.send(true);
|
tx.send(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Switch back to the terminal's main screen (The command line the user sees before opening
|
||||||
|
/// the application)
|
||||||
pub fn to_main_screen(&mut self) {
|
pub fn to_main_screen(&mut self) {
|
||||||
write!(
|
write!(
|
||||||
self.stdout(),
|
self.stdout(),
|
||||||
|
@ -199,6 +207,7 @@ impl State<std::io::Stdout> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<W: Write> State<W> {
|
impl<W: Write> State<W> {
|
||||||
|
/// On `SIGWNICH` the `State` redraws itself according to the new terminal size.
|
||||||
pub fn update_size(&mut self) {
|
pub fn update_size(&mut self) {
|
||||||
let termsize = termion::terminal_size().ok();
|
let termsize = termion::terminal_size().ok();
|
||||||
let termcols = termsize.map(|(w, _)| w);
|
let termcols = termsize.map(|(w, _)| w);
|
||||||
|
@ -221,6 +230,7 @@ impl<W: Write> State<W> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Force a redraw for all dirty components.
|
||||||
pub fn redraw(&mut self) {
|
pub fn redraw(&mut self) {
|
||||||
for i in 0..self.entities.len() {
|
for i in 0..self.entities.len() {
|
||||||
self.draw_entity(i);
|
self.draw_entity(i);
|
||||||
|
@ -231,6 +241,8 @@ impl<W: Write> State<W> {
|
||||||
self.draw_area(a);
|
self.draw_area(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw only a specific `area` on the screen.
|
||||||
fn draw_area(&mut self, area: Area) {
|
fn draw_area(&mut self, area: Area) {
|
||||||
let upper_left = upper_left!(area);
|
let upper_left = upper_left!(area);
|
||||||
let bottom_right = bottom_right!(area);
|
let bottom_right = bottom_right!(area);
|
||||||
|
@ -269,6 +281,8 @@ impl<W: Write> State<W> {
|
||||||
}
|
}
|
||||||
self.flush();
|
self.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw the entire screen from scratch.
|
||||||
pub fn render(&mut self) {
|
pub fn render(&mut self) {
|
||||||
self.update_size();
|
self.update_size();
|
||||||
|
|
||||||
|
@ -306,6 +320,7 @@ impl<W: Write> State<W> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The application's main loop sends `UIEvents` to state via this method.
|
||||||
pub fn rcv_event(&mut self, event: UIEvent) {
|
pub fn rcv_event(&mut self, event: UIEvent) {
|
||||||
match event.event_type {
|
match event.event_type {
|
||||||
// Command type is handled only by State.
|
// Command type is handled only by State.
|
||||||
|
@ -383,6 +398,8 @@ impl<W: Write> State<W> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn try_wait_on_child(&mut self) -> Option<bool> {
|
pub fn try_wait_on_child(&mut self) -> Option<bool> {
|
||||||
if {
|
if {
|
||||||
match self.child {
|
match self.child {
|
||||||
|
|
Loading…
Reference in New Issue