From ff8c1df71db70a3d4ed8c3bb14b164671e944bab Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:00:56 +0000 Subject: [PATCH] feat: correct implementations for kebab, snake and title case --- helix-core/src/case_conversion.rs | 96 ++++++++++++++++--------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/helix-core/src/case_conversion.rs b/helix-core/src/case_conversion.rs index 67bf17180..35287d5be 100644 --- a/helix-core/src/case_conversion.rs +++ b/helix-core/src/case_conversion.rs @@ -88,60 +88,66 @@ pub fn to_pascal_case_with(text: impl Iterator, buf: &mut Tendril) } } -pub fn to_snake_case_with(text: impl Iterator, buf: &mut Tendril) { - let mut at_word_start = true; +pub fn to_title_case_with(text: impl Iterator, buf: &mut Tendril) { + let mut capitalize_next = true; + let mut prev_is_lowercase = false; + for c in text { - // we don't count _ as a word char here so case conversions work well - if !c.is_alphanumeric() { - at_word_start = true; - continue; - } - if at_word_start { - at_word_start = false; - buf.push('_'); - buf.push(c); + if c.is_alphanumeric() { + if capitalize_next || (prev_is_lowercase && c.is_uppercase()) { + buf.extend(c.to_uppercase()); + capitalize_next = false; + } else { + buf.extend(c.to_lowercase()); + } + prev_is_lowercase = c.is_lowercase(); } else { - buf.push(c) + capitalize_next = true; + prev_is_lowercase = false; + buf.push(' '); } } + + *buf = buf.trim().into(); +} + +pub fn to_case_with_separator( + text: impl Iterator, + buf: &mut Tendril, + separator: char, +) { + let mut prev_is_lowercase = false; // Tracks if the previous character was lowercase + let mut prev_is_alphanumeric = false; // Tracks if the previous character was alphanumeric + + for c in text { + if c.is_alphanumeric() { + if prev_is_lowercase && c.is_uppercase() { + buf.push(separator); + } + if !prev_is_alphanumeric && !buf.is_empty() { + buf.push(separator); + } + + buf.push(c.to_ascii_lowercase()); + prev_is_lowercase = c.is_lowercase(); + prev_is_alphanumeric = true; + } else { + prev_is_lowercase = false; + prev_is_alphanumeric = false; + } + } + + if buf.ends_with(separator) { + buf.pop(); + } } pub fn to_kebab_case_with(text: impl Iterator, buf: &mut Tendril) { - let mut at_word_start = false; - for c in text { - // we don't count _ as a word char here so case conversions work well - if !c.is_alphanumeric() { - at_word_start = true; - continue; - } - if at_word_start { - at_word_start = false; - buf.push('-'); - buf.push(c); - } else { - buf.push(c) - } - } + to_case_with_separator(text, buf, '-'); } -pub fn to_title_case_with(text: impl Iterator, buf: &mut Tendril) { - let mut at_word_start = true; - for (i, c) in text.enumerate() { - // we don't count _ as a word char here so case conversions work well - if !c.is_alphanumeric() { - at_word_start = true; - continue; - } - if at_word_start { - at_word_start = false; - if i != 0 { - buf.push(' '); - } - buf.extend(c.to_uppercase()); - } else { - buf.push(c) - } - } +pub fn to_snake_case_with(text: impl Iterator, buf: &mut Tendril) { + to_case_with_separator(text, buf, '_'); } pub fn to_camel_case_with(mut text: impl Iterator, buf: &mut Tendril) {