From c74cd48f38863b3004eaf2b52336ed0597337044 Mon Sep 17 00:00:00 2001
From: Jason Rodney Hansen <jasonrodneyhansen@gmail.com>
Date: Sun, 28 Nov 2021 10:58:52 -0700
Subject: [PATCH] Cleanup

---
 helix-core/src/increment/date_time.rs | 104 +++++++++++++-------------
 helix-term/src/commands.rs            |  10 +--
 2 files changed, 57 insertions(+), 57 deletions(-)

diff --git a/helix-core/src/increment/date_time.rs b/helix-core/src/increment/date_time.rs
index 195bc14b..39646a17 100644
--- a/helix-core/src/increment/date_time.rs
+++ b/helix-core/src/increment/date_time.rs
@@ -67,27 +67,16 @@ impl DateTimeIncrementor {
             let has_date = format.fields.iter().any(|f| f.unit.is_date());
             let has_time = format.fields.iter().any(|f| f.unit.is_time());
 
+            let date_time = &text[date_time.start()..date_time.end()];
             let date_time = match (has_date, has_time) {
-                (true, true) => NaiveDateTime::parse_from_str(
-                    &text[date_time.start()..date_time.end()],
-                    format.fmt,
-                )
-                .ok()?,
+                (true, true) => NaiveDateTime::parse_from_str(date_time, format.fmt).ok()?,
                 (true, false) => {
-                    let date = NaiveDate::parse_from_str(
-                        &text[date_time.start()..date_time.end()],
-                        format.fmt,
-                    )
-                    .ok()?;
+                    let date = NaiveDate::parse_from_str(date_time, format.fmt).ok()?;
 
                     date.and_hms(0, 0, 0)
                 }
                 (false, true) => {
-                    let time = NaiveTime::parse_from_str(
-                        &text[date_time.start()..date_time.end()],
-                        format.fmt,
-                    )
-                    .ok()?;
+                    let time = NaiveTime::parse_from_str(date_time, format.fmt).ok()?;
 
                     NaiveDate::from_ymd(0, 1, 1).and_time(time)
                 }
@@ -123,22 +112,22 @@ impl Increment for DateTimeIncrementor {
 
 static FORMATS: Lazy<Vec<Format>> = Lazy::new(|| {
     vec![
-        Format::new("%Y-%m-%d %H:%M:%S"), // 2021-11-24 07:12:23
-        Format::new("%Y/%m/%d %H:%M:%S"), // 2021/11/24 07:12:23
-        Format::new("%Y-%m-%d %H:%M"),    // 2021-11-24 07:12
-        Format::new("%Y/%m/%d %H:%M"),    // 2021/11/24 07:12
-        Format::new("%Y-%m-%d"),          // 2021-11-24
-        Format::new("%Y/%m/%d"),          // 2021/11/24
-        Format::new("%a %b %d %Y"),       // Wed Nov 24 2021
-        Format::new("%d-%b-%Y"),          // 24-Nov-2021
-        Format::new("%Y %b %d"),          // 2021 Nov 24
-        Format::new("%b %d, %Y"),         // Nov 24, 2021
-        Format::new("%-I:%M:%S %P"),      // 7:21:53 am
-        Format::new("%-I:%M %P"),         // 7:21 am
-        Format::new("%-I:%M:%S %p"),      // 7:21:53 AM
-        Format::new("%-I:%M %p"),         // 7:21 AM
-        Format::new("%H:%M:%S"),          // 23:24:23
-        Format::new("%H:%M"),             // 23:24
+        Format::new("%Y-%m-%d %H:%M:%S").unwrap(), // 2021-11-24 07:12:23
+        Format::new("%Y/%m/%d %H:%M:%S").unwrap(), // 2021/11/24 07:12:23
+        Format::new("%Y-%m-%d %H:%M").unwrap(),    // 2021-11-24 07:12
+        Format::new("%Y/%m/%d %H:%M").unwrap(),    // 2021/11/24 07:12
+        Format::new("%Y-%m-%d").unwrap(),          // 2021-11-24
+        Format::new("%Y/%m/%d").unwrap(),          // 2021/11/24
+        Format::new("%a %b %d %Y").unwrap(),       // Wed Nov 24 2021
+        Format::new("%d-%b-%Y").unwrap(),          // 24-Nov-2021
+        Format::new("%Y %b %d").unwrap(),          // 2021 Nov 24
+        Format::new("%b %d, %Y").unwrap(),         // Nov 24, 2021
+        Format::new("%-I:%M:%S %P").unwrap(),      // 7:21:53 am
+        Format::new("%-I:%M %P").unwrap(),         // 7:21 am
+        Format::new("%-I:%M:%S %p").unwrap(),      // 7:21:53 AM
+        Format::new("%-I:%M %p").unwrap(),         // 7:21 AM
+        Format::new("%H:%M:%S").unwrap(),          // 23:24:23
+        Format::new("%H:%M").unwrap(),             // 23:24
     ]
 });
 
@@ -151,55 +140,65 @@ struct Format {
 }
 
 impl Format {
-    fn new(fmt: &'static str) -> Self {
+    fn new(fmt: &'static str) -> Result<Self, FormatError> {
         let mut remaining = fmt;
         let mut fields = Vec::new();
         let mut regex = String::new();
         let mut max_len = 0;
 
         while let Some(i) = remaining.find('%') {
-            let mut chars = remaining[i + 1..].chars();
-            let spec_len = if let Some(c) = chars.next() {
-                if c == '-' {
-                    if chars.next().is_some() {
-                        2
-                    } else {
-                        0
-                    }
+            let after = &remaining[i + 1..];
+            let mut chars = after.chars();
+            let c = chars
+                .next()
+                .ok_or(FormatError::UnexpectedEndOfFormatString)?;
+
+            let spec_len = if c == '-' {
+                if let Some(c) = chars.next() {
+                    1 + c.len_utf8()
                 } else {
-                    1
+                    return Err(FormatError::UnexpectedEndOfFormatString);
                 }
             } else {
-                0
+                c.len_utf8()
             };
 
             if i < remaining.len() - spec_len {
-                let specifier = &remaining[i + 1..i + 1 + spec_len];
+                let specifier = &after[..spec_len];
                 if let Some(field) = DateField::from_specifier(specifier) {
                     fields.push(field);
                     max_len += field.max_len + remaining[..i].len();
                     regex += &remaining[..i];
                     regex += &format!("({})", field.regex);
-                    remaining = &remaining[i + spec_len + 1..];
+                    remaining = &after[spec_len..];
                 } else {
-                    regex += &remaining[..=i];
+                    return Err(FormatError::UnsupportedSpecifier(
+                        &remaining[i..i + 1 + spec_len],
+                    ));
                 }
             } else {
-                regex += remaining;
+                return Err(FormatError::UnexpectedEndOfFormatString);
             }
         }
 
-        let regex = Regex::new(&regex).unwrap();
+        let regex = Regex::new(&regex).map_err(FormatError::Regex)?;
 
-        Self {
+        Ok(Self {
             fmt,
             fields,
             regex,
             max_len,
-        }
+        })
     }
 }
 
+#[derive(Clone, Debug)]
+enum FormatError {
+    UnexpectedEndOfFormatString,
+    UnsupportedSpecifier(&'static str),
+    Regex(regex::Error),
+}
+
 impl PartialEq for Format {
     fn eq(&self, other: &Self) -> bool {
         self.fmt == other.fmt && self.fields == other.fields && self.max_len == other.max_len
@@ -348,10 +347,11 @@ fn add_months(date_time: NaiveDateTime, amount: i64) -> Option<NaiveDateTime> {
     // Normalize month
     let month = month % 12;
     let month = if month.is_negative() {
-        month + 13
+        month + 12
     } else {
-        month + 1
-    } as u32;
+        month
+    } as u32
+        + 1;
 
     let day = cmp::min(date_time.day(), ndays_in_month(year, month));
 
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 4869a135..c89c81db 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -5803,17 +5803,17 @@ fn increment_impl(cx: &mut Context, amount: i64) {
     let text = doc.text();
 
     let changes = selection.ranges().iter().filter_map(|range| {
-        let incrementor: Option<Box<dyn Increment>> = if let Some(incrementor) =
+        let incrementor: Box<dyn Increment> = if let Some(incrementor) =
             DateTimeIncrementor::from_range(text.slice(..), *range)
         {
-            Some(Box::new(incrementor))
+            Box::new(incrementor)
         } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) {
-            Some(Box::new(incrementor))
+            Box::new(incrementor)
         } else {
-            None
+            return None;
         };
 
-        let (range, new_text) = incrementor?.increment(amount);
+        let (range, new_text) = incrementor.increment(amount);
         Some((range.from(), range.to(), Some(new_text)))
     });