From 03693f96d0265f665ec00b5bb204cb727d7b137a Mon Sep 17 00:00:00 2001 From: rabite Date: Fri, 20 Dec 2019 22:07:38 +0100 Subject: improved Files interface by returning Iterator instead of Vec<&File> --- src/file_browser.rs | 26 +++++++++++++---------- src/files.rs | 59 +++++++++++++++++++++++++++-------------------------- src/listview.rs | 41 +++++++++++++++++++++++++------------ 3 files changed, 73 insertions(+), 53 deletions(-) diff --git a/src/file_browser.rs b/src/file_browser.rs index 1a57c8a..257ca32 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -441,11 +441,11 @@ impl FileBrowser { pub fn move_down_left_widget(&mut self) -> HResult<()> { let left_files_pos = self.left_widget()?.get_selection(); - let next_dir = self.get_left_files()?.get_files() - .iter() + let next_dir = self.get_left_files()? + .iter_files() .skip(left_files_pos + 1) - .find(|file| file.is_dir()) - .cloned().cloned(); + .find(|&file| file.is_dir()) + .cloned(); self.main_widget_goto(&next_dir?).log(); @@ -454,14 +454,15 @@ impl FileBrowser { pub fn move_up_left_widget(&mut self) -> HResult<()> { let left_files_pos = self.left_widget()?.get_selection(); - let skip_files = self.get_left_files()?.len() - left_files_pos; - let next_dir = self.get_left_files()?.get_files() - .iter() + let next_dir = self.get_left_files()? + .iter_files() + .take(left_files_pos) + .collect::>() + .into_iter() .rev() - .skip(skip_files) - .find(|file| file.is_dir()) - .cloned().cloned(); + .find(|&file| file.is_dir()) + .cloned(); self.main_widget_goto(&next_dir?).log(); @@ -1170,7 +1171,10 @@ impl FileBrowser { let xsize = self.get_coordinates()?.xsize(); let ypos = self.get_coordinates()?.position().y(); let pos = self.main_widget()?.get_selection(); - let file = self.main_widget()?.content.get_files().get(pos).cloned()?; + let file = self.main_widget()? + .content + .iter_files() + .nth(pos)?; let permissions = file.pretty_print_permissions().unwrap_or("NOPERMS".into()); let user = file.pretty_user().unwrap_or("NOUSER".into()); diff --git a/src/files.rs b/src/files.rs index fa774c5..d8558af 100644 --- a/src/files.rs +++ b/src/files.rs @@ -238,48 +238,54 @@ impl Files { } pub fn get_file_mut(&mut self, index: usize) -> Option<&mut File> { + self.iter_files_mut() + .nth(index) + } + + pub fn iter_files(&self) -> impl Iterator { let filter = self.filter.clone(); let filter_selected = self.filter_selected; let show_hidden = self.show_hidden; - let file = self.files - .iter_mut() - .filter(|f| + self.files + .iter() + .filter(move |f| f.kind == Kind::Placeholder || !(filter.is_some() && !f.name.contains(filter.as_ref().unwrap())) && (!filter_selected || f.selected)) - .filter(|f| !(!show_hidden && f.name.starts_with("."))) - .nth(index); - file + .filter(move |f| !(!show_hidden && f.name.starts_with("."))) } - pub fn get_files(&self) -> Vec<&File> { + pub fn iter_files_mut(&mut self) -> impl Iterator { + let filter = self.filter.clone(); + let filter_selected = self.filter_selected; + let show_hidden = self.show_hidden; + self.files - .iter() - .filter(|f| + .iter_mut() + .filter(move |f| f.kind == Kind::Placeholder || - !(self.filter.is_some() && - !f.name.contains(self.filter.as_ref().unwrap())) && - (!self.filter_selected || f.selected)) - .filter(|f| !(!self.show_hidden && f.name.starts_with("."))) - .collect() + !(filter.is_some() && + !f.name.contains(filter.as_ref().unwrap())) && + (!filter_selected || f.selected)) + .filter(move |f| !(!show_hidden && f.name.starts_with("."))) } - pub fn get_files_mut(&mut self) -> Vec<&mut File> { - let filter = self.filter.clone(); + #[allow(trivial_bounds)] + pub fn into_iter_files(self) -> impl Iterator { + let filter = self.filter; let filter_selected = self.filter_selected; let show_hidden = self.show_hidden; self.files - .iter_mut() - .filter(|f| + .into_iter() + .filter(move |f| f.kind == Kind::Placeholder || !(filter.is_some() && !f.name.contains(filter.as_ref().unwrap())) && (!filter_selected || f.selected)) - .filter(|f| !(!show_hidden && f.name.starts_with("."))) - .collect() + .filter(move |f| !(!show_hidden && f.name.starts_with("."))) } pub fn sort(&mut self) { @@ -454,10 +460,8 @@ impl Files { } pub fn find_file_with_name(&self, name: &str) -> Option<&File> { - self.get_files() - .iter() + self.iter_files() .find(|f| f.name.to_lowercase().contains(name)) - .cloned() } pub fn find_file_with_path(&mut self, path: &Path) -> Option<&mut File> { @@ -543,15 +547,12 @@ impl Files { } pub fn len(&self) -> usize { - self.get_files().len() + self.iter_files().count() } - pub fn get_selected(&self) -> Vec<&File> { - self.get_files() - .iter() + pub fn get_selected(&self) -> impl Iterator { + self.iter_files() .filter(|f| f.is_selected()) - .map(|f| *f) - .collect() } } diff --git a/src/listview.rs b/src/listview.rs index 53cbff6..f44a705 100644 --- a/src/listview.rs +++ b/src/listview.rs @@ -222,14 +222,31 @@ impl ListView { pub fn selected_file(&self) -> &File { let selection = self.selection; - let file = &self.content.get_files()[selection]; - file + + &self.content + .iter_files() + .nth(selection) + .unwrap_or(&self.content.directory) } pub fn selected_file_mut(&mut self) -> &mut File { let selection = self.selection; - let file = self.content.get_file_mut(selection); - file.unwrap() + + let file = self.content + .iter_files_mut() + .nth(selection) + .map(|f| f as *mut File); + + + // Work around annoying restriction until polonius borrow checker becomes default + // Since we only ever return one mutable borrow this is perfectly safe + // See also: https://github.com/rust-lang/rust/issues/21906 + match file { + Some(file) => unsafe { return file.as_mut().unwrap() }, + None => { + &mut self.content.directory + } + } } pub fn clone_selected_file(&self) -> File { @@ -271,9 +288,8 @@ impl ListView pub fn select_file(&mut self, file: &File) { let pos = self .content - .get_files() - .iter() - .position(|item| item == &file) + .iter_files() + .position(|item| item == file) .unwrap_or(0); self.set_selection(pos); } @@ -308,7 +324,7 @@ impl ListView self.select_file(&file); - if self.seeking == false || self.selection + 1 == self.content.len() { + if self.seeking == false || self.selection + 1 >= self.content.len() { self.selection = 0; self.offset = 0; } else { @@ -390,7 +406,7 @@ impl ListView } pub fn invert_selection(&mut self) { - for file in self.content.get_files_mut() { + for file in self.content.iter_files_mut() { file.toggle_selection(); } @@ -404,7 +420,7 @@ impl ListView } pub fn clear_selections(&mut self) { - for file in self.content.get_files_mut() { + for file in self.content.iter_files_mut() { file.selected = false; } self.content.set_dirty(); @@ -632,9 +648,8 @@ impl ListView fn render(&self) -> Vec { self.content - .get_files() - .iter() - .map(|file| self.render_line(&file)) + .iter_files() + .map(|file| self.render_line(file)) .collect() } } -- cgit v1.2.3