From d56e05d558eb2a34963a800685facff30ae0ebb5 Mon Sep 17 00:00:00 2001 From: GeonHwan Cha Date: Thu, 23 Oct 2025 11:49:42 +0900 Subject: [PATCH] feat(case): add kebab-case conversion --- README.md | 6 ++++-- src/tools/case.rs | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6312331..d4c42dc 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,8 @@ After setting up completions, restart your shell or source your configuration fi │ │ ├── constant │ │ ├── header │ │ ├── sentence -│ │ └── snake +│ │ ├── snake +│ │ └── kebab │ ├── pretty-print (pp) - Unescape newlines and tabs │ └── diff - Compare text with visual output ├── Development Tools @@ -294,12 +295,13 @@ ut random --min 0 --max 1 --step 0.01 --count 10 #### `case` Convert text between different case formats. -- lowercase, UPPERCASE, camelCase, snake_case, Title Case, CONSTANT_CASE, Header-Case, Sentence case +- lowercase, UPPERCASE, camelCase, snake_case, kebab-case, Title Case, CONSTANT_CASE, Header-Case, Sentence case ```bash ut case lower "Hello World" ut case camel "hello_world" ut case snake "HelloWorld" +ut case kebab "HelloWorld" echo -n "Hello :)" | ut case lower - ``` diff --git a/src/tools/case.rs b/src/tools/case.rs index 5e7b611..24f844e 100644 --- a/src/tools/case.rs +++ b/src/tools/case.rs @@ -51,6 +51,11 @@ enum CaseCommand { /// Text to convert (use "-" for stdin) text: StringInput, }, + /// Convert text to kebab-case + Kebab { + /// Text to convert (use "-" for stdin) + text: StringInput, + }, } impl Tool for CaseTool { @@ -68,6 +73,7 @@ impl Tool for CaseTool { CaseCommand::Header { text } => to_header_case(text.as_ref()), CaseCommand::Sentence { text } => to_sentence_case(text.as_ref()), CaseCommand::Snake { text } => to_snake_case(text.as_ref()), + CaseCommand::Kebab { text } => to_kebab_case(text.as_ref()), }; Ok(Some(Output::JsonValue(serde_json::json!(result)))) @@ -153,6 +159,15 @@ fn to_snake_case(text: &str) -> String { .join("_") } +// kebab-case +fn to_kebab_case(text: &str) -> String { + split_words(text) + .iter() + .map(|word| word.to_lowercase()) + .collect::>() + .join("-") +} + // Splits a string into a sequence of words based on the whitespace, hyphens, // underscore and casing boundaries. fn split_words(text: &str) -> Vec { @@ -273,6 +288,15 @@ mod tests { assert_eq!(to_snake_case("hello-world"), "hello_world"); } + #[test] + fn test_kebab_case() { + assert_eq!(to_kebab_case("hello world"), "hello-world"); + assert_eq!(to_kebab_case("Hello World"), "hello-world"); + assert_eq!(to_kebab_case("helloWorld"), "hello-world"); + assert_eq!(to_kebab_case("HELLO_WORLD"), "hello-world"); + assert_eq!(to_kebab_case("hello-world"), "hello-world"); + } + #[test] fn test_split_words() { assert_eq!(split_words("hello world"), vec!["hello", "world"]);