on master help sign in
Don't increment for overlapping changes
commit31ed91dc2e9777a7312bd8d2ed47b9ea6fb223e0 authorJason Rodney Hansen <jasonrodneyhansen@gmail.com> dateMon 29 Nov 2021, 18:22 (5 years ago) parent584a31c
1 file changed+39−13
helix-term/src/commands.rs+39−13
helix-term/src/commands.rs+39−13
@@ -41,7 +41,7 @@ use crate::{
4141
4242use crate::job::{self, Job, Jobs};
4343use futures_util::{FutureExt, StreamExt};
44−use std::num::NonZeroUsize;
44+use std::{collections::HashSet, num::NonZeroUsize};
4545use std::{fmt, future::Future};
4646
4747use std::{
@@ -5802,19 +5802,45 @@ fn increment_impl(cx: &mut Context, amount: i64) {
58025802 let selection = doc.selection(view.id);
58035803 let text = doc.text();
58045804
5805− let changes = selection.ranges().iter().filter_map(|range| {
5806− let incrementor: Box<dyn Increment> = if let Some(incrementor) =
5807− DateTimeIncrementor::from_range(text.slice(..), *range)
5808− {
5809− Box::new(incrementor)
5810− } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) {
5811− Box::new(incrementor)
5812− } else {
5813− return None;
5814− };
5805+ let changes = selection
5806+ .ranges()
5807+ .iter()
5808+ .filter_map(|range| {
5809+ let incrementor: Box<dyn Increment> = if let Some(incrementor) =
5810+ DateTimeIncrementor::from_range(text.slice(..), *range)
5811+ {
5812+ Box::new(incrementor)
5813+ } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range)
5814+ {
5815+ Box::new(incrementor)
5816+ } else {
5817+ return None;
5818+ };
5819+
5820+ let (range, new_text) = incrementor.increment(amount);
5821+
5822+ Some((range.from(), range.to(), Some(new_text)))
5823+ })
5824+ .collect::<Vec<_>>();
58155825
5816− let (range, new_text) = incrementor.increment(amount);
5817− Some((range.from(), range.to(), Some(new_text)))
5826+ // Overlapping changes in a transaction will panic, so we need to find and remove them.
5827+ // For example, if there are cursors on each of the year, month, and day of `2021-11-29`,
5828+ // incrementing will give overlapping changes, with each change incrementing a different part of
5829+ // the date. Since these conflict with each other we remove these changes from the transaction
5830+ // so nothing happens.
5831+ let mut overlapping_indexes = HashSet::new();
5832+ for (i, changes) in changes.windows(2).enumerate() {
5833+ if changes[0].1 > changes[1].0 {
5834+ overlapping_indexes.insert(i);
5835+ overlapping_indexes.insert(i + 1);
5836+ }
5837+ }
5838+ let changes = changes.into_iter().enumerate().filter_map(|(i, change)| {
5839+ if overlapping_indexes.contains(&i) {
5840+ None
5841+ } else {
5842+ Some(change)
5843+ }
58185844 });
58195845
58205846 if changes.clone().count() > 0 {