Fix search/replace start of line anchor (#13920)

This is related to #9428 

I noticed that doing a search and replace for the beginning of a line
`^` results in the trailing line being included in the search. This
seems to be because of the way the range is generated for generating
matches being the up to the start of the trailing line rather than up to
the end of the last line.

I added a test and took a stab at fixing it but it is a bit yolo as this
is the first time I've seen this codebase.
This commit is contained in:
Andy Weiss 2024-07-09 14:39:24 -04:00 committed by GitHub
parent 09e7b481b8
commit c093bc8aa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 1 deletions

View File

@ -2,6 +2,7 @@ use std::{ops::Range, sync::OnceLock, time::Duration};
use gpui::{actions, impl_actions, ViewContext};
use language::Point;
use multi_buffer::MultiBufferRow;
use regex::Regex;
use search::{buffer_search, BufferSearchBar, SearchOptions};
use serde_derive::Deserialize;
@ -362,9 +363,11 @@ fn replace_command(
if let Some(editor) = editor.as_mut() {
editor.update(cx, |editor, cx| {
let snapshot = &editor.snapshot(cx).buffer_snapshot;
let end_row = MultiBufferRow(range.end.saturating_sub(1) as u32);
let end_point = Point::new(end_row.0, snapshot.line_len(end_row));
let range = snapshot
.anchor_before(Point::new(range.start.saturating_sub(1) as u32, 0))
..snapshot.anchor_before(Point::new(range.end as u32, 0));
..snapshot.anchor_after(end_point);
editor.set_search_within_ranges(&[range], cx)
})
}
@ -727,6 +730,50 @@ mod test {
});
}
// cargo test -p vim --features neovim test_replace_with_range_at_start
#[gpui::test]
async fn test_replace_with_range_at_start(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state(indoc! {
"ˇa
a
a
a
a
a
a
"
})
.await;
cx.simulate_shared_keystrokes(": 2 , 5 s / ^ / b").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq(indoc! {
"a
ba
ba
ba
ˇba
a
a
"
});
cx.executor().advance_clock(Duration::from_millis(250));
cx.run_until_parked();
cx.simulate_shared_keystrokes("/ a enter").await;
cx.shared_state().await.assert_eq(indoc! {
"a
ba
ba
ba
bˇa
a
a
"
});
}
// cargo test -p vim --features neovim test_replace_with_range
#[gpui::test]
async fn test_replace_with_range(cx: &mut gpui::TestAppContext) {

View File

@ -0,0 +1,16 @@
{"Put":{"state":"ˇa\na\na\na\na\na\na\n "}}
{"Key":":"}
{"Key":"2"}
{"Key":","}
{"Key":"5"}
{"Key":"s"}
{"Key":"/"}
{"Key":"^"}
{"Key":"/"}
{"Key":"b"}
{"Key":"enter"}
{"Get":{"state":"a\nba\nba\nba\nˇba\na\na\n ","mode":"Normal"}}
{"Key":"/"}
{"Key":"a"}
{"Key":"enter"}
{"Get":{"state":"a\nba\nba\nba\nbˇa\na\na\n ","mode":"Normal"}}