-
Notifications
You must be signed in to change notification settings - Fork 195
Add new str_dedent
function
#514
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
de85c68
b78752e
60e6fe1
a8607e9
f11b135
64424de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -19,3 +19,65 @@ str_remove <- function(string, pattern) { | |||||
str_remove_all <- function(string, pattern) { | ||||||
str_replace_all(string, pattern, "") | ||||||
} | ||||||
|
||||||
|
||||||
#' Remove common leading indentation from strings | ||||||
#' | ||||||
#' @description | ||||||
#' `str_dedent()` is designed to make it possible to correctly indent multiline | ||||||
#' strings inside of function calls, while generating the desired amount of | ||||||
#' whitespace in the output. | ||||||
#' | ||||||
#' It does this by removing the common leading indentation from each line | ||||||
#' (ignoring lines only containing whitespace), and removing the first line, | ||||||
#' if it only contains whitespace. | ||||||
#' | ||||||
#' It is inspired by Python's | ||||||
#' [`textwrap.dedent()`](https://docs.python.org/3/library/textwrap.html#textwrap.dedent). | ||||||
#' | ||||||
#' @inheritParams str_detect | ||||||
#' @return A character vector the same length as `string` | ||||||
#' @export | ||||||
#' @examples | ||||||
#' str_dedent(" | ||||||
#' Hello | ||||||
#' World | ||||||
#' ") | ||||||
#' | ||||||
#' f <- function() { | ||||||
#' str_dedent(" | ||||||
#' Line 1 | ||||||
#' Line 2 | ||||||
#' Line 3 | ||||||
#' ") | ||||||
#' } | ||||||
#' cat(str_dedent(f())) | ||||||
str_dedent <- function(string) { | ||||||
check_character(string) | ||||||
|
||||||
lines <- str_split(string, fixed("\n")) | ||||||
map_chr(lines, str_dedent_1) | ||||||
} | ||||||
|
||||||
str_dedent_1 <- function(lines, trim_empty_ends = TRUE) { | ||||||
if (length(lines) <= 1) { | ||||||
return(lines) | ||||||
} | ||||||
|
||||||
ws <- str_length(str_extract(lines, "^ *")) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Seems like we should also be thinking about tabs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better to just ignore them since we don't use them. If we did, I think we'd need to multiply by the tab stop size. ... Hmmm, I guess we need to think about this because people might be using tabs for indenting. |
||||||
only_ws <- ws == str_length(lines) | ||||||
|
||||||
# Drop the first line if it's completely blank | ||||||
if (only_ws[1]) { | ||||||
lines <- lines[-1] | ||||||
ws <- ws[-1] | ||||||
only_ws <- only_ws[-1] | ||||||
} | ||||||
|
||||||
if (all(only_ws)) { | ||||||
dedented <- lines | ||||||
} else { | ||||||
dedented <- str_sub(lines, start = min(ws[!only_ws]) + 1) | ||||||
} | ||||||
paste0(dedented, collapse = "\n") | ||||||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is my suggestion for the invariants of how this function should work (if we trim leading and trailing whitespace). (Needs a
document()
call)