Add absolute paths to historic elements
This commit is contained in:
parent
128c19875d
commit
364631a155
1 changed files with 94 additions and 42 deletions
|
@ -6,7 +6,7 @@ use gpui::{
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
||||||
use std::{
|
use std::{
|
||||||
path::Path,
|
path::{Path, PathBuf},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{self, AtomicBool},
|
atomic::{self, AtomicBool},
|
||||||
Arc,
|
Arc,
|
||||||
|
@ -25,11 +25,17 @@ pub struct FileFinderDelegate {
|
||||||
latest_search_id: usize,
|
latest_search_id: usize,
|
||||||
latest_search_did_cancel: bool,
|
latest_search_did_cancel: bool,
|
||||||
latest_search_query: Option<PathLikeWithPosition<FileSearchQuery>>,
|
latest_search_query: Option<PathLikeWithPosition<FileSearchQuery>>,
|
||||||
currently_opened_path: Option<ProjectPath>,
|
currently_opened_path: Option<FoundPath>,
|
||||||
matches: Vec<PathMatch>,
|
matches: Vec<PathMatch>,
|
||||||
selected: Option<(usize, Arc<Path>)>,
|
selected: Option<(usize, Arc<Path>)>,
|
||||||
cancel_flag: Arc<AtomicBool>,
|
cancel_flag: Arc<AtomicBool>,
|
||||||
history_items: Vec<ProjectPath>,
|
history_items: Vec<FoundPath>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
struct FoundPath {
|
||||||
|
project: ProjectPath,
|
||||||
|
absolute: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
actions!(file_finder, [Toggle]);
|
actions!(file_finder, [Toggle]);
|
||||||
|
@ -43,10 +49,36 @@ const MAX_RECENT_SELECTIONS: usize = 20;
|
||||||
|
|
||||||
fn toggle_file_finder(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
|
fn toggle_file_finder(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext<Workspace>) {
|
||||||
workspace.toggle_modal(cx, |workspace, cx| {
|
workspace.toggle_modal(cx, |workspace, cx| {
|
||||||
let history_items = workspace.recent_navigation_history(Some(MAX_RECENT_SELECTIONS), cx);
|
let project = workspace.project().read(cx);
|
||||||
|
let project_to_found_path = |project_path: ProjectPath| FoundPath {
|
||||||
|
absolute: project
|
||||||
|
.worktree_for_id(project_path.worktree_id, cx)
|
||||||
|
.map(|worktree| worktree.read(cx).abs_path().join(&project_path.path)),
|
||||||
|
project: project_path,
|
||||||
|
};
|
||||||
|
|
||||||
let currently_opened_path = workspace
|
let currently_opened_path = workspace
|
||||||
.active_item(cx)
|
.active_item(cx)
|
||||||
.and_then(|item| item.project_path(cx));
|
.and_then(|item| item.project_path(cx))
|
||||||
|
.map(project_to_found_path);
|
||||||
|
|
||||||
|
// if exists, bubble the currently opened path to the top
|
||||||
|
let history_items = currently_opened_path
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.chain(
|
||||||
|
workspace
|
||||||
|
.recent_navigation_history(Some(MAX_RECENT_SELECTIONS), cx)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|history_path| {
|
||||||
|
Some(history_path)
|
||||||
|
!= currently_opened_path
|
||||||
|
.as_ref()
|
||||||
|
.map(|found_path| &found_path.project)
|
||||||
|
})
|
||||||
|
.map(project_to_found_path),
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let project = workspace.project().clone();
|
let project = workspace.project().clone();
|
||||||
let workspace = cx.handle().downgrade();
|
let workspace = cx.handle().downgrade();
|
||||||
|
@ -113,11 +145,11 @@ impl FileFinderDelegate {
|
||||||
(file_name, file_name_positions, full_path, path_positions)
|
(file_name, file_name_positions, full_path, path_positions)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
fn new(
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
currently_opened_path: Option<ProjectPath>,
|
currently_opened_path: Option<FoundPath>,
|
||||||
history_items: Vec<ProjectPath>,
|
history_items: Vec<FoundPath>,
|
||||||
cx: &mut ViewContext<FileFinder>,
|
cx: &mut ViewContext<FileFinder>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
cx.observe(&project, |picker, _, cx| {
|
cx.observe(&project, |picker, _, cx| {
|
||||||
|
@ -147,7 +179,7 @@ impl FileFinderDelegate {
|
||||||
let relative_to = self
|
let relative_to = self
|
||||||
.currently_opened_path
|
.currently_opened_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|project_path| Arc::clone(&project_path.path));
|
.map(|found_path| Arc::clone(&found_path.project.path));
|
||||||
let worktrees = self
|
let worktrees = self
|
||||||
.project
|
.project
|
||||||
.read(cx)
|
.read(cx)
|
||||||
|
@ -255,20 +287,33 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
self.latest_search_id = post_inc(&mut self.search_count);
|
self.latest_search_id = post_inc(&mut self.search_count);
|
||||||
self.matches.clear();
|
self.matches.clear();
|
||||||
|
|
||||||
|
let project = self.project.read(cx);
|
||||||
self.matches = self
|
self.matches = self
|
||||||
.currently_opened_path
|
.history_items
|
||||||
.iter() // if exists, bubble the currently opened path to the top
|
.iter()
|
||||||
.chain(self.history_items.iter().filter(|history_item| {
|
|
||||||
Some(*history_item) != self.currently_opened_path.as_ref()
|
|
||||||
}))
|
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, history_item)| PathMatch {
|
.map(|(i, found_path)| {
|
||||||
score: i as f64,
|
let worktree_id = found_path.project.worktree_id;
|
||||||
positions: Vec::new(),
|
// TODO kb wrong:
|
||||||
worktree_id: history_item.worktree_id.to_usize(),
|
// * for no worktree, check the project path
|
||||||
path: Arc::clone(&history_item.path),
|
// * if no project path exists — filter out(?), otherwise take it and open a workspace for it (enum for match kinds?)
|
||||||
path_prefix: "".into(),
|
let path = if project.worktree_for_id(worktree_id, cx).is_some() {
|
||||||
distance_to_relative_ancestor: usize::MAX,
|
Arc::clone(&found_path.project.path)
|
||||||
|
} else {
|
||||||
|
found_path
|
||||||
|
.absolute
|
||||||
|
.as_ref()
|
||||||
|
.map(|abs_path| Arc::from(abs_path.as_path()))
|
||||||
|
.unwrap_or_else(|| Arc::clone(&found_path.project.path))
|
||||||
|
};
|
||||||
|
PathMatch {
|
||||||
|
score: i as f64,
|
||||||
|
positions: Vec::new(),
|
||||||
|
worktree_id: worktree_id.to_usize(),
|
||||||
|
path,
|
||||||
|
path_prefix: "".into(),
|
||||||
|
distance_to_relative_ancestor: usize::MAX,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -876,10 +921,10 @@ mod tests {
|
||||||
// When workspace has an active item, sort items which are closer to that item
|
// When workspace has an active item, sort items which are closer to that item
|
||||||
// first when they have the same name. In this case, b.txt is closer to dir2's a.txt
|
// first when they have the same name. In this case, b.txt is closer to dir2's a.txt
|
||||||
// so that one should be sorted earlier
|
// so that one should be sorted earlier
|
||||||
let b_path = Some(ProjectPath {
|
let b_path = Some(dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("/root/dir2/b.txt")),
|
path: Arc::from(Path::new("/root/dir2/b.txt")),
|
||||||
});
|
}));
|
||||||
let (_, finder) = cx.add_window(|cx| {
|
let (_, finder) = cx.add_window(|cx| {
|
||||||
Picker::new(
|
Picker::new(
|
||||||
FileFinderDelegate::new(
|
FileFinderDelegate::new(
|
||||||
|
@ -1012,10 +1057,10 @@ mod tests {
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
history_after_first,
|
history_after_first,
|
||||||
vec![ProjectPath {
|
vec![dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/first.rs")),
|
path: Arc::from(Path::new("test/first.rs")),
|
||||||
}],
|
})],
|
||||||
"Should show 1st opened item in the history when opening the 2nd item"
|
"Should show 1st opened item in the history when opening the 2nd item"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1032,14 +1077,14 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
history_after_second,
|
history_after_second,
|
||||||
vec![
|
vec![
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/second.rs")),
|
path: Arc::from(Path::new("test/second.rs")),
|
||||||
},
|
}),
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/first.rs")),
|
path: Arc::from(Path::new("test/first.rs")),
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
"Should show 1st and 2nd opened items in the history when opening the 3rd item. \
|
"Should show 1st and 2nd opened items in the history when opening the 3rd item. \
|
||||||
2nd item should be the first in the history, as the last opened."
|
2nd item should be the first in the history, as the last opened."
|
||||||
|
@ -1058,18 +1103,18 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
history_after_third,
|
history_after_third,
|
||||||
vec![
|
vec![
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/third.rs")),
|
path: Arc::from(Path::new("test/third.rs")),
|
||||||
},
|
}),
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/second.rs")),
|
path: Arc::from(Path::new("test/second.rs")),
|
||||||
},
|
}),
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/first.rs")),
|
path: Arc::from(Path::new("test/first.rs")),
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
|
"Should show 1st, 2nd and 3rd opened items in the history when opening the 2nd item again. \
|
||||||
3rd item should be the first in the history, as the last opened."
|
3rd item should be the first in the history, as the last opened."
|
||||||
|
@ -1088,18 +1133,18 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
history_after_second_again,
|
history_after_second_again,
|
||||||
vec![
|
vec![
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/second.rs")),
|
path: Arc::from(Path::new("test/second.rs")),
|
||||||
},
|
}),
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/third.rs")),
|
path: Arc::from(Path::new("test/third.rs")),
|
||||||
},
|
}),
|
||||||
ProjectPath {
|
dummy_found_path(ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::from(Path::new("test/first.rs")),
|
path: Arc::from(Path::new("test/first.rs")),
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
|
"Should show 1st, 2nd and 3rd opened items in the history when opening the 3rd item again. \
|
||||||
2nd item, as the last opened, 3rd item should go next as it was opened right before."
|
2nd item, as the last opened, 3rd item should go next as it was opened right before."
|
||||||
|
@ -1114,7 +1159,7 @@ mod tests {
|
||||||
workspace: &ViewHandle<Workspace>,
|
workspace: &ViewHandle<Workspace>,
|
||||||
deterministic: &gpui::executor::Deterministic,
|
deterministic: &gpui::executor::Deterministic,
|
||||||
cx: &mut gpui::TestAppContext,
|
cx: &mut gpui::TestAppContext,
|
||||||
) -> Vec<ProjectPath> {
|
) -> Vec<FoundPath> {
|
||||||
cx.dispatch_action(window_id, Toggle);
|
cx.dispatch_action(window_id, Toggle);
|
||||||
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
let finder = cx.read(|cx| workspace.read(cx).modal::<FileFinder>().unwrap());
|
||||||
finder
|
finder
|
||||||
|
@ -1216,4 +1261,11 @@ mod tests {
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dummy_found_path(project_path: ProjectPath) -> FoundPath {
|
||||||
|
FoundPath {
|
||||||
|
project: project_path,
|
||||||
|
absolute: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue