From 4f50da759a57c7da0d92f536911d296839c77975 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 24 Mar 2022 17:14:41 +0100 Subject: [PATCH 1/4] Allow customizing whether `FoldMap::unfold` treats ranges as inclusive --- crates/editor/src/display_map.rs | 5 +++-- crates/editor/src/display_map/fold_map.rs | 5 +++-- crates/editor/src/editor.rs | 22 ++++++++++++++-------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 6f3154113760097e3d0768dd20852eccc184c4a6..807049c75c3555cd13f74473cf086b967db67f51 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 @@ -629,7 +630,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 ac4477263d4cb015d86274ab881b4e673f747f73..81da94aca7f402ea98f70715c62d152be13609dc 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 { @@ -1282,7 +1283,7 @@ 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, 5)), true); let (snapshot5, _) = map.read(buffer_snapshot.clone(), vec![]); assert_eq!(snapshot5.text(), "123aaaaa\nbbbbbb\nccc123456eee"); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 6722d2b1fb45c99a210fb4b6b317b7eb54095a4f..7cc203c1849d751272766f398b8803723d414709 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3123,7 +3123,7 @@ impl Editor { } self.start_transaction(cx); - self.unfold_ranges(unfold_ranges, cx); + self.unfold_ranges(unfold_ranges, true, cx); self.buffer.update(cx, |buffer, cx| { for (range, text) in edits { buffer.edit([range], text, cx); @@ -3226,7 +3226,7 @@ impl Editor { } self.start_transaction(cx); - self.unfold_ranges(unfold_ranges, cx); + self.unfold_ranges(unfold_ranges, true, cx); self.buffer.update(cx, |buffer, cx| { for (range, text) in edits { buffer.edit([range], text, cx); @@ -3748,7 +3748,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); } @@ -5202,7 +5202,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 { @@ -5253,7 +5253,7 @@ impl Editor { self.fold_ranges(ranges, cx); } - fn fold_ranges( + pub fn fold_ranges( &mut self, ranges: impl IntoIterator>, cx: &mut ViewContext, @@ -5266,10 +5266,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(); } From 78b52168fa234b30e5133ff0dd379ce057cfddc3 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 24 Mar 2022 17:15:40 +0100 Subject: [PATCH 2/4] Rename `Editor::unfold` to `Editor::unfold_lines` --- crates/editor/src/editor.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 7cc203c1849d751272766f398b8803723d414709..715f76a07fd793507ab15385b7997b37d1dba5f8 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); @@ -5187,7 +5187,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; @@ -6467,7 +6467,7 @@ mod tests { .unindent(), ); - view.unfold(&Unfold, cx); + view.unfold_lines(&UnfoldLines, cx); assert_eq!( view.display_text(cx), " @@ -6488,7 +6488,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()); }); } From 7fa7b7e507f1c648ded3e4e1a0253f2750e6f74b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 24 Mar 2022 17:16:21 +0100 Subject: [PATCH 3/4] Unfold range when selecting the next match Selected matches are unfolded when in project search, buffer search and when hitting `cmd-d` to select the next match. --- crates/editor/src/editor.rs | 2 ++ crates/search/src/buffer_search.rs | 8 +++----- crates/search/src/project_search.rs | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 715f76a07fd793507ab15385b7997b37d1dba5f8..0aadc3fab9b19bc864563c4647f28f5b866fcdae 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -3907,6 +3907,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; @@ -3934,6 +3935,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 { diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 13c73036f4dcc0a5c6c90557221e6d7b9ee6bdfb..a1a40c9e391c645b0a9798dc94a7fdbf92d895b6 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); }); } From 1c25b3d150457ddc648cf601898dd857cfa06e7b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 24 Mar 2022 17:20:28 +0100 Subject: [PATCH 4/4] Test the new `inclusive` parameter when unfolding --- crates/editor/src/display_map/fold_map.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index 81da94aca7f402ea98f70715c62d152be13609dc..586f6e0b04f1547c66b4fe514cead3855555dfe4 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -1283,9 +1283,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)), true); + 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]