From e90e8dc53677f81c7b8d884c020f97847aaca4af Mon Sep 17 00:00:00 2001 From: UG <55311933+UUGTech@users.noreply.github.com> Date: Tue, 20 Jun 2023 19:57:36 +0900 Subject: [PATCH] FuzzyFindPopup for general use (#1672) * replace BranchFindPopup with FuzzyFindPopup * replace FileFindPopup with FuzzyFindPopup --- src/app.rs | 69 ++-- src/components/branchlist.rs | 17 +- src/components/file_find_popup.rs | 349 ------------------ ...anch_find_popup.rs => fuzzy_find_popup.rs} | 78 ++-- src/components/mod.rs | 12 +- src/components/revision_files.rs | 35 +- src/components/revision_files_popup.rs | 4 +- src/queue.rs | 12 +- src/tabs/files.rs | 4 +- 9 files changed, 123 insertions(+), 457 deletions(-) delete mode 100644 src/components/file_find_popup.rs rename src/components/{branch_find_popup.rs => fuzzy_find_popup.rs} (80%) diff --git a/src/app.rs b/src/app.rs index 13a6f159..1811b508 100644 --- a/src/app.rs +++ b/src/app.rs @@ -2,15 +2,16 @@ use crate::{ accessors, cmdbar::CommandBar, components::{ - event_pump, AppOption, BlameFileComponent, BranchFindPopup, + event_pump, AppOption, BlameFileComponent, BranchListComponent, CommandBlocking, CommandInfo, CommitComponent, CompareCommitsComponent, Component, ConfirmComponent, CreateBranchComponent, DrawableComponent, - ExternalEditorComponent, FetchComponent, FileFindPopup, - FileRevlogComponent, HelpComponent, InspectCommitComponent, - MsgComponent, OptionsPopupComponent, PullComponent, - PushComponent, PushTagsComponent, RenameBranchComponent, - ResetPopupComponent, RevisionFilesPopup, StashMsgComponent, + ExternalEditorComponent, FetchComponent, FileRevlogComponent, + FuzzyFindPopup, FuzzyFinderTarget, HelpComponent, + InspectCommitComponent, MsgComponent, OptionsPopupComponent, + PullComponent, PushComponent, PushTagsComponent, + RenameBranchComponent, ResetPopupComponent, + RevisionFilesPopup, StashMsgComponent, SubmodulesListComponent, TagCommitComponent, TagListComponent, }, @@ -45,7 +46,7 @@ use ratatui::{ }; use std::{ cell::{Cell, RefCell}, - path::Path, + path::{Path, PathBuf}, rc::Rc, }; use unicode_width::UnicodeWidthStr; @@ -72,8 +73,7 @@ pub struct App { compare_commits_popup: CompareCommitsComponent, external_editor_popup: ExternalEditorComponent, revision_files_popup: RevisionFilesPopup, - find_file_popup: FileFindPopup, - branch_find_popup: BranchFindPopup, + fuzzy_find_popup: FuzzyFindPopup, push_popup: PushComponent, push_tags_popup: PushTagsComponent, pull_popup: PullComponent, @@ -271,12 +271,7 @@ impl App { theme.clone(), key_config.clone(), ), - find_file_popup: FileFindPopup::new( - &queue, - theme.clone(), - key_config.clone(), - ), - branch_find_popup: BranchFindPopup::new( + fuzzy_find_popup: FuzzyFindPopup::new( &queue, theme.clone(), key_config.clone(), @@ -585,8 +580,7 @@ impl App { accessors!( self, [ - find_file_popup, - branch_find_popup, + fuzzy_find_popup, msg, reset, commit, @@ -637,8 +631,7 @@ impl App { create_branch_popup, rename_branch_popup, revision_files_popup, - find_file_popup, - branch_find_popup, + fuzzy_find_popup, push_popup, push_tags_popup, pull_popup, @@ -897,13 +890,8 @@ impl App { InternalEvent::StatusLastFileMoved => { self.status_tab.last_file_moved()?; } - InternalEvent::OpenFileFinder(files) => { - self.find_file_popup.open(&files)?; - flags - .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); - } - InternalEvent::OpenBranchFinder(branches) => { - self.branch_find_popup.open(branches)?; + InternalEvent::OpenFuzzyFinder(contents, target) => { + self.fuzzy_find_popup.open(contents, target)?; flags .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); } @@ -921,14 +909,25 @@ impl App { flags.insert(NeedsUpdate::ALL); } - InternalEvent::FileFinderChanged(file) => { - self.files_tab.file_finder_update(&file); - self.revision_files_popup.file_finder_update(&file); - flags - .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); - } - InternalEvent::BranchFinderChanged(idx) => { - self.select_branch_popup.branch_finder_update(idx)?; + InternalEvent::FuzzyFinderChanged( + idx, + content, + target, + ) => { + match target { + FuzzyFinderTarget::Branches => self + .select_branch_popup + .branch_finder_update(idx)?, + FuzzyFinderTarget::Files => { + self.files_tab.file_finder_update( + &PathBuf::from(content.clone()), + ); + self.revision_files_popup.file_finder_update( + &PathBuf::from(content), + ); + } + } + flags .insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS); } @@ -1104,7 +1103,7 @@ impl App { res.push(CommandInfo::new( strings::commands::find_file(&self.key_config), - !self.find_file_popup.is_visible(), + !self.fuzzy_find_popup.is_visible(), (!self.any_popup_visible() && self.files_tab.is_visible()) || self.revision_files_popup.is_visible() diff --git a/src/components/branchlist.rs b/src/components/branchlist.rs index 027dc303..262c1530 100644 --- a/src/components/branchlist.rs +++ b/src/components/branchlist.rs @@ -1,7 +1,7 @@ use super::{ utils::scroll_vertical::VerticalScroll, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, - EventState, InspectCommitOpen, + EventState, FuzzyFinderTarget, InspectCommitOpen, }; use crate::{ components::ScrollType, @@ -298,8 +298,10 @@ impl Component for BranchListComponent { .iter() .map(|b| b.name.clone()) .collect(); - self.queue - .push(InternalEvent::OpenBranchFinder(branches)); + self.queue.push(InternalEvent::OpenFuzzyFinder( + branches, + FuzzyFinderTarget::Branches, + )); } } @@ -386,13 +388,8 @@ impl BranchListComponent { Ok(()) } - pub fn branch_finder_update( - &mut self, - idx: Option, - ) -> Result<()> { - if let Some(idx) = idx { - self.set_selection(idx.try_into()?)?; - } + pub fn branch_finder_update(&mut self, idx: usize) -> Result<()> { + self.set_selection(idx.try_into()?)?; Ok(()) } diff --git a/src/components/file_find_popup.rs b/src/components/file_find_popup.rs deleted file mode 100644 index 8ec9e578..00000000 --- a/src/components/file_find_popup.rs +++ /dev/null @@ -1,349 +0,0 @@ -use super::{ - visibility_blocking, CommandBlocking, CommandInfo, Component, - DrawableComponent, EventState, ScrollType, TextInputComponent, -}; -use crate::{ - keys::{key_match, SharedKeyConfig}, - queue::{InternalEvent, Queue}, - string_utils::trim_length_left, - strings, - ui::{self, style::SharedTheme}, -}; -use anyhow::Result; -use asyncgit::sync::TreeFile; -use crossterm::event::Event; -use fuzzy_matcher::FuzzyMatcher; -use ratatui::{ - backend::Backend, - layout::{Constraint, Direction, Layout, Margin, Rect}, - text::{Line, Span}, - widgets::{Block, Borders, Clear}, - Frame, -}; -use std::borrow::Cow; - -pub struct FileFindPopup { - queue: Queue, - visible: bool, - find_text: TextInputComponent, - query: Option, - theme: SharedTheme, - files: Vec, - selection: usize, - selected_index: Option, - files_filtered: Vec<(usize, Vec)>, - key_config: SharedKeyConfig, -} - -impl FileFindPopup { - /// - pub fn new( - queue: &Queue, - theme: SharedTheme, - key_config: SharedKeyConfig, - ) -> Self { - let mut find_text = TextInputComponent::new( - theme.clone(), - key_config.clone(), - "", - "start typing..", - false, - ); - find_text.embed(); - - Self { - queue: queue.clone(), - visible: false, - query: None, - find_text, - theme, - files: Vec::new(), - files_filtered: Vec::new(), - selected_index: None, - key_config, - selection: 0, - } - } - - fn update_query(&mut self) { - if self.find_text.get_text().is_empty() { - self.set_query(None); - } else if self - .query - .as_ref() - .map_or(true, |q| q != self.find_text.get_text()) - { - self.set_query(Some( - self.find_text.get_text().to_string(), - )); - } - } - - fn set_query(&mut self, query: Option) { - self.query = query; - - self.files_filtered.clear(); - - if let Some(q) = &self.query { - let matcher = - fuzzy_matcher::skim::SkimMatcherV2::default(); - - let mut files = self - .files - .iter() - .enumerate() - .filter_map(|a| { - a.1.path.to_str().and_then(|path| { - matcher.fuzzy_indices(path, q).map( - |(score, indices)| (score, a.0, indices), - ) - }) - }) - .collect::>(); - - files.sort_by(|(score1, _, _), (score2, _, _)| { - score2.cmp(score1) - }); - - self.files_filtered.extend( - files.into_iter().map(|entry| (entry.1, entry.2)), - ); - } - - self.selection = 0; - self.refresh_selection(); - } - - fn refresh_selection(&mut self) { - let selection = - self.files_filtered.get(self.selection).map(|a| a.0); - - if self.selected_index != selection { - self.selected_index = selection; - - let file = self - .selected_index - .and_then(|index| self.files.get(index)) - .map(|f| f.path.clone()); - - self.queue.push(InternalEvent::FileFinderChanged(file)); - } - } - - pub fn open(&mut self, files: &[TreeFile]) -> Result<()> { - self.show()?; - self.find_text.show()?; - self.find_text.set_text(String::new()); - self.query = None; - if self.files != *files { - self.files = files.to_owned(); - } - self.update_query(); - - Ok(()) - } - - fn move_selection(&mut self, move_type: ScrollType) -> bool { - let new_selection = match move_type { - ScrollType::Up => self.selection.saturating_sub(1), - ScrollType::Down => self.selection.saturating_add(1), - _ => self.selection, - }; - - let new_selection = new_selection - .clamp(0, self.files_filtered.len().saturating_sub(1)); - - if new_selection != self.selection { - self.selection = new_selection; - self.refresh_selection(); - return true; - } - - false - } -} - -impl DrawableComponent for FileFindPopup { - fn draw( - &self, - f: &mut Frame, - area: Rect, - ) -> Result<()> { - if self.is_visible() { - const MAX_SIZE: (u16, u16) = (50, 20); - - let any_hits = !self.files_filtered.is_empty(); - - let area = ui::centered_rect_absolute( - MAX_SIZE.0, MAX_SIZE.1, area, - ); - - let area = if any_hits { - area - } else { - Layout::default() - .direction(Direction::Vertical) - .constraints( - [ - Constraint::Length(3), - Constraint::Percentage(100), - ] - .as_ref(), - ) - .split(area)[0] - }; - - f.render_widget(Clear, area); - f.render_widget( - Block::default() - .borders(Borders::all()) - .style(self.theme.title(true)) - .title(Span::styled( - strings::POPUP_TITLE_FUZZY_FIND, - self.theme.title(true), - )), - area, - ); - - let chunks = Layout::default() - .direction(Direction::Vertical) - .constraints( - [ - Constraint::Length(1), - Constraint::Percentage(100), - ] - .as_ref(), - ) - .split(area.inner(&Margin { - horizontal: 1, - vertical: 1, - })); - - self.find_text.draw(f, chunks[0])?; - - if any_hits { - let title = - format!("Hits: {}", self.files_filtered.len()); - - let height = usize::from(chunks[1].height); - let width = usize::from(chunks[1].width); - - let items = self - .files_filtered - .iter() - .take(height) - .map(|(idx, indicies)| { - let selected = self - .selected_index - .map_or(false, |index| index == *idx); - let full_text = trim_length_left( - self.files[*idx] - .path - .to_str() - .unwrap_or_default(), - width, - ); - Line::from( - full_text - .char_indices() - .map(|(c_idx, c)| { - Span::styled( - Cow::from(c.to_string()), - self.theme.text( - selected, - indicies.contains(&c_idx), - ), - ) - }) - .collect::>(), - ) - }); - - ui::draw_list_block( - f, - chunks[1], - Block::default() - .title(Span::styled( - title, - self.theme.title(true), - )) - .borders(Borders::TOP), - items, - ); - } - } - Ok(()) - } -} - -impl Component for FileFindPopup { - fn commands( - &self, - out: &mut Vec, - force_all: bool, - ) -> CommandBlocking { - if self.is_visible() || force_all { - out.push(CommandInfo::new( - strings::commands::scroll_popup(&self.key_config), - true, - true, - )); - - out.push(CommandInfo::new( - strings::commands::close_fuzzy_finder( - &self.key_config, - ), - true, - true, - )); - } - - visibility_blocking(self) - } - - fn event( - &mut self, - event: &crossterm::event::Event, - ) -> Result { - if self.is_visible() { - if let Event::Key(key) = event { - if key_match(key, self.key_config.keys.exit_popup) - || key_match(key, self.key_config.keys.enter) - { - self.hide(); - } else if key_match( - key, - self.key_config.keys.popup_down, - ) { - self.move_selection(ScrollType::Down); - } else if key_match( - key, - self.key_config.keys.popup_up, - ) { - self.move_selection(ScrollType::Up); - } - } - - if self.find_text.event(event)?.is_consumed() { - self.update_query(); - } - - return Ok(EventState::Consumed); - } - - Ok(EventState::NotConsumed) - } - - fn is_visible(&self) -> bool { - self.visible - } - - fn hide(&mut self) { - self.visible = false; - } - - fn show(&mut self) -> Result<()> { - self.visible = true; - Ok(()) - } -} diff --git a/src/components/branch_find_popup.rs b/src/components/fuzzy_find_popup.rs similarity index 80% rename from src/components/branch_find_popup.rs rename to src/components/fuzzy_find_popup.rs index 2dafdecd..89b1eb55 100644 --- a/src/components/branch_find_popup.rs +++ b/src/components/fuzzy_find_popup.rs @@ -1,6 +1,7 @@ use super::{ visibility_blocking, CommandBlocking, CommandInfo, Component, - DrawableComponent, EventState, ScrollType, TextInputComponent, + DrawableComponent, EventState, FuzzyFinderTarget, ScrollType, + TextInputComponent, }; use crate::{ keys::{key_match, SharedKeyConfig}, @@ -21,20 +22,21 @@ use ratatui::{ }; use std::borrow::Cow; -pub struct BranchFindPopup { +pub struct FuzzyFindPopup { queue: Queue, visible: bool, find_text: TextInputComponent, query: Option, theme: SharedTheme, - branches: Vec, + contents: Vec, selection: usize, selected_index: Option, - branches_filtered: Vec<(usize, Vec)>, + filtered: Vec<(usize, Vec)>, key_config: SharedKeyConfig, + target: Option, } -impl BranchFindPopup { +impl FuzzyFindPopup { /// pub fn new( queue: &Queue, @@ -56,11 +58,12 @@ impl BranchFindPopup { query: None, find_text, theme, - branches: Vec::new(), - branches_filtered: Vec::new(), + contents: Vec::new(), + filtered: Vec::new(), selected_index: None, key_config, selection: 0, + target: None, } } @@ -81,14 +84,14 @@ impl BranchFindPopup { fn set_query(&mut self, query: Option) { self.query = query; - self.branches_filtered.clear(); + self.filtered.clear(); if let Some(q) = &self.query { let matcher = fuzzy_matcher::skim::SkimMatcherV2::default(); - let mut branches = self - .branches + let mut contents = self + .contents .iter() .enumerate() .filter_map(|a| { @@ -98,12 +101,12 @@ impl BranchFindPopup { }) .collect::>(); - branches.sort_by(|(score1, _, _), (score2, _, _)| { + contents.sort_by(|(score1, _, _), (score2, _, _)| { score2.cmp(score1) }); - self.branches_filtered.extend( - branches.into_iter().map(|entry| (entry.1, entry.2)), + self.filtered.extend( + contents.into_iter().map(|entry| (entry.1, entry.2)), ); } @@ -113,23 +116,37 @@ impl BranchFindPopup { fn refresh_selection(&mut self) { let selection = - self.branches_filtered.get(self.selection).map(|a| a.0); + self.filtered.get(self.selection).map(|a| a.0); if self.selected_index != selection { self.selected_index = selection; - let idx = self.selected_index; - self.queue.push(InternalEvent::BranchFinderChanged(idx)); + if let Some(idx) = self.selected_index { + if let Some(target) = self.target { + self.queue.push( + InternalEvent::FuzzyFinderChanged( + idx, + self.contents[idx].clone(), + target, + ), + ); + } + } } } - pub fn open(&mut self, branches: Vec) -> Result<()> { + pub fn open( + &mut self, + contents: Vec, + target: FuzzyFinderTarget, + ) -> Result<()> { self.show()?; self.find_text.show()?; self.find_text.set_text(String::new()); self.query = None; - if self.branches != branches { - self.branches = branches; + self.target = Some(target); + if self.contents != contents { + self.contents = contents; } self.update_query(); @@ -144,7 +161,7 @@ impl BranchFindPopup { }; let new_selection = new_selection - .clamp(0, self.branches_filtered.len().saturating_sub(1)); + .clamp(0, self.filtered.len().saturating_sub(1)); if new_selection != self.selection { self.selection = new_selection; @@ -156,7 +173,7 @@ impl BranchFindPopup { } } -impl DrawableComponent for BranchFindPopup { +impl DrawableComponent for FuzzyFindPopup { fn draw( &self, f: &mut Frame, @@ -165,7 +182,7 @@ impl DrawableComponent for BranchFindPopup { if self.is_visible() { const MAX_SIZE: (u16, u16) = (50, 20); - let any_hits = !self.branches_filtered.is_empty(); + let any_hits = !self.filtered.is_empty(); let area = ui::centered_rect_absolute( MAX_SIZE.0, MAX_SIZE.1, area, @@ -215,22 +232,18 @@ impl DrawableComponent for BranchFindPopup { self.find_text.draw(f, chunks[0])?; if any_hits { - let title = - format!("Hits: {}", self.branches_filtered.len()); + let title = format!("Hits: {}", self.filtered.len()); let height = usize::from(chunks[1].height); let width = usize::from(chunks[1].width); - let items = self - .branches_filtered - .iter() - .take(height) - .map(|(idx, indicies)| { + let items = self.filtered.iter().take(height).map( + |(idx, indicies)| { let selected = self .selected_index .map_or(false, |index| index == *idx); let full_text = trim_length_left( - &self.branches[*idx], + &self.contents[*idx], width, ); Line::from( @@ -247,7 +260,8 @@ impl DrawableComponent for BranchFindPopup { }) .collect::>(), ) - }); + }, + ); ui::draw_list_block( f, @@ -266,7 +280,7 @@ impl DrawableComponent for BranchFindPopup { } } -impl Component for BranchFindPopup { +impl Component for FuzzyFindPopup { fn commands( &self, out: &mut Vec, diff --git a/src/components/mod.rs b/src/components/mod.rs index 5d882e4e..14498adc 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1,5 +1,4 @@ mod blame_file; -mod branch_find_popup; mod branchlist; mod changes; mod command; @@ -12,8 +11,8 @@ mod cred; mod diff; mod externaleditor; mod fetch; -mod file_find_popup; mod file_revlog; +mod fuzzy_find_popup; mod help; mod inspect_commit; mod msg; @@ -37,7 +36,6 @@ mod utils; pub use self::status_tree::StatusTreeComponent; pub use blame_file::{BlameFileComponent, BlameFileOpen}; -pub use branch_find_popup::BranchFindPopup; pub use branchlist::BranchListComponent; pub use changes::ChangesComponent; pub use command::{CommandInfo, CommandText}; @@ -49,8 +47,8 @@ pub use create_branch::CreateBranchComponent; pub use diff::DiffComponent; pub use externaleditor::ExternalEditorComponent; pub use fetch::FetchComponent; -pub use file_find_popup::FileFindPopup; pub use file_revlog::{FileRevOpen, FileRevlogComponent}; +pub use fuzzy_find_popup::FuzzyFindPopup; pub use help::HelpComponent; pub use inspect_commit::{InspectCommitComponent, InspectCommitOpen}; pub use msg::MsgComponent; @@ -236,6 +234,12 @@ pub enum EventState { NotConsumed, } +#[derive(Copy, Clone)] +pub enum FuzzyFinderTarget { + Branches, + Files, +} + impl EventState { pub fn is_consumed(&self) -> bool { *self == Self::Consumed diff --git a/src/components/revision_files.rs b/src/components/revision_files.rs index c71feb99..ee28cb24 100644 --- a/src/components/revision_files.rs +++ b/src/components/revision_files.rs @@ -1,7 +1,7 @@ use super::{ utils::scroll_vertical::VerticalScroll, BlameFileOpen, CommandBlocking, CommandInfo, Component, DrawableComponent, - EventState, FileRevOpen, SyntaxTextComponent, + EventState, FileRevOpen, FuzzyFinderTarget, SyntaxTextComponent, }; use crate::{ keys::{key_match, SharedKeyConfig}, @@ -30,11 +30,7 @@ use ratatui::{ Frame, }; use std::{borrow::Cow, fmt::Write}; -use std::{ - collections::BTreeSet, - convert::From, - path::{Path, PathBuf}, -}; +use std::{collections::BTreeSet, convert::From, path::Path}; use unicode_truncate::UnicodeTruncateStr; use unicode_width::UnicodeWidthStr; @@ -233,17 +229,26 @@ impl RevisionFilesComponent { } fn open_finder(&self) { - self.queue.push(InternalEvent::OpenFileFinder( - self.files.clone().unwrap_or_default(), - )); + if let Some(files) = self.files.clone() { + self.queue.push(InternalEvent::OpenFuzzyFinder( + files + .iter() + .map(|a| { + a.path + .to_str() + .unwrap_or_default() + .to_string() + }) + .collect(), + FuzzyFinderTarget::Files, + )); + } } - pub fn find_file(&mut self, file: &Option) { - if let Some(file) = file { - self.tree.collapse_but_root(); - if self.tree.select_file(file) { - self.selection_changed(); - } + pub fn find_file(&mut self, file: &Path) { + self.tree.collapse_but_root(); + if self.tree.select_file(file) { + self.selection_changed(); } } diff --git a/src/components/revision_files_popup.rs b/src/components/revision_files_popup.rs index 9c24b72a..19b762d2 100644 --- a/src/components/revision_files_popup.rs +++ b/src/components/revision_files_popup.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::Path; use super::{ revision_files::RevisionFilesComponent, visibility_blocking, @@ -91,7 +91,7 @@ impl RevisionFilesPopup { self.files.any_work_pending() } - pub fn file_finder_update(&mut self, file: &Option) { + pub fn file_finder_update(&mut self, file: &Path) { self.files.find_file(file); } diff --git a/src/queue.rs b/src/queue.rs index 961a53a7..c815ce65 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -1,12 +1,12 @@ use crate::{ components::{ AppOption, BlameFileOpen, FileRevOpen, FileTreeOpen, - InspectCommitOpen, + FuzzyFinderTarget, InspectCommitOpen, }, tabs::StashingOptions, }; use asyncgit::{ - sync::{diff::DiffLinePosition, CommitId, TreeFile}, + sync::{diff::DiffLinePosition, CommitId}, PushType, }; use bitflags::bitflags; @@ -111,13 +111,9 @@ pub enum InternalEvent { /// OptionSwitched(AppOption), /// - OpenFileFinder(Vec), + OpenFuzzyFinder(Vec, FuzzyFinderTarget), /// - OpenBranchFinder(Vec), - /// - FileFinderChanged(Option), - /// - BranchFinderChanged(Option), + FuzzyFinderChanged(usize, String, FuzzyFinderTarget), /// FetchRemotes, /// diff --git a/src/tabs/files.rs b/src/tabs/files.rs index 2d6446d5..9c4c3304 100644 --- a/src/tabs/files.rs +++ b/src/tabs/files.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::Path; use crate::{ components::{ @@ -75,7 +75,7 @@ impl FilesTab { Ok(()) } - pub fn file_finder_update(&mut self, file: &Option) { + pub fn file_finder_update(&mut self, file: &Path) { self.files.find_file(file); } }