diff --git a/DESCRIPTION b/DESCRIPTION index 0c1a567..0bd62a3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,12 +2,9 @@ Type: Package Package: plume Title: A Simple Author Handler for Scientific Writing Version: 0.1.0.9000 -Authors@R: c( +Authors@R: person("Arnaud", "Gallou", , "arangacas@gmail.com", role = c("aut", "cre", "cph"), - comment = c(ORCID = "0000-0002-1002-4247")), - person("Hadley", "Wickham", role = "cph", - comment = "Author of included stringb functions.") - ) + comment = c(ORCID = "0000-0002-1002-4247")) Description: Handles and formats author information in scientific writing in 'R Markdown' and 'Quarto'. 'plume' provides easy-to-use and flexible tools for injecting author metadata in 'YAML' headers as well diff --git a/LICENSE.note b/LICENSE.note deleted file mode 100644 index 5dfb1b9..0000000 --- a/LICENSE.note +++ /dev/null @@ -1,27 +0,0 @@ -The plume package as a whole is distributed under the GPL license. -It includes functions from the stringb package (https://github.com/hadley/stringb), distributed under the MIT license. - -stringb -------- - -# MIT License - -Copyright (c) 2020 RStudio - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/NAMESPACE b/NAMESPACE index 8071179..dfcee32 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -55,6 +55,14 @@ importFrom(rlang,is_true) importFrom(rlang,set_names) importFrom(rlang,sym) importFrom(rlang,syms) +importFrom(stringr,fixed) +importFrom(stringr,regex) +importFrom(stringr,str_extract) +importFrom(stringr,str_extract_all) +importFrom(stringr,str_remove_all) +importFrom(stringr,str_replace) +importFrom(stringr,str_replace_all) +importFrom(stringr,str_split_1) importFrom(tibble,as_tibble) importFrom(tibble,as_tibble_row) importFrom(tibble,rowid_to_column) diff --git a/NEWS.md b/NEWS.md index a78aa11..5740556 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # plume (development version) +* Removed stringb dependency in favour of stringr (#42). + * The `by` parameter in `$set_*()` methods is now deprecated in favour of `.by` (#41). * `Plume` gains a new method `$set_main_contributors()` that allows you to force one or more contributors to appear first in the contribution list for any given role. `Plume`'s contructor also regains the parameter `by` to set the default `by`/`.by` value used in all `set_*()` methods. diff --git a/R/als.R b/R/als.R index 4fd9055..1b044f9 100644 --- a/R/als.R +++ b/R/als.R @@ -10,13 +10,13 @@ als_key_set <- function(format) { } als_extract_keys <- function(x) { - x <- string_split(x) + x <- str_split_1(x, "") x[x %in% letters] } als_extract_mark <- function(format, key) { mark_regex <- paste0("[,^]{1,2}(?=", key, ")") - mark <- string_extract(format, mark_regex) + mark <- str_extract(format, mark_regex) if (is.na(mark)) { return("") } @@ -24,7 +24,7 @@ als_extract_mark <- function(format, key) { } als_sanitise <- function(x) { - string_remove_all(x, "([,^])\\K\\1+") + str_remove_all(x, "(?<=([,^]))\\1+") } als_parse <- function(format) { @@ -40,7 +40,7 @@ als_parse <- function(format) { als_join <- function(elts, marks) { out <- map2_vec(elts, marks, \(elt, mark) { - if (is_blank(elt) & string_contain(mark, "^")) { + if (is_blank(elt) & str_contain(mark, "^")) { return("^") } else if (is_blank(elt)) { return(elt) @@ -52,7 +52,7 @@ als_join <- function(elts, marks) { als_clean <- function(x) { for (pattern in c("(?<=^|\\^),|,$", "\\^{2}")) { - x <- string_remove_all(x, pattern) + x <- str_remove_all(x, pattern) } x } diff --git a/R/checkers.R b/R/checkers.R index 68dfe5f..11588c3 100644 --- a/R/checkers.R +++ b/R/checkers.R @@ -1,9 +1,9 @@ has_uppercase <- function(x) { - string_detect(x, "\\p{Lu}") + str_detect(x, "\\p{Lu}") } detect_name <- function(x, name) { - string_detect(names(x), name) + str_detect(names(x), name) } has_name <- function(x, name) { @@ -14,12 +14,12 @@ has_name.default <- function(x, name) { name %in% names(x) } -has_name.regex <- function(x, name) { +has_name.stringr_regex <- function(x, name) { any(detect_name(x, name)) } has_metachr <- function(x) { - string_detect(x, r"{[\\\[\](){}|?$^*+]}") + str_detect(x, r"{[\\\[\](){}|?$^*+]}") } has_homonyms <- function(x) { @@ -27,7 +27,7 @@ has_homonyms <- function(x) { } has_overflowing_ws <- function(x) { - string_detect(x, "^\\s|\\s$") + str_detect(x, "^\\s|\\s$") } is_empty <- function(x) { @@ -55,7 +55,7 @@ is_nested <- function(x, item) { } is_blank <- function(x) { - string_detect(x, "^\\s*$") + str_detect(x, "^\\s*$") } is_not_na <- Negate(is.na) @@ -258,7 +258,7 @@ check_suffix_format <- function(x, allowed, arg = caller_arg(x)) { } path_is_relative <- function(x) { - !string_detect(x, "^(/|[A-Za-z]:|\\\\|~)") + !str_detect(x, "^(/|[A-Za-z]:|\\\\|~)") } check_path <- function(x, ..., arg = caller_arg(x)) { @@ -274,7 +274,7 @@ check_path <- function(x, ..., arg = caller_arg(x)) { } file_ext <- function(x) { - string_extract(x, "(?<=\\.)[^.]+$") + str_extract(x, "(?<=\\.)[^.]+$") } check_file <- function(x, extension, ..., arg = caller_arg(x)) { @@ -289,7 +289,7 @@ check_file <- function(x, extension, ..., arg = caller_arg(x)) { } is_glueish <- function(x) { - is_string(x) && string_detect(x, "{[^}]+}") + is_string(x) && str_detect(x, "\\{[^}]+\\}") } check_glue <- function(x, allowed, ..., arg = caller_arg(x)) { @@ -310,7 +310,7 @@ check_glue <- function(x, allowed, ..., arg = caller_arg(x)) { } is_orcid <- function(x) { - string_detect(x, "^(?:\\d{4}-){3}\\d{3}(?:\\d|X)$") + str_detect(x, "^(?:\\d{4}-){3}\\d{3}(?:\\d|X)$") } check_orcid <- function(x, ..., arg = caller_arg(x)) { diff --git a/R/credit_roles.R b/R/credit_roles.R index 25a4b5a..83ef383 100644 --- a/R/credit_roles.R +++ b/R/credit_roles.R @@ -18,6 +18,7 @@ credit_roles <- function(oxford_spelling = TRUE) { } full_rename <- function(x, pattern, replacement) { - names(x) <- string_replace(names(x), pattern, replacement) - string_replace(x, pattern, replacement) + names(x) <- str_replace(names(x), pattern, replacement) + x[] <- str_replace(x, pattern, replacement) + x } diff --git a/R/plume-handler.R b/R/plume-handler.R index 95024a7..d863539 100644 --- a/R/plume-handler.R +++ b/R/plume-handler.R @@ -250,7 +250,7 @@ PlumeHandler$set("private", "check_role_system", function() { return() } roles <- select(private$plume, starts_with(var)) - have_explicit_roles <- map_vec(roles, \(role) any(string_detect(role, "\\D"))) + have_explicit_roles <- map_vec(roles, \(role) any(str_detect(role, "\\D"))) if (!all(have_explicit_roles)) { return() } diff --git a/R/plume-package.R b/R/plume-package.R index 7183436..6b6c07e 100644 --- a/R/plume-package.R +++ b/R/plume-package.R @@ -19,6 +19,8 @@ #' @importFrom rlang caller_env caller_arg #' @importFrom glue glue glue_collapse #' @importFrom vctrs vec_group_id vec_duplicate_any vec_restore vec_rank +#' @importFrom stringr str_split_1 str_remove_all str_replace str_replace_all +#' @importFrom stringr str_extract str_extract_all fixed regex #' @importFrom jsonlite toJSON parse_json #' @importFrom yaml yaml.load as.yaml #' @importFrom R6 R6Class diff --git a/R/plume-quarto.R b/R/plume-quarto.R index f39b896..7574f38 100644 --- a/R/plume-quarto.R +++ b/R/plume-quarto.R @@ -234,8 +234,8 @@ parse_affiliation <- function(x) { } keys <- collapse(affiliation_keys, sep = "|") keys_regex <- paste0("\\b(?i:", keys, ")") - nms <- string_extract_all(x, sprintf("%s(?==)", keys_regex)) - els <- string_split(x, sprintf("\\s*%s=\\s*", keys_regex))[-1] + nms <- str_extract_all(x, sprintf("%s(?==)", keys_regex), simplify = TRUE) + els <- str_split_1(x, sprintf("\\s*%s=\\s*", keys_regex))[-1] set_names(els, tolower(nms)) } @@ -244,5 +244,5 @@ make_affiliation_id <- function(x) { } has_affiliation_sep <- function(x) { - string_contain(x, "=") + str_contain(x, "=") } diff --git a/R/strings.R b/R/strings.R deleted file mode 100644 index f530c75..0000000 --- a/R/strings.R +++ /dev/null @@ -1,121 +0,0 @@ -# stringb functions start -# modified from https://github.com/hadley/stringb - -fixed <- function(x) { - structure(x, class = c("fixed", "character")) -} - -regex <- function(x) { - structure(x, class = c("regex", "character")) -} - -is_fixed <- function(x) { - inherits(x, "fixed") -} - -is_perl <- function(x) { - is.null(attr(x, "class")) -} - -string_detect <- function(string, pattern) { - grepl( - pattern, string, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) -} - -string_extract <- function(string, pattern) { - string_sub(string, string_locate(string, pattern)) -} - -string_extract_all <- function(string, pattern) { - loc <- string_locate_all(string, pattern) - out <- lapply(seq_along(string), \(i) { - loc <- loc[[i]] - string_sub(rep(string[[i]], nrow(loc)), loc) - }) - if (length(out) == 1L) { - out <- unlist(out) - } - out -} - -string_locate <- function(string, pattern) { - out <- regexpr( - pattern, string, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) - location(out) -} - -string_locate_all <- function(string, pattern) { - out <- gregexpr( - pattern, string, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) - lapply(out, location, all = TRUE) -} - -location <- function(x, all = FALSE) { - start <- as.vector(x) - if (all && identical(start, -1L)) { - return(cbind(start = integer(), end = integer())) - } - end <- as.vector(x) + attr(x, "match.length") - 1 - no_match <- start == -1L - start[no_match] <- NA - end[no_match] <- NA - cbind(start = start, end = end) -} - -string_replace <- function(string, pattern, replacement) { - sub( - pattern, replacement, string, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) -} - -string_replace_all <- function(string, pattern, replacement) { - gsub( - pattern, replacement, string, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) -} - -string_sub <- function(string, start = 1L, end = -1L) { - if (is.matrix(start)) { - end <- start[, 2] - start <- start[, 1] - } - n <- nchar(string) - start <- ifelse(start < 0, start + n + 1, start) - end <- ifelse(end < 0, end + n + 1, end) - substr(string, start, end) -} - -# stringb functions end - -string_remove_all <- function(string, pattern) { - string_replace_all(string, pattern, "") -} - -string_contain <- function(string, pattern) { - string_detect(string, fixed(pattern)) -} - -string_split <- function(string, pattern = "") { - out <- strsplit( - string, pattern, - fixed = is_fixed(pattern), - perl = is_perl(pattern) - ) - if (length(out) == 1L) { - out <- unlist(out) - } - out -} diff --git a/R/utils.R b/R/utils.R index 8e869b6..b1e7e6c 100644 --- a/R/utils.R +++ b/R/utils.R @@ -23,11 +23,11 @@ not_na_any <- function(cols) { } dot <- function(x) { - string_replace_all(x, "(?<=[\\pL\\pN](?!\\p{Po}))", ".") + str_replace_all(x, "(?<=[\\p{L}\\p{N}](?!\\p{Po}))", ".") } make_initials <- function(x, dot = FALSE) { - out <- string_remove_all(x, "(*UCP)\\B\\w+|[\\s.]+") + out <- str_remove_all(x, "\\B\\w+|[\\s.]+") if (dot) { out <- dot(out) } @@ -106,7 +106,7 @@ get_params_set_to_true <- function() { } extract_glue_vars <- function(x) { - string_extract_all(x, "(?<=\\{\\b)[^}]+") + str_extract_all(x, "(?<=\\{\\b)[^}]+", simplify = TRUE) } group_id <- function(x) { @@ -127,10 +127,19 @@ propagate_na <- function(x, from) { to_chr_class <- function(x, negate = FALSE) { neg <- if (negate) "^" else "" x <- collapse(x) - x <- string_replace(x, r"{([-\\\[\]])}", r"{\\\1}") + x <- str_replace(x, r"{([-\\\[\]])}", r"{\\\1}") paste0("[", neg, x, "]") } +str_contain <- function(string, pattern) { + str_detect(string, fixed(pattern)) +} + +str_detect <- function(string, pattern) { + out <- stringr::str_detect(string, pattern) + replace(out, is.na(string), FALSE) +} + wrap <- function(x, value) { paste0(value, x, value) } diff --git a/R/yaml.R b/R/yaml.R index 3d1e9e8..c49b336 100644 --- a/R/yaml.R +++ b/R/yaml.R @@ -20,8 +20,7 @@ as_json <- function(x) { } separate_yaml_header <- function(x) { - # use of stringr to preserve a match at the end of the string - stringr::str_split_1(x, "(?m:^|\\R\\K)-{3}(?:\\R|$)") + str_split_1(x, "(?m:^|\\R\\K)-{3}(?:\\R|$)") } as_verbatim_lgl <- function(x) { @@ -46,7 +45,7 @@ yaml_inject <- function(lines, replacement) { } has_yaml <- function(x) { - string_detect(x, "(?s)^\\R*---\\R.*\\B---(?:\\R|$)") + str_detect(x, "(?s)^\\R*---\\R.*\\B---(?:\\R|$)") } check_has_yaml <- function(x) { diff --git a/man/plume-package.Rd b/man/plume-package.Rd index ec5622b..bff7f45 100644 --- a/man/plume-package.Rd +++ b/man/plume-package.Rd @@ -23,10 +23,5 @@ Useful links: \author{ \strong{Maintainer}: Arnaud Gallou \email{arangacas@gmail.com} (\href{https://orcid.org/0000-0002-1002-4247}{ORCID}) [copyright holder] -Other contributors: -\itemize{ - \item Hadley Wickham (Author of included stringb functions.) [copyright holder] -} - } \keyword{internal} diff --git a/tests/testthat/helper-plume.R b/tests/testthat/helper-plume.R index 0beca71..309d0ea 100644 --- a/tests/testthat/helper-plume.R +++ b/tests/testthat/helper-plume.R @@ -29,9 +29,9 @@ tempfile_ <- function() { dedent <- function(string) { out <- trimws(string) ws_regex <- "(?<=\n) " - ws <- string_extract_all(out, paste0(ws_regex, "+")) + ws <- str_extract_all(out, paste0(ws_regex, "+"), simplify = TRUE) ws_n <- min(nchar(ws)) - string_remove_all(out, paste0(ws_regex, "{", ws_n, "}")) + str_remove_all(out, paste0(ws_regex, "{", ws_n, "}")) } read_test_file <- function(file) {