aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-term/src/commands.rs52
1 files changed, 39 insertions, 13 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index c89c81db..013a4280 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -41,7 +41,7 @@ use crate::{
use crate::job::{self, Job, Jobs};
use futures_util::{FutureExt, StreamExt};
-use std::num::NonZeroUsize;
+use std::{collections::HashSet, num::NonZeroUsize};
use std::{fmt, future::Future};
use std::{
@@ -5802,19 +5802,45 @@ fn increment_impl(cx: &mut Context, amount: i64) {
let selection = doc.selection(view.id);
let text = doc.text();
- let changes = selection.ranges().iter().filter_map(|range| {
- let incrementor: Box<dyn Increment> = if let Some(incrementor) =
- DateTimeIncrementor::from_range(text.slice(..), *range)
- {
- Box::new(incrementor)
- } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) {
- Box::new(incrementor)
- } else {
- return None;
- };
+ let changes = selection
+ .ranges()
+ .iter()
+ .filter_map(|range| {
+ let incrementor: Box<dyn Increment> = if let Some(incrementor) =
+ DateTimeIncrementor::from_range(text.slice(..), *range)
+ {
+ Box::new(incrementor)
+ } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range)
+ {
+ Box::new(incrementor)
+ } else {
+ return None;
+ };
+
+ let (range, new_text) = incrementor.increment(amount);
+
+ Some((range.from(), range.to(), Some(new_text)))
+ })
+ .collect::<Vec<_>>();
- let (range, new_text) = incrementor.increment(amount);
- Some((range.from(), range.to(), Some(new_text)))
+ // Overlapping changes in a transaction will panic, so we need to find and remove them.
+ // For example, if there are cursors on each of the year, month, and day of `2021-11-29`,
+ // incrementing will give overlapping changes, with each change incrementing a different part of
+ // the date. Since these conflict with each other we remove these changes from the transaction
+ // so nothing happens.
+ let mut overlapping_indexes = HashSet::new();
+ for (i, changes) in changes.windows(2).enumerate() {
+ if changes[0].1 > changes[1].0 {
+ overlapping_indexes.insert(i);
+ overlapping_indexes.insert(i + 1);
+ }
+ }
+ let changes = changes.into_iter().enumerate().filter_map(|(i, change)| {
+ if overlapping_indexes.contains(&i) {
+ None
+ } else {
+ Some(change)
+ }
});
if changes.clone().count() > 0 {