diff options
29 files changed, 797 insertions, 437 deletions
diff --git a/melib/src/async.rs b/melib/src/async.rs index 26a024a1..b9ba191f 100644 --- a/melib/src/async.rs +++ b/melib/src/async.rs @@ -1,3 +1,24 @@ +/* + * meli - async module + * + * 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/>. + */ + /*! * Primitive Async/Wait implementation. * @@ -69,7 +90,7 @@ impl<T> Async<T> { pub fn extract(self) -> T { self.value.unwrap() } - /// Polls worker thread and returns result. + /// Polls worker thread and returns result. pub fn poll(&mut self) -> Result<AsyncStatus, ()> { if self.value.is_some() { return Ok(AsyncStatus::Finished); @@ -99,4 +120,3 @@ impl<T> Async<T> { return Ok(AsyncStatus::Finished); } } - diff --git a/melib/src/conf/mod.rs b/melib/src/conf/mod.rs index 1e718b8c..7092961e 100644 --- a/melib/src/conf/mod.rs +++ b/melib/src/conf/mod.rs @@ -27,9 +27,9 @@ pub mod pager; use pager::PagerSettings; use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; use std::collections::HashMap; use std::fs; +use std::hash::Hasher; use std::path::{Path, PathBuf}; #[derive(Debug, Default, Clone)] diff --git a/melib/src/conf/pager.rs b/melib/src/conf/pager.rs index f30fdbea..54d3a552 100644 --- a/melib/src/conf/pager.rs +++ b/melib/src/conf/pager.rs @@ -1,3 +1,26 @@ +/* + * meli - pager conf module + * + * Copyright 2018 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/>. + */ + +// TODO: Move this to `ui` crate. + fn false_val() -> bool { true } diff --git a/melib/src/lib.rs b/melib/src/lib.rs index 56d7d740..1953a8a1 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -18,10 +18,10 @@ * You should have received a copy of the GNU General Public License * along with meli. If not, see <http://www.gnu.org/licenses/>. */ +pub mod async; pub mod conf; pub mod error; pub mod mailbox; -pub mod async; #[macro_use] extern crate serde_derive; diff --git a/melib/src/mailbox/accounts.rs b/melib/src/mailbox/accounts.rs index 82fb3428..837b5627 100644 --- a/melib/src/mailbox/accounts.rs +++ b/melib/src/mailbox/accounts.rs @@ -23,10 +23,10 @@ * Account management from user configuration. */ +use async::*; use conf::{AccountSettings, Folder}; use mailbox::backends::{Backends, RefreshEventConsumer}; use mailbox::*; -use async::*; use std::ops::{Index, IndexMut}; use std::result; @@ -89,73 +89,73 @@ impl Account { &mut self.workers } fn load_mailbox(&mut self, index: usize, envelopes: Result<Vec<Envelope>>) -> () { - let folder = &self.settings.folders[index]; - if self.sent_folder.is_some() { - let id = self.sent_folder.unwrap(); - if id == index { - self.folders[index] = - Some(Mailbox::new(folder, &None, envelopes)); - } else { - let (sent, cur) = { - let ptr = self.folders.as_mut_ptr(); - unsafe { - use std::slice::from_raw_parts_mut; - ( - from_raw_parts_mut(ptr.offset(id as isize), id + 1), - from_raw_parts_mut(ptr.offset(index as isize), index + 1), - ) - } - }; - let sent_path = &self.settings.folders[id]; - if sent[0].is_none() { - sent[0] = Some(Mailbox::new(sent_path, &None, envelopes.clone())); + let folder = &self.settings.folders[index]; + if self.sent_folder.is_some() { + let id = self.sent_folder.unwrap(); + if id == index { + self.folders[index] = Some(Mailbox::new(folder, &None, envelopes)); + } else { + let (sent, cur) = { + let ptr = self.folders.as_mut_ptr(); + unsafe { + use std::slice::from_raw_parts_mut; + ( + from_raw_parts_mut(ptr.offset(id as isize), id + 1), + from_raw_parts_mut(ptr.offset(index as isize), index + 1), + ) } - cur[0] = Some(Mailbox::new(folder, &sent[0], envelopes)); + }; + let sent_path = &self.settings.folders[id]; + if sent[0].is_none() { + sent[0] = Some(Mailbox::new(sent_path, &None, envelopes.clone())); } - } else { - self.folders[index] = Some(Mailbox::new(folder, &None, envelopes)); - }; + cur[0] = Some(Mailbox::new(folder, &sent[0], envelopes)); + } + } else { + self.folders[index] = Some(Mailbox::new(folder, &None, envelopes)); + }; } pub fn status(&mut self, index: usize) -> result::Result<(), usize> { match self.workers[index].as_mut() { - None => { return Ok(()); }, - Some(ref mut w) => { - match w.poll() { - Ok(AsyncStatus::NoUpdate) => { - return Err(0); - }, - Ok(AsyncStatus::Finished) => { - }, - Ok(AsyncStatus::ProgressReport(n)) => { - return Err(n); - }, - a => { - eprintln!("{:?}", a); - return Err(0); - } + None => { + return Ok(()); + } + Some(ref mut w) => match w.poll() { + Ok(AsyncStatus::NoUpdate) => { + return Err(0); + } + Ok(AsyncStatus::Finished) => {} + Ok(AsyncStatus::ProgressReport(n)) => { + return Err(n); + } + a => { + eprintln!("{:?}", a); + return Err(0); } }, }; - let m = self.workers[index].take().unwrap().extract(); + let m = self.workers[index].take().unwrap().extract(); self.load_mailbox(index, m); self.workers[index] = None; Ok(()) } - } impl Index<usize> for Account { type Output = Result<Mailbox>; fn index(&self, index: usize) -> &Result<Mailbox> { - &self.folders[index].as_ref().expect("BUG: Requested mailbox that is not yet available.") - + &self.folders[index] + .as_ref() + .expect("BUG: Requested mailbox that is not yet available.") } } /// Will panic if mailbox hasn't loaded, ask `status()` first. impl IndexMut<usize> for Account { fn index_mut(&mut self, index: usize) -> &mut Result<Mailbox> { - self.folders[index].as_mut().expect("BUG: Requested mailbox that is not yet available.") + self.folders[index] + .as_mut() + .expect("BUG: Requested mailbox that is not yet available.") } } diff --git a/melib/src/mailbox/backends/imap.rs b/melib/src/mailbox/backends/imap.rs index d33be68b..6ff26cb7 100644 --- a/melib/src/mailbox/backends/imap.rs +++ b/melib/src/mailbox/backends/imap.rs @@ -19,11 +19,11 @@ * along with meli. If not, see <http://www.gnu.org/licenses/>. */ +use async::*; use conf::Folder; use error::Result; -use async::*; use mailbox::backends::{MailBackend, RefreshEventConsumer}; -use mailbox::email::{Envelope, }; +use mailbox::email::Envelope; /// `BackendOp` implementor for Imap #[derive(Debug, Default, Clone)] @@ -35,7 +35,6 @@ impl ImapOp { } } - /* impl BackendOp for ImapOp { diff --git a/melib/src/mailbox/backends/maildir.rs b/melib/src/mailbox/backends/maildir.rs index fe3065fc..5a54bf0b 100644 --- a/melib/src/mailbox/backends/maildir.rs +++ b/melib/src/mailbox/backends/maildir.rs @@ -40,10 +40,10 @@ use std::sync::mpsc::channel; use std::thread; extern crate crossbeam; use memmap::{Mmap, Protection}; -use std::path::PathBuf; use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; use std::fs; +use std::hash::Hasher; +use std::path::PathBuf; /// `BackendOp` implementor for Maildir #[derive(Debug, Default)] @@ -115,7 +115,10 @@ impl BackendOp for MaildirOp { flag } fn set_flag(&mut self, envelope: &mut Envelope, f: &Flag) -> Result<()> { - let idx: usize = self.path.rfind(":2,").ok_or(MeliError::new(format!("Invalid email filename: {:?}", self)))? + 3; + let idx: usize = self.path.rfind(":2,").ok_or(MeliError::new(format!( + "Invalid email filename: {:?}", + self + )))? + 3; let mut new_name: String = self.path[..idx].to_string(); let mut flags = self.fetch_flags(); flags.toggle(*f); @@ -139,13 +142,9 @@ impl BackendOp for MaildirOp { } fs::rename(&self.path, &new_name)?; - envelope.set_operation_token( - Box::new( - BackendOpGenerator::new( - Box::new( move || Box::new(MaildirOp::new(new_name.clone()))) - ) - ) - ); + envelope.set_operation_token(Box::new(BackendOpGenerator::new(Box::new(move || { + Box::new(MaildirOp::new(new_name.clone())) + })))); Ok(()) } } @@ -189,10 +188,8 @@ impl MailBackend for MaildirType { let mut hasher = DefaultHasher::new(); hasher.write(path.as_bytes()); sender.send(RefreshEvent { - folder: format!( - "{}", path - ), - hash: hasher.finish(), + folder: format!("{}", path), + hash: hasher.finish(), }); } _ => {} @@ -201,7 +198,7 @@ impl MailBackend for MaildirType { } } }) - .unwrap(); + .unwrap(); } } @@ -219,9 +216,9 @@ impl MaildirType { p.push(d); if !p.is_dir() { return Err(MeliError::new(format!( - "{} is not a valid maildir folder", - path - ))); + "{} is not a valid maildir folder", + path + ))); } p.pop(); } @@ -236,7 +233,7 @@ impl MaildirType { thread::Builder::new() .name(format!("parsing {:?}", folder)) - .spawn(move || { + .spawn(move || { MaildirType::is_valid(&folder)?; let path = folder.path(); let mut path = PathBuf::from(path); @@ -264,21 +261,24 @@ impl MaildirType { let mut tx = tx.clone(); let s = scope.spawn(move || { let len = chunk.len(); - let size = if len <= 100 { 100 } else { (len / 100) * 100}; - let mut local_r: Vec<Envelope> = Vec::with_capacity(chunk.len()); + let size = if len <= 100 { 100 } else { (len / 100) * 100 }; + let mut local_r: Vec< + Envelope, + > = Vec::with_capacity(chunk.len()); for c in chunk.chunks(size) { let len = c.len(); for e in c { let e_copy = e.to_string(); - if let Some(mut e) = - Envelope::from_token(Box::new(BackendOpGenerator::new(Box::new( - move || Box::new(MaildirOp::new(e_copy.clone())), - )))) { - if e.populate_headers().is_err() { - continue; - } - local_r.push(e); + if let Some(mut e) = Envelope::from_token(Box::new( + BackendOpGenerator::new(Box::new(move || { + Box::new(MaildirOp::new(e_copy.clone())) + })), + )) { + if e.populate_headers().is_err() { + continue; } + local_r.push(e); + } } tx.send(AsyncStatus::ProgressReport(len)); } @@ -294,8 +294,9 @@ impl MaildirType { } tx.send(AsyncStatus::Finished); Ok(r) - }).unwrap() - }; + }) + .unwrap() + }; w.build(handle) } } diff --git a/melib/src/mailbox/backends/mbox.rs b/melib/src/mailbox/backends/mbox.rs index 3d218548..0701666a 100644 --- a/melib/src/mailbox/backends/mbox.rs +++ b/melib/src/mailbox/backends/mbox.rs @@ -19,11 +19,15 @@ * along with meli. If not, see <http://www.gnu.org/licenses/>. */ +/*! + * https://wiki2.dovecot.org/MailboxFormat/mbox + */ + +use async::*; use conf::Folder; use error::Result; -use async::*; use mailbox::backends::{MailBackend, RefreshEventConsumer}; -use mailbox::email::{Envelope, }; +use mailbox::email::Envelope; /// `BackendOp` implementor for Mbox #[derive(Debug, Default, Clone)] diff --git a/melib/src/mailbox/backends/mod.rs b/melib/src/mailbox/backends/mod.rs index 6d75644a..2e998d98 100644 --- a/melib/src/mailbox/backends/mod.rs +++ b/melib/src/mailbox/backends/mod.rs @@ -22,9 +22,9 @@ pub mod imap; pub mod maildir; pub mod mbox; +use async::*; use conf::Folder; use error::Result; -use async::*; use mailbox::backends::imap::ImapType; use mailbox::backends::maildir::MaildirType; use mailbox::backends::mbox::MboxType; diff --git a/melib/src/mailbox/email/attachments.rs b/melib/src/mailbox/email/attachments.rs index 639db8c8..e3ef22d6 100644 --- a/melib/src/mailbox/email/attachments.rs +++ b/melib/src/mailbox/email/attachments.rs @@ -47,7 +47,9 @@ impl Display for MultipartType { MultipartType::Mixed => write!(f, "multipart/mixed"), MultipartType::Alternative => write!(f, "multipart/alternative"), MultipartType::Digest => write!(f, "multipart/digest"), - MultipartType::Unsupported { tag: ref t } => write!(f, "multipart/{}", String::from_utf8_lossy(t)), + MultipartType::Unsupported { tag: ref t } => { + write!(f, "multipart/{}", String::from_utf8_lossy(t)) + } } } } @@ -136,7 +138,7 @@ impl AttachmentBuilder { let mut boundary = None; for (n, v) in params { if n.eq_ignore_ascii_case(b"boundary") { - let mut vec: Vec<u8> = Vec::with_capacity(v.len()+4); + let mut vec: Vec<u8> = Vec::with_capacity(v.len() + 4); vec.extend_from_slice(b"--"); vec.extend(v); vec.extend_from_slice(b"--"); @@ -148,9 +150,7 @@ impl AttachmentBuilder { self.content_type.0 = ContentType::Multipart { boundary: boundary.unwrap(), }; - self.content_type.1 = ContentSubType::Other { - tag: cst.into(), - }; + self.content_type.1 = ContentSubType::Other { tag: cst.into() }; } else if ct.eq_ignore_ascii_case(b"text") { self.content_type.0 = ContentType::Text; if !cst.eq_ignore_ascii_case(b"plain") { @@ -203,25 +203,23 @@ impl AttachmentBuilder { .as_bytes(), ) { Ok(ref s) => { - let s:Vec<u8> = s.clone(); - { - let slice = &s[..]; - if slice.find(b"\r\n").is_some() { - s.replace(b"\r\n", b"\n"); + let s: Vec<u8> = s.clone(); + { + let slice = &s[..]; + if slice.find(b"\r\n").is_some() { + s.replace(b"\r\n", b"\n"); + } } - } - s + s } - _ => self.raw.clone() + _ => self.raw.clone(), }, ContentTransferEncoding::QuotedPrintable => parser::quoted_printable_text(&self.raw) .to_full_result() .unwrap(), ContentTransferEncoding::_7Bit | ContentTransferEncoding::_8Bit - | ContentTransferEncoding::Other { .. } => { - self.raw.clone() - } + | ContentTransferEncoding::Other { .. } => self.raw.clone(), } } pub fn build(self) -> Attachment { @@ -235,7 +233,7 @@ impl AttachmentBuilder { b"mixed" => MultipartType::Mixed, b"alternative" => MultipartType::Alternative, b"digest" => MultipartType::Digest, - _ => MultipartType::Unsupported { tag:tag.clone() }, + _ => MultipartType::Unsupported { tag: tag.clone() }, }, _ => panic!(), }; diff --git a/melib/src/mailbox/email/mod.rs b/melib/src/mailbox/email/mod.rs index 53aba990..c81e8959 100644 --- a/melib/src/mailbox/email/mod.rs +++ b/melib/src/mailbox/email/mod.rs @@ -25,19 +25,19 @@ pub mod attachments; pub mod parser; -use parser::BytesExt; pub use self::attachments::*; use error::{MeliError, Result}; use mailbox::backends::BackendOpGenerator; +use parser::BytesExt; +use std::borrow::Cow; use std::cmp::Ordering; +use std::collections::hash_map::DefaultHasher; use std::fmt; +use std::hash::Hasher; use std::option::Option; use std::string::String; use std::sync::Arc; -use std::borrow::Cow; -use std::collections::hash_map::DefaultHasher; -use std::hash::Hasher; use chrono; use chrono::TimeZone; @@ -257,7 +257,7 @@ impl Envelope { Some(e) } pub fn set_operation_token(&mut self, operation_token: Box<BackendOpGenerator>) { - self.operation_token= Arc::new(operation_token); + self.operation_token = Arc::new(operation_token); } pub fn populate_headers(&mut self) -> Result<()> { @@ -373,7 +373,10 @@ impl Envelope { } pub fn bytes(&self) -> Vec<u8> { let mut operation = self.operation_token.generate(); - operation.as_bytes().map(|v| v.into()).unwrap_or_else(|_| Vec::new()) + operation + .as_bytes() + .map(|v| v.into()) + .unwrap_or_else(|_| Vec::new()) } pub fn body(&self) -> Attachment { let mut operation = self.operation_token.generate(); @@ -385,7 +388,7 @@ impl Envelope { eprintln!("error in parsing mail\n{}", operation.description()); let error_msg = b"Mail cannot be shown because of errors."; let mut builder = AttachmentBuilder::new(error_msg); - return builder.build() + return builder.build(); } }; let mut builder = AttachmentBuilder::new(body); @@ -513,7 +516,8 @@ impl Envelope { } pub fn references(&self) -> Vec<&MessageID> { match self.references { - Some(ref s) => s.refs + Some(ref s) => s + .refs .iter() .fold(Vec::with_capacity(s.refs.len()), |mut acc, x| { acc.push(x); diff --git a/melib/src/mailbox/email/parser.rs b/melib/src/mailbox/email/parser.rs index b383ac10..487ffebc 100644 --- a/melib/src/mailbox/email/parser.rs +++ b/melib/src/mailbox/email/parser.rs @@ -57,7 +57,8 @@ impl BytesExt for [u8] { } // https://stackoverflow.com/a/35907071 fn find(&self, needle: &[u8]) -> Option<usize> { - self.windows(needle.len()).position(|window| window == needle) + self.windows(needle.len()) + .position(|window| window == needle) } fn replace(&self, from: &[u8], to: &[u8]) -> Vec<u8> { let mut ret = self.to_vec(); @@ -68,7 +69,6 @@ impl BytesExt for [u8] { } } - fn quoted_printable_byte(input: &[u8]) -> IResult<&[u8], u8> { if input.len() < 3 { IResult::Incomplete(Needed::Size(1)) @@ -107,9 +107,9 @@ fn header_value(input: &[u8]) -> IResult<&[u8], &[u8]> { let input_len = input.len(); for (i, x) in input.iter().enumerate() { if *x == b'\n' { - if (i + 1) < input_len && input[i + 1] != b' ' && input[i + 1] != b'\t' { - return IResult::Done(&input[(i + 1)..], &input[0..i]); - } else if i + 1 == input_len { + if ((i + 1) < input_len && input[i + 1] != b' ' && input[i + 1] != b'\t') + || i + 1 == input_len + { return IResult::Done(&input[(i + 1)..], &input[0..i]); } } @@ -281,7 +281,8 @@ named!( acc += x.len(); acc }); - let bytes = list.iter() + let bytes = list + .iter() .fold(Vec::with_capacity(list_len), |mut acc, x| { acc.append(&mut x.clone()); acc @@ -636,8 +637,9 @@ pub fn date(input: &[u8]) -> Option<chrono::DateTime<chrono::FixedOffset>> { let parsed_result = phrase(&eat_comments(input)) .to_full_result() .unwrap() - .replace(b"-",b"+"); - chrono::DateTime::parse_from_rfc2822(String::from_utf8_lossy(parsed_result.trim()).as_ref()).ok() + .replace(b"-", b"+"); + chrono::DateTime::parse_from_rfc2822(String::from_utf8_lossy(parsed_result.trim()).as_ref()) + .ok() } #[test] @@ -712,10 +714,11 @@ fn test_attachments() { named!( content_type_parameter<(&[u8], &[u8])>, do_parse!( - tag!(";") >> - name: terminated!(ws!(take_until!("=")) , tag!("=")) >> - value: ws!(alt_complete!( delimited!(tag!("\""), take_until!("\""), tag!("\"")) | is_not!(";"))) >> - ({ (name, value) }) + tag!(";") >> name: terminated!(ws!(take_until!("=")), tag!("=")) + >> value: + ws!(alt_complete!( + delimited!(tag!("\""), take_until!("\""), tag!("\"")) | is_not!(";") + )) >> ({ (name, value) }) ) ); diff --git a/melib/src/mailbox/thread.rs b/melib/src/mailbox/thread.rs index 8684ab93..fda6db66 100644 --- a/melib/src/mailbox/thread.rs +++ b/melib/src/mailbox/thread.rs @@ -385,7 +385,8 @@ pub fn build_threads( if indentation > 0 && thread.has_message() { let subject = collection[thread.message().unwrap()].subject(); if subject == root_subject - || subject.starts_with("Re: ") && subject.as_ref().ends_with(root_subject.as_ref()) + || subject.starts_with("Re: ") + && subject.as_ref().ends_with(root_subject.as_ref()) { threads[i].set_show_subject(false); } @@ -63,7 +63,7 @@ fn make_input_thread( UIMode::Fork, ))); }, - rx, + &rx, ) }) .unwrap() @@ -134,11 +134,11 @@ fn main() { receiver.recv() -> r => { match r.unwrap() { ThreadEvent::Input(Key::Ctrl('z')) => { - state.to_main_screen(); + state.switch_to_main_screen(); //_thread_handler.join().expect("Couldn't join on the associated thread"); let self_pid = nix::unistd::Pid::this(); nix::sys::signal::kill(self_pid, nix::sys::signal::Signal::SIGSTOP).unwrap(); - state.to_alternate_screen(); + state.switch_to_alternate_screen(); _thread_handler = make_input_thread(sender.clone(), rx.clone()); // BUG: thread sends input event after one received key state.update_size(); diff --git a/ui/src/components/mail/listing.rs b/ui/src/components/mail/listing.rs index 01cd46cf..15c18e9c 100644 --- a/ui/src/components/mail/listing.rs +++ b/ui/src/components/mail/listing.rs @@ -1,8 +1,28 @@ +/* + * meli - ui crate. + * + * Copyright 2017-2018 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/>. + */ + use super::*; const MAX_COLS: usize = 500; - /// A list of all mail (`Envelope`s) in a `Mailbox`. On `\n` it opens the `Envelope` content in a /// `MailView`. pub struct MailListing { @@ -21,6 +41,12 @@ pub struct MailListing { view: Option<MailView>, } +impl Default for MailListing { + fn default() -> Self { + Self::new() + } +} + impl MailListing { /// Helper function to format entry strings for MailListing */ /* TODO: Make this configurable */ @@ -67,11 +93,9 @@ impl MailListing { // Get mailbox as a reference. // loop { - match context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) { - Ok(()) => { break; }, - Err(_) => { - // TODO: Show progress visually - } + // TODO: Show progress visually + if let Ok(()) = context.accounts[self.cursor_pos.0].status(self.cursor_pos.1) { + break; } } let mailbox = &mut context.accounts[self.cursor_pos.0][self.cursor_pos.1] @@ -92,7 +116,7 @@ impl MailListing { Color::Default, ((0, 0), (MAX_COLS - 1, 0)), true, - ); + ); self.content = content; return; } @@ -101,31 +125,29 @@ impl MailListing { if threaded { let mut indentations: Vec<bool |