From 1e67e4c1001dbee8202bfaec0f17ce789250c0db Mon Sep 17 00:00:00 2001 From: Abel Vertesy Date: Wed, 2 Sep 2026 14:39:32 +0200 Subject: [PATCH 1/3] Dev (#38) * docs: remove duplicate title * Fix documentation typos and metadata (#17) * Add AGENTS guide for repository (#19) * Add defensive stopifnot checks to file path builder (#18) * Annotate code: explain the non-obvious operations (#30) * Annotate code; flag 3 pre-existing bugs (not fixed) * Fix 3 bugs flagged in PR #30 review - read.simple.ssv(): add missing `asTibble` parameter (was referenced but never defined, erroring whenever wRownames = TRUE, the default). - write.simple.xlsx(): assignRownames() now uses its own argument `x` instead of the undefined `df`, fixing has_row_names = FALSE. - qs.2.table(): fix `qs:qread` -> `qs::qread`, use the real `stringi::stri_detect_regex` function, and define `base_filename`/ `out_path` on every branch so the function actually runs. Also adds `stringi` to Imports/NAMESPACE since it's now genuinely used. Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> * Fix qs.2.table()'s excel branch crashing on a bare data.frame write.simple.xlsx() requires a list of sheets; qs.2.table() was passing the loaded table directly, which fails its is.data.frame(x)-per-element assertion. Wrap it in a list first. Co-Authored-By: Claude Sonnet 5 --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 * Address Codex review: declare stringi dependency, preserve row names on xlsx export - DESCRIPTION: add stringi to Imports, since R/ReadWriter.R now calls stringi::stri_detect_regex() and NAMESPACE already declares the importFrom. - write.simple.xlsx(): when has_row_names = FALSE, the identifier column is moved into row names via column.2.row.names() before writing. The final write.xlsx() call still passed the original has_row_names (FALSE) as rowNames, so those converted identifiers were dropped from the workbook. Track the post-conversion state separately (write_row_names) and pass that to write.xlsx() instead. Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> * Consolidate list-of-functions cleanup into one file.remove() call (#34) Replaces the per-file file.remove() call with a single call that matches every generated list.of.functions.in.*.det.md report by pattern (this repo generates 2: ReadWriter and Deprecated.Functions -- only the first was ever cleaned up before). The old line is commented out, not deleted. Co-authored-by: Claude Sonnet 5 * Fix qs.2.table to preserve directory of absolute input paths Pass dirname(path) as manual_directory and the extensionless basename(path) as manual_file_name for every output branch, so construct.file.path() no longer prepends getwd() to an already absolute filename (Codex review feedback on #38). Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- R/ReadWriter.R | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/R/ReadWriter.R b/R/ReadWriter.R index c197c54..571a9c1 100644 --- a/R/ReadWriter.R +++ b/R/ReadWriter.R @@ -1157,15 +1157,19 @@ qs.2.table <- function(path, out_file = c("tsv", "csv", "csv2", "excel")[1]) { # Base name (without extension) shared by all output formats base_filename <- sub("\\.qs$", "", path) + # Split into directory + extensionless file name so absolute paths in `path` + # are preserved (construct.file.path() would otherwise prepend getwd()). + out_dir <- dirname(base_filename) + out_name <- basename(base_filename) if (out_file == "tsv") { - ReadWriter::write.simple.tsv(data, manual_file_name = base_filename, separator = "\t") + ReadWriter::write.simple.tsv(data, manual_file_name = out_name, manual_directory = out_dir, separator = "\t") out_path <- paste0(base_filename, ".tsv") } else if (out_file == "csv") { - ReadWriter::write.simple.tsv(data, manual_file_name = base_filename, separator = ",") + ReadWriter::write.simple.tsv(data, manual_file_name = out_name, manual_directory = out_dir, separator = ",") out_path <- paste0(base_filename, ".csv") } else if (out_file == "csv2") { - ReadWriter::write.simple.tsv(data, manual_file_name = base_filename, separator = ";") + ReadWriter::write.simple.tsv(data, manual_file_name = out_name, manual_directory = out_dir, separator = ";") out_path <- paste0(base_filename, ".csv") } else if (out_file == "excel") { # write.simple.xlsx() expects a list of sheets; wrap a bare table into one. From 8168a953f32b3a0a55ab958afc46ab75d09f282d Mon Sep 17 00:00:00 2001 From: Abel Vertesy Date: Wed, 2 Sep 2026 15:26:13 +0200 Subject: [PATCH 2/3] Dev (#40) * docs: remove duplicate title * Fix documentation typos and metadata (#17) * Add AGENTS guide for repository (#19) * Add defensive stopifnot checks to file path builder (#18) * Annotate code: explain the non-obvious operations (#30) * Annotate code; flag 3 pre-existing bugs (not fixed) * Fix 3 bugs flagged in PR #30 review - read.simple.ssv(): add missing `asTibble` parameter (was referenced but never defined, erroring whenever wRownames = TRUE, the default). - write.simple.xlsx(): assignRownames() now uses its own argument `x` instead of the undefined `df`, fixing has_row_names = FALSE. - qs.2.table(): fix `qs:qread` -> `qs::qread`, use the real `stringi::stri_detect_regex` function, and define `base_filename`/ `out_path` on every branch so the function actually runs. Also adds `stringi` to Imports/NAMESPACE since it's now genuinely used. Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> * Fix qs.2.table()'s excel branch crashing on a bare data.frame write.simple.xlsx() requires a list of sheets; qs.2.table() was passing the loaded table directly, which fails its is.data.frame(x)-per-element assertion. Wrap it in a list first. Co-Authored-By: Claude Sonnet 5 --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 * Address Codex review: declare stringi dependency, preserve row names on xlsx export - DESCRIPTION: add stringi to Imports, since R/ReadWriter.R now calls stringi::stri_detect_regex() and NAMESPACE already declares the importFrom. - write.simple.xlsx(): when has_row_names = FALSE, the identifier column is moved into row names via column.2.row.names() before writing. The final write.xlsx() call still passed the original has_row_names (FALSE) as rowNames, so those converted identifiers were dropped from the workbook. Track the post-conversion state separately (write_row_names) and pass that to write.xlsx() instead. Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> * Consolidate list-of-functions cleanup into one file.remove() call (#34) Replaces the per-file file.remove() call with a single call that matches every generated list.of.functions.in.*.det.md report by pattern (this repo generates 2: ReadWriter and Deprecated.Functions -- only the first was ever cleaned up before). The old line is commented out, not deleted. Co-authored-by: Claude Sonnet 5 * Fix qs.2.table to preserve directory of absolute input paths Pass dirname(path) as manual_directory and the extensionless basename(path) as manual_file_name for every output branch, so construct.file.path() no longer prepends getwd() to an already absolute filename (Codex review feedback on #38). Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> * Fix Excel output path for QS conversion --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- R/ReadWriter.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/ReadWriter.R b/R/ReadWriter.R index 571a9c1..284780a 100644 --- a/R/ReadWriter.R +++ b/R/ReadWriter.R @@ -1174,7 +1174,7 @@ qs.2.table <- function(path, out_file = c("tsv", "csv", "csv2", "excel")[1]) { } else if (out_file == "excel") { # write.simple.xlsx() expects a list of sheets; wrap a bare table into one. payload <- if (is.data.frame(data) || is.matrix(data)) list(data) else data - ReadWriter::write.simple.xlsx(payload, manual_file_name = base_filename) + ReadWriter::write.simple.xlsx(payload, manual_file_name = out_name, manual_directory = out_dir) out_path <- paste0(base_filename, ".xlsx") } From dc9f536db7c55fd62f140419968ea86bf71d1d97 Mon Sep 17 00:00:00 2001 From: Abel Vertesy Date: Wed, 2 Sep 2026 15:34:06 +0200 Subject: [PATCH 3/3] Repackaged version: v1.7.0 --- CITATION.cff | 2 +- DESCRIPTION | 6 +++--- Development/Create_the_ReadWriter_Package.R | 18 ++++++++++++++++-- Development/config.R | 2 +- NAMESPACE | 2 ++ man/read.simple.xls.Rd | 2 +- man/write.simplest.Rd | 2 +- 7 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 0944304..e13124e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,6 +1,6 @@ cff-version: 1.2.0 title: vertesy/ReadWriter Functions to read and write tabular data files conveniently. -version: v1.6.9 +version: v1.7.0 message: >- If you use this software, please cite it using these metadata. type: software diff --git a/DESCRIPTION b/DESCRIPTION index f4f3d37..a5fd083 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: ReadWriter Title: ReadWriter -Version: 1.6.9 +Version: 1.7.0 Authors@R: person("Abel", "Vertesy", , "av@imba.oeaw.ac.at", role = c("aut", "cre")) Description: ReadWriter is a set of R functions to read and write files @@ -9,13 +9,13 @@ License: GPL-3 + file LICENSE BugReports: https://github.com/vertesy/ReadWriter/issues Depends: Stringendo (>= 0.5.0) -Imports: +Imports: gtools, openxlsx, qs, readr, stringi Encoding: UTF-8 -Packaged: 2026-08-25 16:41:37.734198 +Packaged: 2026-09-02 15:32:34.871125 Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.2 diff --git a/Development/Create_the_ReadWriter_Package.R b/Development/Create_the_ReadWriter_Package.R index db44c14..da72cae 100644 --- a/Development/Create_the_ReadWriter_Package.R +++ b/Development/Create_the_ReadWriter_Package.R @@ -15,10 +15,24 @@ config.path <- file.path(repository.dir, "Development/config.R") "TAKE A LOOK AT" file.edit(config.path) source(config.path) -package.name <- DESCRIPTION$'package.name' + +# Check and Document your package ------------------------------------------------ +devtools::check_man(repository.dir) PackageTools::document_and_create_package(repository.dir, config_file = 'config.R') -'git add commit push to remote' + + +# Automated Codebase linting to tidyverse style ------------------------------------------------ +styler::style_pkg(repository.dir) +# styler::style_file("~/GitHub/Packages/Seurat.utils/R/Seurat.Utils.Visualization.R") + +# Replaces T with TRUE and F with FALSE ------------------------------------------------ +(ls.scripts.full.path <- list.files(file.path(repository.dir, "R"), full.names = T, pattern = '.R$')) +for (scriptX in ls.scripts.full.path) { + PackageTools::replace_tf_with_true_false(scriptX) + PackageTools::replace_short_calls(scriptX) +} + # Install your package ------------------------------------------------ "disable rprofile by" diff --git a/Development/config.R b/Development/config.R index 593f8b9..0c2ef1b 100644 --- a/Development/config.R +++ b/Development/config.R @@ -3,7 +3,7 @@ DESCRIPTION <- list( package.name = "ReadWriter", - version = "1.6.9", + version = "1.7.0", title = "ReadWriter", description = "ReadWriter is a set of R functions to read and write files conveniently. Builds on Stringendo and complements CodeAndRoll2.", diff --git a/NAMESPACE b/NAMESPACE index 5d57af3..7cf54dc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -23,6 +23,8 @@ export(write.simple.tsv) export(write.simple.vec) export(write.simple.xlsx) export(write.simplest) +importFrom(Stringendo,ParseFullFilePath) +importFrom(Stringendo,sppp) importFrom(gtools,na.replace) importFrom(openxlsx,createStyle) importFrom(openxlsx,getSheetNames) diff --git a/man/read.simple.xls.Rd b/man/read.simple.xls.Rd index 1663ee1..48bfabb 100644 --- a/man/read.simple.xls.Rd +++ b/man/read.simple.xls.Rd @@ -5,7 +5,7 @@ \title{read.simple.xls} \usage{ read.simple.xls( - pfn = kollapse(...), + pfn = Stringendo::kollapse(...), row_namePos = NULL, ..., header_ = TRUE, diff --git a/man/write.simplest.Rd b/man/write.simplest.Rd index 737e6a4..b6fcccc 100644 --- a/man/write.simplest.Rd +++ b/man/write.simplest.Rd @@ -8,7 +8,7 @@ write.simplest( vec = LETTERS[1:11], append = TRUE, header = NULL, - prefix = kppws(substitute(vec), idate()), + prefix = Stringendo::kppws(substitute(vec), Stringendo::idate()), file_path = get0("path_write_simplest", ifnotfound = "./__clipboard.txt") ) }