Z 1200/replace in buffer (#2922)

This is still WIP, mostly pending styling. I added a pretty rudimentary
text field and no buttons whatsoever other than that. I am targeting a
Preview of 09.13, as I am gonna be on PTO for the next week.

I dislike the current implementation slightly because of `regex`'s crate
syntax and lack of support of backreferences. What strikes me as odd wrt
to syntax is that it will just replace a capture name with empty string
if that capture is missing from the regex. While this is perfectly fine
behaviour for conditionally-matched capture groups (e.g. `(foo)?`), I
think it should still error out if there's no group with a given name
(conditional or not).
Release Notes:

- Added "Replace" functionality to buffer search.
This commit is contained in:
Piotr Osiewicz 2023-09-12 18:46:54 +02:00 committed by GitHub
parent c545788168
commit 4cb8647702
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 471 additions and 96 deletions

View file

@ -18,7 +18,7 @@ use gpui::{
ViewHandle, WeakViewHandle,
};
use language::Bias;
use project::{LocalWorktree, Project};
use project::{search::SearchQuery, LocalWorktree, Project};
use serde::Deserialize;
use smallvec::{smallvec, SmallVec};
use smol::Timer;
@ -26,6 +26,7 @@ use std::{
borrow::Cow,
ops::RangeInclusive,
path::{Path, PathBuf},
sync::Arc,
time::Duration,
};
use terminal::{
@ -380,10 +381,10 @@ impl TerminalView {
pub fn find_matches(
&mut self,
query: project::search::SearchQuery,
query: Arc<project::search::SearchQuery>,
cx: &mut ViewContext<Self>,
) -> Task<Vec<RangeInclusive<Point>>> {
let searcher = regex_search_for_query(query);
let searcher = regex_search_for_query(&query);
if let Some(searcher) = searcher {
self.terminal
@ -486,7 +487,7 @@ fn possible_open_targets(
.collect()
}
pub fn regex_search_for_query(query: project::search::SearchQuery) -> Option<RegexSearch> {
pub fn regex_search_for_query(query: &project::search::SearchQuery) -> Option<RegexSearch> {
let query = query.as_str();
let searcher = RegexSearch::new(&query);
searcher.ok()
@ -798,6 +799,7 @@ impl SearchableItem for TerminalView {
case: false,
word: false,
regex: false,
replacement: false,
}
}
@ -851,10 +853,10 @@ impl SearchableItem for TerminalView {
/// Get all of the matches for this query, should be done on the background
fn find_matches(
&mut self,
query: project::search::SearchQuery,
query: Arc<project::search::SearchQuery>,
cx: &mut ViewContext<Self>,
) -> Task<Vec<Self::Match>> {
if let Some(searcher) = regex_search_for_query(query) {
if let Some(searcher) = regex_search_for_query(&query) {
self.terminal()
.update(cx, |term, cx| term.find_matches(searcher, cx))
} else {
@ -898,6 +900,9 @@ impl SearchableItem for TerminalView {
res
}
fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext<Self>) {
// Replacement is not supported in terminal view, so this is a no-op.
}
}
///Get's the working directory for the given workspace, respecting the user's settings.