diff --git a/CHANGELOG.md b/CHANGELOG.md index 34f85b0..a0c52b9 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ### v0.8.4 +* New lowercase command #183 (thanks @asvln) +* New uppercase command #183 (thanks @asvln) +* New camelcase command #183 (thanks @asvln) +* New snakecase command #183 (thanks @asvln) +* New kebabcase command #183 (thanks @asvln) * Docs - update --collection documentation for json_parse and json_encode commands #175 ### v0.8.3 (2021-07-10) diff --git a/Cargo.lock b/Cargo.lock index 2846658..c8f7eb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler" version = "1.0.2" @@ -162,6 +164,7 @@ dependencies = [ "fsio", "ftp", "glob", + "heck", "home", "ignore", "java-properties", @@ -346,6 +349,15 @@ dependencies = [ "regex 1.5.4", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -928,6 +940,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + [[package]] name = "unicode-xid" version = "0.2.2" diff --git a/docs/sdk.md b/docs/sdk.md index dd18a08..594e5a4 100644 --- a/docs/sdk.md +++ b/docs/sdk.md @@ -145,15 +145,19 @@ * [std::string::Base64Decode (base64_decode)](#std__string__Base64Decode) * [std::string::Base64Encode (base64_encode)](#std__string__Base64Encode) * [std::string::BytesToString (bytes_to_string)](#std__string__BytesToString) +* [std::string::CamelCase (camelcase)](#std__string__CamelCase) * [std::string::Concat (concat)](#std__string__Concat) * [std::string::Contains (contains)](#std__string__Contains) * [std::string::EndsWith (ends_with)](#std__string__EndsWith) * [std::string::Equals (equals, eq)](#std__string__Equals) * [std::string::IndexOf (indexof)](#std__string__IndexOf) * [std::string::IsEmpty (is_empty)](#std__string__IsEmpty) +* [std::string::KebabCase (kebabcase)](#std__string__KebabCase) * [std::string::LastIndexOf (last_indexof)](#std__string__LastIndexOf) * [std::string::Length (length, strlen)](#std__string__Length) +* [std::string::Lowercase (lowercase)](#std__string__Lowercase) * [std::string::Replace (replace)](#std__string__Replace) +* [std::string::SnakeCase (snakecase)](#std__string__SnakeCase) * [std::string::Split (split)](#std__string__Split) * [std::string::StartsWith (starts_with)](#std__string__StartsWith) * [std::string::StringToBytes (string_to_bytes)](#std__string__StringToBytes) @@ -161,6 +165,7 @@ * [std::string::Trim (trim)](#std__string__Trim) * [std::string::TrimEnd (trim_end)](#std__string__TrimEnd) * [std::string::TrimStart (trim_start)](#std__string__TrimStart) +* [std::string::Uppercase (uppercase)](#std__string__Uppercase) * [std::test::Assert (assert)](#std__test__Assert) * [std::test::AssertEquals (assert_eq)](#std__test__AssertEquals) * [std::test::AssertError (assert_error)](#std__test__AssertError) @@ -5455,6 +5460,35 @@ assert_eq ${text} "hello world" #### Aliases: bytes_to_string + +## std::string::CamelCase +```sh +var = camelcase text +``` + +Converts the provided string into camel case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = camelcase "hello, world!" +assert_eq ${string} "HelloWorld" +``` + + + +#### Aliases: +camelcase + ## std::string::Concat @@ -5657,6 +5691,35 @@ empty = is_empty ${value} #### Aliases: is_empty + +## std::string::KebabCase +```sh +var = kebobcase text +``` + +Converts the provided string into kebob case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = kebobcase "Hello, World!" +assert_eq ${string} "hello-world" +``` + + + +#### Aliases: +kebabcase + ## std::string::LastIndexOf ```sh @@ -5712,6 +5775,34 @@ len = length "Hello World" #### Aliases: length, strlen + +## std::string::Lowercase +```sh +var = lowercase text +``` + +Converts the provided string into lowercase. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = lowercase "Hello World" +assert_eq ${string} "hello world" +``` + + + +#### Aliases: +lowercase + ## std::string::Replace ```sh @@ -5743,6 +5834,35 @@ assert_eq ${updated} "my large stuff value with lots of stuff" #### Aliases: replace + +## std::string::SnakeCase +```sh +var = snakecase text +``` + +Converts the provided string into snake case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = snakecase "Hello, World!" +assert_eq ${string} "hello_world" +``` + + + +#### Aliases: +snakecase + ## std::string::Split ```sh @@ -5983,6 +6103,34 @@ trimmed = trim_start " some text " #### Aliases: trim_start + +## std::string::Uppercase +```sh +var = uppercase text +``` + +Converts the provided string into uppercase. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = uppercase "Hello World" +assert_eq ${string} "HELLO WORLD" +``` + + + +#### Aliases: +uppercase + ## std::test::Assert ```sh diff --git a/duckscript/src/lib.rs b/duckscript/src/lib.rs index 6359132..222d5a3 100755 --- a/duckscript/src/lib.rs +++ b/duckscript/src/lib.rs @@ -5,8 +5,8 @@ arithmetic_overflow, array_into_iter, asm_sub_register, + bad_asm_style, bindings_with_variant_name, - broken_intra_doc_links, cenum_impl_drop_cast, clashing_extern_declarations, coherence_leak_check, @@ -18,10 +18,13 @@ dead_code, deprecated, deprecated_in_future, + deref_nullptr, drop_bounds, + dyn_drop, ellipsis_inclusive_range_patterns, explicit_outlives_requirements, exported_private_dependencies, + forbidden_lint_groups, function_item_references, ill_formed_attribute_input, illegal_floating_point_literal_pattern, @@ -30,18 +33,20 @@ incomplete_features, incomplete_include, indirect_structural_match, + ineffective_unstable_trait_impl, inline_no_sanitize, - invalid_codeblock_attributes, + invalid_doc_attributes, invalid_type_param_default, invalid_value, irrefutable_let_patterns, keyword_idents, + large_assignments, late_bound_lifetime_arguments, + legacy_derive_helpers, macro_expanded_macro_exports_accessed_by_absolute_paths, meta_variable_misuse, missing_abi, missing_copy_implementations, - missing_crate_level_docs, missing_docs, missing_fragment_specifier, mixed_script_confusables, @@ -50,26 +55,29 @@ no_mangle_const_items, no_mangle_generic_items, non_ascii_idents, - non_autolinks, non_camel_case_types, + non_fmt_panics, non_shorthand_field_patterns, non_snake_case, non_upper_case_globals, nontrivial_structural_match, + noop_method_call, order_dependent_trait_objects, overflowing_literals, overlapping_range_endpoints, - panic_fmt, path_statements, patterns_in_fns_without_body, pointer_structural_match, - private_doc_tests, private_in_public, - private_intra_doc_links, + proc_macro_back_compat, proc_macro_derive_resolution_fallback, pub_use_of_private_extern_crate, redundant_semicolons, - safe_packed_borrows, + rust_2021_incompatible_closure_captures, + rust_2021_incompatible_or_patterns, + rust_2021_prefixes_incompatible_syntax, + rust_2021_prelude_collisions, + semicolon_in_expressions_from_macros, soft_unstable, stable_features, temporary_cstring_as_ptr, @@ -89,8 +97,10 @@ unreachable_patterns, unreachable_pub, unsafe_code, + unsafe_op_in_unsafe_fn, unstable_features, unstable_name_collisions, + unsupported_calling_conventions, unsupported_naked_functions, unused_allocation, unused_assignments, @@ -112,17 +122,13 @@ unused_qualifications, unused_unsafe, unused_variables, - useless_deprecated, - where_clauses_object_safety, - while_true + useless_deprecated )] #![warn(macro_use_extern_crate, unknown_lints)] #![allow( bare_trait_objects, box_pointers, elided_lifetimes_in_paths, - invalid_html_tags, - missing_doc_code_examples, missing_debug_implementations, single_use_lifetimes, unused_results, diff --git a/duckscript_cli/src/main.rs b/duckscript_cli/src/main.rs index 12bb785..f4681d7 100755 --- a/duckscript_cli/src/main.rs +++ b/duckscript_cli/src/main.rs @@ -5,8 +5,8 @@ arithmetic_overflow, array_into_iter, asm_sub_register, + bad_asm_style, bindings_with_variant_name, - broken_intra_doc_links, cenum_impl_drop_cast, clashing_extern_declarations, coherence_leak_check, @@ -18,10 +18,13 @@ dead_code, deprecated, deprecated_in_future, + deref_nullptr, drop_bounds, + dyn_drop, ellipsis_inclusive_range_patterns, explicit_outlives_requirements, exported_private_dependencies, + forbidden_lint_groups, function_item_references, ill_formed_attribute_input, illegal_floating_point_literal_pattern, @@ -30,18 +33,20 @@ incomplete_features, incomplete_include, indirect_structural_match, + ineffective_unstable_trait_impl, inline_no_sanitize, - invalid_codeblock_attributes, + invalid_doc_attributes, invalid_type_param_default, invalid_value, irrefutable_let_patterns, keyword_idents, + large_assignments, late_bound_lifetime_arguments, + legacy_derive_helpers, macro_expanded_macro_exports_accessed_by_absolute_paths, meta_variable_misuse, missing_abi, missing_copy_implementations, - missing_crate_level_docs, missing_docs, missing_fragment_specifier, mixed_script_confusables, @@ -50,26 +55,29 @@ no_mangle_const_items, no_mangle_generic_items, non_ascii_idents, - non_autolinks, non_camel_case_types, + non_fmt_panics, non_shorthand_field_patterns, non_snake_case, non_upper_case_globals, nontrivial_structural_match, + noop_method_call, order_dependent_trait_objects, overflowing_literals, overlapping_range_endpoints, - panic_fmt, path_statements, patterns_in_fns_without_body, pointer_structural_match, - private_doc_tests, private_in_public, - private_intra_doc_links, + proc_macro_back_compat, proc_macro_derive_resolution_fallback, pub_use_of_private_extern_crate, redundant_semicolons, - safe_packed_borrows, + rust_2021_incompatible_closure_captures, + rust_2021_incompatible_or_patterns, + rust_2021_prefixes_incompatible_syntax, + rust_2021_prelude_collisions, + semicolon_in_expressions_from_macros, soft_unstable, stable_features, temporary_cstring_as_ptr, @@ -89,8 +97,10 @@ unreachable_patterns, unreachable_pub, unsafe_code, + unsafe_op_in_unsafe_fn, unstable_features, unstable_name_collisions, + unsupported_calling_conventions, unsupported_naked_functions, unused_allocation, unused_assignments, @@ -112,17 +122,13 @@ unused_qualifications, unused_unsafe, unused_variables, - useless_deprecated, - where_clauses_object_safety, - while_true + useless_deprecated )] #![warn(macro_use_extern_crate, unknown_lints)] #![allow( bare_trait_objects, box_pointers, elided_lifetimes_in_paths, - invalid_html_tags, - missing_doc_code_examples, missing_debug_implementations, single_use_lifetimes, unused_results, diff --git a/duckscript_sdk/Cargo.toml b/duckscript_sdk/Cargo.toml index 8f2c293..96a6870 100644 --- a/duckscript_sdk/Cargo.toml +++ b/duckscript_sdk/Cargo.toml @@ -31,6 +31,7 @@ fs_extra = "^1" fsio = { version = "^0.2", features = ["temp-path"] } ftp = "^3" glob = "^0.3" +heck = "^0.3" home = "^0.5" ignore = "^0.4" java-properties = "^1" diff --git a/duckscript_sdk/src/lib.rs b/duckscript_sdk/src/lib.rs index e27c822..e0fa31e 100755 --- a/duckscript_sdk/src/lib.rs +++ b/duckscript_sdk/src/lib.rs @@ -5,8 +5,8 @@ arithmetic_overflow, array_into_iter, asm_sub_register, + bad_asm_style, bindings_with_variant_name, - broken_intra_doc_links, cenum_impl_drop_cast, clashing_extern_declarations, coherence_leak_check, @@ -18,10 +18,13 @@ dead_code, deprecated, deprecated_in_future, + deref_nullptr, drop_bounds, + dyn_drop, ellipsis_inclusive_range_patterns, explicit_outlives_requirements, exported_private_dependencies, + forbidden_lint_groups, function_item_references, ill_formed_attribute_input, illegal_floating_point_literal_pattern, @@ -30,18 +33,20 @@ incomplete_features, incomplete_include, indirect_structural_match, + ineffective_unstable_trait_impl, inline_no_sanitize, - invalid_codeblock_attributes, + invalid_doc_attributes, invalid_type_param_default, invalid_value, irrefutable_let_patterns, keyword_idents, + large_assignments, late_bound_lifetime_arguments, + legacy_derive_helpers, macro_expanded_macro_exports_accessed_by_absolute_paths, meta_variable_misuse, missing_abi, missing_copy_implementations, - missing_crate_level_docs, missing_docs, missing_fragment_specifier, mixed_script_confusables, @@ -50,26 +55,29 @@ no_mangle_const_items, no_mangle_generic_items, non_ascii_idents, - non_autolinks, non_camel_case_types, + non_fmt_panics, non_shorthand_field_patterns, non_snake_case, non_upper_case_globals, nontrivial_structural_match, + noop_method_call, order_dependent_trait_objects, overflowing_literals, overlapping_range_endpoints, - panic_fmt, path_statements, patterns_in_fns_without_body, pointer_structural_match, - private_doc_tests, private_in_public, - private_intra_doc_links, + proc_macro_back_compat, proc_macro_derive_resolution_fallback, pub_use_of_private_extern_crate, redundant_semicolons, - safe_packed_borrows, + rust_2021_incompatible_closure_captures, + rust_2021_incompatible_or_patterns, + rust_2021_prefixes_incompatible_syntax, + rust_2021_prelude_collisions, + semicolon_in_expressions_from_macros, soft_unstable, stable_features, temporary_cstring_as_ptr, @@ -89,8 +97,10 @@ unreachable_patterns, unreachable_pub, unsafe_code, + unsafe_op_in_unsafe_fn, unstable_features, unstable_name_collisions, + unsupported_calling_conventions, unsupported_naked_functions, unused_allocation, unused_assignments, @@ -112,17 +122,13 @@ unused_qualifications, unused_unsafe, unused_variables, - useless_deprecated, - where_clauses_object_safety, - while_true + useless_deprecated )] #![warn(macro_use_extern_crate, unknown_lints)] #![allow( bare_trait_objects, box_pointers, elided_lifetimes_in_paths, - invalid_html_tags, - missing_doc_code_examples, missing_debug_implementations, single_use_lifetimes, unused_results, diff --git a/duckscript_sdk/src/sdk/std/string/camelcase/help.md b/duckscript_sdk/src/sdk/std/string/camelcase/help.md new file mode 100644 index 0000000..b3a2536 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/camelcase/help.md @@ -0,0 +1,22 @@ +```sh +var = camelcase text +``` + +Converts the provided string into camel case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = camelcase "hello, world!" +assert_eq ${string} "HelloWorld" +``` + diff --git a/duckscript_sdk/src/sdk/std/string/camelcase/mod.rs b/duckscript_sdk/src/sdk/std/string/camelcase/mod.rs new file mode 100755 index 0000000..ce65638 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/camelcase/mod.rs @@ -0,0 +1,44 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult}; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +#[derive(Clone)] +pub(crate) struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "CamelCase") + } + + fn aliases(&self) -> Vec { + vec!["camelcase".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn run(&self, arguments: Vec) -> CommandResult { + if arguments.is_empty() { + CommandResult::Error("No arguments provided.".to_string()) + } else { + let value = heck::CamelCase::to_camel_case(arguments[0].as_str()); + CommandResult::Continue(Some(value)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/camelcase/mod_test.rs b/duckscript_sdk/src/sdk/std/string/camelcase/mod_test.rs new file mode 100644 index 0000000..7e1d33f --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/camelcase/mod_test.rs @@ -0,0 +1,22 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = camelcase", "out"); +} + +#[test] +fn run_single_argument() { + test::run_script_and_validate( + vec![create("")], + r#"out = camelcase "hello, world!""#, + CommandValidation::Match("out".to_string(), "HelloWorld".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/string/kebabcase/help.md b/duckscript_sdk/src/sdk/std/string/kebabcase/help.md new file mode 100644 index 0000000..df4a529 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/kebabcase/help.md @@ -0,0 +1,22 @@ +```sh +var = kebobcase text +``` + +Converts the provided string into kebob case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = kebobcase "Hello, World!" +assert_eq ${string} "hello-world" +``` + diff --git a/duckscript_sdk/src/sdk/std/string/kebabcase/mod.rs b/duckscript_sdk/src/sdk/std/string/kebabcase/mod.rs new file mode 100755 index 0000000..db38eb3 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/kebabcase/mod.rs @@ -0,0 +1,44 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult}; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +#[derive(Clone)] +pub(crate) struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "KebabCase") + } + + fn aliases(&self) -> Vec { + vec!["kebabcase".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn run(&self, arguments: Vec) -> CommandResult { + if arguments.is_empty() { + CommandResult::Error("No arguments provided.".to_string()) + } else { + let value = heck::KebabCase::to_kebab_case(arguments[0].as_str()); + CommandResult::Continue(Some(value)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/kebabcase/mod_test.rs b/duckscript_sdk/src/sdk/std/string/kebabcase/mod_test.rs new file mode 100644 index 0000000..f09e511 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/kebabcase/mod_test.rs @@ -0,0 +1,22 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = kebabcase", "out"); +} + +#[test] +fn run_single_argument() { + test::run_script_and_validate( + vec![create("")], + r#"out = kebabcase "Hello, World!""#, + CommandValidation::Match("out".to_string(), "hello-world".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/string/lowercase/help.md b/duckscript_sdk/src/sdk/std/string/lowercase/help.md new file mode 100644 index 0000000..a6a5c85 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/lowercase/help.md @@ -0,0 +1,21 @@ +```sh +var = lowercase text +``` + +Converts the provided string into lowercase. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = lowercase "Hello World" +assert_eq ${string} "hello world" +``` + diff --git a/duckscript_sdk/src/sdk/std/string/lowercase/mod.rs b/duckscript_sdk/src/sdk/std/string/lowercase/mod.rs new file mode 100755 index 0000000..2c3283d --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/lowercase/mod.rs @@ -0,0 +1,44 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult}; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +#[derive(Clone)] +pub(crate) struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "Lowercase") + } + + fn aliases(&self) -> Vec { + vec!["lowercase".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn run(&self, arguments: Vec) -> CommandResult { + if arguments.is_empty() { + CommandResult::Error("No arguments provided.".to_string()) + } else { + let value = arguments[0].to_lowercase(); + CommandResult::Continue(Some(value)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/lowercase/mod_test.rs b/duckscript_sdk/src/sdk/std/string/lowercase/mod_test.rs new file mode 100644 index 0000000..e55fb3d --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/lowercase/mod_test.rs @@ -0,0 +1,22 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = lowercase", "out"); +} + +#[test] +fn run_single_argument() { + test::run_script_and_validate( + vec![create("")], + r#"out = lowercase "Hello World""#, + CommandValidation::Match("out".to_string(), "hello world".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/string/mod.rs b/duckscript_sdk/src/sdk/std/string/mod.rs index 3ebe21d..7b38a0c 100755 --- a/duckscript_sdk/src/sdk/std/string/mod.rs +++ b/duckscript_sdk/src/sdk/std/string/mod.rs @@ -2,15 +2,19 @@ mod base64; mod base64_decode; mod base64_encode; pub(crate) mod bytes_to_string; +mod camelcase; mod concat; mod contains; mod ends_with; pub(crate) mod equals; mod indexof; mod is_empty; +mod kebabcase; mod last_indexof; mod length; +mod lowercase; mod replace; +mod snakecase; mod split; mod starts_with; pub(crate) mod string_to_bytes; @@ -18,6 +22,7 @@ mod substring; mod trim; mod trim_end; mod trim_start; +mod uppercase; use crate::utils::pckg; use duckscript::types::command::Commands; @@ -32,15 +37,19 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr commands.set(base64_decode::create(&package))?; commands.set(base64_encode::create(&package))?; commands.set(bytes_to_string::create(&package))?; + commands.set(camelcase::create(&package))?; commands.set(concat::create(&package)?)?; commands.set(contains::create(&package))?; commands.set(ends_with::create(&package))?; commands.set(equals::create(&package))?; commands.set(indexof::create(&package))?; commands.set(is_empty::create(&package))?; + commands.set(kebabcase::create(&package))?; commands.set(last_indexof::create(&package))?; commands.set(length::create(&package))?; + commands.set(lowercase::create(&package))?; commands.set(replace::create(&package))?; + commands.set(snakecase::create(&package))?; commands.set(split::create(&package))?; commands.set(starts_with::create(&package))?; commands.set(string_to_bytes::create(&package))?; @@ -48,6 +57,7 @@ pub(crate) fn load(commands: &mut Commands, parent: &str) -> Result<(), ScriptEr commands.set(trim::create(&package))?; commands.set(trim_start::create(&package))?; commands.set(trim_end::create(&package))?; + commands.set(uppercase::create(&package))?; Ok(()) } diff --git a/duckscript_sdk/src/sdk/std/string/snakecase/help.md b/duckscript_sdk/src/sdk/std/string/snakecase/help.md new file mode 100644 index 0000000..d12c006 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/snakecase/help.md @@ -0,0 +1,22 @@ +```sh +var = snakecase text +``` + +Converts the provided string into snake case. +All non-alphanumeric characters are ignored. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = snakecase "Hello, World!" +assert_eq ${string} "hello_world" +``` + diff --git a/duckscript_sdk/src/sdk/std/string/snakecase/mod.rs b/duckscript_sdk/src/sdk/std/string/snakecase/mod.rs new file mode 100755 index 0000000..2f31d4e --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/snakecase/mod.rs @@ -0,0 +1,44 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult}; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +#[derive(Clone)] +pub(crate) struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "SnakeCase") + } + + fn aliases(&self) -> Vec { + vec!["snakecase".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn run(&self, arguments: Vec) -> CommandResult { + if arguments.is_empty() { + CommandResult::Error("No arguments provided.".to_string()) + } else { + let value = heck::SnakeCase::to_snake_case(arguments[0].as_str()); + CommandResult::Continue(Some(value)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/snakecase/mod_test.rs b/duckscript_sdk/src/sdk/std/string/snakecase/mod_test.rs new file mode 100644 index 0000000..0bcfaa9 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/snakecase/mod_test.rs @@ -0,0 +1,22 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = snakecase", "out"); +} + +#[test] +fn run_single_argument() { + test::run_script_and_validate( + vec![create("")], + r#"out = snakecase "Hello, World!""#, + CommandValidation::Match("out".to_string(), "hello_world".to_string()), + ); +} diff --git a/duckscript_sdk/src/sdk/std/string/uppercase/help.md b/duckscript_sdk/src/sdk/std/string/uppercase/help.md new file mode 100644 index 0000000..f261545 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/uppercase/help.md @@ -0,0 +1,21 @@ +```sh +var = uppercase text +``` + +Converts the provided string into uppercase. + +#### Parameters + +The string to convert. + +#### Return Value + +The converted string. + +#### Examples + +```sh +string = uppercase "Hello World" +assert_eq ${string} "HELLO WORLD" +``` + diff --git a/duckscript_sdk/src/sdk/std/string/uppercase/mod.rs b/duckscript_sdk/src/sdk/std/string/uppercase/mod.rs new file mode 100755 index 0000000..11d2a2f --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/uppercase/mod.rs @@ -0,0 +1,44 @@ +use crate::utils::pckg; +use duckscript::types::command::{Command, CommandResult}; + +#[cfg(test)] +#[path = "./mod_test.rs"] +mod mod_test; + +#[derive(Clone)] +pub(crate) struct CommandImpl { + package: String, +} + +impl Command for CommandImpl { + fn name(&self) -> String { + pckg::concat(&self.package, "Uppercase") + } + + fn aliases(&self) -> Vec { + vec!["uppercase".to_string()] + } + + fn help(&self) -> String { + include_str!("help.md").to_string() + } + + fn clone_and_box(&self) -> Box { + Box::new((*self).clone()) + } + + fn run(&self, arguments: Vec) -> CommandResult { + if arguments.is_empty() { + CommandResult::Error("No arguments provided.".to_string()) + } else { + let value = arguments[0].to_uppercase(); + CommandResult::Continue(Some(value)) + } + } +} + +pub(crate) fn create(package: &str) -> Box { + Box::new(CommandImpl { + package: package.to_string(), + }) +} diff --git a/duckscript_sdk/src/sdk/std/string/uppercase/mod_test.rs b/duckscript_sdk/src/sdk/std/string/uppercase/mod_test.rs new file mode 100644 index 0000000..bfd6905 --- /dev/null +++ b/duckscript_sdk/src/sdk/std/string/uppercase/mod_test.rs @@ -0,0 +1,22 @@ +use super::*; +use crate::test; +use crate::test::CommandValidation; + +#[test] +fn common_functions() { + test::test_common_command_functions(create("")); +} + +#[test] +fn run_no_args() { + test::run_script_and_error(vec![create("")], "out = uppercase", "out"); +} + +#[test] +fn run_single_argument() { + test::run_script_and_validate( + vec![create("")], + r#"out = uppercase "hello world""#, + CommandValidation::Match("out".to_string(), "HELLO WORLD".to_string()), + ); +} diff --git a/duckscript_sdk/src/test/mod.rs b/duckscript_sdk/src/test/mod.rs index c3162bd..dde918e 100644 --- a/duckscript_sdk/src/test/mod.rs +++ b/duckscript_sdk/src/test/mod.rs @@ -244,7 +244,7 @@ pub(crate) fn run_script_and_error( context } - Err(error) => panic!(error.to_string()), + Err(error) => panic!("{}", error.to_string()), } } @@ -313,7 +313,7 @@ pub(crate) fn run_script_and_validate( context } - Err(error) => panic!(error.to_string()), + Err(error) => panic!("{}", error.to_string()), } } diff --git a/test/std/string/camelcase_test.ds b/test/std/string/camelcase_test.ds new file mode 100644 index 0000000..f350fc9 --- /dev/null +++ b/test/std/string/camelcase_test.ds @@ -0,0 +1,12 @@ + +fn test_without_symbols + output = camelcase "Hello world 22" + + assert_eq ${output} "HelloWorld22" +end + +fn test_with_symbols + output = camelcase "Hello!@#$% world^&*()[]{}22" + + assert_eq ${output} "HelloWorld22" +end diff --git a/test/std/string/kebabcase_test.ds b/test/std/string/kebabcase_test.ds new file mode 100644 index 0000000..efde724 --- /dev/null +++ b/test/std/string/kebabcase_test.ds @@ -0,0 +1,12 @@ + +fn test_without_symbols + output = kebabcase "Hello World 22" + + assert_eq ${output} "hello-world-22" +end + +fn test_with_symbols + output = kebabcase "hello!@#$% world^&*()[]{}22" + + assert_eq ${output} "hello-world-22" +end diff --git a/test/std/string/lowercase_test.ds b/test/std/string/lowercase_test.ds new file mode 100644 index 0000000..f1521cf --- /dev/null +++ b/test/std/string/lowercase_test.ds @@ -0,0 +1,6 @@ + +fn test_conversion + output = lowercase "Hello World" + + assert_eq ${output} "hello world" +end diff --git a/test/std/string/snakecase_test.ds b/test/std/string/snakecase_test.ds new file mode 100644 index 0000000..19e6ef7 --- /dev/null +++ b/test/std/string/snakecase_test.ds @@ -0,0 +1,12 @@ + +fn test_without_symbols + output = snakecase "Hello world 22" + + assert_eq ${output} "hello_world_22" +end + +fn test_with_symbols + output = snakecase "Hello!@#$% world^&*()[]{}22" + + assert_eq ${output} "hello_world_22" +end diff --git a/test/std/string/uppercase_test.ds b/test/std/string/uppercase_test.ds new file mode 100644 index 0000000..da6b65f --- /dev/null +++ b/test/std/string/uppercase_test.ds @@ -0,0 +1,6 @@ + +fn test_conversion + output = uppercase "Hello World" + + assert_eq ${output} "HELLO WORLD" +end