From 9cb66ef818f6598eb779f931e201a8d38e86a484 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 25 Aug 2022 15:17:18 +0300 Subject: [PATCH] Fix all clippy warnings in `meli` crate --- config_macros.rs | 4 +- src/bin.rs | 38 +-- src/command.rs | 14 +- src/components/contacts.rs | 54 ++-- src/components/contacts/contact_list.rs | 10 +- src/components/mail/compose.rs | 113 +++----- .../mail/compose/edit_attachments.rs | 6 +- src/components/mail/compose/gpg.rs | 14 +- src/components/mail/listing.rs | 55 ++-- src/components/mail/listing/compact.rs | 25 +- src/components/mail/listing/conversations.rs | 19 +- src/components/mail/listing/offline.rs | 8 +- src/components/mail/listing/plain.rs | 13 +- src/components/mail/listing/thread.rs | 13 +- src/components/mail/pgp.rs | 2 +- src/components/mail/status.rs | 6 +- src/components/mail/view.rs | 266 ++++++++---------- src/components/mail/view/envelope.rs | 206 +++++++------- src/components/mail/view/thread.rs | 41 +-- src/components/notifications.rs | 9 +- src/components/utilities.rs | 31 +- src/components/utilities/dialogs.rs | 6 +- src/components/utilities/pager.rs | 18 +- src/components/utilities/widgets.rs | 12 +- src/conf.rs | 23 +- src/conf/accounts.rs | 104 +++---- src/conf/overrides.rs | 4 +- src/conf/shortcuts.rs | 17 +- src/conf/tags.rs | 11 +- src/conf/themes.rs | 172 +++++------ src/mailcap.rs | 36 +-- src/sqlite3.rs | 40 ++- src/state.rs | 73 ++--- src/terminal/cells.rs | 12 +- src/terminal/color.rs | 15 +- src/terminal/embed/grid.rs | 52 ++-- src/terminal/keys.rs | 16 +- src/types.rs | 8 +- src/types/helpers.rs | 3 +- 39 files changed, 688 insertions(+), 881 deletions(-) diff --git a/config_macros.rs b/config_macros.rs index e4c3ca5c..1c8e40c3 100644 --- a/config_macros.rs +++ b/config_macros.rs @@ -50,7 +50,9 @@ pub fn override_derive(filenames: &[(&str, &str)]) { * along with meli. If not, see . */ -//! This module is automatically generated by build.rs. +#![allow(clippy::derivable_impls)] + +//! This module is automatically generated by config_macros.rs. use super::*; "## diff --git a/src/bin.rs b/src/bin.rs index e1c627b5..510a5908 100644 --- a/src/bin.rs +++ b/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 { match src { "" | "meli" | "main" => Ok(ManPages::Main), @@ -132,8 +135,7 @@ fn parse_manpage(src: &str) -> Result { } } -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>, } @@ -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::(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) => { diff --git a/src/command.rs b/src/command.rs index 8f8cede5..f219641c 100644 --- a/src/command.rs +++ b/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 { } 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() diff --git a/src/components/contacts.rs b/src/components/contacts.rs index ef00c85f..e72ab3f2 100644 --- a/src/components/contacts.rs +++ b/src/components/contacts.rs @@ -29,7 +29,7 @@ pub use self::contact_list::*; #[derive(Debug)] enum ViewMode { ReadOnly, - Discard(UIDialog), + Discard(Box>), 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 = 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 } diff --git a/src/components/contacts/contact_list.rs b/src/components/contacts/contact_list.rs index 38fe87f2..b240c9fd 100644 --- a/src/components/contacts/contact_list.rs +++ b/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 diff --git a/src/components/mail/compose.rs b/src/components/mail/compose.rs index 605231af..217f5fe4 100644 --- a/src/components/mail/compose.rs +++ b/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::
::try_into( + if let Ok(ours) = TryInto::
::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 = book.search(term); results .into_iter() - .map(|r| AutoCompleteEntry::from(r)) + .map(AutoCompleteEntry::from) .collect::>() }), )); } 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::>(); - results - .into_iter() - .map(|r| AutoCompleteEntry::from(r)) + .map(AutoCompleteEntry::from) .collect::>() }), )); } 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::() { - 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| { diff --git a/src/components/mail/compose/edit_attachments.rs b/src/components/mail/compose/edit_attachments.rs index 8acac898..54a625ea 100644 --- a/src/components/mail/compose/edit_attachments.rs +++ b/src/components/mail/compose/edit_attachments.rs @@ -37,7 +37,7 @@ impl Default for EditAttachmentCursor { pub enum EditAttachmentMode { Overview, Edit { - inner: FormWidget, + inner: Box>, no: usize, }, } @@ -68,7 +68,7 @@ impl EditAttachments { } impl EditAttachmentsRefMut<'_, '_> { - fn new_edit_widget(&self, no: usize) -> Option> { + fn new_edit_widget(&self, no: usize) -> Option>> { 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)) } } diff --git a/src/components/mail/compose/gpg.rs b/src/components/mail/compose/gpg.rs index 448a5bfe..eaba98f7 100644 --- a/src/components/mail/compose/gpg.rs +++ b/src/components/mail/compose/gpg.rs @@ -36,7 +36,7 @@ pub enum KeySelection { err: MeliError, }, Loaded { - widget: UIDialog, + widget: Box>, keys: Vec, }, } @@ -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, } -impl GpgComposeState { - pub fn new() -> Self { +impl Default for GpgComposeState { + fn default() -> Self { GpgComposeState { sign_mail: ToggleFlag::Unset, encrypt_mail: ToggleFlag::Unset, diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs index c9685672..c9f894d1 100644 --- a/src/components/mail/listing.rs +++ b/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::>>(); 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> + 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), + Threaded(Box), + Compact(Box), + Conversations(Box), + Offline(Box), } 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, status: Option, 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, diff --git a/src/components/mail/listing/compact.rs b/src/components/mail/listing/compact.rs index 955310c8..ab55248f 100644 --- a/src/components/mail/listing/compact.rs +++ b/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>>)>, + #[allow(clippy::type_complexity)] select_job: Option<(String, JoinHandle>>)>, filter_term: String, filtered_selection: Vec, @@ -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 { + 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(); diff --git a/src/components/mail/listing/conversations.rs b/src/components/mail/listing/conversations.rs index f73c67d3..b29b4324 100644 --- a/src/components/mail/listing/conversations.rs +++ b/src/components/mail/listing/conversations.rs @@ -101,8 +101,10 @@ pub struct ConversationsListing { subsort: (SortField, SortOrder), all_threads: HashSet, order: HashMap, + #[allow(clippy::type_complexity)] rows: std::result::Result, String>, + #[allow(clippy::type_complexity)] search_job: Option<(String, JoinHandle>>)>, filter_term: String, filtered_selection: Vec, @@ -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 { + 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(); diff --git a/src/components/mail/listing/offline.rs b/src/components/mail/listing/offline.rs index 3aabe0ef..2c04702b 100644 --- a/src/components/mail/listing/offline.rs +++ b/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 { + Box::new(OfflineListing { cursor_pos, _row_updates: SmallVec::new(), _selection: HashMap::default(), dirty: true, id: ComponentId::new_v4(), - } + }) } } diff --git a/src/components/mail/listing/plain.rs b/src/components/mail/listing/plain.rs index e8e77bcc..8b5f38a5 100644 --- a/src/components/mail/listing/plain.rs +++ b/src/components/mail/listing/plain.rs @@ -133,6 +133,7 @@ pub struct PlainListing { /// Cache current view. data_columns: DataColumns, + #[allow(clippy::type_complexity)] search_job: Option<(String, JoinHandle>>)>, filter_term: String, filtered_selection: Vec, @@ -311,7 +312,7 @@ impl MailListingTrait for PlainListing { let roots = items .filter_map(|r| threads.groups[&r].root().map(|r| r.root)) .collect::<_>(); - let thread_nodes: &HashMap = &threads.thread_nodes(); + let thread_nodes: &HashMap = threads.thread_nodes(); let env_hash_iter = Box::new( threads .threads_group_iter(roots) @@ -685,8 +686,8 @@ impl fmt::Display for PlainListing { impl PlainListing { const DESCRIPTION: &'static str = "plain listing"; - pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self { - PlainListing { + pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box { + Box::new(PlainListing { cursor_pos: (0, 1, 0), new_cursor_pos: (coordinates.0, coordinates.1, 0), length: 0, @@ -714,7 +715,7 @@ impl PlainListing { movement: None, id: ComponentId::new_v4(), - } + }) } fn make_entry_string(&self, e: EnvelopeRef, context: &Context) -> EntryStrings { @@ -884,7 +885,7 @@ impl PlainListing { Box::new(self.local_collection.iter().cloned()) as Box> } else { - Box::new(self.filtered_selection.iter().map(|h| *h)) + Box::new(self.filtered_selection.iter().cloned()) as Box> }; @@ -1234,7 +1235,7 @@ impl Component for PlainListing { .flatten() .chain(cursor_iter.into_iter().flatten()) .cloned(); - let stack: SmallVec<[_; 8]> = SmallVec::from_iter(iter.into_iter()); + let stack: SmallVec<[_; 8]> = SmallVec::from_iter(iter); for i in stack { self.perform_action(context, i, a); } diff --git a/src/components/mail/listing/thread.rs b/src/components/mail/listing/thread.rs index 06c4e3a7..44fe2b63 100644 --- a/src/components/mail/listing/thread.rs +++ b/src/components/mail/listing/thread.rs @@ -241,6 +241,7 @@ impl MailListingTrait for ThreadListing { } let mut rows = Vec::with_capacity(1024); let mut min_width = (0, 0, 0, 0, 0); + #[allow(clippy::type_complexity)] let mut row_widths: ( SmallVec<[u8; 1024]>, SmallVec<[u8; 1024]>, @@ -260,7 +261,7 @@ impl MailListingTrait for ThreadListing { .filter_map(|r| threads.groups[&r].root().map(|r| r.root)) .collect::<_>(); let mut iter = threads.threads_group_iter(roots).peekable(); - let thread_nodes: &HashMap = &threads.thread_nodes(); + let thread_nodes: &HashMap = threads.thread_nodes(); /* This is just a desugared for loop so that we can use .peek() */ let mut idx = 0; let mut prev_group = ThreadHash::null(); @@ -737,8 +738,8 @@ impl fmt::Display for ThreadListing { } impl ThreadListing { - pub fn new(coordinates: (AccountHash, MailboxHash)) -> Self { - ThreadListing { + pub fn new(coordinates: (AccountHash, MailboxHash)) -> Box { + Box::new(ThreadListing { cursor_pos: (coordinates.0, 0, 0), new_cursor_pos: (coordinates.0, coordinates.1, 0), length: 0, @@ -757,7 +758,7 @@ impl ThreadListing { initialised: false, movement: None, id: ComponentId::new_v4(), - } + }) } fn highlight_line_self(&mut self, _idx: usize, _context: &Context) { @@ -879,7 +880,7 @@ impl ThreadListing { EntryStrings { date: DateString(ConversationsListing::format_date(context, e.date())), subject: SubjectString(subject), - flag: FlagString(format!("{}", if e.has_attachments() { "📎" } else { "" },)), + flag: FlagString((if e.has_attachments() { "📎" } else { "" }).to_string()), from: FromString(address_list!((e.from()) as comma_sep_list)), tags: TagString(tags, colors), } @@ -1243,7 +1244,7 @@ impl Component for ThreadListing { } UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => { let account = &context.accounts[&self.cursor_pos.0]; - if !account.collection.contains_key(&new_hash) { + if !account.collection.contains_key(new_hash) { return false; } if let Some(row) = self.order.remove(old_hash) { diff --git a/src/components/mail/pgp.rs b/src/components/mail/pgp.rs index da31d671..7fce3f7f 100644 --- a/src/components/mail/pgp.rs +++ b/src/components/mail/pgp.rs @@ -39,7 +39,7 @@ pub async fn verify(a: Attachment) -> Result<()> { let (data, sig) = melib_pgp::verify_signature(&a).chain_err_summary(|| "Could not verify signature.")?; let mut ctx = Context::new()?; - let sig = ctx.new_data_mem(&sig.body().trim())?; + let sig = ctx.new_data_mem(sig.body().trim())?; let data = ctx.new_data_mem(&data)?; ctx.verify(sig, data)?.await } diff --git a/src/components/mail/status.rs b/src/components/mail/status.rs index d63e5384..5926b922 100644 --- a/src/components/mail/status.rs +++ b/src/components/mail/status.rs @@ -292,7 +292,7 @@ impl Component for AccountStatus { None, ); line += 1; - for (name, status) in extensions.into_iter() { + for (name, status) in extensions.iter() { width = self.content.size().0; write_string_to_grid( name.trim_at_boundary(30), @@ -418,7 +418,7 @@ impl Component for AccountStatus { return true; } UIEvent::Input(ref key) if shortcut!(key == shortcuts["general"]["scroll_right"]) => { - self.cursor.0 = self.cursor.0 + 1; + self.cursor.0 += 1; self.dirty = true; return true; } @@ -428,7 +428,7 @@ impl Component for AccountStatus { return true; } UIEvent::Input(ref key) if shortcut!(key == shortcuts["general"]["scroll_down"]) => { - self.cursor.1 = self.cursor.1 + 1; + self.cursor.1 += 1; self.dirty = true; return true; } diff --git a/src/components/mail/view.rs b/src/components/mail/view.rs index facb81cc..47641095 100644 --- a/src/components/mail/view.rs +++ b/src/components/mail/view.rs @@ -58,7 +58,7 @@ enum ViewMode { Source(Source), //Ansi(RawBuffer), Subview, - ContactSelector(UIDialog), + ContactSelector(Box>), } impl Default for ViewMode { @@ -76,69 +76,65 @@ impl ViewMode { } } */ + fn is_attachment(&self) -> bool { - match self { - ViewMode::Attachment(_) => true, - _ => false, - } + matches!(self, ViewMode::Attachment(_)) } + fn is_contact_selector(&self) -> bool { - match self { - ViewMode::ContactSelector(_) => true, - _ => false, - } + matches!(self, ViewMode::ContactSelector(_)) } } #[derive(Debug)] pub enum AttachmentDisplay { Alternative { - inner: Attachment, + inner: Box, shown_display: usize, display: Vec, }, InlineText { - inner: Attachment, + inner: Box, comment: Option, text: String, }, InlineOther { - inner: Attachment, + inner: Box, }, Attachment { - inner: Attachment, + inner: Box, }, SignedPending { - inner: Attachment, + inner: Box, display: Vec, handle: JoinHandle>, job_id: JobId, }, SignedFailed { - inner: Attachment, + inner: Box, display: Vec, error: MeliError, }, SignedUnverified { - inner: Attachment, + inner: Box, display: Vec, }, SignedVerified { - inner: Attachment, + inner: Box, display: Vec, description: String, }, EncryptedPending { - inner: Attachment, + inner: Box, handle: JoinHandle)>>, }, EncryptedFailed { - inner: Attachment, + inner: Box, error: MeliError, }, EncryptedSuccess { - inner: Attachment, - plaintext: Attachment, + inner: Box, + plaintext: Box, plaintext_display: Vec, description: String, }, @@ -191,8 +187,8 @@ enum MailViewState { }, Loaded { bytes: Vec, - env: Envelope, - body: Attachment, + env: Box, + body: Box, display: Vec, body_text: String, links: Vec, @@ -313,9 +309,10 @@ impl MailView { .get_env_mut(self.coordinates.2) .populate_headers(&bytes); } - let env = - account.collection.get_env(self.coordinates.2).clone(); - let body = AttachmentBuilder::new(&bytes).build(); + let env = Box::new( + account.collection.get_env(self.coordinates.2).clone(), + ); + let body = Box::new(AttachmentBuilder::new(&bytes).build()); let display = Self::attachment_to( &body, context, @@ -415,7 +412,7 @@ impl MailView { .. } => ( bytes, - self.attachment_displays_to_text(&display, context, false), + self.attachment_displays_to_text(display, context, false), env, ), MailViewState::Error { .. } => { @@ -489,13 +486,13 @@ impl MailView { if !acc.ends_with("\n\n") { acc.push_str("\n\n"); } - acc.push_str(&text); + acc.push_str(text); } InlineText { inner: _, text, comment: _, - } => acc.push_str(&text), + } => acc.push_str(text), InlineOther { inner } => { if !acc.ends_with("\n\n") { acc.push_str("\n\n"); @@ -550,7 +547,7 @@ impl MailView { if description.is_empty() { acc.push_str("Verified signature.\n\n"); } else { - acc.push_str(&description); + acc.push_str(description); acc.push_str("\n\n"); } } @@ -574,7 +571,7 @@ impl MailView { if description.is_empty() { acc.push_str("Succesfully decrypted.\n\n"); } else { - acc.push_str(&description); + acc.push_str(description); acc.push_str("\n\n"); } } @@ -672,35 +669,32 @@ impl MailView { s.push(' '); } - s.extend(att.to_string().chars()); + s.push_str(&att.to_string()); paths.push(cur_path.clone()); - match att.content_type { - ContentType::Multipart { .. } => { - let mut iter = (0..sub_att_display_vec.len()).peekable(); - if has_sibling { - branches.push(true); - } else { - branches.push(false); - } - while let Some(i) = iter.next() { - *idx += 1; - cur_path.push(i); - append_entry( - (idx, (depth + 1, &sub_att_display_vec[i])), - branches, - paths, - cur_path, - iter.peek() != None, - s, - ); - if Some(i) == default_alternative { - s.push_str(" (displayed by default)"); - } - cur_path.pop(); - } - branches.pop(); + if matches!(att.content_type, ContentType::Multipart { .. }) { + let mut iter = (0..sub_att_display_vec.len()).peekable(); + if has_sibling { + branches.push(true); + } else { + branches.push(false); } - _ => {} + while let Some(i) = iter.next() { + *idx += 1; + cur_path.push(i); + append_entry( + (idx, (depth + 1, &sub_att_display_vec[i])), + branches, + paths, + cur_path, + iter.peek() != None, + s, + ); + if Some(i) == default_alternative { + s.push_str(" (displayed by default)"); + } + cur_path.pop(); + } + branches.pop(); } } @@ -735,7 +729,9 @@ impl MailView { active_jobs: &mut HashSet, ) { if a.content_disposition.kind.is_attachment() || a.content_type == "message/rfc822" { - acc.push(AttachmentDisplay::Attachment { inner: a.clone() }); + acc.push(AttachmentDisplay::Attachment { + inner: Box::new(a.clone()), + }); } else if a.content_type().is_text_html() { let bytes = decode(a, None); let filter_invocation = @@ -764,7 +760,7 @@ impl MailView { )); let text = String::from_utf8_lossy(&bytes).to_string(); acc.push(AttachmentDisplay::InlineText { - inner: a.clone(), + inner: Box::new(a.clone()), comment, text, }); @@ -785,7 +781,7 @@ impl MailView { ) .to_string(); acc.push(AttachmentDisplay::InlineText { - inner: a.clone(), + inner: Box::new(a.clone()), comment, text, }); @@ -794,7 +790,7 @@ impl MailView { } else if a.is_text() { let bytes = decode(a, None); acc.push(AttachmentDisplay::InlineText { - inner: a.clone(), + inner: Box::new(a.clone()), comment: None, text: String::from_utf8_lossy(&bytes).to_string(), }); @@ -838,7 +834,7 @@ impl MailView { rec(a, context, coordinates, &mut display, active_jobs); } acc.push(AttachmentDisplay::Alternative { - inner: a.clone(), + inner: Box::new(a.clone()), shown_display: chosen_attachment_idx, display, }); @@ -847,7 +843,7 @@ impl MailView { #[cfg(not(feature = "gpgme"))] { acc.push(AttachmentDisplay::SignedUnverified { - inner: a.clone(), + inner: Box::new(a.clone()), display: { let mut v = vec![]; rec(&parts[0], context, coordinates, &mut v, active_jobs); @@ -869,7 +865,7 @@ impl MailView { StatusEvent::NewJob(handle.job_id), )); acc.push(AttachmentDisplay::SignedPending { - inner: a.clone(), + inner: Box::new(a.clone()), job_id: handle.job_id, display: { let mut v = vec![]; @@ -880,7 +876,7 @@ impl MailView { }); } else { acc.push(AttachmentDisplay::SignedUnverified { - inner: a.clone(), + inner: Box::new(a.clone()), display: { let mut v = vec![]; rec(&parts[0], context, coordinates, &mut v, active_jobs); @@ -896,7 +892,7 @@ impl MailView { #[cfg(not(feature = "gpgme"))] { acc.push(AttachmentDisplay::EncryptedFailed { - inner: a.clone(), + inner: Box::new(a.clone()), error: MeliError::new("Cannot decrypt: meli must be compiled with libgpgme support."), }); } @@ -914,12 +910,12 @@ impl MailView { StatusEvent::NewJob(handle.job_id), )); acc.push(AttachmentDisplay::EncryptedPending { - inner: a.clone(), + inner: Box::new(a.clone()), handle, }); } else { acc.push(AttachmentDisplay::EncryptedFailed { - inner: a.clone(), + inner: Box::new(a.clone()), error: MeliError::new("Undecrypted."), }); } @@ -963,17 +959,13 @@ impl MailView { } else { return None; }; - if let Some(path) = - self.attachment_paths.get(lidx).and_then( - |path| { - if path.len() > 0 { - Some(path) - } else { - None - } - }, - ) - { + if let Some(path) = self.attachment_paths.get(lidx).and_then(|path| { + if !path.is_empty() { + Some(path) + } else { + None + } + }) { let first = path[0]; use AttachmentDisplay::*; let root_attachment = match &display[first] { @@ -1022,14 +1014,11 @@ impl MailView { if path.is_empty() { return Some(a); } - match a.content_type { - ContentType::Multipart { ref parts, .. } => { - let first = path[0]; - if first < parts.len() { - return find_attachment(&parts[first], &path[1..]); - } + if let ContentType::Multipart { ref parts, .. } = a.content_type { + let first = path[0]; + if first < parts.len() { + return find_attachment(&parts[first], &path[1..]); } - _ => {} } None } @@ -1080,7 +1069,7 @@ impl MailView { entries.push((new_card, format!("{}", addr))); } drop(envelope); - self.mode = ViewMode::ContactSelector(Selector::new( + self.mode = ViewMode::ContactSelector(Box::new(Selector::new( "select contacts to add", entries, false, @@ -1088,7 +1077,7 @@ impl MailView { Some(UIEvent::FinishedUIDialog(id, Box::new(results.to_vec()))) })), context, - )); + ))); self.dirty = true; self.initialised = false; } @@ -1420,10 +1409,7 @@ impl Component for MailView { err.to_string(), Some(NotificationType::Error(err.kind)), )); - log( - format!("Failed to open envelope: {}", err.to_string()), - ERROR, - ); + log(format!("Failed to open envelope: {}", err), ERROR); self.init_futures(context); return; } else { @@ -1444,7 +1430,7 @@ impl Component for MailView { let mut text = "Viewing attachment. Press `r` to return \n".to_string(); if let Some(attachment) = self.open_attachment(aidx, context) { if attachment.is_html() { - self.subview = Some(Box::new(HtmlView::new(&attachment, context))); + self.subview = Some(Box::new(HtmlView::new(attachment, context))); self.mode = ViewMode::Subview; } else { text.push_str(&attachment.text()); @@ -1475,7 +1461,7 @@ impl Component for MailView { } } ViewMode::Normal if body.is_html() => { - self.subview = Some(Box::new(HtmlView::new(&body, context))); + self.subview = Some(Box::new(HtmlView::new(body, context))); self.mode = ViewMode::Subview; } ViewMode::Normal @@ -1497,13 +1483,12 @@ impl Component for MailView { } => { self.subview = Some(Box::new(HtmlView::new( - &body - .content_type + body.content_type .parts() .unwrap() - .into_iter() + .iter() .find(|a| a.is_html()) - .unwrap_or(&body), + .unwrap_or(body), context, ))); self.mode = ViewMode::Subview; @@ -1541,7 +1526,7 @@ impl Component for MailView { if !ret.ends_with("\n\n") { ret.push_str("\n\n"); } - ret.extend(body_text.chars()); + ret.push_str(body_text); if !ret.ends_with("\n\n") { ret.push_str("\n\n"); } @@ -1721,10 +1706,8 @@ impl Component for MailView { self.force_draw_headers = true; if self.pager.cursor_pos() == 0 { self.headers_cursor = self.headers_cursor.saturating_sub(1); - } else { - if self.pager.process_event(event, context) { - return true; - } + } else if self.pager.process_event(event, context) { + return true; } self.pager.set_dirty(true); return true; @@ -1767,11 +1750,13 @@ impl Component for MailView { .get_env_mut(self.coordinates.2) .populate_headers(&bytes); } - let env = context.accounts[&self.coordinates.0] - .collection - .get_env(self.coordinates.2) - .clone(); - let body = AttachmentBuilder::new(&bytes).build(); + let env = Box::new( + context.accounts[&self.coordinates.0] + .collection + .get_env(self.coordinates.2) + .clone(), + ); + let body = Box::new(AttachmentBuilder::new(&bytes).build()); let display = Self::attachment_to( &body, context, @@ -1823,9 +1808,11 @@ impl Component for MailView { *d = AttachmentDisplay::SignedVerified { inner: std::mem::replace( inner, - AttachmentBuilder::new(&[]).build(), + Box::new( + AttachmentBuilder::new(&[]).build(), + ), ), - display: std::mem::replace(display, vec![]), + display: std::mem::take(display), description: String::new(), }; } @@ -1833,9 +1820,11 @@ impl Component for MailView { *d = AttachmentDisplay::SignedFailed { inner: std::mem::replace( inner, - AttachmentBuilder::new(&[]).build(), + Box::new( + AttachmentBuilder::new(&[]).build(), + ), ), - display: std::mem::replace(display, vec![]), + display: std::mem::take(display), error, }; } @@ -1851,9 +1840,10 @@ impl Component for MailView { Ok(None) => { /* something happened, perhaps a worker thread panicked */ } Ok(Some(Ok((metadata, decrypted_bytes)))) => { - let plaintext = + let plaintext = Box::new( AttachmentBuilder::new(&decrypted_bytes) - .build(); + .build(), + ); let plaintext_display = Self::attachment_to( &plaintext, context, @@ -1863,7 +1853,9 @@ impl Component for MailView { *d = AttachmentDisplay::EncryptedSuccess { inner: std::mem::replace( inner, - AttachmentBuilder::new(&[]).build(), + Box::new( + AttachmentBuilder::new(&[]).build(), + ), ), plaintext, plaintext_display, @@ -1874,7 +1866,9 @@ impl Component for MailView { *d = AttachmentDisplay::EncryptedFailed { inner: std::mem::replace( inner, - AttachmentBuilder::new(&[]).build(), + Box::new( + AttachmentBuilder::new(&[]).build(), + ), ), error, }; @@ -1888,9 +1882,9 @@ impl Component for MailView { let mut new_body_text = String::new(); if let MailViewState::Loaded { ref display, .. } = self.state { new_body_text = - self.attachment_displays_to_text(&display, context, true); + self.attachment_displays_to_text(display, context, true); let (paths, attachment_tree_s) = - self.attachment_displays_to_tree(&display); + self.attachment_displays_to_tree(display); self.attachment_tree = attachment_tree_s; self.attachment_paths = paths; } @@ -2042,7 +2036,7 @@ impl Component for MailView { .get(&env_hash) .map(|env| env.message_id_display()) .unwrap_or_else(|| "Not found".into()), - err.to_string() + err ); log(&err_string, ERROR); context.replies.push_back(UIEvent::Notification( @@ -2088,7 +2082,7 @@ impl Component for MailView { .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 @@ -2218,7 +2212,7 @@ impl Component for MailView { if let Ok(command) = query_default_app(&attachment_type) { let p = create_temp_file( &decode(attachment, None), - filename.as_ref().map(|s| s.as_str()), + filename.as_deref(), None, true, ); @@ -2400,10 +2394,7 @@ impl Component for MailView { err.to_string(), Some(NotificationType::Error(err.kind)), )); - log( - format!("Failed to open envelope: {}", err.to_string()), - ERROR, - ); + log(format!("Failed to open envelope: {}", err), ERROR); self.init_futures(context); return true; } else { @@ -2424,11 +2415,7 @@ impl Component for MailView { Some(NotificationType::Error(melib::ErrorKind::External)), )); log( - format!( - "Failed to create file at {}: {}", - path.display(), - err.to_string() - ), + format!("Failed to create file at {}: {}", path.display(), err), ERROR, ); return true; @@ -2461,10 +2448,7 @@ impl Component for MailView { err.to_string(), Some(NotificationType::Error(err.kind)), )); - log( - format!("Failed to open envelope: {}", err.to_string()), - ERROR, - ); + log(format!("Failed to open envelope: {}", err), ERROR); self.init_futures(context); return true; } else { @@ -2490,11 +2474,7 @@ impl Component for MailView { Some(NotificationType::Error(melib::ErrorKind::External)), )); log( - format!( - "Failed to create file at {}: {}", - path.display(), - err.to_string() - ), + format!("Failed to create file at {}: {}", path.display(), err), ERROR, ); } @@ -2521,11 +2501,7 @@ impl Component for MailView { Some(NotificationType::Error(melib::ErrorKind::External)), )); log( - format!( - "Failed to create file at {}: {}", - path.display(), - err.to_string() - ), + format!("Failed to create file at {}: {}", path.display(), err), ERROR, ); return true; diff --git a/src/components/mail/view/envelope.rs b/src/components/mail/view/envelope.rs index 9e1ccda8..2861c337 100644 --- a/src/components/mail/view/envelope.rs +++ b/src/components/mail/view/envelope.rs @@ -36,10 +36,7 @@ enum ViewMode { impl ViewMode { fn is_attachment(&self) -> bool { - match self { - ViewMode::Attachment(_) => true, - _ => false, - } + matches!(self, ViewMode::Attachment(_)) } } @@ -53,7 +50,7 @@ pub struct EnvelopeView { mode: ViewMode, mail: Mail, - account_hash: AccountHash, + _account_hash: AccountHash, cmd_buf: String, id: ComponentId, } @@ -69,7 +66,7 @@ impl EnvelopeView { mail: Mail, pager: Option, subview: Option>, - account_hash: AccountHash, + _account_hash: AccountHash, ) -> Self { EnvelopeView { pager, @@ -77,7 +74,7 @@ impl EnvelopeView { dirty: true, mode: ViewMode::Normal, mail, - account_hash, + _account_hash, cmd_buf: String::with_capacity(4), id: ComponentId::new_v4(), } @@ -87,7 +84,7 @@ impl EnvelopeView { fn attachment_to_text(&self, body: &Attachment, context: &mut Context) -> String { let finder = LinkFinder::new(); let body_text = String::from_utf8_lossy(&decode_rec( - &body, + body, Some(Box::new(|a: &Attachment, v: &mut Vec| { if a.content_type().is_text_html() { let settings = &context.settings; @@ -107,14 +104,13 @@ impl EnvelopeView { err.to_string(), Some(NotificationType::Error(melib::ErrorKind::External)), )); - return; } Ok(mut html_filter) => { html_filter .stdin .as_mut() .unwrap() - .write_all(&v) + .write_all(v) .expect("Failed to write to stdin"); *v = format!( "Text piped through `{}`. Press `v` to open in web browser. \n\n", @@ -286,7 +282,7 @@ impl Component for EnvelopeView { match self.mode { ViewMode::Attachment(aidx) if body.attachments()[aidx].is_html() => { let attachment = &body.attachments()[aidx]; - self.subview = Some(Box::new(HtmlView::new(&attachment, context))); + self.subview = Some(Box::new(HtmlView::new(attachment, context))); } ViewMode::Normal if body.is_html() => { self.subview = Some(Box::new(HtmlView::new(&body, context))); @@ -336,7 +332,7 @@ impl Component for EnvelopeView { .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); return true; } @@ -368,71 +364,70 @@ impl Component for EnvelopeView { .replies .push_back(UIEvent::StatusEvent(StatusEvent::BufClear)); - { - if let Some(u) = self.mail.body().attachments().get(lidx) { - match u.content_type() { - ContentType::MessageRfc822 => { - self.mode = ViewMode::Subview; - let colors = crate::conf::value(context, "mail.view.body"); - self.subview = Some(Box::new(Pager::from_string( - String::from_utf8_lossy(&decode_rec(u, None)).to_string(), - Some(context), - None, - None, - colors, - ))); - } + if let Some(u) = self.mail.body().attachments().get(lidx) { + match u.content_type() { + ContentType::MessageRfc822 => { + self.mode = ViewMode::Subview; + let colors = crate::conf::value(context, "mail.view.body"); + self.subview = Some(Box::new(Pager::from_string( + String::from_utf8_lossy(&decode_rec(u, None)).to_string(), + Some(context), + None, + None, + colors, + ))); + } - ContentType::Text { .. } - | ContentType::PGPSignature - | ContentType::CMSSignature => { - self.mode = ViewMode::Attachment(lidx); - self.dirty = true; - } - ContentType::Multipart { .. } => { - context.replies.push_back(UIEvent::StatusEvent( - StatusEvent::DisplayMessage( - "Multipart attachments are not supported yet.".to_string(), - ), - )); - return true; - } - ContentType::Other { .. } => { - let attachment_type = u.mime_type(); - let filename = u.filename(); - if let Ok(command) = query_default_app(&attachment_type) { - let p = create_temp_file( - &decode(u, None), - filename.as_ref().map(|s| s.as_str()), - None, - true, - ); - let (exec_cmd, argument) = super::desktop_exec_to_command( - &command, - p.path.display().to_string(), - false, - ); - match Command::new(&exec_cmd) - .arg(&argument) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - { - Ok(child) => { - context.temp_files.push(p); - context.children.push(child); - } - Err(err) => { - context.replies.push_back(UIEvent::StatusEvent( - StatusEvent::DisplayMessage(format!( - "Failed to start `{} {}`: {}", - &exec_cmd, &argument, err - )), - )); - } + ContentType::Text { .. } + | ContentType::PGPSignature + | ContentType::CMSSignature => { + self.mode = ViewMode::Attachment(lidx); + self.dirty = true; + } + ContentType::Multipart { .. } => { + context.replies.push_back(UIEvent::StatusEvent( + StatusEvent::DisplayMessage( + "Multipart attachments are not supported yet.".to_string(), + ), + )); + return true; + } + ContentType::Other { .. } => { + let attachment_type = u.mime_type(); + let filename = u.filename(); + if let Ok(command) = query_default_app(&attachment_type) { + let p = create_temp_file( + &decode(u, None), + filename.as_deref(), + None, + true, + ); + let (exec_cmd, argument) = super::desktop_exec_to_command( + &command, + p.path.display().to_string(), + false, + ); + match Command::new(&exec_cmd) + .arg(&argument) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + { + Ok(child) => { + context.temp_files.push(p); + context.children.push(child); } - } else { - context.replies.push_back(UIEvent::StatusEvent( + Err(err) => { + context.replies.push_back(UIEvent::StatusEvent( + StatusEvent::DisplayMessage(format!( + "Failed to start `{} {}`: {}", + &exec_cmd, &argument, err + )), + )); + } + } + } else { + context.replies.push_back(UIEvent::StatusEvent( StatusEvent::DisplayMessage(if let Some(filename) = filename.as_ref() { format!( "Couldn't find a default application for file {} (type {})", @@ -445,29 +440,28 @@ impl Component for EnvelopeView { attachment_type ) }), - )); - return true; - } - } - ContentType::OctetStream { .. } => { - context.replies.push_back(UIEvent::StatusEvent( - StatusEvent::DisplayMessage( - "application/octet-stream isn't supported yet".to_string(), - ), )); return true; } } - } else { - context.replies.push_back(UIEvent::StatusEvent( - StatusEvent::DisplayMessage(format!( - "Attachment `{}` not found.", - lidx - )), - )); - return true; + ContentType::OctetStream { .. } => { + context.replies.push_back(UIEvent::StatusEvent( + StatusEvent::DisplayMessage( + "application/octet-stream isn't supported yet".to_string(), + ), + )); + return true; + } } - }; + } else { + context + .replies + .push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(format!( + "Attachment `{}` not found.", + lidx + )))); + return true; + } return true; } UIEvent::Input(Key::Char('g')) @@ -492,22 +486,16 @@ impl Component for EnvelopeView { } }; - let url_launcher = context - .settings - .pager - .url_launcher - .as_ref() - .map(|s| s.as_str()) - .unwrap_or( - #[cfg(target_os = "macos")] - { - "open" - }, - #[cfg(not(target_os = "macos"))] - { - "xdg-open" - }, - ); + let url_launcher = context.settings.pager.url_launcher.as_deref().unwrap_or( + #[cfg(target_os = "macos")] + { + "open" + }, + #[cfg(not(target_os = "macos"))] + { + "xdg-open" + }, + ); match Command::new(url_launcher) .arg(url) .stdin(Stdio::piped()) diff --git a/src/components/mail/view/thread.rs b/src/components/mail/view/thread.rs index 3601bdbc..34001386 100644 --- a/src/components/mail/view/thread.rs +++ b/src/components/mail/view/thread.rs @@ -415,11 +415,7 @@ impl ThreadView { idx: usize, context: &Context, ) { - let visibles: Vec<&usize> = self - .visible_entries - .iter() - .flat_map(|ref v| v.iter()) - .collect(); + let visibles: Vec<&usize> = self.visible_entries.iter().flat_map(|v| v.iter()).collect(); if idx == *visibles[self.cursor_pos] { let theme_default = crate::conf::value(context, "theme_default"); let bg_color = crate::conf::value(context, "highlight").bg; @@ -514,11 +510,8 @@ impl ThreadView { if page_no != prev_page_no { clear_area(grid, area, crate::conf::value(context, "theme_default")); } - let visibles: Vec<&usize> = self - .visible_entries - .iter() - .flat_map(|ref v| v.iter()) - .collect(); + let visibles: Vec<&usize> = + self.visible_entries.iter().flat_map(|v| v.iter()).collect(); for (visible_entry_counter, v) in visibles.iter().skip(top_idx).take(rows).enumerate() { if visible_entry_counter >= rows { @@ -595,11 +588,8 @@ impl ThreadView { self.cursor_pos = self.new_cursor_pos; /* If cursor position has changed, remove the highlight from the previous position and * apply it in the new one. */ - let visibles: Vec<&usize> = self - .visible_entries - .iter() - .flat_map(|ref v| v.iter()) - .collect(); + let visibles: Vec<&usize> = + self.visible_entries.iter().flat_map(|v| v.iter()).collect(); for &idx in &[old_cursor_pos, self.cursor_pos] { let entry_idx = *visibles[idx]; let src_area = { get_entry_area(entry_idx, &self.entries) }; @@ -948,11 +938,7 @@ impl ThreadView { /// Current position in self.entries (not in drawn entries which might exclude nonvisible ones) fn current_pos(&self) -> usize { - let visibles: Vec<&usize> = self - .visible_entries - .iter() - .flat_map(|ref v| v.iter()) - .collect(); + let visibles: Vec<&usize> = self.visible_entries.iter().flat_map(|v| v.iter()).collect(); *visibles[self.new_cursor_pos] } } @@ -999,15 +985,12 @@ impl Component for ThreadView { self.dirty = false; } fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { - match event { - UIEvent::Action(Listing(OpenInNewTab)) => { - /* Handle this before self.mailview does */ - context - .replies - .push_back(UIEvent::Action(Tab(New(Some(Box::new(self.clone())))))); - return true; - } - _ => {} + if let UIEvent::Action(Listing(OpenInNewTab)) = event { + /* Handle this before self.mailview does */ + context + .replies + .push_back(UIEvent::Action(Tab(New(Some(Box::new(self.clone())))))); + return true; } if self.show_mailview && self.mailview.process_event(event, context) { diff --git a/src/components/notifications.rs b/src/components/notifications.rs index 1d676e66..caf85f94 100644 --- a/src/components/notifications.rs +++ b/src/components/notifications.rs @@ -169,7 +169,7 @@ mod dbus { } /// Passes notifications to a user defined shell command -#[derive(Debug)] +#[derive(Default, Debug)] pub struct NotificationCommand {} impl NotificationCommand { @@ -204,7 +204,7 @@ impl Component for NotificationCommand { } Err(err) => { log( - format!("Could not run notification script: {}.", err.to_string()), + format!("Could not run notification script: {}.", err), ERROR, ); debug!("Could not run notification script: {:?}", err); @@ -226,10 +226,7 @@ impl Component for NotificationCommand { } Err(err) => { log( - format!( - "Could not run notification script: {}.", - err.to_string() - ), + format!("Could not run notification script: {}.", err), ERROR, ); debug!("Could not run notification script: {:?}", err); diff --git a/src/components/utilities.rs b/src/components/utilities.rs index 4feadbef..b8a98880 100644 --- a/src/components/utilities.rs +++ b/src/components/utilities.rs @@ -67,7 +67,7 @@ pub struct StatusBar { done_jobs: HashSet, scroll_contexts: IndexMap, - auto_complete: AutoComplete, + auto_complete: Box, cmd_history: Vec, } @@ -136,7 +136,7 @@ impl StatusBar { .set_bg(attribute.bg) .set_attrs(attribute.attrs); } - let offset = self.status.find('|').unwrap_or_else(|| self.status.len()); + let offset = self.status.find('|').unwrap_or(self.status.len()); if y < get_y(bottom_right!(area)) + 1 { for x in get_x(upper_left!(area)) ..std::cmp::min( @@ -209,8 +209,7 @@ impl StatusBar { .settings .terminal .mouse_flag - .as_ref() - .map(|s| s.as_str()) + .as_deref() .unwrap_or("🖱️ ") } else { "" @@ -362,7 +361,7 @@ impl Component for StatusBar { } suggestions.sort_by(|a, b| a.entry.cmp(&b.entry)); - suggestions.dedup_by(|a, b| &a.entry == &b.entry); + suggestions.dedup_by(|a, b| a.entry == b.entry); if self.auto_complete.set_suggestions(suggestions) { let len = self.auto_complete.suggestions().len() - 1; self.auto_complete.set_cursor(len); @@ -529,7 +528,7 @@ impl Component for StatusBar { self.container.set_dirty(true); } UIEvent::ChangeMode(m) => { - let offset = self.status.find('|').unwrap_or_else(|| self.status.len()); + let offset = self.status.find('|').unwrap_or(self.status.len()); self.status.replace_range( ..offset, &format!( @@ -540,8 +539,7 @@ impl Component for StatusBar { .settings .terminal .mouse_flag - .as_ref() - .map(|s| s.as_str()) + .as_deref() .unwrap_or("🖱️ ") } else { "" @@ -559,7 +557,7 @@ impl Component for StatusBar { .replies .push_back(UIEvent::Command(self.ex_buffer.as_str().to_string())); } - if parse_command(&self.ex_buffer.as_str().as_bytes()).is_ok() + if parse_command(self.ex_buffer.as_str().as_bytes()).is_ok() && self.cmd_history.last().map(String::as_str) != Some(self.ex_buffer.as_str()) { @@ -1138,7 +1136,7 @@ impl Component for Tabbed { None, ); write_string_to_grid( - &k, + k, &mut self.help_content, self.theme_default.fg, self.theme_default.bg, @@ -1485,13 +1483,13 @@ impl Component for Tabbed { self.help_screen_cursor.1 = self.help_screen_cursor.1.saturating_sub(1); } _ if shortcut!(key == shortcuts["general"]["scroll_down"]) => { - self.help_screen_cursor.1 = self.help_screen_cursor.1 + 1; + self.help_screen_cursor.1 += 1; } _ if shortcut!(key == shortcuts["general"]["scroll_left"]) => { self.help_screen_cursor.0 = self.help_screen_cursor.0.saturating_sub(1); } _ if shortcut!(key == shortcuts["general"]["scroll_right"]) => { - self.help_screen_cursor.0 = self.help_screen_cursor.0 + 1; + self.help_screen_cursor.0 += 1; } _ => { /* ignore, don't pass to components below the shortcut panel */ @@ -1600,7 +1598,7 @@ impl Component for RawBuffer { true } UIEvent::Input(Key::Right) => { - self.cursor.0 = self.cursor.0 + 1; + self.cursor.0 += 1; self.dirty = true; true } @@ -1610,7 +1608,7 @@ impl Component for RawBuffer { true } UIEvent::Input(Key::Down) => { - self.cursor.1 = self.cursor.1 + 1; + self.cursor.1 += 1; self.dirty = true; true } @@ -1641,9 +1639,6 @@ impl RawBuffer { } } pub fn title(&self) -> &str { - self.title - .as_ref() - .map(String::as_str) - .unwrap_or("untitled") + self.title.as_deref().unwrap_or("untitled") } } diff --git a/src/components/utilities/dialogs.rs b/src/components/utilities/dialogs.rs index 747cb3ce..1cdac8c1 100644 --- a/src/components/utilities/dialogs.rs +++ b/src/components/utilities/dialogs.rs @@ -760,7 +760,7 @@ impl Selec ) -> Selector { let entry_titles = entries .iter_mut() - .map(|(_id, ref mut title)| std::mem::replace(title, String::new())) + .map(|(_id, ref mut title)| std::mem::take(title)) .collect::>(); let mut identifiers: Vec<(T, bool)> = entries.into_iter().map(|(id, _)| (id, false)).collect(); @@ -812,7 +812,7 @@ impl Selec if self.single_only { for (i, e) in self.entry_titles.iter().enumerate() { write_string_to_grid( - &e, + e, &mut content, self.theme_default.fg, self.theme_default.bg, @@ -824,7 +824,7 @@ impl Selec } else { for (i, e) in self.entry_titles.iter().enumerate() { write_string_to_grid( - &format!("[ ] {}", &e), + &format!("[ ] {}", e), &mut content, self.theme_default.fg, self.theme_default.bg, diff --git a/src/components/utilities/pager.rs b/src/components/utilities/pager.rs index 601e24ac..9f24543e 100644 --- a/src/components/utilities/pager.rs +++ b/src/components/utilities/pager.rs @@ -39,7 +39,6 @@ pub struct Pager { colors: ThemeAttribute, initialised: bool, show_scrollbar: bool, - content: CellBuffer, filtered_content: Option<(String, Result)>, text_lines: Vec, line_breaker: LineBreakText, @@ -57,8 +56,10 @@ impl Pager { pub const DESCRIPTION: &'static str = "pager"; const PAGES_AHEAD_TO_RENDER_NO: usize = 16; pub fn new(context: &Context) -> Self { - let mut ret = Pager::default(); - ret.minimum_width = context.settings.pager.minimum_width; + let mut ret = Pager { + minimum_width: context.settings.pager.minimum_width, + ..Pager::default() + }; ret.set_colors(crate::conf::value(context, "theme_default")) .set_reflow(if context.settings.pager.split_long_lines { Reflow::All @@ -178,10 +179,7 @@ impl Pager { .stdout(Stdio::piped()) .spawn() .chain_err_summary(|| "Failed to start pager filter process")?; - let stdin = filter_child - .stdin - .as_mut() - .ok_or_else(|| "failed to open stdin")?; + let stdin = filter_child.stdin.as_mut().ok_or("failed to open stdin")?; stdin .write_all(text.as_bytes()) .chain_err_summary(|| "Failed to write to stdin")?; @@ -196,7 +194,7 @@ impl Pager { for b in out { embedded.process_byte(&mut dev_null, b); } - Ok(std::mem::replace(embedded.buffer_mut(), Default::default())) + Ok(std::mem::take(embedded.buffer_mut())) }; let buf = _f(cmd, &self.text); if let Some((width, height)) = buf.as_ref().ok().map(CellBuffer::size) { @@ -301,7 +299,7 @@ impl Pager { Ok(ref content) => { copy_area( grid, - &content, + content, area, ( ( @@ -353,7 +351,7 @@ impl Pager { (upper_left, bottom_right), None, ); - if l.starts_with("⤷") { + if l.starts_with('⤷') { grid[upper_left] .set_fg(crate::conf::value(context, "highlight").fg) .set_attrs(crate::conf::value(context, "highlight").attrs); diff --git a/src/components/utilities/widgets.rs b/src/components/utilities/widgets.rs index 10e332af..9400a4e2 100644 --- a/src/components/utilities/widgets.rs +++ b/src/components/utilities/widgets.rs @@ -42,7 +42,7 @@ impl Default for FormFocus { } pub enum Field { - Text(UText, Option<(AutoCompleteFn, AutoComplete)>), + Text(UText, Option<(AutoCompleteFn, Box)>), Choice(Vec>, Cursor), } @@ -456,6 +456,10 @@ impl FormWidget self.layout.len() } + pub fn is_empty(&self) -> bool { + self.layout.len() == 0 + } + pub fn add_button(&mut self, val: (Cow<'static, str>, T)) { self.buttons.push(val); } @@ -1003,7 +1007,7 @@ impl Component for AutoComplete { } impl AutoComplete { - pub fn new(entries: Vec) -> Self { + pub fn new(entries: Vec) -> Box { let mut ret = AutoComplete { entries: Vec::new(), content: CellBuffer::default(), @@ -1012,7 +1016,7 @@ impl AutoComplete { id: ComponentId::new_v4(), }; ret.set_suggestions(entries); - ret + Box::new(ret) } pub fn set_suggestions(&mut self, entries: Vec) -> bool { @@ -1401,7 +1405,7 @@ impl Component for ProgressSpinner { if self.active { write_string_to_grid( match self.kind.as_ref() { - Ok(kind) => (Self::KINDS[*kind].1)[self.stage].as_ref(), + Ok(kind) => (Self::KINDS[*kind].1)[self.stage], Err(custom) => custom[self.stage].as_ref(), }, grid, diff --git a/src/conf.rs b/src/conf.rs index d4eeea10..de75884d 100644 --- a/src/conf.rs +++ b/src/conf.rs @@ -250,7 +250,7 @@ impl From for AccountConf { let root_mailbox = x.root_mailbox.clone(); let identity = x.identity.clone(); let display_name = x.display_name.clone(); - let order = x.order.clone(); + let order = x.order; let mailboxes = x .mailboxes .iter() @@ -365,13 +365,14 @@ impl FileSettings { pub fn validate(path: PathBuf, interactive: bool, clear_extras: bool) -> Result { let s = pp::pp(&path)?; - let map: toml::map::Map = toml::from_str(&s).map_err(|e| { - MeliError::new(format!( - "{}:\nConfig file is invalid TOML: {}", - path.display(), - e.to_string() - )) - })?; + let map: toml::map::Map = + toml::from_str(&s).map_err(|err| { + MeliError::new(format!( + "{}:\nConfig file is invalid TOML: {}", + path.display(), + err + )) + })?; /* * Check that a global composing option is set and return a user-friendly error message because the * default serde one is confusing. @@ -410,11 +411,11 @@ This is required so that you don't accidentally start meli and find out later th path.display() ))); } - let mut s: FileSettings = toml::from_str(&s).map_err(|e| { + let mut s: FileSettings = toml::from_str(&s).map_err(|err| { MeliError::new(format!( "{}:\nConfig file contains errors: {}", path.display(), - e.to_string() + err )) })?; let backends = melib::backends::Backends::new(); @@ -831,7 +832,7 @@ mod pp { } i += 1; } - return Ok(("", None)); + Ok(("", None)) } } diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs index 072452dc..2429dcbb 100644 --- a/src/conf/accounts.rs +++ b/src/conf/accounts.rs @@ -89,18 +89,11 @@ impl Default for MailboxStatus { impl MailboxStatus { pub fn is_available(&self) -> bool { - if let MailboxStatus::Available = self { - true - } else { - false - } + matches!(self, MailboxStatus::Available) } + pub fn is_parsing(&self) -> bool { - if let MailboxStatus::Parsing(_, _) = self { - true - } else { - false - } + matches!(self, MailboxStatus::Parsing(_, _)) } } @@ -132,7 +125,7 @@ impl MailboxEntry { if let Some(name) = self.conf.mailbox_conf.alias.as_ref() { name } else { - &self.ref_mailbox.name() + self.ref_mailbox.name() } } } @@ -165,6 +158,7 @@ pub enum JobRequest { }, Fetch { mailbox_hash: MailboxHash, + #[allow(clippy::type_complexity)] handle: JoinHandle<( Option>>, Pin>> + Send + 'static>>, @@ -345,26 +339,17 @@ impl core::fmt::Display for JobRequest { impl JobRequest { pub fn is_watch(&self) -> bool { - match self { - JobRequest::Watch { .. } => true, - _ => false, - } + matches!(self, JobRequest::Watch { .. }) } pub fn is_fetch(&self, mailbox_hash: MailboxHash) -> bool { - match self { - JobRequest::Fetch { - mailbox_hash: h, .. - } if *h == mailbox_hash => true, - _ => false, - } + matches!(self, JobRequest::Fetch { + mailbox_hash: h, .. + } if *h == mailbox_hash) } pub fn is_online(&self) -> bool { - match self { - JobRequest::IsOnline { .. } => true, - _ => false, - } + matches!(self, JobRequest::IsOnline { .. }) } } @@ -388,7 +373,6 @@ impl Drop for Account { let writer = io::BufWriter::new(f); if let Err(err) = serde_json::to_writer(writer, &self.address_book) { eprintln!("{}", err); - return; }; }; /* @@ -455,7 +439,7 @@ impl Account { )?; let data_dir = xdg::BaseDirectories::with_profile("meli", &name).unwrap(); - let mut address_book = AddressBook::with_account(&settings.account()); + let mut address_book = AddressBook::with_account(settings.account()); if let Ok(data) = data_dir.place_data_file("addressbook") { if data.exists() { @@ -730,7 +714,7 @@ impl Account { format!( "Failed to update envelope {} in cache: {}", envelope.message_id_display(), - err.to_string() + err ), melib::ERROR, ); @@ -804,7 +788,7 @@ impl Account { "Failed to update envelope {} in cache: {}", self.collection.envelopes.read().unwrap()[&env_hash] .message_id_display(), - err.to_string() + err ), melib::ERROR, ); @@ -834,7 +818,7 @@ impl Account { "Failed to update envelope {} in cache: {}", &self.collection.envelopes.read().unwrap()[&new_hash] .message_id_display(), - err.to_string() + err ), melib::ERROR, ); @@ -961,7 +945,7 @@ impl Account { "Failed to remove envelope {} [{}] in cache: {}", &envelopes[&env_hash].message_id_display(), env_hash, - err.to_string() + err ), melib::ERROR, ); @@ -1193,14 +1177,10 @@ impl Account { self.special_use_mailbox(SpecialUsageMailbox::Normal), ] { if let Some(mailbox_hash) = mailbox { - if let Err(e) = self.save(bytes, *mailbox_hash, Some(flags)) { - debug!("{:?} could not save msg", e); + if let Err(err) = self.save(bytes, *mailbox_hash, Some(flags)) { + debug!("{:?} could not save msg", err); melib::log( - format!( - "Could not save in '{}' mailbox: {}.", - *mailbox_hash, - e.to_string() - ), + format!("Could not save in '{}' mailbox: {}.", *mailbox_hash, err), melib::ERROR, ); } else { @@ -1311,9 +1291,7 @@ impl Account { ) }; melib::log(&error_message, melib::LoggingLevel::ERROR); - return Err( - MeliError::new(error_message.clone()).set_summary("Message not sent.") - ); + return Err(MeliError::new(error_message).set_summary("Message not sent.")); } Ok(None) } @@ -1334,11 +1312,11 @@ impl Account { } SendMail::ServerSubmission => { if self.backend_capabilities.supports_submission { - let job = self.backend.write().unwrap().submit( - message.clone().into_bytes(), - None, - None, - )?; + let job = + self.backend + .write() + .unwrap() + .submit(message.into_bytes(), None, None)?; let handle = if self.backend_capabilities.is_async { self.job_executor.spawn_specialized(job) @@ -1348,8 +1326,8 @@ impl Account { self.insert_job(handle.job_id, JobRequest::SendMessageBackground { handle }); return Ok(None); } - return Err(MeliError::new("Server does not support submission.") - .set_summary("Message not sent.")); + Err(MeliError::new("Server does not support submission.") + .set_summary("Message not sent.")) } } } @@ -1400,8 +1378,9 @@ impl Account { ) }; melib::log(&error_message, melib::LoggingLevel::ERROR); - return Err(MeliError::new(error_message.clone()) - .set_summary("Message not sent.")); + return Err( + MeliError::new(error_message).set_summary("Message not sent.") + ); } Ok(()) } @@ -1423,8 +1402,8 @@ impl Account { fut.await?; return Ok(()); } - return Err(MeliError::new("Server does not support submission.") - .set_summary("Message not sent.")); + Err(MeliError::new("Server does not support submission.") + .set_summary("Message not sent.")) } } }) @@ -1537,11 +1516,7 @@ impl Account { .mailbox_entries .iter() .find(|(_, f)| f.conf.mailbox_conf().usage == Some(special_use)); - if let Some(ret) = ret.as_ref() { - Some(ret.1.ref_mailbox.hash()) - } else { - None - } + ret.as_ref().map(|ret| ret.1.ref_mailbox.hash()) } /* Call only in Context::is_online, since only Context can launch the watcher threads if an @@ -1575,7 +1550,7 @@ impl Account { self.insert_job(handle.job_id, JobRequest::IsOnline { handle }); } } - return self.is_online.clone(); + self.is_online.clone() } pub fn search( @@ -2272,7 +2247,7 @@ fn build_mailboxes_order( node } - tree.push(rec(*h, &mailbox_entries, 0)); + tree.push(rec(*h, mailbox_entries, 0)); } } @@ -2356,7 +2331,6 @@ fn build_mailboxes_order( fn rec( node: &mut MailboxNode, mailbox_entries: &IndexMap, - depth: usize, mut indentation: u32, has_sibling: bool, ) { @@ -2379,16 +2353,10 @@ fn build_mailboxes_order( } while let Some(i) = iter.next() { let c = &mut node.children[i]; - rec( - c, - mailbox_entries, - depth + 1, - indentation, - iter.peek() != None, - ); + rec(c, mailbox_entries, indentation, iter.peek() != None); } } - rec(node, &mailbox_entries, 1, 0, false); + rec(node, mailbox_entries, 0, false); } } diff --git a/src/conf/overrides.rs b/src/conf/overrides.rs index 4ff11a78..581c35e1 100644 --- a/src/conf/overrides.rs +++ b/src/conf/overrides.rs @@ -19,7 +19,9 @@ * along with meli. If not, see . */ -//! This module is automatically generated by build.rs. +#![allow(clippy::derivable_impls)] + +//! This module is automatically generated by config_macros.rs. use super::*; #[derive(Debug, Serialize, Deserialize, Clone)] diff --git a/src/conf/shortcuts.rs b/src/conf/shortcuts.rs index d0b294e5..50875b3f 100644 --- a/src/conf/shortcuts.rs +++ b/src/conf/shortcuts.rs @@ -34,7 +34,7 @@ macro_rules! shortcut { }; } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct Shortcuts { #[serde(default)] @@ -55,21 +55,6 @@ pub struct Shortcuts { pub pager: PagerShortcuts, } -impl Default for Shortcuts { - fn default() -> Self { - Self { - general: GeneralShortcuts::default(), - listing: ListingShortcuts::default(), - composing: ComposingShortcuts::default(), - compact_listing: CompactListingShortcuts::default(), - contact_list: ContactListShortcuts::default(), - envelope_view: EnvelopeViewShortcuts::default(), - thread_view: ThreadViewShortcuts::default(), - pager: PagerShortcuts::default(), - } - } -} - impl DotAddressable for Shortcuts { fn lookup(&self, parent_field: &str, path: &[&str]) -> Result { match path.first() { diff --git a/src/conf/tags.rs b/src/conf/tags.rs index 42f94be0..9f75a222 100644 --- a/src/conf/tags.rs +++ b/src/conf/tags.rs @@ -28,7 +28,7 @@ use serde::{Deserialize, Deserializer}; use std::collections::{hash_map::DefaultHasher, HashMap, HashSet}; use std::hash::Hasher; -#[derive(Debug, Deserialize, Clone, Serialize)] +#[derive(Default, Debug, Deserialize, Clone, Serialize)] #[serde(deny_unknown_fields)] pub struct TagsSettings { #[serde(default, deserialize_with = "tag_color_de")] @@ -37,15 +37,6 @@ pub struct TagsSettings { pub ignore_tags: HashSet, } -impl Default for TagsSettings { - fn default() -> Self { - TagsSettings { - colors: Default::default(), - ignore_tags: Default::default(), - } - } -} - pub fn tag_set_de<'de, D, T: std::convert::From>>( deserializer: D, ) -> std::result::Result diff --git a/src/conf/themes.rs b/src/conf/themes.rs index 73d9fcaa..315c1bce 100644 --- a/src/conf/themes.rs +++ b/src/conf/themes.rs @@ -102,7 +102,7 @@ pub fn attrs(context: &Context, key: &'static str) -> Attr { } #[inline(always)] -fn unlink<'k, 't: 'k>(theme: &'t Theme, key: &'k Cow<'static, str>) -> ThemeAttribute { +fn unlink<'k, 't: 'k>(theme: &'t Theme, key: &'k str) -> ThemeAttribute { ThemeAttribute { fg: unlink_fg(theme, &ColorField::Fg, key), bg: unlink_bg(theme, &ColorField::Bg, key), @@ -111,11 +111,7 @@ fn unlink<'k, 't: 'k>(theme: &'t Theme, key: &'k Cow<'static, str>) -> ThemeAttr } #[inline(always)] -fn unlink_fg<'k, 't: 'k>( - theme: &'t Theme, - mut field: &'k ColorField, - mut key: &'k Cow<'static, str>, -) -> Color { +fn unlink_fg<'k, 't: 'k>(theme: &'t Theme, mut field: &'k ColorField, mut key: &'k str) -> Color { loop { match field { ColorField::LikeSelf | ColorField::Fg => match &theme[key].fg { @@ -166,11 +162,7 @@ fn unlink_fg<'k, 't: 'k>( } #[inline(always)] -fn unlink_bg<'k, 't: 'k>( - theme: &'t Theme, - mut field: &'k ColorField, - mut key: &'k Cow<'static, str>, -) -> Color { +fn unlink_bg<'k, 't: 'k>(theme: &'t Theme, mut field: &'k ColorField, mut key: &'k str) -> Color { loop { match field { ColorField::LikeSelf | ColorField::Bg => match &theme[key].bg { @@ -220,7 +212,7 @@ fn unlink_bg<'k, 't: 'k>( } #[inline(always)] -fn unlink_attrs<'k, 't: 'k>(theme: &'t Theme, mut key: &'k Cow<'static, str>) -> Attr { +fn unlink_attrs<'k, 't: 'k>(theme: &'t Theme, mut key: &'k str) -> Attr { loop { match &theme[key].attrs { ThemeValue::Link(ref new_key, ()) => key = new_key, @@ -416,8 +408,8 @@ impl<'de> Deserialize<'de> for ThemeValue { D: Deserializer<'de>, { if let Ok(s) = ::deserialize(deserializer) { - if s.starts_with("$") { - Ok(ThemeValue::Alias(s[1..].to_string().into())) + if let Some(stripped) = s.strip_prefix('$') { + Ok(ThemeValue::Alias(stripped.to_string().into())) } else if let Ok(c) = Attr::from_string_de::<'de, D, String>(s.clone()) { Ok(ThemeValue::Value(c)) } else { @@ -467,8 +459,8 @@ impl<'de> Deserialize<'de> for ThemeValue { D: Deserializer<'de>, { if let Ok(s) = ::deserialize(deserializer) { - if s.starts_with("$") { - Ok(ThemeValue::Alias(s[1..].to_string().into())) + if let Some(stripped) = s.strip_prefix('$') { + Ok(ThemeValue::Alias(stripped.to_string().into())) } else if let Ok(c) = Color::from_string_de::<'de, D>(s.clone()) { Ok(ThemeValue::Value(c)) } else if s.ends_with(".fg") { @@ -606,37 +598,26 @@ mod regexp { fn next(&mut self) -> Option { loop { - let next_byte_offset = self.pcre_iter.next(); - if next_byte_offset.is_none() { - return None; - } - let next_byte_offset = next_byte_offset.unwrap(); + let next_byte_offset = self.pcre_iter.next()?; if next_byte_offset.is_err() { continue; } let next_byte_offset = next_byte_offset.unwrap(); - let mut next_char_index = self.char_indices.next(); - if next_char_index.is_none() { - return None; - } + let mut next_char_index = self.char_indices.next()?; - while next_byte_offset.start() < next_char_index.unwrap().0 { + while next_byte_offset.start() < next_char_index.0 { self.char_offset += 1; - next_char_index = self.char_indices.next(); - if next_char_index.is_none() { - return None; - } + next_char_index = self.char_indices.next()?; } let start = self.char_offset; while next_byte_offset.end() - >= self + > self .char_indices .next() .map(|(v, _)| v) - .unwrap_or(next_byte_offset.end()) - + 1 + .unwrap_or_else(|| next_byte_offset.end()) { self.char_offset += 1; } @@ -1219,7 +1200,7 @@ impl Themes { Ok(()) } pub fn validate(&self) -> Result<()> { - let hash_set: HashSet<&'static str> = DEFAULT_KEYS.into_iter().map(|k| *k).collect(); + let hash_set: HashSet<&'static str> = DEFAULT_KEYS.iter().copied().collect(); Themes::validate_keys("light", &self.light, &hash_set)?; Themes::validate_keys("dark", &self.dark, &hash_set)?; for (name, t) in self.other_themes.iter() { @@ -1255,51 +1236,49 @@ impl Themes { t => self.other_themes.get(t).unwrap_or(&self.dark), }; let mut ret = String::new(); - ret.extend(format!("[terminal.themes.{}]\n", key).chars()); + ret.push_str(&format!("[terminal.themes.{}]\n", key)); if unlink { for k in theme.keys() { - ret.extend( - format!( - "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", - k, - toml::to_string(&unlink_fg(&theme, &ColorField::Fg, k)).unwrap(), - toml::to_string(&unlink_bg(&theme, &ColorField::Bg, k)).unwrap(), - toml::to_string(&unlink_attrs(&theme, k)).unwrap(), - ) - .chars(), - ); + ret.push_str(&format!( + "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", + k, + toml::to_string(&unlink_fg(theme, &ColorField::Fg, k)).unwrap(), + toml::to_string(&unlink_bg(theme, &ColorField::Bg, k)).unwrap(), + toml::to_string(&unlink_attrs(theme, k)).unwrap(), + )); } } else { for k in theme.keys() { - ret.extend( - format!( - "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", - k, - toml::to_string(&theme[k].fg).unwrap(), - toml::to_string(&theme[k].bg).unwrap(), - toml::to_string(&theme[k].attrs).unwrap(), - ) - .chars(), - ); + ret.push_str(&format!( + "\"{}\" = {{ fg = {}, bg = {}, attrs = {} }}\n", + k, + toml::to_string(&theme[k].fg).unwrap(), + toml::to_string(&theme[k].bg).unwrap(), + toml::to_string(&theme[k].attrs).unwrap(), + )); } } ret } - pub fn to_string(&self) -> String { - let mut ret = String::new(); - ret.extend(self.key_to_string("dark", true).chars()); - - ret.push_str("\n\n"); - ret.extend(self.key_to_string("light", true).chars()); - for name in self.other_themes.keys() { - ret.push_str("\n\n"); - ret.extend(self.key_to_string(name, true).chars()); - } - ret - } +} + +impl std::fmt::Display for Themes { + fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { + let mut ret = String::new(); + ret.push_str(&self.key_to_string("dark", true)); + + ret.push_str("\n\n"); + ret.push_str(&self.key_to_string("light", true)); + for name in self.other_themes.keys() { + ret.push_str("\n\n"); + ret.push_str(&self.key_to_string(name, true)); + } + write!(fmt, "{}", ret) + } } impl Default for Themes { + #[allow(clippy::needless_update)] fn default() -> Themes { let mut light = IndexMap::default(); let mut dark = IndexMap::default(); @@ -1762,9 +1741,9 @@ impl Serialize for Themes { new_map.insert( k.clone(), ThemeAttribute { - fg: unlink_fg(&t, &ColorField::Fg, k), - bg: unlink_bg(&t, &ColorField::Bg, k), - attrs: unlink_attrs(&t, k), + fg: unlink_fg(t, &ColorField::Fg, k), + bg: unlink_bg(t, &ColorField::Bg, k), + attrs: unlink_attrs(t, k), }, ); } @@ -1790,10 +1769,10 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { } fn is_cyclic_util<'a>( course: Course, - k: &'a Cow<'static, str>, - visited: &mut IndexMap<(&'a Cow<'static, str>, Course), bool>, - stack: &mut IndexMap<(&'a Cow<'static, str>, Course), bool>, - path: &mut SmallVec<[(&'a Cow<'static, str>, Course); 16]>, + k: &'a str, + visited: &mut IndexMap<(&'a str, Course), bool>, + stack: &mut IndexMap<(&'a str, Course), bool>, + path: &mut SmallVec<[(&'a str, Course); 16]>, theme: &'a Theme, ) -> bool { if !visited[&(k, course)] { @@ -1804,6 +1783,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { Course::Fg => match theme[k].fg { ThemeValue::Link(ref l, ColorField::LikeSelf) | ThemeValue::Link(ref l, ColorField::Fg) => { + let l = l.as_ref(); path.push((l, Course::Fg)); if (!visited[&(l, Course::Fg)] && is_cyclic_util(course, l, visited, stack, path, theme)) @@ -1814,6 +1794,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Link(ref l, ColorField::Bg) => { + let l = l.as_ref(); path.push((l, Course::Bg)); if (!visited[&(l, Course::Bg)] && is_cyclic_util(Course::Bg, l, visited, stack, path, theme)) @@ -1824,6 +1805,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Alias(ref ident) => { + let ident = ident.as_ref(); path.push((ident, Course::ColorAliasFg)); if (!visited[&(ident, Course::ColorAliasFg)] && is_cyclic_util( @@ -1845,6 +1827,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { Course::Bg => match theme[k].bg { ThemeValue::Link(ref l, ColorField::LikeSelf) | ThemeValue::Link(ref l, ColorField::Bg) => { + let l = l.as_ref(); path.push((l, Course::Bg)); if (!visited[&(l, Course::Bg)] && is_cyclic_util(Course::Bg, l, visited, stack, path, theme)) @@ -1855,6 +1838,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Link(ref l, ColorField::Fg) => { + let l = l.as_ref(); path.push((l, Course::Fg)); if (!visited[&(l, Course::Fg)] && is_cyclic_util(Course::Fg, l, visited, stack, path, theme)) @@ -1865,6 +1849,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Alias(ref ident) => { + let ident = ident.as_ref(); path.push((ident, Course::ColorAliasBg)); if (!visited[&(ident, Course::ColorAliasBg)] && is_cyclic_util( @@ -1885,6 +1870,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { }, Course::Attrs => match theme[k].attrs { ThemeValue::Link(ref l, _) => { + let l = l.as_ref(); path.push((l, course)); if (!visited[&(l, course)] && is_cyclic_util(course, l, visited, stack, path, theme)) @@ -1895,6 +1881,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Alias(ref ident) => { + let ident = ident.as_ref(); path.push((ident, Course::AttrAlias)); if (!visited[&(ident, Course::AttrAlias)] && is_cyclic_util( @@ -1915,6 +1902,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { }, Course::ColorAliasFg | Course::ColorAliasBg => match &theme.color_aliases[k] { ThemeValue::Link(ref l, ref field) => { + let l = l.as_ref(); let course = match (course, field) { (Course::ColorAliasFg, ColorField::LikeSelf) => Course::Fg, (Course::ColorAliasBg, ColorField::LikeSelf) => Course::Bg, @@ -1934,6 +1922,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Alias(ref ident) => { + let ident = ident.as_ref(); path.push((ident, course)); if (!visited[&(ident, course)] && is_cyclic_util(course, ident, visited, stack, path, theme)) @@ -1947,6 +1936,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { }, Course::AttrAlias => match &theme.attr_aliases[k] { ThemeValue::Link(ref l, ()) => { + let l = l.as_ref(); path.push((l, Course::Attrs)); if (!visited[&(l, Course::Attrs)] && is_cyclic_util(Course::Attrs, l, visited, stack, path, theme)) @@ -1957,6 +1947,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { path.pop(); } ThemeValue::Alias(ref ident) => { + let ident = ident.as_ref(); path.push((ident, course)); if (!visited[&(ident, course)] && is_cyclic_util(course, ident, visited, stack, path, theme)) @@ -1977,35 +1968,28 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { let mut path = SmallVec::new(); let mut visited = theme .keys() - .map(|k| { - std::iter::once(((k, Course::Fg), false)) - .chain(std::iter::once(((k, Course::Bg), false))) - .chain(std::iter::once(((k, Course::Attrs), false))) + .flat_map(|k| { + std::iter::once(((k.as_ref(), Course::Fg), false)) + .chain(std::iter::once(((k.as_ref(), Course::Bg), false))) + .chain(std::iter::once(((k.as_ref(), Course::Attrs), false))) }) - .flatten() - .chain( - theme - .color_aliases - .keys() - .map(|k| { - std::iter::once(((k, Course::ColorAliasFg), false)) - .chain(std::iter::once(((k, Course::ColorAliasBg), false))) - }) - .flatten(), - ) + .chain(theme.color_aliases.keys().flat_map(|k| { + std::iter::once(((k.as_ref(), Course::ColorAliasFg), false)) + .chain(std::iter::once(((k.as_ref(), Course::ColorAliasBg), false))) + })) .chain( theme .attr_aliases .keys() - .map(|k| ((k, Course::AttrAlias), false)), + .map(|k| ((k.as_ref(), Course::AttrAlias), false)), ) - .collect::, Course), bool>>(); + .collect::>(); let mut stack = visited.clone(); for k in theme.keys() { for &course in [Course::Fg, Course::Bg, Course::Attrs].iter() { - path.push((k, course)); - if is_cyclic_util(course, k, &mut visited, &mut stack, &mut path, &theme) { + path.push((k.as_ref(), course)); + if is_cyclic_util(course, k, &mut visited, &mut stack, &mut path, theme) { let path = path .into_iter() .map(|(k, c)| match c { @@ -2037,7 +2021,7 @@ fn is_cyclic(theme: &Theme) -> std::result::Result<(), String> { } } - return Ok(()); + Ok(()) } #[test] diff --git a/src/mailcap.rs b/src/mailcap.rs index 745945d3..7ff0e824 100644 --- a/src/mailcap.rs +++ b/src/mailcap.rs @@ -96,6 +96,7 @@ impl MailcapEntry { //let flags = parts_iter.next().unwrap(); if key.starts_with(&content_type) || key.matches_glob(&content_type) { let mut copiousoutput = false; + #[allow(clippy::while_let_on_iterator)] while let Some(flag) = parts_iter.next() { if flag.trim() == "copiousoutput" { copiousoutput = true; @@ -118,6 +119,7 @@ impl MailcapEntry { //let flags = parts_iter.next().unwrap(); if key.starts_with(&content_type) || key.matches_glob(&content_type) { let mut copiousoutput = false; + #[allow(clippy::while_let_on_iterator)] while let Some(flag) = parts_iter.next() { if flag.trim() == "copiousoutput" { copiousoutput = true; @@ -178,7 +180,7 @@ impl MailcapEntry { .collect::>(); let cmd_string = format!("{} {}", cmd, args.join(" ")); melib::log( - format!("Executing: sh -c \"{}\"", cmd_string.replace("\"", "\\\"")), + format!("Executing: sh -c \"{}\"", cmd_string.replace('"', "\\\"")), melib::DEBUG, ); if copiousoutput { @@ -212,25 +214,23 @@ impl MailcapEntry { .spawn()?; pager.stdin.as_mut().unwrap().write_all(&out)?; debug!(pager.wait_with_output()?.stdout); + } else if needs_stdin { + let mut child = Command::new("sh") + .args(&["-c", &cmd_string]) + .stdin(Stdio::piped()) + .stdout(Stdio::inherit()) + .spawn()?; + + child.stdin.as_mut().unwrap().write_all(&decode(a, None))?; + debug!(child.wait_with_output()?.stdout); } else { - if needs_stdin { - let mut child = Command::new("sh") - .args(&["-c", &cmd_string]) - .stdin(Stdio::piped()) - .stdout(Stdio::inherit()) - .spawn()?; + let child = Command::new("sh") + .args(&["-c", &cmd_string]) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .spawn()?; - child.stdin.as_mut().unwrap().write_all(&decode(a, None))?; - debug!(child.wait_with_output()?.stdout); - } else { - let child = Command::new("sh") - .args(&["-c", &cmd_string]) - .stdin(Stdio::inherit()) - .stdout(Stdio::inherit()) - .spawn()?; - - debug!(child.wait_with_output()?.stdout); - } + debug!(child.wait_with_output()?.stdout); } context.replies.push_back(UIEvent::Fork(ForkType::Finished)); Ok(()) diff --git a/src/sqlite3.rs b/src/sqlite3.rs index a9ebd526..c2ad9659 100644 --- a/src/sqlite3.rs +++ b/src/sqlite3.rs @@ -168,14 +168,14 @@ pub async fn insert( format!( "Failed to open envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ) ); log( format!( "Failed to open envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ), ERROR, ); @@ -190,13 +190,13 @@ pub async fn insert( debug!( "Failed to insert envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ); log( format!( "Failed to insert envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ), ERROR, ); @@ -217,19 +217,19 @@ pub async fn insert( if let Err(err) = conn.execute( "INSERT OR REPLACE INTO envelopes (account_id, hash, date, _from, _to, cc, bcc, subject, message_id, in_reply_to, _references, flags, has_attachments, body_text, timestamp) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)", - params![account_id, envelope.hash().to_be_bytes().to_vec(), envelope.date_as_str(), envelope.field_from_to_string(), envelope.field_to_to_string(), envelope.field_cc_to_string(), envelope.field_bcc_to_string(), envelope.subject().into_owned().trim_end_matches('\u{0}'), envelope.message_id_display().to_string(), envelope.in_reply_to_display().map(|f| f.to_string()).unwrap_or(String::new()), envelope.field_references_to_string(), i64::from(envelope.flags().bits()), if envelope.has_attachments() { 1 } else { 0 }, body, envelope.date().to_be_bytes().to_vec()], + params![account_id, envelope.hash().to_be_bytes().to_vec(), envelope.date_as_str(), envelope.field_from_to_string(), envelope.field_to_to_string(), envelope.field_cc_to_string(), envelope.field_bcc_to_string(), envelope.subject().into_owned().trim_end_matches('\u{0}'), envelope.message_id_display().to_string(), envelope.in_reply_to_display().map(|f| f.to_string()).unwrap_or_default(), envelope.field_references_to_string(), i64::from(envelope.flags().bits()), if envelope.has_attachments() { 1 } else { 0 }, body, envelope.date().to_be_bytes().to_vec()], ) .map_err(|e| MeliError::new(e.to_string())) { debug!( "Failed to insert envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ); log( format!( "Failed to insert envelope {}: {}", envelope.message_id_display(), - err.to_string() + err ), ERROR, ); @@ -253,17 +253,9 @@ pub fn remove(env_hash: EnvelopeHash) -> Result<()> { ) .map_err(|e| MeliError::new(e.to_string())) { - debug!( - "Failed to remove envelope {}: {}", - env_hash, - err.to_string() - ); + debug!("Failed to remove envelope {}: {}", env_hash, err); log( - format!( - "Failed to remove envelope {}: {}", - env_hash, - err.to_string() - ), + format!("Failed to remove envelope {}: {}", env_hash, err), ERROR, ); return Err(err); @@ -324,11 +316,11 @@ pub fn index(context: &mut crate::state::Context, account_index: usize) -> Resul .await .chain_err_summary(|| format!("Failed to open envelope {}", env_hash))?; let envelopes_lck = acc_mutex.read().unwrap(); - if let Some(e) = envelopes_lck.get(&env_hash) { + if let Some(e) = envelopes_lck.get(env_hash) { let body = e.body_bytes(&bytes).text().replace('\0', ""); conn.execute("INSERT OR REPLACE INTO envelopes (account_id, hash, date, _from, _to, cc, bcc, subject, message_id, in_reply_to, _references, flags, has_attachments, body_text, timestamp) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)", - params![account_id, e.hash().to_be_bytes().to_vec(), e.date_as_str(), e.field_from_to_string(), e.field_to_to_string(), e.field_cc_to_string(), e.field_bcc_to_string(), e.subject().into_owned().trim_end_matches('\u{0}'), e.message_id_display().to_string(), e.in_reply_to_display().map(|f| f.to_string()).unwrap_or(String::new()), e.field_references_to_string(), i64::from(e.flags().bits()), if e.has_attachments() { 1 } else { 0 }, body, e.date().to_be_bytes().to_vec()], + params![account_id, e.hash().to_be_bytes().to_vec(), e.date_as_str(), e.field_from_to_string(), e.field_to_to_string(), e.field_cc_to_string(), e.field_bcc_to_string(), e.subject().into_owned().trim_end_matches('\u{0}'), e.message_id_display().to_string(), e.in_reply_to_display().map(|f| f.to_string()).unwrap_or_default(), e.field_references_to_string(), i64::from(e.flags().bits()), if e.has_attachments() { 1 } else { 0 }, body, e.date().to_be_bytes().to_vec()], ).chain_err_summary(|| format!( "Failed to insert envelope {}", e.message_id_display()))?; } } @@ -366,7 +358,7 @@ pub fn search( .prepare( debug!(format!( "SELECT hash FROM envelopes WHERE {} ORDER BY {} {};", - query_to_sql(&query), + query_to_sql(query), sort_field, sort_order )) @@ -375,7 +367,7 @@ pub fn search( .map_err(|e| MeliError::new(e.to_string()))?; let results = stmt - .query_map([], |row| Ok(row.get(0)?)) + .query_map([], |row| row.get(0)) .map_err(|e| MeliError::new(e.to_string()))? .map(|r: std::result::Result, rusqlite::Error>| { Ok(u64::from_be_bytes( @@ -424,14 +416,14 @@ pub fn query_to_sql(q: &Query) -> String { s.push_str("%\" "); } And(q1, q2) => { - s.push_str("("); + s.push('('); rec(q1, s); s.push_str(") AND ("); rec(q2, s); s.push_str(") "); } Or(q1, q2) => { - s.push_str("("); + s.push('('); rec(q1, s); s.push_str(") OR ("); rec(q2, s); @@ -445,7 +437,7 @@ pub fn query_to_sql(q: &Query) -> String { Flags(v) => { let total = v.len(); if total > 1 { - s.push_str("("); + s.push('('); } for (i, f) in v.iter().enumerate() { match f.as_str() { diff --git a/src/state.rs b/src/state.rs index b58d3c1f..146a6ce1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -134,20 +134,18 @@ impl Context { } = self; let was_online = accounts[account_pos].is_online.is_ok(); let ret = accounts[account_pos].is_online(); - if ret.is_ok() { - if !was_online { - debug!("inserting mailbox hashes:"); - for mailbox_node in accounts[account_pos].list_mailboxes() { - debug!( - "hash & mailbox: {:?} {}", - mailbox_node.hash, - accounts[account_pos][&mailbox_node.hash].name() - ); - } - accounts[account_pos].watch(); - - replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash())); + if ret.is_ok() && !was_online { + debug!("inserting mailbox hashes:"); + for mailbox_node in accounts[account_pos].list_mailboxes() { + debug!( + "hash & mailbox: {:?} {}", + mailbox_node.hash, + accounts[account_pos][&mailbox_node.hash].name() + ); } + accounts[account_pos].watch(); + + replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash())); } if ret.is_ok() != was_online { replies.push_back(UIEvent::AccountStatusChange(accounts[account_pos].hash())); @@ -331,7 +329,7 @@ impl State { display_messages_area: ((0, 0), (0, 0)), context: Context { accounts, - settings: settings, + settings, dirty_areas: VecDeque::with_capacity(5), replies: VecDeque::with_capacity(5), temp_files: Vec::new(), @@ -399,10 +397,8 @@ impl State { } self.rcv_event(notification); } - } else { - if let melib::backends::RefreshEventKind::Failure(err) = event.kind { - debug!(err); - } + } else if let melib::backends::RefreshEventKind::Failure(err) = event.kind { + debug!(err); } } @@ -850,7 +846,7 @@ impl State { )); } AccountAction(ref account_name, PrintAccountSetting(ref setting)) => { - let path = setting.split(".").collect::>(); + let path = setting.split('.').collect::>(); if let Some(pos) = self .context .accounts @@ -858,13 +854,12 @@ impl State { .position(|(_h, a)| a.name() == account_name) { self.context.replies.push_back(UIEvent::StatusEvent( - StatusEvent::UpdateStatus(format!( - "{}", + StatusEvent::UpdateStatus( self.context.accounts[pos] .settings .lookup("settings", &path) - .unwrap_or_else(|err| err.to_string()) - )), + .unwrap_or_else(|err| err.to_string()), + ), )); } else { self.context.replies.push_back(UIEvent::Notification( @@ -872,20 +867,18 @@ impl State { format!("Account {} was not found.", account_name), Some(NotificationType::Error(ErrorKind::None)), )); - return; } } PrintSetting(ref setting) => { - let path = setting.split(".").collect::>(); + let path = setting.split('.').collect::>(); self.context .replies - .push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus(format!( - "{}", + .push_back(UIEvent::StatusEvent(StatusEvent::UpdateStatus( self.context .settings .lookup("settings", &path) - .unwrap_or_else(|err| err.to_string()) - )))); + .unwrap_or_else(|err| err.to_string()), + ))); } ToggleMouse => { self.screen.mouse = !self.screen.mouse; @@ -920,7 +913,7 @@ impl State { match event { // Command type is handled only by State. UIEvent::Command(cmd) => { - if let Ok(action) = parse_command(&cmd.as_bytes()) { + if let Ok(action) = parse_command(cmd.as_bytes()) { if action.needs_confirmation() { self.overlay.push(Box::new(UIConfirmationDialog::new( "You sure?", @@ -932,7 +925,7 @@ impl State { Box::new(if result { Some(action) } else { None }), )) })), - &mut self.context, + &self.context, ))); } else if let Action::ReloadConfiguration = action { match Settings::new().and_then(|new_settings| { @@ -952,7 +945,7 @@ impl State { Ok(new_settings) }) { Ok(new_settings) => { - let old_settings = std::mem::replace(&mut self.context.settings, new_settings); + let old_settings = Box::new(std::mem::replace(&mut self.context.settings, new_settings)); self.context.replies.push_back(UIEvent::ConfigReload { old_settings }); @@ -1130,11 +1123,8 @@ impl State { match w { Ok(Some(_)) => true, Ok(None) => false, - Err(e) => { - log( - format!("Failed to wait on editor process: {}", e.to_string()), - ERROR, - ); + Err(err) => { + log(format!("Failed to wait on editor process: {}", err), ERROR); return None; } } @@ -1144,11 +1134,8 @@ impl State { match w { Ok(Some(_)) => true, Ok(None) => false, - Err(e) => { - log( - format!("Failed to wait on child process: {}", e.to_string()), - ERROR, - ); + Err(err) => { + log(format!("Failed to wait on child process: {}", err), ERROR); return None; } } @@ -1174,7 +1161,7 @@ impl State { } pub fn switch_to_alternate_screen(&mut self) { - self.screen.switch_to_alternate_screen(&mut self.context); + self.screen.switch_to_alternate_screen(&self.context); } fn flush(&mut self) { diff --git a/src/terminal/cells.rs b/src/terminal/cells.rs index a7ce43d8..ba739a62 100644 --- a/src/terminal/cells.rs +++ b/src/terminal/cells.rs @@ -151,7 +151,7 @@ impl CellBuffer { pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Option) -> bool { let newlen = newcols * newrows; if (self.cols, self.rows) == (newcols, newrows) || newlen >= Self::MAX_SIZE { - return !(newlen >= Self::MAX_SIZE); + return newlen < Self::MAX_SIZE; } let blank = blank.unwrap_or(self.default_cell); @@ -432,10 +432,10 @@ impl CellBuffer { pub fn set_tag(&mut self, tag: u64, start: (usize, usize), end: (usize, usize)) { let start = self .pos_to_index(start.0, start.1) - .unwrap_or(self.buf.len().saturating_sub(1)); + .unwrap_or_else(|| self.buf.len().saturating_sub(1)); let end = self .pos_to_index(end.0, end.1) - .unwrap_or(self.buf.len().saturating_sub(1)); + .unwrap_or_else(|| self.buf.len().saturating_sub(1)); if start != end { self.tag_associations.push((tag, (start, end))); } @@ -856,9 +856,9 @@ impl Attr { "Blink" => Ok(Attr::BLINK), "Reverse" => Ok(Attr::REVERSE), "Hidden" => Ok(Attr::HIDDEN), - combination if combination.contains("|") => { + combination if combination.contains('|') => { let mut ret = Attr::DEFAULT; - for c in combination.trim().split("|") { + for c in combination.trim().split('|') { ret |= Self::from_string_de::<'de, D, &str>(c)?; } Ok(ret) @@ -1725,7 +1725,7 @@ impl core::cmp::Ord for FormatTag { impl core::cmp::PartialOrd for FormatTag { fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(&other)) + Some(self.cmp(other)) } } diff --git a/src/terminal/color.rs b/src/terminal/color.rs index d65671a7..872394d9 100644 --- a/src/terminal/color.rs +++ b/src/terminal/color.rs @@ -391,10 +391,12 @@ impl Color { "Yellow5" => 106, "Yellow6" => 148, "Default" => return Ok(Color::Default), - s if s.starts_with("#") + s if s.starts_with('#') && s.len() == 7 && s[1..].as_bytes().iter().all(|&b| { - (b >= b'0' && b <= b'9') || (b >= b'a' && b <= b'f') || (b >= b'A' && b <= b'F') + (b'0'..=b'9').contains(&b) + || (b'a'..=b'f').contains(&b) + || (b'A'..=b'F').contains(&b) }) => { return Ok(Color::Rgb( @@ -406,10 +408,12 @@ impl Color { .map_err(|_| de::Error::custom("invalid `color` value"))?, )) } - s if s.starts_with("#") + s if s.starts_with('#') && s.len() == 4 && s[1..].as_bytes().iter().all(|&b| { - (b >= b'0' && b <= b'9') || (b >= b'a' && b <= b'f') || (b >= b'A' && b <= b'F') + (b'0'..=b'9').contains(&b) + || (b'a'..=b'f').contains(&b) + || (b'A'..=b'F').contains(&b) }) => { return Ok(Color::Rgb( @@ -421,7 +425,8 @@ impl Color { .map_err(|_| de::Error::custom("invalid `color` value"))?, )) } - _ => u8::from_str_radix(&s, 10) + _ => s + .parse::() .map_err(|_| de::Error::custom("invalid `color` value"))?, }; Ok(Color::Byte(byte)) diff --git a/src/terminal/embed/grid.rs b/src/terminal/embed/grid.rs index 35837697..cd74e795 100644 --- a/src/terminal/embed/grid.rs +++ b/src/terminal/embed/grid.rs @@ -346,7 +346,7 @@ impl EmbedGrid { *state = State::CsiQ(buf1); } /* OSC stuff */ - (c, State::Osc1(ref mut buf)) if (c >= b'0' && c <= b'9') || c == b'?' => { + (c, State::Osc1(ref mut buf)) if (b'0'..=b'9').contains(&c) || c == b'?' => { buf.push(c); } (b';', State::Osc1(ref mut buf1_p)) => { @@ -354,7 +354,7 @@ impl EmbedGrid { let buf2 = SmallVec::new(); *state = State::Osc2(buf1, buf2); } - (c, State::Osc2(_, ref mut buf)) if (c >= b'0' && c <= b'9') || c == b'?' => { + (c, State::Osc2(_, ref mut buf)) if (b'0'..=b'9').contains(&c) || c == b'?' => { buf.push(c); } /* Normal */ @@ -512,7 +512,7 @@ impl EmbedGrid { *state = State::Normal; } /* CSI ? stuff */ - (c, State::CsiQ(ref mut buf)) if c >= b'0' && c <= b'9' => { + (c, State::CsiQ(ref mut buf)) if (b'0'..=b'9').contains(&c) => { buf.push(c); } (b'h', State::CsiQ(ref buf)) => { @@ -569,7 +569,7 @@ impl EmbedGrid { *state = State::Normal; } /* END OF CSI ? stuff */ - (c, State::Csi) if c >= b'0' && c <= b'9' => { + (c, State::Csi) if (b'0'..=b'9').contains(&c) => { let mut buf1 = SmallVec::new(); buf1.push(c); *state = State::Csi1(buf1); @@ -973,17 +973,9 @@ impl EmbedGrid { *bg_color = Color::Default; } b"1" => { /* bold */ } - b"7" => { - /* Inverse */ - let temp = *fg_color; - *fg_color = *bg_color; - *bg_color = temp; - } - b"27" => { - /* Inverse off */ - let temp = *fg_color; - *fg_color = *bg_color; - *bg_color = temp; + b"7" | b"27" => { + /* Inverse on/off */ + std::mem::swap(&mut (*fg_color), &mut (*bg_color)) } b"30" => *fg_color = Color::Black, b"31" => *fg_color = Color::Red, @@ -1037,17 +1029,9 @@ impl EmbedGrid { *bg_color = Color::Default; } b"1" => { /* bold */ } - b"7" => { - /* Inverse */ - let temp = *fg_color; - *fg_color = *bg_color; - *bg_color = temp; - } - b"27" => { - /* Inverse off */ - let temp = *fg_color; - *fg_color = *bg_color; - *bg_color = temp; + b"7" | b"27" => { + /* Inverse on/off */ + std::mem::swap(&mut (*fg_color), &mut (*bg_color)) } b"30" => *fg_color = Color::Black, b"31" => *fg_color = Color::Red, @@ -1094,7 +1078,7 @@ impl EmbedGrid { grid[cursor_val!()].set_bg(*bg_color); *state = State::Normal; } - (c, State::Csi1(ref mut buf)) if (c >= b'0' && c <= b'9') || c == b' ' => { + (c, State::Csi1(ref mut buf)) if (b'0'..=b'9').contains(&c) || c == b' ' => { buf.push(c); } (b';', State::Csi2(ref mut buf1_p, ref mut buf2_p)) => { @@ -1144,7 +1128,7 @@ impl EmbedGrid { //debug!("cursor became: {:?}", cursor); *state = State::Normal; } - (c, State::Csi2(_, ref mut buf)) if c >= b'0' && c <= b'9' => { + (c, State::Csi2(_, ref mut buf)) if (b'0'..=b'9').contains(&c) => { buf.push(c); } (b'r', State::Csi2(_, _)) | (b'r', State::Csi) => { @@ -1177,7 +1161,7 @@ impl EmbedGrid { *state = State::Normal; } - (c, State::Csi3(_, _, ref mut buf)) if c >= b'0' && c <= b'9' => { + (c, State::Csi3(_, _, ref mut buf)) if (b'0'..=b'9').contains(&c) => { buf.push(c); } (b'm', State::Csi3(ref buf1, ref buf2, ref buf3)) @@ -1185,7 +1169,7 @@ impl EmbedGrid { { /* Set character attributes | foreground color */ *fg_color = if let Ok(byte) = - u8::from_str_radix(unsafe { std::str::from_utf8_unchecked(buf3) }, 10) + unsafe { std::str::from_utf8_unchecked(buf3) }.parse::() { //debug!("parsed buf as {}", byte); Color::Byte(byte) @@ -1200,7 +1184,7 @@ impl EmbedGrid { { /* Set character attributes | background color */ *bg_color = if let Ok(byte) = - u8::from_str_radix(unsafe { std::str::from_utf8_unchecked(buf3) }, 10) + unsafe { std::str::from_utf8_unchecked(buf3) }.parse::() { //debug!("parsed buf as {}", byte); Color::Byte(byte) @@ -1246,3 +1230,9 @@ impl EmbedGrid { } } } + +impl Default for EmbedGrid { + fn default() -> Self { + Self::new() + } +} diff --git a/src/terminal/keys.rs b/src/terminal/keys.rs index bdb4f456..bfc3ac2b 100644 --- a/src/terminal/keys.rs +++ b/src/terminal/keys.rs @@ -182,7 +182,7 @@ pub fn get_events( select! { default => { if stdin_fd.revents().is_some() { - 'stdin_while: while let Some(c) = stdin_iter.next(){ + 'stdin_while: for c in stdin_iter.by_ref() { match (c, &mut input_mode) { (Ok((TermionEvent::Key(k), bytes)), InputMode::Normal) => { closure((Key::from(k), bytes)); @@ -192,7 +192,7 @@ pub fn get_events( Ok((TermionEvent::Key(TermionKey::Char(k)), ref mut bytes)), InputMode::Paste(ref mut buf), ) => { paste_buf.push(k); - let bytes = std::mem::replace(bytes, Vec::new()); + let bytes = std::mem::take(bytes); buf.extend(bytes.into_iter()); continue 'stdin_while; } @@ -203,7 +203,7 @@ pub fn get_events( (Ok((TermionEvent::Unsupported(ref k), _)), InputMode::Paste(ref mut buf)) if k.as_slice() == BRACKET_PASTE_END => { - let buf = std::mem::replace(buf, Vec::new()); + let buf = std::mem::take(buf); input_mode = InputMode::Normal; let ret = Key::from(&paste_buf); paste_buf.clear(); @@ -277,12 +277,12 @@ impl<'de> Deserialize<'de> for Key { "Enter" | "enter" => Ok(Key::Char('\n')), "Tab" | "tab" => Ok(Key::Char('\t')), "Esc" | "esc" => Ok(Key::Esc), - ref s if s.len() == 1 => Ok(Key::Char(s.chars().nth(0).unwrap())), - ref s if s.starts_with("F") && (s.len() == 2 || s.len() == 3) => { + s if s.len() == 1 => Ok(Key::Char(s.chars().next().unwrap())), + s if s.starts_with('F') && (s.len() == 2 || s.len() == 3) => { use std::str::FromStr; if let Ok(n) = u8::from_str(&s[1..]) { - if n >= 1 && n <= 12 { + if (1..=12).contains(&n) { return Ok(Key::F(n)); } } @@ -291,7 +291,7 @@ impl<'de> Deserialize<'de> for Key { &s[1..] ))) } - ref s if s.starts_with("M-") && s.len() == 3 => { + s if s.starts_with("M-") && s.len() == 3 => { let c = s.as_bytes()[2] as char; if c.is_lowercase() || c.is_numeric() { @@ -303,7 +303,7 @@ impl<'de> Deserialize<'de> for Key { &s[2..] ))) } - ref s if s.starts_with("C-") && s.len() == 3 => { + s if s.starts_with("C-") && s.len() == 3 => { let c = s.as_bytes()[2] as char; if c.is_lowercase() || c.is_numeric() { diff --git a/src/types.rs b/src/types.rs index eec5b51b..158d8281 100644 --- a/src/types.rs +++ b/src/types.rs @@ -149,12 +149,12 @@ pub enum UIEvent { GlobalUIDialog(Box), Timer(Uuid), ConfigReload { - old_settings: crate::conf::Settings, + old_settings: Box, }, VisibilityChange(bool), } -pub struct CallbackFn(pub Box () + Send + 'static>); +pub struct CallbackFn(pub Box); impl core::fmt::Debug for CallbackFn { fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { @@ -322,8 +322,6 @@ pub struct RateLimit { last_tick: std::time::Instant, pub timer: crate::jobs::Timer, rate: std::time::Duration, - reqs: u64, - millis: std::time::Duration, pub active: bool, } @@ -336,8 +334,6 @@ impl RateLimit { std::time::Duration::from_millis(millis), ), rate: std::time::Duration::from_millis(millis / reqs), - reqs, - millis: std::time::Duration::from_millis(millis), active: false, } } diff --git a/src/types/helpers.rs b/src/types/helpers.rs index 87850e49..1f33f676 100644 --- a/src/types/helpers.rs +++ b/src/types/helpers.rs @@ -36,7 +36,7 @@ pub struct File { impl Drop for File { fn drop(&mut self) { if self.delete_on_drop { - std::fs::remove_file(self.path()).unwrap_or_else(|_| {}); + let _ = std::fs::remove_file(self.path()); } } } @@ -54,6 +54,7 @@ impl File { pub fn path(&self) -> &PathBuf { &self.path } + pub fn read_to_string(&self) -> String { let mut buf = Vec::new(); let mut f = fs::File::open(&self.path)