file_finder: Add skip_focus_for_active_in_search
setting (#27624)
Closes #27073 Currently, when searching for a file with Ctrl+P, and the first file found is the active one, file_finder skips focus to the second file automatically. This PR adds a setting to disable this and make the first file always the focused one. Default setting is still skipping the active file. Release Notes: - Added the `skip_focus_for_active_in_search` setting for the file finder, which allows turning off the default behavior of skipping focus on the active file while searching in the file finder. --------- Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This commit is contained in:
parent
d03d8ccec1
commit
84e4891d54
5 changed files with 107 additions and 9 deletions
|
@ -834,7 +834,20 @@
|
|||
// "modal_max_width": "full"
|
||||
//
|
||||
// Default: small
|
||||
"modal_max_width": "small"
|
||||
"modal_max_width": "small",
|
||||
// Determines whether the file finder should skip focus for the active file in search results.
|
||||
// There are 2 possible values:
|
||||
//
|
||||
// 1. true: When searching for files, if the currently active file appears as the first result,
|
||||
// auto-focus will skip it and focus the second result instead.
|
||||
// "skip_focus_for_active_in_search": true
|
||||
//
|
||||
// 2. false: When searching for files, the first result will always receive focus,
|
||||
// even if it's the currently active file.
|
||||
// "skip_focus_for_active_in_search": false
|
||||
//
|
||||
// Default: true
|
||||
"skip_focus_for_active_in_search": true
|
||||
},
|
||||
// Whether or not to remove any trailing whitespace from lines of a buffer
|
||||
// before saving it.
|
||||
|
|
|
@ -822,7 +822,6 @@ impl FileFinderDelegate {
|
|||
did_cancel: bool,
|
||||
query: FileSearchQuery,
|
||||
matches: impl IntoIterator<Item = ProjectPanelOrdMatch>,
|
||||
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
) {
|
||||
if search_id >= self.latest_search_id {
|
||||
|
@ -849,7 +848,7 @@ impl FileFinderDelegate {
|
|||
);
|
||||
|
||||
self.selected_index = selected_match.map_or_else(
|
||||
|| self.calculate_selected_index(),
|
||||
|| self.calculate_selected_index(cx),
|
||||
|m| {
|
||||
self.matches
|
||||
.position(&m, self.currently_opened_path.as_ref())
|
||||
|
@ -1092,12 +1091,14 @@ impl FileFinderDelegate {
|
|||
}
|
||||
|
||||
/// Skips first history match (that is displayed topmost) if it's currently opened.
|
||||
fn calculate_selected_index(&self) -> usize {
|
||||
if let Some(Match::History { path, .. }) = self.matches.get(0) {
|
||||
if Some(path) == self.currently_opened_path.as_ref() {
|
||||
let elements_after_first = self.matches.len() - 1;
|
||||
if elements_after_first > 0 {
|
||||
return 1;
|
||||
fn calculate_selected_index(&self, cx: &mut Context<Picker<Self>>) -> usize {
|
||||
if FileFinderSettings::get_global(cx).skip_focus_for_active_in_search {
|
||||
if let Some(Match::History { path, .. }) = self.matches.get(0) {
|
||||
if Some(path) == self.currently_opened_path.as_ref() {
|
||||
let elements_after_first = self.matches.len() - 1;
|
||||
if elements_after_first > 0 {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use settings::{Settings, SettingsSources};
|
|||
pub struct FileFinderSettings {
|
||||
pub file_icons: bool,
|
||||
pub modal_max_width: Option<FileFinderWidth>,
|
||||
pub skip_focus_for_active_in_search: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)]
|
||||
|
@ -19,6 +20,10 @@ pub struct FileFinderSettingsContent {
|
|||
///
|
||||
/// Default: small
|
||||
pub modal_max_width: Option<FileFinderWidth>,
|
||||
/// Determines whether the file finder should skip focus for the active file in search results.
|
||||
///
|
||||
/// Default: true
|
||||
pub skip_focus_for_active_in_search: Option<bool>,
|
||||
}
|
||||
|
||||
impl Settings for FileFinderSettings {
|
||||
|
|
|
@ -1359,6 +1359,73 @@ async fn test_keep_opened_file_on_top_of_search_results_and_select_next_one(
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_setting_auto_select_first_and_select_active_file(cx: &mut TestAppContext) {
|
||||
let app_state = init_test(cx);
|
||||
|
||||
cx.update(|cx| {
|
||||
let settings = *FileFinderSettings::get_global(cx);
|
||||
|
||||
FileFinderSettings::override_global(
|
||||
FileFinderSettings {
|
||||
skip_focus_for_active_in_search: false,
|
||||
..settings
|
||||
},
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
app_state
|
||||
.fs
|
||||
.as_fake()
|
||||
.insert_tree(
|
||||
path!("/src"),
|
||||
json!({
|
||||
"test": {
|
||||
"bar.rs": "// Bar file",
|
||||
"lib.rs": "// Lib file",
|
||||
"maaa.rs": "// Maaaaaaa",
|
||||
"main.rs": "// Main file",
|
||||
"moo.rs": "// Moooooo",
|
||||
}
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let project = Project::test(app_state.fs.clone(), [path!("/src").as_ref()], cx).await;
|
||||
let (workspace, cx) = cx.add_window_view(|window, cx| Workspace::test_new(project, window, cx));
|
||||
|
||||
open_close_queried_buffer("bar", 1, "bar.rs", &workspace, cx).await;
|
||||
open_close_queried_buffer("lib", 1, "lib.rs", &workspace, cx).await;
|
||||
open_queried_buffer("main", 1, "main.rs", &workspace, cx).await;
|
||||
|
||||
// main.rs is on top, previously used is selected
|
||||
let picker = open_file_picker(&workspace, cx);
|
||||
picker.update(cx, |finder, _| {
|
||||
assert_eq!(finder.delegate.matches.len(), 3);
|
||||
assert_match_selection(finder, 0, "main.rs");
|
||||
assert_match_at_position(finder, 1, "lib.rs");
|
||||
assert_match_at_position(finder, 2, "bar.rs");
|
||||
});
|
||||
|
||||
// all files match, main.rs is on top, and is selected
|
||||
picker
|
||||
.update_in(cx, |finder, window, cx| {
|
||||
finder
|
||||
.delegate
|
||||
.update_matches(".rs".to_string(), window, cx)
|
||||
})
|
||||
.await;
|
||||
picker.update(cx, |finder, _| {
|
||||
assert_eq!(finder.delegate.matches.len(), 5);
|
||||
assert_match_selection(finder, 0, "main.rs");
|
||||
assert_match_at_position(finder, 1, "bar.rs");
|
||||
assert_match_at_position(finder, 2, "lib.rs");
|
||||
assert_match_at_position(finder, 3, "moo.rs");
|
||||
assert_match_at_position(finder, 4, "maaa.rs");
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_non_separate_history_items(cx: &mut TestAppContext) {
|
||||
let app_state = init_test(cx);
|
||||
|
|
|
@ -2037,12 +2037,24 @@ Or to set a `socks5` proxy:
|
|||
|
||||
## File Finder
|
||||
|
||||
### File Icons
|
||||
|
||||
- Description: Whether to show file icons in the file finder.
|
||||
- Setting: `file_icons`
|
||||
- Default: `true`
|
||||
|
||||
### Modal Max Width
|
||||
|
||||
- Description: Max-width of the file finder modal. It can take one of these values: `small`, `medium`, `large`, `xlarge`, and `full`.
|
||||
- Setting: `modal_max_width`
|
||||
- Default: `small`
|
||||
|
||||
### Skip Focus For Active In Search
|
||||
|
||||
- Description: Determines whether the file finder should skip focus for the active file in search results.
|
||||
- Setting: `skip_focus_for_active_in_search`
|
||||
- Default: `true`
|
||||
|
||||
## Preferred Line Length
|
||||
|
||||
- Description: The column at which to soft-wrap lines, for buffers where soft-wrap is enabled.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue