Allow a new search to be created with cmd-enter

This replaces the `cmd-alt-shift-F` binding to open a new search. Instead, you can preserve the existing search results by entering a query and then hitting `cmd-enter` instead of `enter`. This opens a new project find view and restores the previous view to whatever query it was previously displaying. It's a bit strange, but I don't want to rely on splitting as the only way of creating multiple sets of search results.
This commit is contained in:
Nathan Sobo 2022-02-26 13:23:05 -07:00
parent ae1a46a4e4
commit 2f427769df
3 changed files with 578 additions and 514 deletions

View file

@ -5144,6 +5144,14 @@ impl Editor {
self.buffer.read(cx).read(cx).text()
}
pub fn set_text(&mut self, text: impl Into<String>, cx: &mut ViewContext<Self>) {
self.buffer
.read(cx)
.as_singleton()
.expect("you can only call set_text on editors for singleton buffers")
.update(cx, |buffer, cx| buffer.set_text(text, cx));
}
pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
self.display_map
.update(cx, |map, cx| map.snapshot(cx))

View file

@ -15,8 +15,9 @@ use std::{
use util::ResultExt as _;
use workspace::{Item, ItemHandle, ItemNavHistory, ItemView, Settings, Workspace};
action!(Deploy, bool);
action!(Deploy);
action!(Search);
action!(SearchInNew);
action!(ToggleSearchOption, SearchOption);
action!(ToggleFocus);
@ -24,12 +25,13 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([
Binding::new("cmd-shift-F", ToggleFocus, Some("ProjectFindView")),
Binding::new("cmd-f", ToggleFocus, Some("ProjectFindView")),
Binding::new("cmd-shift-F", Deploy(true), Some("Workspace")),
Binding::new("cmd-alt-shift-F", Deploy(false), Some("Workspace")),
Binding::new("cmd-shift-F", Deploy, Some("Workspace")),
Binding::new("enter", Search, Some("ProjectFindView")),
Binding::new("cmd-enter", SearchInNew, Some("ProjectFindView")),
]);
cx.add_action(ProjectFindView::deploy);
cx.add_action(ProjectFindView::search);
cx.add_action(ProjectFindView::search_in_new);
cx.add_action(ProjectFindView::toggle_search_option);
cx.add_action(ProjectFindView::toggle_focus);
}
@ -85,6 +87,7 @@ impl ProjectFind {
let search = self
.project
.update(cx, |project, cx| project.search(query.clone(), cx));
self.active_query = Some(query);
self.highlighted_ranges.clear();
self.pending_search = Some(cx.spawn_weak(|this, mut cx| async move {
let matches = search.await.log_err()?;
@ -107,7 +110,6 @@ impl ProjectFind {
}
});
this.pending_search.take();
this.active_query = Some(query);
cx.notify();
});
}
@ -128,6 +130,27 @@ impl Item for ProjectFind {
) -> Self::View {
let settings = workspace.settings();
let excerpts = model.read(cx).excerpts.clone();
let mut query_text = String::new();
let mut regex = false;
let mut case_sensitive = false;
let mut whole_word = false;
if let Some(active_query) = model.read(cx).active_query.as_ref() {
query_text = active_query.as_str().to_string();
regex = active_query.is_regex();
case_sensitive = active_query.case_sensitive();
whole_word = active_query.whole_word();
}
let query_editor = cx.add_view(|cx| {
let mut editor = Editor::single_line(
settings.clone(),
Some(|theme| theme.find.editor.input.clone()),
cx,
);
editor.set_text(query_text, cx);
editor
});
let results_editor = cx.add_view(|cx| {
let mut editor = Editor::for_buffer(
excerpts,
@ -146,17 +169,11 @@ impl Item for ProjectFind {
ProjectFindView {
model,
query_editor: cx.add_view(|cx| {
Editor::single_line(
settings.clone(),
Some(|theme| theme.find.editor.input.clone()),
cx,
)
}),
query_editor,
results_editor,
case_sensitive: false,
whole_word: false,
regex: false,
case_sensitive,
whole_word,
regex,
query_contains_error: false,
settings,
}
@ -368,37 +385,69 @@ impl ItemView for ProjectFindView {
}
impl ProjectFindView {
fn deploy(
workspace: &mut Workspace,
&Deploy(activate_existing): &Deploy,
cx: &mut ViewContext<Workspace>,
) {
if activate_existing {
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
if let Some(existing) = workspace.item_of_type::<ProjectFind>(cx) {
workspace.activate_item(&existing, cx);
return;
}
}
} else {
let model = cx.add_model(|cx| ProjectFind::new(workspace.project().clone(), cx));
workspace.open_item(model, cx);
}
}
fn search(&mut self, _: &Search, cx: &mut ViewContext<Self>) {
if let Some(query) = self.build_search_query(cx) {
self.model.update(cx, |model, cx| model.search(query, cx));
}
}
fn search_in_new(workspace: &mut Workspace, _: &SearchInNew, cx: &mut ViewContext<Workspace>) {
if let Some(find_view) = workspace
.active_item(cx)
.and_then(|item| item.downcast::<ProjectFindView>())
{
let new_query = find_view.update(cx, |find_view, cx| {
let new_query = find_view.build_search_query(cx);
if new_query.is_some() {
if let Some(old_query) = find_view.model.read(cx).active_query.clone() {
find_view.query_editor.update(cx, |editor, cx| {
editor.set_text(old_query.as_str(), cx);
});
find_view.regex = old_query.is_regex();
find_view.whole_word = old_query.whole_word();
find_view.case_sensitive = old_query.case_sensitive();
}
}
new_query
});
if let Some(new_query) = new_query {
let model = cx.add_model(|cx| {
let mut model = ProjectFind::new(workspace.project().clone(), cx);
model.search(new_query, cx);
model
});
workspace.open_item(model, cx);
}
}
}
fn build_search_query(&mut self, cx: &mut ViewContext<Self>) -> Option<SearchQuery> {
let text = self.query_editor.read(cx).text(cx);
let query = if self.regex {
if self.regex {
match SearchQuery::regex(text, self.whole_word, self.case_sensitive) {
Ok(query) => query,
Ok(query) => Some(query),
Err(_) => {
self.query_contains_error = true;
cx.notify();
return;
None
}
}
} else {
SearchQuery::text(text, self.whole_word, self.case_sensitive)
};
self.model.update(cx, |model, cx| model.search(query, cx));
Some(SearchQuery::text(
text,
self.whole_word,
self.case_sensitive,
))
}
}
fn toggle_search_option(

View file

@ -1345,6 +1345,13 @@ impl Buffer {
let _ = language_server.latest_snapshot.blocking_send(snapshot);
}
pub fn set_text<T>(&mut self, text: T, cx: &mut ModelContext<Self>) -> Option<clock::Local>
where
T: Into<String>,
{
self.edit_internal([0..self.len()], text, false, cx)
}
pub fn edit<I, S, T>(
&mut self,
ranges_iter: I,