Browse Source

Fix all clippy warnings in `meli` crate

tables
Manos Pitsidianakis 1 month ago
parent
commit
9cb66ef818
  1. 4
      config_macros.rs
  2. 38
      src/bin.rs
  3. 14
      src/command.rs
  4. 54
      src/components/contacts.rs
  5. 10
      src/components/contacts/contact_list.rs
  6. 113
      src/components/mail/compose.rs
  7. 6
      src/components/mail/compose/edit_attachments.rs
  8. 14
      src/components/mail/compose/gpg.rs
  9. 55
      src/components/mail/listing.rs
  10. 25
      src/components/mail/listing/compact.rs
  11. 19
      src/components/mail/listing/conversations.rs
  12. 8
      src/components/mail/listing/offline.rs
  13. 13
      src/components/mail/listing/plain.rs
  14. 13
      src/components/mail/listing/thread.rs
  15. 2
      src/components/mail/pgp.rs
  16. 6
      src/components/mail/status.rs
  17. 264
      src/components/mail/view.rs
  18. 206
      src/components/mail/view/envelope.rs
  19. 41
      src/components/mail/view/thread.rs
  20. 9
      src/components/notifications.rs
  21. 31
      src/components/utilities.rs
  22. 6
      src/components/utilities/dialogs.rs
  23. 18
      src/components/utilities/pager.rs
  24. 12
      src/components/utilities/widgets.rs
  25. 23
      src/conf.rs
  26. 104
      src/conf/accounts.rs
  27. 4
      src/conf/overrides.rs
  28. 17
      src/conf/shortcuts.rs
  29. 11
      src/conf/tags.rs
  30. 158
      src/conf/themes.rs
  31. 36
      src/mailcap.rs
  32. 40
      src/sqlite3.rs
  33. 73
      src/state.rs
  34. 12
      src/terminal/cells.rs
  35. 15
      src/terminal/color.rs
  36. 52
      src/terminal/embed/grid.rs
  37. 16
      src/terminal/keys.rs
  38. 8
      src/types.rs
  39. 3
      src/types/helpers.rs

4
config_macros.rs

@ -50,7 +50,9 @@ pub fn override_derive(filenames: &[(&str, &str)]) {
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
//! This module is automatically generated by build.rs.
#![allow(clippy::derivable_impls)]
//! This module is automatically generated by config_macros.rs.
use super::*;
"##

38
src/bin.rs

@ -42,6 +42,8 @@ extern crate serde_json;
extern crate smallvec;
extern crate termion;
use structopt::StructOpt;
#[global_allocator]
static GLOBAL: System = System;
@ -120,6 +122,7 @@ fn notify(
Ok(r)
}
#[cfg(feature = "cli-docs")]
fn parse_manpage(src: &str) -> Result<ManPages> {
match src {
"" | "meli" | "main" => Ok(ManPages::Main),
@ -132,8 +135,7 @@ fn parse_manpage(src: &str) -> Result<ManPages> {
}
}
use structopt::StructOpt;
#[cfg(feature = "cli-docs")]
#[derive(Copy, Clone, Debug)]
/// Choose manpage
enum ManPages {
@ -193,9 +195,11 @@ enum SubCommand {
#[derive(Debug, StructOpt)]
struct ManOpt {
#[structopt(default_value = "meli", possible_values=&["meli", "conf", "themes"], value_name="PAGE", parse(try_from_str = parse_manpage))]
#[cfg(feature = "cli-docs")]
page: ManPages,
/// If true, output text in stdout instead of spawning $PAGER.
#[structopt(long = "no-raw", alias = "no-raw", value_name = "bool")]
#[cfg(feature = "cli-docs")]
no_raw: Option<Option<bool>>,
}
@ -243,7 +247,7 @@ fn run_app(opt: Opt) -> Result<()> {
#[cfg(feature = "cli-docs")]
Some(SubCommand::Man(manopt)) => {
let ManOpt { page, no_raw } = manopt;
const MANPAGES: [&'static [u8]; 3] = [
const MANPAGES: [&[u8]; 3] = [
include_bytes!(concat!(env!("OUT_DIR"), "/meli.txt.gz")),
include_bytes!(concat!(env!("OUT_DIR"), "/meli.conf.txt.gz")),
include_bytes!(concat!(env!("OUT_DIR"), "/meli-themes.txt.gz")),
@ -255,10 +259,9 @@ fn run_app(opt: Opt) -> Result<()> {
str::parse::<usize>(unsafe {
std::str::from_utf8_unchecked(gz.header().unwrap().comment().unwrap())
})
.expect(&format!(
"{:?} was not compressed with size comment header",
page
)),
.unwrap_or_else(|_| {
panic!("{:?} was not compressed with size comment header", page)
}),
);
gz.read_to_string(&mut v)?;
@ -271,19 +274,18 @@ fn run_app(opt: Opt) -> Result<()> {
return Ok(());
}
}
} else {
if unsafe { libc::isatty(libc::STDOUT_FILENO) != 1 } {
println!("{}", &v);
return Ok(());
}
} else if unsafe { libc::isatty(libc::STDOUT_FILENO) != 1 } {
println!("{}", &v);
return Ok(());
}
use std::process::{Command, Stdio};
let mut handle = Command::new(std::env::var("PAGER").unwrap_or("more".to_string()))
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?;
let mut handle =
Command::new(std::env::var("PAGER").unwrap_or_else(|_| "more".to_string()))
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()?;
handle.stdin.take().unwrap().write_all(v.as_bytes())?;
handle.wait()?;
@ -314,7 +316,7 @@ fn run_app(opt: Opt) -> Result<()> {
}
Some(SubCommand::PrintLoadedThemes) => {
let s = conf::FileSettings::new()?;
print!("{}", s.terminal.themes.to_string());
print!("{}", s.terminal.themes);
return Ok(());
}
Some(SubCommand::PrintDefaultTheme) => {

14
src/command.rs

@ -116,7 +116,7 @@ impl TokenStream {
}
*s = &s[ptr..];
//println!("\t before s.is_empty() {:?} {:?}", t, s);
if s.is_empty() || &*s == &" " {
if s.is_empty() || *s == " " {
match t.inner() {
Literal(lit) => {
sugg.insert(format!("{}{}", if s.is_empty() { " " } else { "" }, lit));
@ -126,7 +126,7 @@ impl TokenStream {
//println!("adding empty suggestions for {:?}", t);
let mut _s = *s;
let mut m = t.matches(&mut _s, sugg);
tokens.extend(m.drain(..));
tokens.append(&mut m);
}
}
Seq(_s) => {}
@ -167,7 +167,7 @@ impl TokenStream {
let mut _s = *s;
let mut m = t.matches(&mut _s, sugg);
if !m.is_empty() {
tokens.extend(m.drain(..));
tokens.append(&mut m);
//println!("_s is empty {}", _s.is_empty());
cont = !_s.is_empty();
*s = _s;
@ -262,7 +262,7 @@ define_commands!([
desc: "set [seen/unseen], toggles message's Seen flag.",
tokens: &[One(Literal("set")), One(Alternatives(&[to_stream!(One(Literal("seen"))), to_stream!(One(Literal("unseen")))]))],
parser: (
fn seen_flag<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> {
fn seen_flag(input: &'_ [u8]) -> IResult<&'_ [u8], Action> {
let (input, _) = tag("set")(input.trim())?;
let (input, _) = is_a(" ")(input)?;
let (input, ret) = alt((map(tag("seen"), |_| Listing(SetSeen)), map(tag("unseen"), |_| Listing(SetUnseen))))(input)?;
@ -275,7 +275,7 @@ define_commands!([
desc: "delete message",
tokens: &[One(Literal("delete"))],
parser: (
fn delete_message<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> {
fn delete_message(input: &'_ [u8]) -> IResult<&'_ [u8], Action> {
let (input, ret) = map(preceded(tag("delete"), eof), |_| Listing(Delete))(input)?;
let (input, _) = eof(input)?;
Ok((input, ret))
@ -536,7 +536,7 @@ define_commands!([
desc: "filter EXECUTABLE ARGS",
tokens: &[One(Literal("filter")), One(Filepath), ZeroOrMore(QuotedStringValue)],
parser:(
fn filter<'a>(input: &'a [u8]) -> IResult<&'a [u8], Action> {
fn filter(input: &'_ [u8]) -> IResult<&'_ [u8], Action> {
let (input, _) = tag("filter")(input.trim())?;
let (input, _) = is_a(" ")(input)?;
let (input, cmd) = map_res(not_line_ending, std::str::from_utf8)(input)?;
@ -1080,7 +1080,7 @@ pub fn command_completion_suggestions(input: &str) -> Vec<String> {
}
if let Some((s, Filepath)) = _m.last() {
let p = std::path::Path::new(s);
sugg.extend(p.complete(true).into_iter().map(|m| m.into()));
sugg.extend(p.complete(true).into_iter());
}
}
sugg.into_iter()

54
src/components/contacts.rs

@ -29,7 +29,7 @@ pub use self::contact_list::*;
#[derive(Debug)]
enum ViewMode {
ReadOnly,
Discard(UIDialog<char>),
Discard(Box<UIDialog<char>>),
Edit,
//New,
}
@ -113,27 +113,21 @@ impl ContactManager {
self.form = FormWidget::new(("Save".into(), true));
self.form.add_button(("Cancel(Esc)".into(), false));
self.form
.push(("NAME".into(), self.card.name().to_string().into()));
.push(("NAME".into(), self.card.name().to_string()));
self.form.push((
"ADDITIONAL NAME".into(),
self.card.additionalname().to_string().into(),
));
self.form.push((
"NAME PREFIX".into(),
self.card.name_prefix().to_string().into(),
));
self.form.push((
"NAME SUFFIX".into(),
self.card.name_suffix().to_string().into(),
self.card.additionalname().to_string(),
));
self.form
.push(("E-MAIL".into(), self.card.email().to_string().into()));
.push(("NAME PREFIX".into(), self.card.name_prefix().to_string()));
self.form
.push(("URL".into(), self.card.url().to_string().into()));
.push(("NAME SUFFIX".into(), self.card.name_suffix().to_string()));
self.form
.push(("KEY".into(), self.card.key().to_string().into()));
.push(("E-MAIL".into(), self.card.email().to_string()));
self.form.push(("URL".into(), self.card.url().to_string()));
self.form.push(("KEY".into(), self.card.key().to_string()));
for (k, v) in self.card.extra_properties() {
self.form.push((k.to_string().into(), v.to_string().into()));
self.form.push((k.to_string().into(), v.to_string()));
}
}
@ -168,26 +162,20 @@ impl Component for ContactManager {
(set_y(upper_left, get_y(upper_left) + 2), bottom_right),
context,
);
match self.mode {
ViewMode::Discard(ref mut selector) => {
/* Let user choose whether to quit with/without saving or cancel */
selector.draw(grid, area, context);
}
_ => {}
if let ViewMode::Discard(ref mut selector) = self.mode {
/* Let user choose whether to quit with/without saving or cancel */
selector.draw(grid, area, context);
}
context.dirty_areas.push_back(area);
}
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
match event {
UIEvent::ConfigReload { old_settings: _ } => {
self.theme_default = crate::conf::value(context, "theme_default");
self.content = CellBuffer::new_with_context(100, 1, None, context);
self.initialized = false;
self.set_dirty(true);
}
_ => {}
if let UIEvent::ConfigReload { old_settings: _ } = event {
self.theme_default = crate::conf::value(context, "theme_default");
self.content = CellBuffer::new_with_context(100, 1, None, context);
self.initialized = false;
self.set_dirty(true);
}
match self.mode {
ViewMode::Discard(ref mut selector) => {
@ -209,9 +197,7 @@ impl Component for ContactManager {
match self.form.buttons_result() {
None => {}
Some(true) => {
let fields = std::mem::replace(&mut self.form, FormWidget::default())
.collect()
.unwrap();
let fields = std::mem::take(&mut self.form).collect().unwrap();
let fields: HashMap<String, String> = fields
.into_iter()
.map(|(s, v)| {
@ -290,7 +276,7 @@ impl Component for ContactManager {
let parent_id = self.parent_id;
/* Play it safe and ask user for confirmation */
self.mode = ViewMode::Discard(UIDialog::new(
self.mode = ViewMode::Discard(Box::new(UIDialog::new(
"this contact has unsaved changes",
vec![
('x', "quit without saving".to_string()),
@ -305,7 +291,7 @@ impl Component for ContactManager {
_ => None,
})),
context,
));
)));
self.set_dirty(true);
false
}

10
src/components/contacts/contact_list.rs

@ -34,7 +34,7 @@ enum ViewMode {
#[derive(Debug)]
struct AccountMenuEntry {
name: String,
hash: AccountHash,
_hash: AccountHash,
// Index in the config account vector.
index: usize,
}
@ -82,7 +82,7 @@ impl ContactList {
.enumerate()
.map(|(i, (h, a))| AccountMenuEntry {
name: a.name().to_string(),
hash: *h,
_hash: *h,
index: i,
})
.collect();
@ -216,7 +216,6 @@ impl ContactList {
((0, 0), (message.len() - 1, 0)),
None,
);
return;
}
}
@ -241,7 +240,7 @@ impl ContactList {
self.dirty = false;
let mut y = get_y(upper_left);
for a in &self.accounts {
self.print_account(grid, (set_y(upper_left, y), bottom_right), &a, context);
self.print_account(grid, (set_y(upper_left, y), bottom_right), a, context);
y += 1;
}
@ -393,6 +392,7 @@ impl ContactList {
}
}
PageMovement::PageDown(multiplier) => {
#[allow(clippy::comparison_chain)]
if self.new_cursor_pos + rows * multiplier < self.length {
self.new_cursor_pos += rows * multiplier;
} else if self.new_cursor_pos + rows * multiplier > self.length {
@ -782,7 +782,7 @@ impl Component for ContactList {
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
return true;
}
UIEvent::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
UIEvent::Input(Key::Char(c)) if ('0'..='9').contains(&c) => {
self.cmd_buf.push(c);
context
.replies

113
src/components/mail/compose.rs

@ -116,19 +116,11 @@ enum ViewMode {
impl ViewMode {
fn is_edit(&self) -> bool {
if let ViewMode::Edit = self {
true
} else {
false
}
matches!(self, ViewMode::Edit)
}
fn is_edit_attachments(&self) -> bool {
if let ViewMode::EditAttachments { .. } = self {
true
} else {
false
}
matches!(self, ViewMode::EditAttachments { .. })
}
}
@ -160,7 +152,7 @@ impl Composer {
form: FormWidget::default(),
mode: ViewMode::Edit,
#[cfg(feature = "gpgme")]
gpg_state: gpg::GpgComposeState::new(),
gpg_state: gpg::GpgComposeState::default(),
dirty: true,
has_changes: false,
embed_area: ((0, 0), (0, 0)),
@ -249,11 +241,7 @@ impl Composer {
ret.draft
.set_header("In-Reply-To", envelope.message_id_display().into());
if let Some(reply_to) = envelope
.other_headers()
.get("To")
.and_then(|v| v.as_str().try_into().ok())
{
if let Some(reply_to) = envelope.other_headers().get("To").map(|v| v.as_str()) {
let to: &str = reply_to;
let extra_identities = &account.settings.account.extra_identities;
if let Some(extra) = extra_identities
@ -288,30 +276,26 @@ impl Composer {
.and_then(|v| v.as_str().try_into().ok())
{
to.insert(reply_to);
} else if let Some(reply_to) = envelope
.other_headers()
.get("Reply-To")
.and_then(|v| v.as_str().try_into().ok())
{
to.insert(reply_to);
} else {
if let Some(reply_to) = envelope
.other_headers()
.get("Reply-To")
.and_then(|v| v.as_str().try_into().ok())
{
to.insert(reply_to);
} else {
to.extend(envelope.from().iter().cloned());
}
to.extend(envelope.from().iter().cloned());
}
to.extend(envelope.to().iter().cloned());
if let Some(ours) = TryInto::<Address>::try_into(
if let Ok(ours) = TryInto::<Address>::try_into(
crate::components::mail::get_display_name(context, coordinates.0).as_str(),
)
.ok()
{
) {
to.remove(&ours);
}
ret.draft.set_header("To", {
let mut ret: String =
to.into_iter()
.fold(String::new(), |mut s: String, n: Address| {
s.extend(n.to_string().chars());
s.push_str(&n.to_string());
s.push_str(", ");
s
});
@ -320,14 +304,12 @@ impl Composer {
ret
});
ret.draft.set_header("Cc", envelope.field_cc_to_string());
} else if let Some(reply_to) = envelope.other_headers().get("Mail-Reply-To") {
ret.draft.set_header("To", reply_to.to_string());
} else if let Some(reply_to) = envelope.other_headers().get("Reply-To") {
ret.draft.set_header("To", reply_to.to_string());
} else {
if let Some(reply_to) = envelope.other_headers().get("Mail-Reply-To") {
ret.draft.set_header("To", reply_to.to_string());
} else if let Some(reply_to) = envelope.other_headers().get("Reply-To") {
ret.draft.set_header("To", reply_to.to_string());
} else {
ret.draft.set_header("To", envelope.field_from_to_string());
}
ret.draft.set_header("To", envelope.field_from_to_string());
}
ret.draft.body = {
let mut ret = attribution_string(
@ -481,7 +463,7 @@ To: {}
let header_values = self.form.values_mut();
let draft_header_map = self.draft.headers_mut();
for (k, v) in draft_header_map.iter_mut() {
if let Some(ref vn) = header_values.get(k.as_str()) {
if let Some(vn) = header_values.get(k.as_str()) {
*v = vn.as_str().to_string();
}
}
@ -498,23 +480,22 @@ To: {}
if k == "To" || k == "Cc" || k == "Bcc" {
self.form.push_cl((
k.into(),
headers[k].to_string().into(),
headers[k].to_string(),
Box::new(move |c, term| {
let book: &AddressBook = &c.accounts[&account_hash].address_book;
let results: Vec<String> = book.search(term);
results
.into_iter()
.map(|r| AutoCompleteEntry::from(r))
.map(AutoCompleteEntry::from)
.collect::<Vec<AutoCompleteEntry>>()
}),
));
} else if k == "From" {
self.form.push_cl((
k.into(),
headers[k].to_string().into(),
headers[k].to_string(),
Box::new(move |c, _term| {
let results: Vec<(String, String)> = c
.accounts
c.accounts
.values()
.map(|acc| {
let addr = if let Some(display_name) =
@ -548,15 +529,12 @@ To: {}
(addr, desc)
})
.collect::<Vec<_>>();
results
.into_iter()
.map(|r| AutoCompleteEntry::from(r))
.map(AutoCompleteEntry::from)
.collect::<Vec<AutoCompleteEntry>>()
}),
));
} else {
self.form.push((k.into(), headers[k].to_string().into()));
self.form.push((k.into(), headers[k].to_string()));
}
}
}
@ -858,7 +836,7 @@ impl Component for Composer {
clear_area(grid, embed_area, theme_default);
copy_area(
grid,
&guard.grid.buffer(),
guard.grid.buffer(),
embed_area,
((0, 0), pos_dec(guard.grid.terminal_size, (1, 1))),
);
@ -871,7 +849,7 @@ impl Component for Composer {
let guard = embed_pty.lock().unwrap();
copy_area(
grid,
&guard.grid.buffer(),
guard.grid.buffer(),
embed_area,
((0, 0), pos_dec(guard.grid.terminal_size, (1, 1))),
);
@ -1120,8 +1098,7 @@ impl Component for Composer {
UIEvent::FinishedUIDialog(id, ref mut result),
) if selector.id() == *id => {
if let Some(to_val) = result.downcast_mut::<String>() {
self.draft
.set_header("To", std::mem::replace(to_val, String::new()));
self.draft.set_header("To", std::mem::take(to_val));
self.update_form();
}
self.mode = ViewMode::Edit;
@ -1677,7 +1654,7 @@ impl Component for Composer {
log(
format!(
"Executing: sh -c \"{}\"",
editor_command.replace("\"", "\\\"")
editor_command.replace('"', "\\\"")
),
DEBUG,
);
@ -1804,9 +1781,10 @@ impl Component for Composer {
return true;
}
Action::Compose(ComposeAction::AddAttachmentFilePicker(ref command)) => {
let command = if let Some(ref cmd) = command
.as_ref()
.or_else(|| context.settings.terminal.file_picker_command.as_ref())
let command = if let Some(cmd) =
command
.as_ref()
.or(context.settings.terminal.file_picker_command.as_ref())
{
cmd.as_str()
} else {
@ -1823,7 +1801,7 @@ impl Component for Composer {
}
log(
format!("Executing: sh -c \"{}\"", command.replace("\"", "\\\"")),
format!("Executing: sh -c \"{}\"", command.replace('"', "\\\"")),
DEBUG,
);
match Command::new("sh")
@ -1838,7 +1816,7 @@ impl Component for Composer {
debug!(&String::from_utf8_lossy(&stderr));
for path in stderr.split(|c| [b'\0', b'\t', b'\n'].contains(c)) {
match melib::email::compose::attachment_from_file(
&String::from_utf8_lossy(&path).as_ref(),
&String::from_utf8_lossy(path).as_ref(),
) {
Ok(a) => {
self.draft.attachments_mut().push(a);
@ -1848,7 +1826,7 @@ impl Component for Composer {
context.replies.push_back(UIEvent::Notification(
Some(format!(
"could not add attachment: {}",
String::from_utf8_lossy(&path)
String::from_utf8_lossy(path)
)),
err.to_string(),
Some(NotificationType::Error(
@ -1984,7 +1962,7 @@ impl Component for Composer {
Some(Box::new(move |id: ComponentId, results: &[char]| {
Some(UIEvent::FinishedUIDialog(
id,
Box::new(results.get(0).map(|c| *c).unwrap_or('n')),
Box::new(results.get(0).copied().unwrap_or('n')),
))
})),
context,
@ -2033,7 +2011,7 @@ impl Component for Composer {
Some(Box::new(move |id: ComponentId, results: &[char]| {
Some(UIEvent::FinishedUIDialog(
id,
Box::new(results.get(0).map(|c| *c).unwrap_or('n')),
Box::new(results.get(0).copied().unwrap_or('n')),
))
})),
context,
@ -2136,7 +2114,7 @@ pub fn send_draft(
let body: AttachmentBuilder = Attachment::new(
content_type,
Default::default(),
std::mem::replace(&mut draft.body, String::new()).into_bytes(),
std::mem::take(&mut draft.body).into_bytes(),
)
.into();
draft.attachments.insert(0, body);
@ -2195,6 +2173,7 @@ pub fn send_draft_async(
let format_flowed = *account_settings!(context[account_hash].composing.format_flowed);
let event_sender = context.sender.clone();
#[cfg(feature = "gpgme")]
#[allow(clippy::type_complexity)]
let mut filters_stack: Vec<
Box<
dyn FnOnce(
@ -2207,7 +2186,7 @@ pub fn send_draft_async(
#[cfg(feature = "gpgme")]
if gpg_state.sign_mail.is_true() && !gpg_state.encrypt_mail.is_true() {
filters_stack.push(Box::new(crate::components::mail::pgp::sign_filter(
gpg_state.sign_keys.clone(),
gpg_state.sign_keys,
)?));
} else if gpg_state.encrypt_mail.is_true() {
filters_stack.push(Box::new(crate::components::mail::pgp::encrypt_filter(
@ -2216,7 +2195,7 @@ pub fn send_draft_async(
} else {
None
},
gpg_state.encrypt_keys.clone(),
gpg_state.encrypt_keys,
)?));
}
let send_mail = account_settings!(context[account_hash].composing.send_mail).clone();
@ -2233,11 +2212,11 @@ pub fn send_draft_async(
let mut body: AttachmentBuilder = Attachment::new(
content_type,
Default::default(),
std::mem::replace(&mut draft.body, String::new()).into_bytes(),
std::mem::take(&mut draft.body).into_bytes(),
)
.into();
if !draft.attachments.is_empty() {
let mut parts = std::mem::replace(&mut draft.attachments, Vec::new());
let mut parts = std::mem::take(&mut draft.attachments);
parts.insert(0, body);
let boundary = ContentType::make_boundary(&parts);
body = Attachment::new(
@ -2261,7 +2240,7 @@ pub fn send_draft_async(
let message = Arc::new(draft.finalise()?);
let ret = send_cb(message.clone()).await;
let is_ok = ret.is_ok();
if !is_ok || (store_sent_mail && is_ok) {
if !is_ok || store_sent_mail {
event_sender
.send(ThreadEvent::UIEvent(UIEvent::Callback(CallbackFn(
Box::new(move |context| {

6
src/components/mail/compose/edit_attachments.rs

@ -37,7 +37,7 @@ impl Default for EditAttachmentCursor {
pub enum EditAttachmentMode {
Overview,
Edit {
inner: FormWidget<FormButtonActions>,
inner: Box<FormWidget<FormButtonActions>>,
no: usize,
},
}
@ -68,7 +68,7 @@ impl EditAttachments {
}
impl EditAttachmentsRefMut<'_, '_> {
fn new_edit_widget(&self, no: usize) -> Option<FormWidget<FormButtonActions>> {
fn new_edit_widget(&self, no: usize) -> Option<Box<FormWidget<FormButtonActions>>> {
if no >= self.draft.attachments().len() {
return None;
}
@ -80,7 +80,7 @@ impl EditAttachmentsRefMut<'_, '_> {
ret.add_button(("Cancel".into(), FormButtonActions::Cancel));
ret.push(("Filename".into(), filename.unwrap_or_default().to_string()));
ret.push(("Mime type".into(), mime_type.to_string()));
Some(ret)
Some(Box::new(ret))
}
}

14
src/components/mail/compose/gpg.rs

@ -36,7 +36,7 @@ pub enum KeySelection {
err: MeliError,
},
Loaded {
widget: UIDialog<melib::gpgme::Key>,
widget: Box<UIDialog<melib::gpgme::Key>>,
keys: Vec<melib::gpgme::Key>,
},
}
@ -129,7 +129,7 @@ impl Component for KeySelection {
match Self::new(
*secret,
*local,
std::mem::replace(pattern, String::new()),
std::mem::take(pattern),
*allow_remote_lookup,
context,
) {
@ -166,7 +166,7 @@ impl Component for KeySelection {
}
return false;
}
let mut widget = UIDialog::new(
let mut widget = Box::new(UIDialog::new(
"select key",
keys.iter()
.map(|k| {
@ -185,12 +185,12 @@ impl Component for KeySelection {
move |id: ComponentId, results: &[melib::gpgme::Key]| {
Some(UIEvent::FinishedUIDialog(
id,
Box::new(results.get(0).map(|k| k.clone())),
Box::new(results.get(0).cloned()),
))
},
)),
context,
);
));
widget.set_dirty(true);
*self = KeySelection::Loaded { widget, keys };
}
@ -275,8 +275,8 @@ pub struct GpgComposeState {
pub sign_keys: Vec<melib::gpgme::Key>,
}
impl GpgComposeState {
pub fn new() -> Self {
impl Default for GpgComposeState {
fn default() -> Self {
GpgComposeState {
sign_mail: ToggleFlag::Unset,
encrypt_mail: ToggleFlag::Unset,

55
src/components/mail/listing.rs

@ -176,7 +176,6 @@ struct AccountMenuEntry {
name: String,
hash: AccountHash,
index: usize,
visible: bool,
entries: SmallVec<[MailboxMenuEntry; 16]>,
}
@ -380,7 +379,7 @@ pub trait MailListingTrait: ListingTrait {
.map(|&env_hash| account.operation(env_hash).and_then(|mut op| op.as_bytes()))
.collect::<Result<Vec<_>>>();
let path_ = path.to_path_buf();
let format = format.clone().unwrap_or_default();
let format = (*format).unwrap_or_default();
let collection = account.collection.clone();
let (sender, mut receiver) = crate::jobs::oneshot::channel();
let fut: Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>> =
@ -521,11 +520,11 @@ pub trait ListingTrait: Component {
#[derive(Debug)]
pub enum ListingComponent {
Plain(PlainListing),
Threaded(ThreadListing),
Compact(CompactListing),
Conversations(ConversationsListing),
Offline(OfflineListing),
Plain(Box<PlainListing>),
Threaded(Box<ThreadListing>),
Compact(Box<CompactListing>),
Conversations(Box<ConversationsListing>),
Offline(Box<OfflineListing>),
}
use crate::ListingComponent::*;
@ -534,11 +533,11 @@ impl core::ops::Deref for ListingComponent {
fn deref(&self) -> &Self::Target {
match &self {
Compact(ref l) => l,
Plain(ref l) => l,
Threaded(ref l) => l,
Conversations(ref l) => l,
Offline(ref l) => l,
Compact(ref l) => l.as_ref(),
Plain(ref l) => l.as_ref(),
Threaded(ref l) => l.as_ref(),
Conversations(ref l) => l.as_ref(),
Offline(ref l) => l.as_ref(),
}
}
}
@ -546,11 +545,11 @@ impl core::ops::Deref for ListingComponent {
impl core::ops::DerefMut for ListingComponent {
fn deref_mut(&mut self) -> &mut (dyn MailListingTrait + 'static) {
match self {
Compact(l) => l,
Plain(l) => l,
Threaded(l) => l,
Conversations(l) => l,
Offline(l) => l,
Compact(l) => l.as_mut(),
Plain(l) => l.as_mut(),
Threaded(l) => l.as_mut(),
Conversations(l) => l.as_mut(),
Offline(l) => l.as_mut(),
}
}
}
@ -611,7 +610,6 @@ pub struct Listing {
accounts: Vec<AccountMenuEntry>,
status: Option<AccountStatus>,
dirty: bool,
visible: bool,
cursor_pos: (usize, MenuEntryCursor),
menu_cursor_pos: (usize, MenuEntryCursor),
menu_content: CellBuffer,
@ -755,12 +753,10 @@ impl Component for Listing {
}
return true;
}
UIEvent::StartupCheck(ref f) => {
if self.component.coordinates().1 == *f {
if !self.startup_checks_rate.tick() {
return false;
}
}
UIEvent::StartupCheck(ref f)
if self.component.coordinates().1 == *f && !self.startup_checks_rate.tick() =>
{
return false;
}
UIEvent::Timer(n) if *n == self.startup_checks_rate.id() => {
if self.startup_checks_rate.active {
@ -1127,7 +1123,7 @@ impl Component for Listing {
Action::Listing(ListingAction::Import(file_path, mailbox_path)) => {
let account = &mut context.accounts[self.cursor_pos.0];
if let Err(err) = account
.mailbox_by_path(&mailbox_path)
.mailbox_by_path(mailbox_path)
.and_then(|mailbox_hash| {
Ok((
std::fs::read(&file_path).chain_err_summary(|| {
@ -1687,7 +1683,7 @@ impl Component for Listing {
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
return true;
}
UIEvent::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
UIEvent::Input(Key::Char(c)) if ('0'..='9').contains(&c) => {
self.cmd_buf.push(c);
self.component.set_modifier_active(true);
context
@ -1808,7 +1804,6 @@ impl Listing {
name: a.name().to_string(),
hash: *h,
index: i,
visible: true,
entries,
}
})
@ -1818,7 +1813,6 @@ impl Listing {
component: Offline(OfflineListing::new((first_account_hash, 0))),
accounts: account_entries,
status: None,
visible: true,
dirty: true,
cursor_pos: (0, MenuEntryCursor::Mailbox(0)),
menu_cursor_pos: (0, MenuEntryCursor::Mailbox(0)),
@ -1954,7 +1948,6 @@ impl Listing {
#[derive(Copy, Debug, Clone)]
struct Line {
visible: bool,
collapsed: bool,
depth: usize,
inc: usize,
@ -1990,7 +1983,7 @@ impl Listing {
indentation,
has_sibling,
mailbox_hash,
visible,
visible: _,
collapsed,
},
) in self.accounts[aidx].entries.iter().enumerate()
@ -1999,7 +1992,6 @@ impl Listing {
match context.accounts[self.accounts[aidx].index][&mailbox_hash].status {
crate::conf::accounts::MailboxStatus::Failed(_) => {
lines.push(Line {
visible,
collapsed,
depth,
inc: i,
@ -2012,7 +2004,6 @@ impl Listing {
}
_ => {
lines.push(Line {
visible,
collapsed,
depth,
inc: i,

25
src/components/mail/listing/compact.rs

@ -172,9 +172,12 @@ pub struct CompactListing {
/// Cache current view.
data_columns: DataColumns,
rows_drawn: SegmentTree,
#[allow(clippy::type_complexity)]
rows: Vec<((usize, (ThreadHash, EnvelopeHash)), EntryStrings)>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
#[allow(clippy::type_complexity)]
select_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
@ -220,7 +223,7 @@ impl MailListingTrait for CompactListing {
.flatten()
.chain(cursor_iter.into_iter().flatten())
.cloned();
SmallVec::from_iter(iter.into_iter())
SmallVec::from_iter(iter)
}
/// Fill the `self.data_columns` `CellBuffers` with the contents of the account mailbox the user has
@ -324,6 +327,7 @@ impl MailListingTrait for CompactListing {
self.length = 0;
let mut rows = Vec::with_capacity(1024);
let mut min_width = (0, 0, 0, 0);
#[allow(clippy::type_complexity)]
let mut row_widths: (
SmallVec<[u8; 1024]>,
SmallVec<[u8; 1024]>,
@ -404,11 +408,7 @@ impl MailListingTrait for CompactListing {
);
/* subject */
row_widths.3.push(
(entry_strings
.flag
.grapheme_width()
.try_into()
.unwrap_or(255)
(entry_strings.flag.grapheme_width()
+ 1
+ entry_strings.subject.grapheme_width()
+ 1
@ -876,8 +876,8 @@ impl fmt::Display for CompactListing {
impl CompactListing {
pub const DESCRIPTION: &'static str = "compact listing";
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
CompactListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(CompactListing {
cursor_pos: (coordinates.0, 1, 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
@ -905,8 +905,9 @@ impl CompactListing {
modifier_active: false,
modifier_command: None,
id: ComponentId::new_v4(),
}
})
}
fn make_entry_string(
&self,
e: &Envelope,
@ -1423,7 +1424,7 @@ impl CompactListing {
}
/* Set fg color for flags */
let mut x = 0;
if self.selection.get(&thread_hash).cloned().unwrap_or(false) {
if self.selection.get(thread_hash).cloned().unwrap_or(false) {
x += selected_flag_len;
}
if thread.snoozed() {
@ -1887,7 +1888,7 @@ impl Component for CompactListing {
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[&self.cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&new_hash) {
if !account.collection.contains_key(new_hash) {
return false;
}
let new_env_thread_node_hash = account.collection.get_env(*new_hash).thread();
@ -1917,7 +1918,7 @@ impl Component for CompactListing {
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[&self.cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&env_hash) {
if !account.collection.contains_key(env_hash) {
return false;
}
let new_env_thread_node_hash = account.collection.get_env(*env_hash).thread();

19
src/components/mail/listing/conversations.rs

@ -101,8 +101,10 @@ pub struct ConversationsListing {
subsort: (SortField, SortOrder),
all_threads: HashSet<ThreadHash>,
order: HashMap<ThreadHash, usize>,
#[allow(clippy::type_complexity)]
rows: std::result::Result<Vec<((usize, (ThreadHash, EnvelopeHash)), EntryStrings)>, String>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
@ -148,7 +150,7 @@ impl MailListingTrait for ConversationsListing {
.flatten()
.chain(cursor_iter.into_iter().flatten())
.cloned();
SmallVec::from_iter(iter.into_iter())
SmallVec::from_iter(iter)
}
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
@ -376,7 +378,7 @@ impl ListingTrait for ConversationsListing {
if let Err(message) = self.rows.as_ref() {
clear_area(grid, area, self.color_cache.theme_default);
write_string_to_grid(
&message,
message,
grid,
self.color_cache.theme_default.fg,
self.color_cache.theme_default.bg,
@ -584,8 +586,8 @@ impl ConversationsListing {
const DESCRIPTION: &'static str = "conversations listing";
//const PADDING_CHAR: char = ' '; //โ–‘';
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self {
ConversationsListing {
pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(ConversationsListing {
cursor_pos: (coordinates.0, 1, 0),
new_cursor_pos: (coordinates.0, coordinates.1, 0),
length: 0,
@ -609,7 +611,7 @@ impl ConversationsListing {
modifier_active: false,
modifier_command: None,
id: ComponentId::new_v4(),
}
})
}
pub(super) fn make_entry_string(
@ -714,8 +716,7 @@ impl ConversationsListing {
.settings
.listing
.datetime_fmt
.as_ref()
.map(String::as_str)
.as_deref()
.or(Some("%Y-%m-%d %T")),
false,
),
@ -1226,7 +1227,7 @@ impl Component for ConversationsListing {
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[&self.cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&new_hash) {
if !account.collection.contains_key(new_hash) {
return false;
}
let env_thread_node_hash = account.collection.get_env(*new_hash).thread();
@ -1258,7 +1259,7 @@ impl Component for ConversationsListing {
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[&self.cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1);
if !account.collection.contains_key(&env_hash) {
if !account.collection.contains_key(env_hash) {
return false;
}
let env_thread_node_hash = account.collection.get_env(*env_hash).thread();

8
src/components/mail/listing/offline.rs

@ -41,7 +41,7 @@ impl MailListingTrait for OfflineListing {
}
fn get_focused_items(&self, _context: &Context) -> SmallVec<[ThreadHash; 8]> {
return SmallVec::new();
SmallVec::new()
}
fn refresh_mailbox(&mut self, _context: &mut Context, _force: bool) {}
@ -93,14 +93,14 @@ impl fmt::Display for OfflineListing {
}
impl OfflineListing {
pub fn new(cursor_pos: (AccountHash, MailboxHash)) -> Self {
OfflineListing {
pub fn new(cursor_pos: (AccountHash, MailboxHash)) -> Box<Self> {
Box::new(OfflineListing {
cursor_pos,