From 51c9e98bc8fd0fd83dc02468cf476671f2f5efd4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:45:39 +0000 Subject: [PATCH 01/10] Initial plan From 4fcc767e941d0c40096a56172b7d958f6d0796d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:48:59 +0000 Subject: [PATCH 02/10] refactor: replace stringr/stringi usage with base R Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- DESCRIPTION | 2 -- NAMESPACE | 10 ------ NEWS.md | 1 + R/interact.R | 3 +- R/read_log_file.R | 64 +++++++++++++++------------------ R/writer.R | 26 ++++---------- tests/testthat/test-writer.R | 1 - vignettes/generate-lockfile.Rmd | 3 +- 8 files changed, 37 insertions(+), 73 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5fb05bb4..b629de88 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -45,9 +45,7 @@ Imports: rlang, stats, tidyr, - stringr, sessioninfo (>= 1.2), - stringi, tibble, digest, lifecycle, diff --git a/NAMESPACE b/NAMESPACE index f41f44b9..8616cf0a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,16 +33,6 @@ importFrom(purrr,set_names) importFrom(rlang,.data) importFrom(sessioninfo,session_info) importFrom(stats,aggregate) -importFrom(stringi,stri_wrap) -importFrom(stringr,str_c) -importFrom(stringr,str_count) -importFrom(stringr,str_detect) -importFrom(stringr,str_extract) -importFrom(stringr,str_remove) -importFrom(stringr,str_remove_all) -importFrom(stringr,str_replace_all) -importFrom(stringr,str_starts) -importFrom(stringr,str_trim) importFrom(tibble,tibble) importFrom(tidyr,all_of) importFrom(tidyr,complete) diff --git a/NEWS.md b/NEWS.md index 06acc05d..76088750 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ ## Updates - Removed .dcf file for old Addin (#280) +- Reworked string handling to use base R and removed `{stringr}`/`{stringi}` dependencies. ## Documentation diff --git a/R/interact.R b/R/interact.R index 00f3b527..cfe05b7e 100644 --- a/R/interact.R +++ b/R/interact.R @@ -140,7 +140,6 @@ run_file <- function(file) { #' Safely run an R script and record results, outputs, messages, errors, warnings #' #' @importFrom purrr safely discard -#' @importFrom stringr str_starts #' #' @param file File to run #' @@ -150,7 +149,7 @@ run_file <- function(file) { #' run_safely_loudly <- function(file) { ret <- loudly(run_safely(file)) - set_log_element("messages", discard(ret$messages, ~ str_starts(.x, "Error"))) + set_log_element("messages", discard(ret$messages, ~ startsWith(.x, "Error"))) set_log_element("output", ret$output) set_log_element("result", ret$result$result) set_log_element("warnings", ret$warnings) diff --git a/R/read_log_file.R b/R/read_log_file.R index c3cdad90..6b45d155 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -2,11 +2,6 @@ #' #' @param log_txt String vector. Object with log text lines #' -#' @importFrom stringr str_detect -#' @importFrom stringr str_count -#' @importFrom stringr str_remove -#' @importFrom stringr str_replace_all -#' #' @return tibble that ensures formatted subsections #' #' @examples @@ -19,21 +14,21 @@ reformat_subsections <- function(log_txt) { adj_log_txt <- c() for (i in log_txt) { - adj_tf <- stringr::str_detect( - i, - "Errors:|Warnings:|Messages:|Output:|Result:" + adj_tf <- grepl( + "Errors:|Warnings:|Messages:|Output:|Result:", + i ) if (adj_tf) { - nrem <- stringr::str_count(i) - i <- stringr::str_remove(i, ":") + nrem <- nchar(i) + i <- sub(":", "", i) i <- paste("-", i, paste(rep("-", 54 - nrem), collapse = ""), collapse = "" ) } # replace utf8 line and double line to ascii due to cli symbol variation - i <- stringr::str_replace_all(i, "\u2550", "=") - i <- stringr::str_replace_all(i, "\u2500", "=") + i <- gsub("\u2550", "=", i, fixed = TRUE) + i <- gsub("\u2500", "=", i, fixed = TRUE) adj_log_txt <- c(adj_log_txt, i) } return(adj_log_txt) @@ -43,8 +38,6 @@ reformat_subsections <- function(log_txt) { #' #' @param adj_log_txt String vector. Object with formatted log text lines #' -#' @importFrom stringr str_remove_all -#' #' @return list that includes nested log sections #' #' @noRd @@ -67,8 +60,7 @@ nest_sections <- function(adj_log_txt) { } } } - sect_headers <- - stringr::str_remove_all(sect_headers, "-?\\s{3,}-?") + sect_headers <- gsub("-?\\s{3,}-?", "", sect_headers) names(sect_info) <- sect_headers return(sect_info) @@ -79,26 +71,27 @@ nest_sections <- function(adj_log_txt) { #' @param adj_log_txt String vector. Object with formatted log text lines #' @param sect_info String vector. Object with nested sections #' -#' @importFrom stringr str_extract -#' @importFrom stringr str_trim -#' @importFrom stringr str_remove_all -#' #' @return list that includes nested log subsections #' #' @noRd #' nest_subsections <- function(adj_log_txt, sect_info) { + extract_match <- function(x, pattern) { + reg_match <- regexpr(pattern, x, perl = TRUE) + result <- regmatches(x, reg_match) + result[reg_match == -1] <- NA_character_ + result + } + subsect_headers <- stats::na.omit( - stringr::str_extract(adj_log_txt, "[\\-|\\=]\\s\\w+\\s(\\w+\\s)?[\\-|\\=]{3,70}") + extract_match(adj_log_txt, "[\\-|\\=]\\s\\w+\\s(\\w+\\s)?[\\-|\\=]{3,70}") ) subset_sections <- function(section) { subsect_status <- FALSE subsect_info <- list() for (i in section) { if (i %in% subsect_headers) { - latest_subsect <- stringr::str_trim( - stringr::str_remove_all(i, "[\\-|\\=]") - ) + latest_subsect <- trimws(gsub("[\\-|\\=]", "", i)) subsect_status <- TRUE } else if (subsect_status) { subsect_info[[latest_subsect]] <- @@ -135,7 +128,6 @@ nest_log <- function(adj_log_txt) { #' #' @importFrom tibble tibble #' @importFrom tidyr separate -#' @importFrom stringr str_replace_all #' @importFrom dplyr rename_with #' @importFrom dplyr mutate #' @@ -170,7 +162,7 @@ parse_log <- function(nested_log) { parsed_log$`User and File Information` <- nested_log$`User and File Information` %>% unlist() %>% - stringr::str_trim() %>% + trimws() %>% tibble::tibble() %>% tidyr::separate(".", sep = "\\: ", @@ -182,7 +174,7 @@ parse_log <- function(nested_log) { parsed_log$`Session Information`$`Session info` <- nested_log$`Session Information`$`Session info` %>% unlist() %>% - stringr::str_trim() %>% + trimws() %>% tibble::tibble() %>% tidyr::separate(".", sep = "\\s", @@ -190,13 +182,13 @@ parse_log <- function(nested_log) { extra = "merge", fill = "right" ) %>% - dplyr::mutate(dplyr::across(tidyselect::where(is.character), stringr::str_trim)) + dplyr::mutate(dplyr::across(tidyselect::where(is.character), trimws)) parsed_log$`Session Information`$`Packages` <- nested_log$`Session Information`$`Packages` %>% # remove indicator whether the package is attached to the search path - stringr::str_replace_all("\\*", " ") %>% + gsub("\\*", " ", x = .) %>% # account for loaded packages due to load_all() - stringr::str_replace_all(" P ", " ") %>% + gsub(" P ", " ", x = .) %>% readr::read_table(skip = 1, col_names = FALSE) # handle case where log is has 7 columns due to sessioninfo v1.2.2 or earlier @@ -213,8 +205,8 @@ parse_log <- function(nested_log) { "r_version" )) %>% dplyr::mutate( - lang = stringr::str_remove(lang, "\\("), - r_version = stringr::str_remove(r_version, "\\)") + lang = sub("\\(", "", lang), + r_version = sub("\\)", "", r_version) ) } else { parsed_log$`Session Information`$`Packages` <- @@ -230,7 +222,7 @@ parse_log <- function(nested_log) { parsed_log$`Session Information`$`External software` <- nested_log$`Session Information`$`External software` %>% - stringr::str_trim() %>% + trimws() %>% tibble::tibble() %>% tidyr::separate(".", sep = "\\s", @@ -238,14 +230,14 @@ parse_log <- function(nested_log) { extra = "merge", fill = "right" ) %>% - dplyr::mutate(dplyr::across(tidyselect::where(is.character), stringr::str_trim)) + dplyr::mutate(dplyr::across(tidyselect::where(is.character), trimws)) } if ("Repo URLs" %in% names(nested_log)) { parsed_log$`Repo URLs` <- nested_log$`Repo URLs` %>% unlist() %>% - stringr::str_trim() %>% + trimws() %>% tibble::tibble() %>% tidyr::separate(".", sep = "\\:\\s+", @@ -269,7 +261,7 @@ parse_log <- function(nested_log) { sep = "\\} ", into = c("library", "function_names") ) %>% - dplyr::mutate(library = stringr::str_remove(library, "\\{")) + dplyr::mutate(library = sub("\\{", "", library)) } if ("Program Run Time Information" %in% names(nested_log)) { diff --git a/R/writer.R b/R/writer.R index 6f94b114..5f34bb7e 100644 --- a/R/writer.R +++ b/R/writer.R @@ -43,8 +43,6 @@ write_metadata <- function() { #' Format log.rx's session info attribute for writing #' #' @importFrom purrr map_chr -#' @importFrom stringi stri_wrap -#' @importFrom stringr str_c #' #' @return A vector of log.rx's session info attribute #' @@ -59,11 +57,8 @@ write_session_info <- function() { .x )) %>% # wrap any other elements over 80 characters - map_chr(~ stri_wrap(.x, - width = 80, exdent = 2, simplify = FALSE, use_length = TRUE, - normalize = FALSE, whitespace_only = TRUE - ) %>% - map_chr(~ str_c(.x, collapse = "\n\t", character(1)))) + map_chr(~ strwrap(.x, width = 80, exdent = 2) %>% + paste(collapse = "\n\t")) return(session_info) } @@ -247,7 +242,7 @@ write_errors <- function() { paste0( "Errors:\n\t", - str_replace_all(errors$message, "\n", "\n\t") + gsub("\n", "\n\t", errors$message, fixed = TRUE) ) } @@ -269,7 +264,6 @@ write_warnings <- function() { #' Format messages attribute for writing #' #' @importFrom purrr map -#' @importFrom stringr str_remove_all #' #' @return A formatted vector of messages #' @@ -277,7 +271,7 @@ write_warnings <- function() { #' write_messages <- function() { messages <- get_log_element("messages") %>% - map(~ str_remove_all(.x, "\n")) + map(~ gsub("\n", "", .x, fixed = TRUE)) paste0( "Messages:\n\t", @@ -287,8 +281,6 @@ write_messages <- function() { #' Format output attribute for writing #' -#' @importFrom stringr str_replace_all -#' #' @return A formatted vector of output #' #' @noRd @@ -298,7 +290,7 @@ write_output <- function() { paste0( "Output:\n\t", - str_replace_all(output, "\n", "\n\t") + gsub("\n", "\n\t", output, fixed = TRUE) ) } @@ -361,12 +353,6 @@ write_extra_info <- function() { call. = FALSE ) } - if (!requireNamespace("stringr", quietly = TRUE)) { - stop( - "Package \"stringr\" must be installed to use this function.", - call. = FALSE - ) - } extra_info <- get_log_element("extra_info") results <- yaml::as.yaml( extra_info, @@ -375,6 +361,6 @@ write_extra_info <- function() { logical = yaml::verbatim_logical ) ) - results <- stringr::str_split(results, pattern = "\n")[[1]] + results <- strsplit(results, split = "\n", fixed = TRUE)[[1]] return(results) } diff --git a/tests/testthat/test-writer.R b/tests/testthat/test-writer.R index b8805b7b..f3a5a786 100644 --- a/tests/testthat/test-writer.R +++ b/tests/testthat/test-writer.R @@ -292,7 +292,6 @@ test_that("write_repo_urls will return a formatted log output element", { test_that("write_extra_info will return a formatted log output element", { skip_if_not_installed("yaml") - skip_if_not_installed("stringr") options("log.rx" = NULL) ref_extra_info1 <- list("some info", "more info") fp <- test_path("ref", "safely_loudly_test_file_result.R") diff --git a/vignettes/generate-lockfile.Rmd b/vignettes/generate-lockfile.Rmd index f8a1c99c..49da2f70 100644 --- a/vignettes/generate-lockfile.Rmd +++ b/vignettes/generate-lockfile.Rmd @@ -19,7 +19,6 @@ knitr::opts_chunk$set( ```{r setup, message = FALSE} library(logrx) -library(stringr) library(dplyr) library(tidyr) library(renv) @@ -55,7 +54,7 @@ Create a renv lockfile based on the used packages mentioned in the log file. ```{r gen_lockfile, error = TRUE} pkgs <- parsedFile$`Used Package and Functions` %>% - transmute(package_name = str_extract(library, "(?<=package\\:).+")) + transmute(package_name = sub("^.*package\\:", "", library)) used_pkgs <- parsedFile$`Session Information`$Packages %>% filter(package %in% pkgs$package_name) From 6515d987fb6a824ea2f6bf966f1b11f1f8d89ba3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:49:36 +0000 Subject: [PATCH 03/10] chore: address review feedback on base regex migration Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 1 + vignettes/generate-lockfile.Rmd | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index 6b45d155..c0d501b4 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -76,6 +76,7 @@ nest_sections <- function(adj_log_txt) { #' @noRd #' nest_subsections <- function(adj_log_txt, sect_info) { + # Extract the first regex match from each string, returning NA for no match. extract_match <- function(x, pattern) { reg_match <- regexpr(pattern, x, perl = TRUE) result <- regmatches(x, reg_match) diff --git a/vignettes/generate-lockfile.Rmd b/vignettes/generate-lockfile.Rmd index 49da2f70..3d795a91 100644 --- a/vignettes/generate-lockfile.Rmd +++ b/vignettes/generate-lockfile.Rmd @@ -54,7 +54,7 @@ Create a renv lockfile based on the used packages mentioned in the log file. ```{r gen_lockfile, error = TRUE} pkgs <- parsedFile$`Used Package and Functions` %>% - transmute(package_name = sub("^.*package\\:", "", library)) + transmute(package_name = sub("^package\\:", "", library)) used_pkgs <- parsedFile$`Session Information`$Packages %>% filter(package %in% pkgs$package_name) From 121f47b36346cd6b86c1e1525942c97891547b0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:50:07 +0000 Subject: [PATCH 04/10] style: improve variable and helper comment clarity Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index c0d501b4..d8f9576e 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -19,10 +19,10 @@ reformat_subsections <- function(log_txt) { i ) if (adj_tf) { - nrem <- nchar(i) + char_count <- nchar(i) i <- sub(":", "", i) i <- - paste("-", i, paste(rep("-", 54 - nrem), collapse = ""), + paste("-", i, paste(rep("-", 54 - char_count), collapse = ""), collapse = "" ) } @@ -76,7 +76,7 @@ nest_sections <- function(adj_log_txt) { #' @noRd #' nest_subsections <- function(adj_log_txt, sect_info) { - # Extract the first regex match from each string, returning NA for no match. + # Extract the first regex match from each string and return NA when no match exists. extract_match <- function(x, pattern) { reg_match <- regexpr(pattern, x, perl = TRUE) result <- regmatches(x, reg_match) From 2e141d0165e3c2e6ee04b72f0a4ee808b9b758d3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:50:56 +0000 Subject: [PATCH 05/10] test: cover subsection extraction behavior and fix header padding Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 2 +- tests/testthat/test-parse.R | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index d8f9576e..07a7d7cb 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -19,8 +19,8 @@ reformat_subsections <- function(log_txt) { i ) if (adj_tf) { - char_count <- nchar(i) i <- sub(":", "", i) + char_count <- nchar(i) i <- paste("-", i, paste(rep("-", 54 - char_count), collapse = ""), collapse = "" diff --git a/tests/testthat/test-parse.R b/tests/testthat/test-parse.R index 12ffa984..2ae4726f 100644 --- a/tests/testthat/test-parse.R +++ b/tests/testthat/test-parse.R @@ -55,3 +55,24 @@ test_that("read_log_file will parse a logrx log file and create the necessary ob rm(scriptPath, logDir, parsedFile) log_remove() }) + +test_that("nest_subsections handles both matched and unmatched subsection headers", { + matched_headers <- c("- Session info -------") + section_with_header <- list( + `Session Information` = c("- Session info -------", " setting value", " foo bar") + ) + + matched_result <- logrx:::nest_subsections(matched_headers, section_with_header) + expect_named(matched_result[[1]], "Session info") + expect_identical( + matched_result[[1]][["Session info"]], + c(" setting value", " foo bar") + ) + + no_headers <- c("plain text") + section_without_header <- list(`Session Information` = c("line one", "line two")) + unmatched_result <- logrx:::nest_subsections(no_headers, section_without_header) + expect_length(unmatched_result[[1]], 2) + expect_identical(unmatched_result[[1]][[1]], "line one") + expect_identical(unmatched_result[[1]][[2]], "line two") +}) From 2b0f9f70221c9855c4b52e24f2628a41dd61c21b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:51:30 +0000 Subject: [PATCH 06/10] fix: harden regex extraction and preserve original padding behavior Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index 07a7d7cb..50bd9090 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -19,8 +19,8 @@ reformat_subsections <- function(log_txt) { i ) if (adj_tf) { - i <- sub(":", "", i) char_count <- nchar(i) + i <- sub(":", "", i) i <- paste("-", i, paste(rep("-", 54 - char_count), collapse = ""), collapse = "" @@ -79,8 +79,11 @@ nest_subsections <- function(adj_log_txt, sect_info) { # Extract the first regex match from each string and return NA when no match exists. extract_match <- function(x, pattern) { reg_match <- regexpr(pattern, x, perl = TRUE) - result <- regmatches(x, reg_match) - result[reg_match == -1] <- NA_character_ + result <- rep(NA_character_, length(x)) + has_match <- reg_match != -1 + if (any(has_match)) { + result[has_match] <- regmatches(x[has_match], reg_match[has_match]) + } result } From 4f765c086d07412817a431edde90d581fc74a707 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:52:06 +0000 Subject: [PATCH 07/10] chore: align wrap behavior and improve helper naming Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 6 +++--- R/writer.R | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index 50bd9090..f3c4a394 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -78,11 +78,11 @@ nest_sections <- function(adj_log_txt) { nest_subsections <- function(adj_log_txt, sect_info) { # Extract the first regex match from each string and return NA when no match exists. extract_match <- function(x, pattern) { - reg_match <- regexpr(pattern, x, perl = TRUE) + match_positions <- regexpr(pattern, x, perl = TRUE) result <- rep(NA_character_, length(x)) - has_match <- reg_match != -1 + has_match <- match_positions != -1 if (any(has_match)) { - result[has_match] <- regmatches(x[has_match], reg_match[has_match]) + result[has_match] <- regmatches(x[has_match], match_positions[has_match]) } result } diff --git a/R/writer.R b/R/writer.R index 5f34bb7e..d905889c 100644 --- a/R/writer.R +++ b/R/writer.R @@ -57,7 +57,7 @@ write_session_info <- function() { .x )) %>% # wrap any other elements over 80 characters - map_chr(~ strwrap(.x, width = 80, exdent = 2) %>% + map_chr(~ strwrap(.x, width = 80, exdent = 2, whitespace = FALSE) %>% paste(collapse = "\n\t")) return(session_info) From 466528c27bfd5afc41377dbc86f6a49bf35c18c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:52:56 +0000 Subject: [PATCH 08/10] fix: resolve remaining review nits in base string replacements Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 4 ++-- R/writer.R | 2 +- vignettes/generate-lockfile.Rmd | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index f3c4a394..a65cb927 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -190,9 +190,9 @@ parse_log <- function(nested_log) { parsed_log$`Session Information`$`Packages` <- nested_log$`Session Information`$`Packages` %>% # remove indicator whether the package is attached to the search path - gsub("\\*", " ", x = .) %>% + gsub("*", " ", x = ., fixed = TRUE) %>% # account for loaded packages due to load_all() - gsub(" P ", " ", x = .) %>% + gsub(" P ", " ", x = ., fixed = TRUE) %>% readr::read_table(skip = 1, col_names = FALSE) # handle case where log is has 7 columns due to sessioninfo v1.2.2 or earlier diff --git a/R/writer.R b/R/writer.R index d905889c..5f34bb7e 100644 --- a/R/writer.R +++ b/R/writer.R @@ -57,7 +57,7 @@ write_session_info <- function() { .x )) %>% # wrap any other elements over 80 characters - map_chr(~ strwrap(.x, width = 80, exdent = 2, whitespace = FALSE) %>% + map_chr(~ strwrap(.x, width = 80, exdent = 2) %>% paste(collapse = "\n\t")) return(session_info) diff --git a/vignettes/generate-lockfile.Rmd b/vignettes/generate-lockfile.Rmd index 3d795a91..816d0109 100644 --- a/vignettes/generate-lockfile.Rmd +++ b/vignettes/generate-lockfile.Rmd @@ -54,7 +54,7 @@ Create a renv lockfile based on the used packages mentioned in the log file. ```{r gen_lockfile, error = TRUE} pkgs <- parsedFile$`Used Package and Functions` %>% - transmute(package_name = sub("^package\\:", "", library)) + transmute(package_name = sub("package:", "", library, fixed = TRUE)) used_pkgs <- parsedFile$`Session Information`$Packages %>% filter(package %in% pkgs$package_name) From 6f9e32b41048c78df53f0d7c2c3fe4ab4f1955b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:53:41 +0000 Subject: [PATCH 09/10] chore: clarify extract helper and normalize gsub call style Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/R/read_log_file.R b/R/read_log_file.R index a65cb927..8d605049 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -76,7 +76,8 @@ nest_sections <- function(adj_log_txt) { #' @noRd #' nest_subsections <- function(adj_log_txt, sect_info) { - # Extract the first regex match from each string and return NA when no match exists. + # Extract the first regex match from each string in `x` using `pattern`. + # Returns a character vector the same length as `x`, with `NA` for no match. extract_match <- function(x, pattern) { match_positions <- regexpr(pattern, x, perl = TRUE) result <- rep(NA_character_, length(x)) @@ -190,9 +191,9 @@ parse_log <- function(nested_log) { parsed_log$`Session Information`$`Packages` <- nested_log$`Session Information`$`Packages` %>% # remove indicator whether the package is attached to the search path - gsub("*", " ", x = ., fixed = TRUE) %>% + gsub("\\*", " ", ., fixed = TRUE) %>% # account for loaded packages due to load_all() - gsub(" P ", " ", x = ., fixed = TRUE) %>% + gsub(" P ", " ", ., fixed = TRUE) %>% readr::read_table(skip = 1, col_names = FALSE) # handle case where log is has 7 columns due to sessioninfo v1.2.2 or earlier From d22a87ca325de82b8b7abe147d547b4ed1fa909f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 19 Apr 2026 19:54:10 +0000 Subject: [PATCH 10/10] docs: expand inline helper parameter description Agent-Logs-Url: https://github.com/pharmaverse/logrx/sessions/1f987006-2fc0-4e5a-83dd-83305347351d Co-authored-by: bms63 <10111024+bms63@users.noreply.github.com> --- R/read_log_file.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/read_log_file.R b/R/read_log_file.R index 8d605049..9793214a 100644 --- a/R/read_log_file.R +++ b/R/read_log_file.R @@ -77,6 +77,8 @@ nest_sections <- function(adj_log_txt) { #' nest_subsections <- function(adj_log_txt, sect_info) { # Extract the first regex match from each string in `x` using `pattern`. + # x: character vector of strings to inspect. + # pattern: regular expression pattern to extract. # Returns a character vector the same length as `x`, with `NA` for no match. extract_match <- function(x, pattern) { match_positions <- regexpr(pattern, x, perl = TRUE)