@@ -608,9 +608,10 @@ pub fn split_selection_on_newline(cx: &mut Context) {
608// I'd probably collect all the matches right now and store the current index. The cache needs
608// I'd probably collect all the matches right now and store the current index. The cache needs
609// wiping if input happens.
609// wiping if input happens.
611−fn _search(doc: &mut Document, view_id: ViewId, contents: &str, regex: &Regex) {
611+fn _search(doc: &mut Document, view_id: ViewId, contents: &str, regex: &Regex, extend: bool) {
612 let text = doc.text();
612 let text = doc.text();
613− let start = doc.selection(view_id).cursor();
613+ let selection = doc.selection(view_id);
614+ let start = selection.cursor();
615 // use find_at to find the next match after the cursor, loop around the end
616 // use find_at to find the next match after the cursor, loop around the end
616 let mat = regex
617 let mat = regex
@@ -619,7 +620,13 @@ fn _search(doc: &mut Document, view_id: ViewId, contents: &str, regex: &Regex) {
619 if let Some(mat) = mat {
620 if let Some(mat) = mat {
620 let start = text.byte_to_char(mat.start());
621 let start = text.byte_to_char(mat.start());
621 let end = text.byte_to_char(mat.end());
622 let end = text.byte_to_char(mat.end());
624+ let selection = if extend {
625+ selection.clone().add(Range::new(start, end - 1))
622− let selection = Selection::single(start, end - 1);
627+ Selection::single(start, end - 1)
623 // TODO: (first_match, regex) stuff in register?
630 // TODO: (first_match, regex) stuff in register?
624 doc.set_selection(view_id, selection);
631 doc.set_selection(view_id, selection);
@@ -639,7 +646,7 @@ pub fn search(cx: &mut Context) {
639 let prompt = ui::regex_prompt(cx, "search:".to_string(), move |doc, regex| {
646 let prompt = ui::regex_prompt(cx, "search:".to_string(), move |doc, regex| {
640 let text = doc.text();
647 let text = doc.text();
641 let start = doc.selection(view_id).cursor();
648 let start = doc.selection(view_id).cursor();
642− _search(doc, view_id, &contents, ®ex);
649+ _search(doc, view_id, &contents, ®ex, false);
644 // TODO: only store on enter (accept), not update
651 // TODO: only store on enter (accept), not update
645 register::set('\\', vec![regex.as_str().to_string()]);
652 register::set('\\', vec![regex.as_str().to_string()]);
@@ -648,17 +655,25 @@ pub fn search(cx: &mut Context) {
648 cx.push_layer(Box::new(prompt));
655 cx.push_layer(Box::new(prompt));
651−pub fn search_next(cx: &mut Context) {
658+pub fn _search_next(cx: &mut Context, extend: bool) {
652 if let Some(query) = register::get('\\') {
659 if let Some(query) = register::get('\\') {
653 let query = query.first().unwrap();
660 let query = query.first().unwrap();
654 let view_id = cx.view_id;
661 let view_id = cx.view_id;
655 let doc = cx.doc();
662 let doc = cx.doc();
656 let contents = doc.text().slice(..).to_string();
663 let contents = doc.text().slice(..).to_string();
657 let regex = Regex::new(&query).unwrap();
664 let regex = Regex::new(&query).unwrap();
658− _search(doc, view_id, &contents, ®ex);
665+ _search(doc, view_id, &contents, ®ex, extend);
669+pub fn search_next(cx: &mut Context) {
670+ _search_next(cx, false);
673+pub fn extend_search_next(cx: &mut Context) {
674+ _search_next(cx, true);
662pub fn search_selection(cx: &mut Context) {
677pub fn search_selection(cx: &mut Context) {
663 let (view, doc) = cx.current();
678 let (view, doc) = cx.current();
664 let contents = doc.text().slice(..);
679 let contents = doc.text().slice(..);