mirror of
https://github.com/nushell/nushell.git
synced 2025-01-08 23:40:17 +01:00
ebe42241fe
# Description This PR allows the helper attribute `nu_value(rename = "...")` to be used on struct fields and enum variants. This allows renaming keys and variants just like [`#[serde(rename = "name")]`](https://serde.rs/field-attrs.html#rename). This has no singular variants for `IntoValue` or `FromValue`, both need to use the same (but I think this shouldn't be an issue for now). # User-Facing Changes Users of the derive macros `IntoValue` and `FromValue` may now use `#[nu_value(rename = "...")]` to rename single fields, but no already existing code will break.
77 lines
2.3 KiB
Rust
77 lines
2.3 KiB
Rust
use heck::*;
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
pub enum Case {
|
|
// directly supported by heck
|
|
Pascal,
|
|
Camel,
|
|
Snake,
|
|
Kebab,
|
|
ScreamingSnake,
|
|
Title,
|
|
Cobol,
|
|
Train,
|
|
|
|
// custom variants
|
|
Upper,
|
|
Lower,
|
|
Flat,
|
|
ScreamingFlat,
|
|
}
|
|
|
|
impl Case {
|
|
pub fn from_str(s: impl AsRef<str>) -> Option<Self> {
|
|
match s.as_ref() {
|
|
// The matched case are all useful variants from `convert_case` with aliases
|
|
// that `serde` uses.
|
|
"PascalCase" | "UpperCamelCase" => Case::Pascal,
|
|
"camelCase" | "lowerCamelCase" => Case::Camel,
|
|
"snake_case" => Case::Snake,
|
|
"kebab-case" => Case::Kebab,
|
|
"SCREAMING_SNAKE_CASE" | "UPPER_SNAKE_CASE" | "SHOUTY_SNAKE_CASE" => {
|
|
Case::ScreamingSnake
|
|
}
|
|
"Title Case" => Case::Title,
|
|
"COBOL-CASE" | "SCREAMING-KEBAB-CASE" | "UPPER-KEBAB-CASE" => Case::Cobol,
|
|
"Train-Case" => Case::Train,
|
|
|
|
"UPPER CASE" | "UPPER WITH SPACES CASE" => Case::Upper,
|
|
"lower case" | "lower with spaces case" => Case::Lower,
|
|
"flatcase" | "lowercase" => Case::Flat,
|
|
"SCREAMINGFLATCASE" | "UPPERFLATCASE" | "UPPERCASE" => Case::ScreamingFlat,
|
|
|
|
_ => return None,
|
|
}
|
|
.into()
|
|
}
|
|
}
|
|
|
|
pub trait Casing {
|
|
fn to_case(&self, case: impl Into<Option<Case>>) -> String;
|
|
}
|
|
|
|
impl<T: ToString> Casing for T {
|
|
fn to_case(&self, case: impl Into<Option<Case>>) -> String {
|
|
let s = self.to_string();
|
|
let Some(case) = case.into() else {
|
|
return s.to_string();
|
|
};
|
|
|
|
match case {
|
|
Case::Pascal => s.to_upper_camel_case(),
|
|
Case::Camel => s.to_lower_camel_case(),
|
|
Case::Snake => s.to_snake_case(),
|
|
Case::Kebab => s.to_kebab_case(),
|
|
Case::ScreamingSnake => s.to_shouty_snake_case(),
|
|
Case::Title => s.to_title_case(),
|
|
Case::Cobol => s.to_shouty_kebab_case(),
|
|
Case::Train => s.to_train_case(),
|
|
|
|
Case::Upper => s.to_shouty_snake_case().replace('_', " "),
|
|
Case::Lower => s.to_snake_case().replace('_', " "),
|
|
Case::Flat => s.to_snake_case().replace('_', ""),
|
|
Case::ScreamingFlat => s.to_shouty_snake_case().replace('_', ""),
|
|
}
|
|
}
|
|
}
|