aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/increment/date.rs (renamed from helix-core/src/date.rs)37
-rw-r--r--helix-core/src/increment/mod.rs8
-rw-r--r--helix-core/src/increment/number.rs (renamed from helix-core/src/numbers.rs)30
-rw-r--r--helix-core/src/lib.rs3
-rw-r--r--helix-term/src/commands.rs30
5 files changed, 63 insertions, 45 deletions
diff --git a/helix-core/src/date.rs b/helix-core/src/increment/date.rs
index c447ef70..05442990 100644
--- a/helix-core/src/date.rs
+++ b/helix-core/src/increment/date.rs
@@ -9,6 +9,8 @@ use crate::{Range, Tendril};
use chrono::{Datelike, Duration, NaiveDate};
+use super::Increment;
+
fn ndays_in_month(year: i32, month: u32) -> u32 {
// The first day of the next month...
let (y, m) = if month == 12 {
@@ -29,6 +31,7 @@ fn add_days(date: NaiveDate, amount: i64) -> Option<NaiveDate> {
fn add_months(date: NaiveDate, amount: i64) -> Option<NaiveDate> {
let month = date.month0() as i64 + amount;
let year = date.year() + i32::try_from(month / 12).ok()?;
+ let year = if month.is_negative() { year - 1 } else { year };
// Normalize month
let month = month % 12;
@@ -45,7 +48,6 @@ fn add_months(date: NaiveDate, amount: i64) -> Option<NaiveDate> {
fn add_years(date: NaiveDate, amount: i64) -> Option<NaiveDate> {
let year = i32::try_from(date.year() as i64 + amount).ok()?;
-
let ndays = ndays_in_month(year, date.month());
if date.day() > ndays {
@@ -85,9 +87,8 @@ enum DateField {
#[derive(Debug, PartialEq, Eq)]
pub struct DateIncrementor {
- pub date: NaiveDate,
- pub range: Range,
-
+ date: NaiveDate,
+ range: Range,
field: DateField,
format: Format,
}
@@ -150,8 +151,10 @@ impl DateIncrementor {
})
})
}
+}
- pub fn incremented_text(&self, amount: i64) -> Tendril {
+impl Increment for DateIncrementor {
+ fn increment(&self, amount: i64) -> (Range, Tendril) {
let date = match self.field {
DateField::Year => add_years(self.date, amount),
DateField::Month => add_months(self.date, amount),
@@ -159,15 +162,18 @@ impl DateIncrementor {
}
.unwrap_or(self.date);
- format!(
- "{:04}{}{:02}{}{:02}",
- date.year(),
- self.format.separator,
- date.month(),
- self.format.separator,
- date.day()
+ (
+ self.range,
+ format!(
+ "{:04}{}{:02}{}{:02}",
+ date.year(),
+ self.format.separator,
+ date.month(),
+ self.format.separator,
+ date.day()
+ )
+ .into(),
)
- .into()
}
}
@@ -437,6 +443,8 @@ mod test {
("2020-02-29", 0, 1, "2021-03-01"),
("2020-01-31", 5, 1, "2020-02-29"),
("2020-01-20", 5, 1, "2020-02-20"),
+ ("2021-01-01", 5, -1, "2020-12-01"),
+ ("2021-01-31", 5, -2, "2020-11-30"),
("2020-02-28", 8, 1, "2020-02-29"),
("2021-02-28", 8, 1, "2021-03-01"),
("2021-02-28", 0, -1, "2020-02-28"),
@@ -457,7 +465,8 @@ mod test {
assert_eq!(
DateIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
diff --git a/helix-core/src/increment/mod.rs b/helix-core/src/increment/mod.rs
new file mode 100644
index 00000000..71a1f183
--- /dev/null
+++ b/helix-core/src/increment/mod.rs
@@ -0,0 +1,8 @@
+pub mod date;
+pub mod number;
+
+use crate::{Range, Tendril};
+
+pub trait Increment {
+ fn increment(&self, amount: i64) -> (Range, Tendril);
+}
diff --git a/helix-core/src/numbers.rs b/helix-core/src/increment/number.rs
index e9f3c898..a19b7e75 100644
--- a/helix-core/src/numbers.rs
+++ b/helix-core/src/increment/number.rs
@@ -2,6 +2,8 @@ use std::borrow::Cow;
use ropey::RopeSlice;
+use super::Increment;
+
use crate::{
textobject::{textobject_word, TextObject},
Range, Tendril,
@@ -9,9 +11,9 @@ use crate::{
#[derive(Debug, PartialEq, Eq)]
pub struct NumberIncrementor<'a> {
- pub range: Range,
- pub value: i64,
- pub radix: u32,
+ value: i64,
+ radix: u32,
+ range: Range,
text: RopeSlice<'a>,
}
@@ -71,9 +73,10 @@ impl<'a> NumberIncrementor<'a> {
text,
})
}
+}
- /// Add `amount` to the number and return the formatted text.
- pub fn incremented_text(&self, amount: i64) -> Tendril {
+impl<'a> Increment for NumberIncrementor<'a> {
+ fn increment(&self, amount: i64) -> (Range, Tendril) {
let old_text: Cow<str> = self.text.slice(self.range.from()..self.range.to()).into();
let old_length = old_text.len();
let new_value = self.value.wrapping_add(amount);
@@ -144,7 +147,7 @@ impl<'a> NumberIncrementor<'a> {
}
}
- new_text.into()
+ (self.range, new_text.into())
}
}
@@ -366,7 +369,8 @@ mod test {
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
@@ -392,7 +396,8 @@ mod test {
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
@@ -419,7 +424,8 @@ mod test {
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
@@ -464,7 +470,8 @@ mod test {
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
@@ -491,7 +498,8 @@ mod test {
assert_eq!(
NumberIncrementor::from_range(rope.slice(..), range)
.unwrap()
- .incremented_text(amount),
+ .increment(amount)
+ .1,
expected.into()
);
}
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index b16a716f..4ae044cc 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -1,17 +1,16 @@
pub mod auto_pairs;
pub mod chars;
pub mod comment;
-pub mod date;
pub mod diagnostic;
pub mod diff;
pub mod graphemes;
pub mod history;
+pub mod increment;
pub mod indent;
pub mod line_ending;
pub mod macros;
pub mod match_brackets;
pub mod movement;
-pub mod numbers;
pub mod object;
pub mod path;
mod position;
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 639bbd83..6329dec7 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1,14 +1,13 @@
use helix_core::{
- comment, coords_at_pos,
- date::DateIncrementor,
- find_first_non_whitespace_char, find_root, graphemes,
+ comment, coords_at_pos, find_first_non_whitespace_char, find_root, graphemes,
history::UndoKind,
+ increment::date::DateIncrementor,
+ increment::{number::NumberIncrementor, Increment},
indent,
indent::IndentStyle,
line_ending::{get_line_ending_of_str, line_end_char_index, str_is_line_ending},
match_brackets,
movement::{self, Direction},
- numbers::NumberIncrementor,
object, pos_at_coords,
regex::{self, Regex, RegexBuilder},
search, selection, surround, textobject,
@@ -5804,23 +5803,18 @@ fn increment_impl(cx: &mut Context, amount: i64) {
let text = doc.text();
let changes = selection.ranges().iter().filter_map(|range| {
- if let Some(incrementor) = DateIncrementor::from_range(text.slice(..), *range) {
- let new_text = incrementor.incremented_text(amount);
- Some((
- incrementor.range.from(),
- incrementor.range.to(),
- Some(new_text),
- ))
+ let incrementor: Option<Box<dyn Increment>> = if let Some(incrementor) =
+ DateIncrementor::from_range(text.slice(..), *range)
+ {
+ Some(Box::new(incrementor))
} else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) {
- let new_text = incrementor.incremented_text(amount);
- Some((
- incrementor.range.from(),
- incrementor.range.to(),
- Some(new_text),
- ))
+ Some(Box::new(incrementor))
} else {
None
- }
+ };
+
+ let (range, new_text) = incrementor?.increment(amount);
+ Some((range.from(), range.to(), Some(new_text)))
});
if changes.clone().count() > 0 {