Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConvertCase trait as a wrapper for other convert case functions #27

Closed
wants to merge 9 commits into from

Conversation

ssd532
Copy link

@ssd532 ssd532 commented Jan 3, 2021

ConvertCase implements convert_case() which accepts customization options to tweak the behaviour of other case conversion functions. Currently, it accepts number_starts_word option to have word boundaries when characters in a word change from numeric to alphabetic or vice versa.

Other case conversion functions are implemented in terms on convert_case() by passing number_starts_word as false by default.

ref: #18
ref: Peternator7/strum#72

Closes #18

jplatte and others added 8 commits December 29, 2020 14:49
ConvertCase implements convert_case() which accepts customization options to tweak behaviour of other case conversion functions. Currently, it accepts `number_starts_word` option to have word boundaries when characters in a word change from numeric to alphabetic or vice versa. 

Other case conversion functions are implemented in terms on convert_case() by passing `number_starts_word` as false by default. 

ref: withoutboats#18
ref: Peternator7/strum#72
@ssd532
Copy link
Author

ssd532 commented Jan 3, 2021

Hi @jplatte please review this PR. Let us know if anything needs to be fixed/improved. Also, One thing I would like to get some help on is writing tests in convert_case using macros -- I have just started learning Rust -- if you give some pointers I can give it a go. Thank you.

@ssd532
Copy link
Author

ssd532 commented Jan 3, 2021

I have added a macro for the tests. Please check if the implementation is okay or it needs to be changed. Thanks.

@jplatte
Copy link
Collaborator

jplatte commented Jan 16, 2021

I must have been affected by a GitHub bug, because I never received a single notification about this. Will review soon!

Copy link
Collaborator

@jplatte jplatte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, and sorry for the delay in reviewing it!

As-is, this PR makes the code base a bit harder to understand, and unnecessarily so in my opinion. This is because it introduces dependencies from the existing case transformation traits to the convert_case modules, but also vice-versa.

I would much prefer if all of the actual logic is done in convert_case, and then after this PR is merged it should be pretty simple to merge all of the other traits into ConvertCase (although I'm not certain yet whether I should do this with the next release).

I hope my suggestions below are clear; if they are not please let me know.

Comment on lines +11 to +12
///
///
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should just be one empty doc comment line.

Comment on lines +14 to +15
/// ```rust
///
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swap these two lines (there should not be an empty line at the start of the code block).

/// let sentence = "Aes128";
/// assert_eq!(sentence.convert_case(ConvertCaseOpt { case: Case::ShoutyKebab, number_starts_word: true }),
/// "AES-128");
///
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code block should explicitly be terminated:

Suggested change
///
/// ```

UpperCamel,
}

pub fn convert_case(s: &str, opt: ConvertCaseOpt) -> String {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a separate free function? I think the body of this should just be moved into the trait implementation below.

}
}
impl ConvertCase for str {
fn convert_case(&self, opt: ConvertCaseOpt) -> Self::Owned {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be named convert_case_with, and convert_case should be

fn convert_case(&self, case: Case) -> Self::Owned {
    self.convert_case_with(ConvertCaseOpt { case, number_starts_word: false })
}

}

/// supported cases
pub enum Case {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please derive Clone, Copy and Debug.

}

pub fn convert_case(s: &str, opt: ConvertCaseOpt) -> String {
match opt.case {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a nicer way to express this function would be transform(s, number_starts_word, case.with_word(), case.boundary()) where

impl Case {
    pub(crate) fn with_word(self) -> fn(&str, &mut String) { ... }
    pub(crate) fn boundary(self) -> fn(&mut String) { ... }
}

represent the actual differing logic that was previously in the individual trait implementations.

@@ -81,6 +83,8 @@ where
Lowercase,
/// The previous cased character in the current word is uppercase.
Uppercase,
/// The previous cased character in the current word is numeric
Numeric,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have expected the logic change in transform to look different, but I also haven't thought about it much. Will review this part in more detail later.

@@ -17,9 +18,19 @@ pub trait ToKebabCase: ToOwned {
fn to_kebab_case(&self) -> Self::Owned;
}

pub fn to_kebab(s: &str, number_starts_word: bool) -> String {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the proposed changes to the convert_case module, this function doesn't need to exist.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the other modules.

Comment on lines +27 to +33
convert_case(
&self,
ConvertCaseOpt {
case: Case::Kebab,
number_starts_word: false,
},
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the proposed changes to the convert_case module, this implementation simply becomes

Suggested change
convert_case(
&self,
ConvertCaseOpt {
case: Case::Kebab,
number_starts_word: false,
},
)
self.convert_case(Case::Kebab)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the other modules.

@jplatte jplatte mentioned this pull request Jan 16, 2021
@jplatte jplatte changed the base branch from master to v0.3.x September 11, 2021 21:58
@jplatte
Copy link
Collaborator

jplatte commented Sep 11, 2021

Ping @ssd532, are you still interested in finishing this?

@jplatte jplatte mentioned this pull request Oct 11, 2021
@jplatte jplatte self-assigned this Apr 21, 2022
@jplatte
Copy link
Collaborator

jplatte commented Aug 15, 2023

Closing due to inactivity.

@jplatte jplatte closed this Aug 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kebab case doesn't treat numbers as separate word?
2 participants