From de85c684706b3d37461a036b2fc555fa2ecec913 Mon Sep 17 00:00:00 2001 From: chrimaho Date: Sat, 10 Jun 2023 17:11:02 +1000 Subject: [PATCH 1/3] Add new `str_dedent` function --- NAMESPACE | 143 ++++++++++++++++++----------------- R/remove.R | 57 ++++++++++++++ _pkgdown.yml | 1 + tests/testthat/test-remove.R | 14 ++++ 4 files changed, 144 insertions(+), 71 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 07f842ab..2c921be3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,75 +1,76 @@ # Generated by roxygen2: do not edit by hand -S3method("[",stringr_pattern) -S3method("[",stringr_view) -S3method(print,stringr_view) -S3method(type,character) -S3method(type,default) -S3method(type,stringr_boundary) -S3method(type,stringr_coll) -S3method(type,stringr_fixed) -S3method(type,stringr_regex) -export("%>%") -export("str_sub<-") -export(boundary) -export(coll) -export(fixed) -export(invert_match) -export(regex) -export(str_c) -export(str_conv) -export(str_count) -export(str_detect) -export(str_dup) -export(str_ends) -export(str_equal) -export(str_escape) -export(str_extract) -export(str_extract_all) -export(str_flatten) -export(str_flatten_comma) -export(str_glue) -export(str_glue_data) -export(str_interp) -export(str_length) -export(str_like) -export(str_locate) -export(str_locate_all) -export(str_match) -export(str_match_all) -export(str_order) -export(str_pad) -export(str_rank) -export(str_remove) -export(str_remove_all) -export(str_replace) -export(str_replace_all) -export(str_replace_na) -export(str_sort) -export(str_split) -export(str_split_1) -export(str_split_fixed) -export(str_split_i) -export(str_squish) -export(str_starts) -export(str_sub) -export(str_sub_all) -export(str_subset) -export(str_to_lower) -export(str_to_sentence) -export(str_to_title) -export(str_to_upper) -export(str_trim) -export(str_trunc) -export(str_unique) -export(str_view) -export(str_view_all) -export(str_which) -export(str_width) -export(str_wrap) -export(word) +S3method("[", stringr_pattern) +S3method("[", stringr_view) +S3method(print, stringr_view) +S3method(type, character) +S3method(type,default ) +S3method(type, stringr_boundary) +S3method(type, stringr_coll) +S3method(type, stringr_fixed) +S3method(type, stringr_regex) +export ("%>%") +export ("str_sub<-") +export (boundary) +export (coll) +export (fixed) +export (invert_match) +export (regex) +export (str_c) +export (str_conv) +export (str_count) +export (str_detect) +export (str_dedent) +export (str_dup) +export (str_ends) +export (str_equal) +export (str_escape) +export (str_extract) +export (str_extract_all) +export (str_flatten) +export (str_flatten_comma) +export (str_glue) +export (str_glue_data) +export (str_interp) +export (str_length) +export (str_like) +export (str_locate) +export (str_locate_all) +export (str_match) +export (str_match_all) +export (str_order) +export (str_pad) +export (str_rank) +export (str_remove) +export (str_remove_all) +export (str_replace) +export (str_replace_all) +export (str_replace_na) +export (str_sort) +export (str_split) +export (str_split_1) +export (str_split_fixed) +export (str_split_i) +export (str_squish) +export (str_starts) +export (str_sub) +export (str_sub_all) +export (str_subset) +export (str_to_lower) +export (str_to_sentence) +export (str_to_title) +export (str_to_upper) +export (str_trim) +export (str_trunc) +export (str_unique) +export (str_view) +export (str_view_all) +export (str_which) +export (str_width) +export (str_wrap) +export (word) import(rlang) import(stringi) -importFrom(glue,glue) -importFrom(lifecycle,deprecated) -importFrom(magrittr,"%>%") +importFrom(glue, glue) +importFrom(lifecycle, deprecated) +importFrom(magrittr, "%>%") diff --git a/R/remove.R b/R/remove.R index a943cede..f2292cff 100644 --- a/R/remove.R +++ b/R/remove.R @@ -19,3 +19,60 @@ str_remove <- function(string, pattern) { str_remove_all <- function(string, pattern) { str_replace_all(string, pattern, "") } + + +#' @title str_dedent +#' @description Remove common leading indentation from strings +#' @note This function is similar to Python's `dedent` function in the `textwrap` library. It removes common leading indentation from strings. +#' @param text `character` The input string or character vector. +#' @return The input string or character vector with leading indentation removed. +#' @author chrimaho +#' @importFrom stringr str_replace_all +#' @importFrom stringr str_extract +#' @importFrom stringr regex +#' @examples +#' dedent(" Hello\n World") +#' # Expected Output: "Hello\n World" +#' +#' dedent(" Line 1\n Line 2\n Line 3") +#' # Expected Output: "Line 1\nLine 2\nLine 3" +#' +#' dedent("No indentation") +#' # Expected Output: "No indentation" +#' +#' dedent( +#' " +#' this +#' is +#' a +#' test +#' " +#' ) +#' # Expected Output: "\nthis\nis\n a\ntest\n" +#' @rdname str_dedent +#' @export +str_dedent <- function(text) { + lines <- strsplit(text, "\n", fixed=TRUE)[[1]] + + # Determine the common leading whitespace + leading_ws <- NULL + for (line in lines) { + if (str_extract(line, regex("^\\s*$"))) { + next + } + leading_ws <- str_extract(line, regex("^\\s+")) + break + } + + if (is.null(leading_ws)) { + return(text) + } + + # Remove the common leading whitespace from each line + dedented_lines <- str_replace_all(lines, regex(sprintf("^%s", leading_ws)), "") + + # Combine the lines back into a single string + dedented_text <- paste(dedented_lines, collapse = "\n") + + return(dedented_text) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index b0229c94..97497a25 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -21,6 +21,7 @@ reference: - subtitle: String contents: - str_count + - str_dedent - str_detect - str_escape - str_extract diff --git a/tests/testthat/test-remove.R b/tests/testthat/test-remove.R index 04f6aa52..ba3b650d 100644 --- a/tests/testthat/test-remove.R +++ b/tests/testthat/test-remove.R @@ -2,3 +2,17 @@ test_that("succesfully wraps str_replace_all", { expect_equal(str_remove_all("abababa", "ba"), "a") expect_equal(str_remove("abababa", "ba"), "ababa") }) + +test_that("successfully dedent str_dedent",{ + expect_equal(dedent(" Hello\n World"), "Hello\n World") + expect_equal(dedent(" Line 1\n Line 2\n Line 3"), "Line 1\nLine 2\nLine 3") + expect_equal(dedent("No indentation"), "No indentation") + expect_equal(dedent( + " + this + is + a + test + " + ), "\nthis\nis\n a\ntest\n") +}) \ No newline at end of file From 60e6fe13522b7bbf611dfb4aa95936d7bbbbc416 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 16 Jul 2024 07:40:26 -0500 Subject: [PATCH 2/3] Re-document --- NAMESPACE | 144 +++++++++++++++++++++++----------------------- man/str_dedent.Rd | 43 ++++++++++++++ 2 files changed, 115 insertions(+), 72 deletions(-) create mode 100644 man/str_dedent.Rd diff --git a/NAMESPACE b/NAMESPACE index 2c921be3..60742f92 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,76 +1,76 @@ # Generated by roxygen2: do not edit by hand -S3method("[", stringr_pattern) -S3method("[", stringr_view) -S3method(print, stringr_view) -S3method(type, character) -S3method(type,default ) -S3method(type, stringr_boundary) -S3method(type, stringr_coll) -S3method(type, stringr_fixed) -S3method(type, stringr_regex) -export ("%>%") -export ("str_sub<-") -export (boundary) -export (coll) -export (fixed) -export (invert_match) -export (regex) -export (str_c) -export (str_conv) -export (str_count) -export (str_detect) -export (str_dedent) -export (str_dup) -export (str_ends) -export (str_equal) -export (str_escape) -export (str_extract) -export (str_extract_all) -export (str_flatten) -export (str_flatten_comma) -export (str_glue) -export (str_glue_data) -export (str_interp) -export (str_length) -export (str_like) -export (str_locate) -export (str_locate_all) -export (str_match) -export (str_match_all) -export (str_order) -export (str_pad) -export (str_rank) -export (str_remove) -export (str_remove_all) -export (str_replace) -export (str_replace_all) -export (str_replace_na) -export (str_sort) -export (str_split) -export (str_split_1) -export (str_split_fixed) -export (str_split_i) -export (str_squish) -export (str_starts) -export (str_sub) -export (str_sub_all) -export (str_subset) -export (str_to_lower) -export (str_to_sentence) -export (str_to_title) -export (str_to_upper) -export (str_trim) -export (str_trunc) -export (str_unique) -export (str_view) -export (str_view_all) -export (str_which) -export (str_width) -export (str_wrap) -export (word) +S3method("[",stringr_pattern) +S3method("[",stringr_view) +S3method(print,stringr_view) +S3method(type,character) +S3method(type,default) +S3method(type,stringr_boundary) +S3method(type,stringr_coll) +S3method(type,stringr_fixed) +S3method(type,stringr_regex) +export("%>%") +export("str_sub<-") +export(boundary) +export(coll) +export(fixed) +export(invert_match) +export(regex) +export(str_c) +export(str_conv) +export(str_count) +export(str_dedent) +export(str_detect) +export(str_dup) +export(str_ends) +export(str_equal) +export(str_escape) +export(str_extract) +export(str_extract_all) +export(str_flatten) +export(str_flatten_comma) +export(str_glue) +export(str_glue_data) +export(str_interp) +export(str_length) +export(str_like) +export(str_locate) +export(str_locate_all) +export(str_match) +export(str_match_all) +export(str_order) +export(str_pad) +export(str_rank) +export(str_remove) +export(str_remove_all) +export(str_replace) +export(str_replace_all) +export(str_replace_na) +export(str_sort) +export(str_split) +export(str_split_1) +export(str_split_fixed) +export(str_split_i) +export(str_squish) +export(str_starts) +export(str_sub) +export(str_sub_all) +export(str_subset) +export(str_to_lower) +export(str_to_sentence) +export(str_to_title) +export(str_to_upper) +export(str_trim) +export(str_trunc) +export(str_unique) +export(str_view) +export(str_view_all) +export(str_which) +export(str_width) +export(str_wrap) +export(word) import(rlang) import(stringi) -importFrom(glue, glue) -importFrom(lifecycle, deprecated) -importFrom(magrittr, "%>%") +importFrom(glue,glue) +importFrom(lifecycle,deprecated) +importFrom(magrittr,"%>%") diff --git a/man/str_dedent.Rd b/man/str_dedent.Rd new file mode 100644 index 00000000..0eefd1a5 --- /dev/null +++ b/man/str_dedent.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/remove.R +\name{str_dedent} +\alias{str_dedent} +\title{str_dedent} +\usage{ +str_dedent(text) +} +\arguments{ +\item{text}{\code{character} The input string or character vector.} +} +\value{ +The input string or character vector with leading indentation removed. +} +\description{ +Remove common leading indentation from strings +} +\note{ +This function is similar to Python's \code{dedent} function in the \code{textwrap} library. It removes common leading indentation from strings. +} +\examples{ +dedent(" Hello\n World") +# Expected Output: "Hello\n World" + +dedent(" Line 1\n Line 2\n Line 3") +# Expected Output: "Line 1\nLine 2\nLine 3" + +dedent("No indentation") +# Expected Output: "No indentation" + +dedent( + " + this + is + a + test + " +) +# Expected Output: "\nthis\nis\n a\ntest\n" +} +\author{ +chrimaho +} From a8607e93d1448302b4e4c9789d07a7eb610f33cd Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 16 Jul 2024 07:48:38 -0500 Subject: [PATCH 3/3] Polish implementation --- R/remove.R | 48 +++++++++++++++++------------------- man/str_dedent.Rd | 23 ++++++----------- tests/testthat/test-remove.R | 10 ++++---- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/R/remove.R b/R/remove.R index f2292cff..80825f45 100644 --- a/R/remove.R +++ b/R/remove.R @@ -21,26 +21,22 @@ str_remove_all <- function(string, pattern) { } -#' @title str_dedent -#' @description Remove common leading indentation from strings -#' @note This function is similar to Python's `dedent` function in the `textwrap` library. It removes common leading indentation from strings. +#' Remove common leading indentation from strings +#' +#' This function is similar to Python's `dedent` function in the `textwrap` +#' library. It removes common leading indentation from strings. +#' #' @param text `character` The input string or character vector. #' @return The input string or character vector with leading indentation removed. -#' @author chrimaho -#' @importFrom stringr str_replace_all -#' @importFrom stringr str_extract -#' @importFrom stringr regex +#' @export #' @examples -#' dedent(" Hello\n World") -#' # Expected Output: "Hello\n World" +#' str_dedent(" Hello\n World") #' -#' dedent(" Line 1\n Line 2\n Line 3") -#' # Expected Output: "Line 1\nLine 2\nLine 3" +#' str_dedent(" Line 1\n Line 2\n Line 3") #' -#' dedent("No indentation") -#' # Expected Output: "No indentation" +#' str_dedent("No indentation") #' -#' dedent( +#' str_dedent( #' " #' this #' is @@ -48,20 +44,22 @@ str_remove_all <- function(string, pattern) { #' test #' " #' ) -#' # Expected Output: "\nthis\nis\n a\ntest\n" -#' @rdname str_dedent -#' @export str_dedent <- function(text) { - lines <- strsplit(text, "\n", fixed=TRUE)[[1]] + lines <- str_split_1(text, fixed("\n")) # Determine the common leading whitespace - leading_ws <- NULL + leading_ws <- "" for (line in lines) { - if (str_extract(line, regex("^\\s*$"))) { + # Ignore completely blank lines + if (str_detect(line, "^\\s*$")) { next } - leading_ws <- str_extract(line, regex("^\\s+")) - break + + ws <- str_extract(line, "^\\s+") + if (!is.na(ws)) { + leading_ws <- ws + break + } } if (is.null(leading_ws)) { @@ -69,10 +67,8 @@ str_dedent <- function(text) { } # Remove the common leading whitespace from each line - dedented_lines <- str_replace_all(lines, regex(sprintf("^%s", leading_ws)), "") + dedented_lines <- str_replace_all(lines, paste0("^", leading_ws), "") # Combine the lines back into a single string - dedented_text <- paste(dedented_lines, collapse = "\n") - - return(dedented_text) + paste(dedented_lines, collapse = "\n") } diff --git a/man/str_dedent.Rd b/man/str_dedent.Rd index 0eefd1a5..9584a20b 100644 --- a/man/str_dedent.Rd +++ b/man/str_dedent.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/remove.R \name{str_dedent} \alias{str_dedent} -\title{str_dedent} +\title{Remove common leading indentation from strings} \usage{ str_dedent(text) } @@ -13,22 +13,17 @@ str_dedent(text) The input string or character vector with leading indentation removed. } \description{ -Remove common leading indentation from strings -} -\note{ -This function is similar to Python's \code{dedent} function in the \code{textwrap} library. It removes common leading indentation from strings. +This function is similar to Python's \code{dedent} function in the \code{textwrap} +library. It removes common leading indentation from strings. } \examples{ -dedent(" Hello\n World") -# Expected Output: "Hello\n World" +str_dedent(" Hello\n World") -dedent(" Line 1\n Line 2\n Line 3") -# Expected Output: "Line 1\nLine 2\nLine 3" +str_dedent(" Line 1\n Line 2\n Line 3") -dedent("No indentation") -# Expected Output: "No indentation" +str_dedent("No indentation") -dedent( +str_dedent( " this is @@ -36,8 +31,4 @@ dedent( test " ) -# Expected Output: "\nthis\nis\n a\ntest\n" -} -\author{ -chrimaho } diff --git a/tests/testthat/test-remove.R b/tests/testthat/test-remove.R index ba3b650d..fc027428 100644 --- a/tests/testthat/test-remove.R +++ b/tests/testthat/test-remove.R @@ -4,10 +4,10 @@ test_that("succesfully wraps str_replace_all", { }) test_that("successfully dedent str_dedent",{ - expect_equal(dedent(" Hello\n World"), "Hello\n World") - expect_equal(dedent(" Line 1\n Line 2\n Line 3"), "Line 1\nLine 2\nLine 3") - expect_equal(dedent("No indentation"), "No indentation") - expect_equal(dedent( + expect_equal(str_dedent(" Hello\n World"), "Hello\n World") + expect_equal(str_dedent(" Line 1\n Line 2\n Line 3"), "Line 1\nLine 2\nLine 3") + expect_equal(str_dedent("No indentation"), "No indentation") + expect_equal(str_dedent( " this is @@ -15,4 +15,4 @@ test_that("successfully dedent str_dedent",{ test " ), "\nthis\nis\n a\ntest\n") -}) \ No newline at end of file +})