diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index aee964ec56534053fb2042acae92aa9812c09838..0c07f46ed99e9d3d4fe26cded85bab662781c6ab 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -114,6 +114,7 @@ impl DisplayMap { pub fn unfold( &mut self, ranges: impl IntoIterator>, + inclusive: bool, cx: &mut ModelContext, ) { let snapshot = self.buffer.read(cx).snapshot(cx); @@ -124,7 +125,7 @@ impl DisplayMap { .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); self.block_map.read(snapshot, edits); - let (snapshot, edits) = fold_map.unfold(ranges); + let (snapshot, edits) = fold_map.unfold(ranges, inclusive); let (snapshot, edits) = self.tab_map.sync(snapshot, edits); let (snapshot, edits) = self .wrap_map @@ -632,7 +633,7 @@ mod tests { if rng.gen() && fold_count > 0 { log::info!("unfolding ranges: {:?}", ranges); map.update(cx, |map, cx| { - map.unfold(ranges, cx); + map.unfold(ranges, true, cx); }); } else { log::info!("folding ranges: {:?}", ranges); diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index 4b07854c3ea5fa432f8bb86e5aae5517bb78e8df..2c09244a7df38492b10ad4837f5443e3e8f7c457 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -140,13 +140,14 @@ impl<'a> FoldMapWriter<'a> { pub fn unfold( &mut self, ranges: impl IntoIterator>, + inclusive: bool, ) -> (FoldSnapshot, Vec) { let mut edits = Vec::new(); let mut fold_ixs_to_delete = Vec::new(); let buffer = self.0.buffer.lock().clone(); for range in ranges.into_iter() { // Remove intersecting folds and add their ranges to edits that are passed to sync. - let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range, true); + let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range, inclusive); while let Some(fold) = folds_cursor.item() { let offset_range = fold.0.start.to_offset(&buffer)..fold.0.end.to_offset(&buffer); if offset_range.end > offset_range.start { @@ -1278,9 +1279,14 @@ mod tests { assert_eq!(snapshot4.text(), "123a…c123456eee"); let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]); - writer.unfold(Some(Point::new(0, 4)..Point::new(0, 5))); + writer.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), false); let (snapshot5, _) = map.read(buffer_snapshot.clone(), vec![]); - assert_eq!(snapshot5.text(), "123aaaaa\nbbbbbb\nccc123456eee"); + assert_eq!(snapshot5.text(), "123a…c123456eee"); + + let (mut writer, _, _) = map.write(buffer_snapshot.clone(), vec![]); + writer.unfold(Some(Point::new(0, 4)..Point::new(0, 4)), true); + let (snapshot6, _) = map.read(buffer_snapshot.clone(), vec![]); + assert_eq!(snapshot6.text(), "123aaaaa\nbbbbbb\nccc123456eee"); } #[gpui::test] diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 901699f7c47b9f7764286d8c4020a4d765593870..d841024f8880b44579b1aec0df3f1b06b4150675 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -122,7 +122,7 @@ action!(ConfirmRename); action!(PageUp); action!(PageDown); action!(Fold); -action!(Unfold); +action!(UnfoldLines); action!(FoldSelectedRanges); action!(Scroll, Vector2F); action!(Select, SelectPhase); @@ -263,7 +263,7 @@ pub fn init(cx: &mut MutableAppContext) { Binding::new("pageup", PageUp, Some("Editor")), Binding::new("pagedown", PageDown, Some("Editor")), Binding::new("alt-cmd-[", Fold, Some("Editor")), - Binding::new("alt-cmd-]", Unfold, Some("Editor")), + Binding::new("alt-cmd-]", UnfoldLines, Some("Editor")), Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")), Binding::new("ctrl-space", ShowCompletions, Some("Editor")), Binding::new("cmd-.", ToggleCodeActions(false), Some("Editor")), @@ -329,7 +329,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Editor::page_up); cx.add_action(Editor::page_down); cx.add_action(Editor::fold); - cx.add_action(Editor::unfold); + cx.add_action(Editor::unfold_lines); cx.add_action(Editor::fold_selected_ranges); cx.add_action(Editor::show_completions); cx.add_action(Editor::toggle_code_actions); @@ -3138,7 +3138,7 @@ impl Editor { } self.transact(cx, |this, cx| { - this.unfold_ranges(unfold_ranges, cx); + this.unfold_ranges(unfold_ranges, true, cx); this.buffer.update(cx, |buffer, cx| { for (range, text) in edits { buffer.edit([range], text, cx); @@ -3241,7 +3241,7 @@ impl Editor { } self.transact(cx, |this, cx| { - this.unfold_ranges(unfold_ranges, cx); + this.unfold_ranges(unfold_ranges, true, cx); this.buffer.update(cx, |buffer, cx| { for (range, text) in edits { buffer.edit([range], text, cx); @@ -3766,7 +3766,7 @@ impl Editor { to_unfold.push(selection.start..selection.end); } } - self.unfold_ranges(to_unfold, cx); + self.unfold_ranges(to_unfold, true, cx); self.update_selections(new_selections, Some(Autoscroll::Fit), cx); } @@ -3925,6 +3925,7 @@ impl Editor { reversed: false, goal: SelectionGoal::None, }); + self.unfold_ranges([next_selected_range], false, cx); self.update_selections(selections, Some(Autoscroll::Newest), cx); } else { select_next_state.done = true; @@ -3952,6 +3953,7 @@ impl Editor { wordwise: true, done: false, }; + self.unfold_ranges([selection.start..selection.end], false, cx); self.update_selections(selections, Some(Autoscroll::Newest), cx); self.select_next_state = Some(select_state); } else { @@ -5196,7 +5198,7 @@ impl Editor { self.fold_ranges(fold_ranges, cx); } - pub fn unfold(&mut self, _: &Unfold, cx: &mut ViewContext) { + pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext) { let selections = self.local_selections::(cx); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; @@ -5211,7 +5213,7 @@ impl Editor { start..end }) .collect::>(); - self.unfold_ranges(ranges, cx); + self.unfold_ranges(ranges, true, cx); } fn is_line_foldable(&self, display_map: &DisplaySnapshot, display_row: u32) -> bool { @@ -5262,7 +5264,7 @@ impl Editor { self.fold_ranges(ranges, cx); } - fn fold_ranges( + pub fn fold_ranges( &mut self, ranges: impl IntoIterator>, cx: &mut ViewContext, @@ -5275,10 +5277,16 @@ impl Editor { } } - fn unfold_ranges(&mut self, ranges: Vec>, cx: &mut ViewContext) { - if !ranges.is_empty() { + pub fn unfold_ranges( + &mut self, + ranges: impl IntoIterator>, + inclusive: bool, + cx: &mut ViewContext, + ) { + let mut ranges = ranges.into_iter().peekable(); + if ranges.peek().is_some() { self.display_map - .update(cx, |map, cx| map.unfold(ranges, cx)); + .update(cx, |map, cx| map.unfold(ranges, inclusive, cx)); self.request_autoscroll(Autoscroll::Fit, cx); cx.notify(); } @@ -6581,7 +6589,7 @@ mod tests { .unindent(), ); - view.unfold(&Unfold, cx); + view.unfold_lines(&UnfoldLines, cx); assert_eq!( view.display_text(cx), " @@ -6602,7 +6610,7 @@ mod tests { .unindent(), ); - view.unfold(&Unfold, cx); + view.unfold_lines(&UnfoldLines, cx); assert_eq!(view.display_text(cx), buffer.read(cx).read(cx).text()); }); } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 0b1ed2c35b1054d26f184c451e1d42eca83f51b7..da9ee0664ba5423f1a8e8fffd2e53d5c1300fb52 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -336,11 +336,9 @@ impl SearchBar { direction, &editor.buffer().read(cx).read(cx), ); - editor.select_ranges( - [ranges[new_index].clone()], - Some(Autoscroll::Fit), - cx, - ); + let range_to_select = ranges[new_index].clone(); + editor.unfold_ranges([range_to_select.clone()], false, cx); + editor.select_ranges([range_to_select], Some(Autoscroll::Fit), cx); } }); } diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 212e1c66a7d9be5c41e657a2e7d97266eba85a3c..d78fcb12b72697df3ebeee81d1e4e5de993581ac 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -489,6 +489,7 @@ impl ProjectSearchView { ); let range_to_select = model.match_ranges[new_index].clone(); self.results_editor.update(cx, |editor, cx| { + editor.unfold_ranges([range_to_select.clone()], false, cx); editor.select_ranges([range_to_select], Some(Autoscroll::Fit), cx); }); }