Add some documentation

embed
Manos Pitsidianakis 2018-08-06 22:20:34 +03:00
parent c32c6b82c8
commit 8a7dfcd4ee
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
13 changed files with 76 additions and 22 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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::*;

View File

@ -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::*;

View File

@ -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;

View File

@ -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 */

View File

@ -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 {

View File

@ -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;
}

View File

@ -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});

View File

@ -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>,

View File

@ -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,

View File

@ -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;

View File

@ -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 {