Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/commands.rs')
-rw-r--r--helix-term/src/commands.rs47
1 files changed, 32 insertions, 15 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 9284df28..0d8c2550 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -5368,6 +5368,7 @@ fn rotate_selections_last(cx: &mut Context) {
doc.set_selection(view.id, selection);
}
+#[derive(Debug)]
enum ReorderStrategy {
RotateForward,
RotateBackward,
@@ -5380,34 +5381,50 @@ fn reorder_selection_contents(cx: &mut Context, strategy: ReorderStrategy) {
let text = doc.text().slice(..);
let selection = doc.selection(view.id);
- let mut fragments: Vec<_> = selection
+
+ let mut ranges: Vec<_> = selection
.slices(text)
.map(|fragment| fragment.chunks().collect())
.collect();
- let group = count
- .map(|count| count.get())
- .unwrap_or(fragments.len()) // default to rotating everything as one group
- .min(fragments.len());
-
- for chunk in fragments.chunks_mut(group) {
- // TODO: also modify main index
- match strategy {
- ReorderStrategy::RotateForward => chunk.rotate_right(1),
- ReorderStrategy::RotateBackward => chunk.rotate_left(1),
- ReorderStrategy::Reverse => chunk.reverse(),
- };
- }
+ let rotate_by = count.map_or(1, |count| count.get().min(ranges.len()));
+
+ let primary_index = match strategy {
+ ReorderStrategy::RotateForward => {
+ ranges.rotate_right(rotate_by);
+ // Like `usize::wrapping_add`, but provide a custom range from `0` to `ranges.len()`
+ (selection.primary_index() + ranges.len() + rotate_by) % ranges.len()
+ }
+ ReorderStrategy::RotateBackward => {
+ ranges.rotate_left(rotate_by);
+ // Like `usize::wrapping_sub`, but provide a custom range from `0` to `ranges.len()`
+ (selection.primary_index() + ranges.len() - rotate_by) % ranges.len()
+ }
+ ReorderStrategy::Reverse => {
+ if rotate_by % 2 == 0 {
+ // nothing changed, if we reverse something an even
+ // amount of times, the output will be the same
+ return;
+ }
+ ranges.reverse();
+ // -1 to turn 1-based len into 0-based index
+ (ranges.len() - 1) - selection.primary_index()
+ }
+ };
let transaction = Transaction::change(
doc.text(),
selection
.ranges()
.iter()
- .zip(fragments)
+ .zip(ranges)
.map(|(range, fragment)| (range.from(), range.to(), Some(fragment))),
);
+ doc.set_selection(
+ view.id,
+ Selection::new(selection.ranges().into(), primary_index),
+ );
doc.apply(&transaction, view.id);
}