Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ export(str_starts)
export(str_sub)
export(str_sub_all)
export(str_subset)
export(str_to_camel)
export(str_to_kebab)
export(str_to_lower)
export(str_to_sentence)
export(str_to_snake)
export(str_to_title)
export(str_to_upper)
export(str_trim)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# stringr (development version)

* New `str_to_camel()`, `str_to_snake()`, and `str_to_kebab()` for changing "programming" case (@librill, #573).
* All relevant stringr functions now preserve names (@jonovik, #575).
* New `vignette("locale-sensitive")` about locale sensitive functions (@kylieainslie, #404)
* New `str_ilike()` that follows the conventions of the SQL ILIKE operator (@edward-burn, #543).
Expand Down
65 changes: 65 additions & 0 deletions R/case.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,68 @@ str_to_sentence <- function(string, locale = "en") {
)
copy_names(string, out)
}


#' Convert between different types of programming case
#'
#' @description
#' * `str_to_camel()` converts to camel case, where the first letter of
#' each word is capitalized, with no separation between words. By default
#' the first letter of the first word is not capitalized.
#'
#' * `str_to_kebab()` converts to kebab case, where words are converted to
#' lower case and separated by dashes (`-`).
#'
#' * `str_to_snake()` converts to snake case, where words are converted to
#' lower case and separated by underscores (`_`).
#' @inheritParams str_to_lower
#' @export
#' @param first_upper Logical. Should the first letter be capitalized?
#' @examples
#' str_to_camel("my-variable")
#' str_to_camel("my-variable", first_upper = TRUE)
#'
#' str_to_snake("MyVariable")
#' str_to_kebab("MyVariable")
str_to_camel <- function(string, first_upper = FALSE) {
check_character(string)
check_bool(first_upper)

string <- string |>
to_words() |>
str_to_title() |>
str_remove_all(pattern = "\\s+")

if (!first_upper) {
str_sub(string, 1, 1) <- str_to_lower(str_sub(string, 1, 1))
}

string
}
#' @export
#' @rdname str_to_camel
str_to_snake <- function(string) {
check_character(string)
string |>
to_words() |>
str_replace_all(pattern = "\\s+", replacement = "_")
}
#' @export
#' @rdname str_to_camel
str_to_kebab <- function(string) {
check_character(string)
string |>
to_words() |>
str_replace_all(pattern = "\\s+", replacement = "-")
}

to_words <- function(string) {
string |>
str_replace_all("([a-z])([A-Z])", "\\1 \\2") |>
str_replace_all("([a-zA-Z])([0-9])", "\\1 \\2") |>
str_replace_all("([0-9])([a-zA-Z])", "\\1 \\2") |>
str_replace_all("([A-Z]+)([A-Z][a-z])", "\\1 \\2") |>
str_to_lower() |>
str_replace_all(pattern = "[:punct:]", replacement = " ") |>
str_trim()
}
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ reference:
- str_conv
- str_like
- str_replace_na
- str_to_camel
- str_view
- word

Expand Down
38 changes: 38 additions & 0 deletions man/str_to_camel.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 27 additions & 1 deletion tests/testthat/test-case.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ test_that("to_title creates one capital letter per word", {
})

test_that("to_sentence capitalizes just the first letter", {
x <- "This is a sentence."
expect_identical(str_to_sentence("a Test"), "A test")
})

Expand All @@ -20,3 +19,30 @@ test_that("case conversions preserve names", {
expect_equal(names(str_to_upper(x)), names(x))
expect_equal(names(str_to_title(x)), names(x))
})

# programming cases -----------------------------------------------------------

test_that("to_camel can control case of first argument", {
expect_equal(str_to_camel("my_variable"), "myVariable")
expect_equal(str_to_camel("my_variable", first_upper = TRUE), "MyVariable")
})

test_that("to_kebab converts to kebab case", {
expect_equal(str_to_kebab("myVariable"), "my-variable")
expect_equal(str_to_kebab("MyVariable"), "my-variable")
expect_equal(str_to_kebab("MyVariable1"), "my-variable-1")
})

test_that("to_snake converts to snake case", {
expect_equal(str_to_snake("myVariable"), "my_variable")
expect_equal(str_to_snake("MyVariable"), "my_variable")
expect_equal(str_to_snake("MyVariable1"), "my_variable_1")
})

test_that("to_words handles common compound cases", {
expect_equal(to_words("a_b"), "a b")
expect_equal(to_words("a-b"), "a b")
expect_equal(to_words("aB"), "a b")
expect_equal(to_words("a123b"), "a 123 b")
expect_equal(to_words("HTML"), "html")
})
Loading