@@ -659,7 +659,13 @@ pub fn select_on_matches(
660 let start = text.byte_to_char(start_byte + mat.start());
660 let start = text.byte_to_char(start_byte + mat.start());
661 let end = text.byte_to_char(start_byte + mat.end());
661 let end = text.byte_to_char(start_byte + mat.end());
662− result.push(Range::new(start, end));
663+ let range = Range::new(start, end);
664+ // Make sure the match is not right outside of the selection.
665+ // These invalid matches can come from using RegEx anchors like `^`, `$`
666+ if range != Range::point(sel.to()) {
@@ -929,6 +935,76 @@ mod test {
929 assert_eq!(Range::new(6, 5).min_width_1(s), Range::new(6, 5));
935 assert_eq!(Range::new(6, 5).min_width_1(s), Range::new(6, 5));
939+ fn test_select_on_matches() {
940+ use crate::regex::{Regex, RegexBuilder};
942+ let r = Rope::from_str("Nobody expects the Spanish inquisition");
943+ let s = r.slice(..);
945+ let selection = Selection::single(0, r.len_chars());
947+ select_on_matches(s, &selection, &Regex::new(r"[A-Z][a-z]*").unwrap()),
948+ Some(Selection::new(
949+ smallvec![Range::new(0, 6), Range::new(19, 26)],
954+ let r = Rope::from_str("This\nString\n\ncontains multiple\nlines");
955+ let s = r.slice(..);
957+ let start_of_line = RegexBuilder::new(r"^").multi_line(true).build().unwrap();
958+ let end_of_line = RegexBuilder::new(r"$").multi_line(true).build().unwrap();
960+ // line without ending
962+ select_on_matches(s, &Selection::single(0, 4), &start_of_line),
963+ Some(Selection::single(0, 0))
966+ select_on_matches(s, &Selection::single(0, 4), &end_of_line),
971+ select_on_matches(s, &Selection::single(0, 5), &start_of_line),
972+ Some(Selection::single(0, 0))
975+ select_on_matches(s, &Selection::single(0, 5), &end_of_line),
976+ Some(Selection::single(4, 4))
978+ // line with start of next line
980+ select_on_matches(s, &Selection::single(0, 6), &start_of_line),
981+ Some(Selection::new(
982+ smallvec![Range::point(0), Range::point(5)],
987+ select_on_matches(s, &Selection::single(0, 6), &end_of_line),
988+ Some(Selection::single(4, 4))
995+ &Selection::single(0, s.len_chars()),
996+ &RegexBuilder::new(r"^[a-z ]*$")
1001+ Some(Selection::new(
1002+ smallvec![Range::point(12), Range::new(13, 30), Range::new(31, 36)],
933 fn test_line_range() {
1009 fn test_line_range() {
934 let r = Rope::from_str("\r\nHi\r\nthere!");
1010 let r = Rope::from_str("\r\nHi\r\nthere!");