diff --git a/R/build_tt.R b/R/build_tt.R new file mode 100644 index 00000000..607ed2e7 --- /dev/null +++ b/R/build_tt.R @@ -0,0 +1,39 @@ +# internal function +# style_tt() stores style calls and we only want to evaluate them at the end because +# some rows may be added, which changes how the style is applied +build_tt <- function(x) { + m <- meta(x) + + out <- x + + # format data before drawing the table + for (l in m$lazy_format) { + tmp <- out + class(tmp) <- "data.frame" + l[["x"]] <- tmp + out <- eval(l) + } + + # draw the table + lazy_tt <- meta(x, "lazy_tt") + lazy_tt[["x"]] <- out + out <- eval(lazy_tt) + + # group the table (before style) + for (l in m$lazy_group) { + l[["x"]] <- out + out <- eval(l) + } + + # style the table + for (l in m$lazy_style) { + l[["x"]] <- out + out <- eval(l) + } + + m <- meta(x) + m$lazy_style <- list() + attr(out, "tinytable_meta") <- m + + return(out) +} diff --git a/R/group_tabularray.R b/R/group_tabularray.R index e75d66a0..9ad70746 100644 --- a/R/group_tabularray.R +++ b/R/group_tabularray.R @@ -1,22 +1,20 @@ -group_tabularray <- function(x, i, j, indent, ...) { +group_tabularray <- function(x, i, j, indent) { out <- x # columns first to count headers properly if (!is.null(j)) { - out <- group_tabularray_col(out, j, ...) + out <- group_tabularray_col(out, j) } if (!is.null(i)) { - out <- group_tabularray_row(out, i, indent, ...) + out <- group_tabularray_row(out, i, indent) } return(out) } -group_tabularray_col <- function(x, j, ...) { +group_tabularray_col <- function(x, j) { m <- meta(x) - dots <- list(...) - out <- strsplit(x, split = "\\n")[[1]] header <- rep("", m$ncols) @@ -52,10 +50,6 @@ group_tabularray_col <- function(x, j, ...) { i = 1 - meta(out)$nhead, j = z, colspan = max(j[[k]]) - min(j[[k]]) + 1) - if (!"halign" %in% names(dots)) { - args["align"] <- "c" - } - args <- c(args, dots) out <- do.call(style_tt, args) } @@ -64,7 +58,7 @@ group_tabularray_col <- function(x, j, ...) { } -group_tabularray_row <- function(x, i, indent, ...) { +group_tabularray_row <- function(x, i, indent) { m <- meta(x) @@ -73,12 +67,13 @@ group_tabularray_row <- function(x, i, indent, ...) { } label <- names(i) - m$nrows <- m$nrows + length(label) tab <- strsplit(x, "\\n")[[1]] # store the original body lines when creating the table, and use those to guess the boundaries. # a hack, but probably safer than most regex approaches I can think of. - body <- which(tab %in% m$body) + body_min <- max(grep("TinyTableHeader|toprule|inner close", tab)) + 1 + body_max <- min(grep("bottomrule|end.tblr", tab)) + body <- body_min:body_max top <- tab[1:(min(body) - 1)] mid <- tab[min(body):max(body)] bot <- tab[(max(body) + 1):length(tab)] @@ -107,16 +102,10 @@ group_tabularray_row <- function(x, i, indent, ...) { # we also want to indent the header i <- idx$new[!is.na(idx$old)] + m$nhead if (m$nhead > 0) i <- c(1:m$nhead, i) - cellspec <- sprintf("cell{%s}{%s}={%s},", i, 1, sprintf("preto={\\hspace{%sem}}", indent)) + cellspec <- sprintf("cell{%s}{%s}={%s},\n", i, 1, sprintf("preto={\\hspace{%sem}}", indent)) cellspec <- paste(cellspec, collapse = "") tab <- tabularray_insert(tab, content = cellspec, type = "inner") - dots <- list(...) - if (length(dots) > 0) { - args <- c(list(x = tab, i = idx$new[is.na(idx$old)]), dots) - tab <- do.call(style_tt, args) - } - return(tab) } diff --git a/R/group_tt.R b/R/group_tt.R index 0304e099..07a42484 100644 --- a/R/group_tt.R +++ b/R/group_tt.R @@ -5,7 +5,7 @@ #' @inheritParams style_tt #' @param indent integer number of `pt` to use when indenting the non-labelled rows. #' @param ... All additional arguments (ex: `italic`, `bold`, `color`) are automatically passed to the `style_tt()` function and applied to the labels. -group_tt <- function(x, i = NULL, j = NULL, indent = 1, ...) { +group_tt <- function(x, i = NULL, j = NULL, indent = 1) { if (is.null(meta(x))) stop("`x` must be generated by `tinytable::tt()`.", call. = FALSE) if (!isTRUE(meta(x, "output") %in% c("html", "latex"))) return(x) @@ -24,11 +24,13 @@ group_tt <- function(x, i = NULL, j = NULL, indent = 1, ...) { i <- unlist(i) if (meta(out)$output == "latex") { - out <- group_tabularray(out, i = i, j = j, indent = indent, ...) + cal <- call("group_tabularray", i = i, j = j, indent = indent) } else if (meta(out)$output == "html") { - out <- group_bootstrap(out, i = i, j = j, indent = indent, ...) + cal <- call("group_botstrap", i = i, j = j, indent = indent) } + out <- meta(out, "lazy_group", c(meta(out)$lazy_group, list(cal))) + return(out) } diff --git a/R/style_tt.R b/R/style_tt.R index 57bb9dcd..2ddacde7 100644 --- a/R/style_tt.R +++ b/R/style_tt.R @@ -60,6 +60,7 @@ style_tt <- function (x, tabularray_outer = NULL, bootstrap_css = NULL, bootstrap_css_rule = NULL) { + out <- x cal <- call("style_tt_lazy", # out <- style_tt_lazy( diff --git a/R/tt.R b/R/tt.R index 5edc2252..2bb3d227 100644 --- a/R/tt.R +++ b/R/tt.R @@ -71,8 +71,6 @@ tt <- function(x, out <- meta(out, "nhead", if (is.null(colnames(x))) 0 else 1) out <- meta(out, "nrows", nrow(x)) out <- meta(out, "ncols", ncol(x)) - out <- meta(out, "lazy_style", list()) - out <- meta(out, "lazy_format", list()) class(out) <- c("tinytable", class(out)) # build table diff --git a/R/tt_tabularray.R b/R/tt_tabularray.R index fae247fe..2ddb2385 100644 --- a/R/tt_tabularray.R +++ b/R/tt_tabularray.R @@ -54,7 +54,6 @@ tt_tabularray <- function(x, caption, theme, width, notes, placement) { # needed later, apparently attr(out, "tinytable_meta") <- m - out <- meta(out, "nhead", if (is.null(colnames(x))) 1 else 0 ) if (!is.null(width)) { tabularray_cols <- rep("X[]", ncol(x)) diff --git a/R/utils.R b/R/utils.R index 7f9ba41e..153fcbeb 100644 --- a/R/utils.R +++ b/R/utils.R @@ -29,38 +29,3 @@ meta <- function(x, get, set) { } - -# style_tt() stores style calls and we only want to evaluate them at the end because -# some rows may be added, which changes how the style is applied -build_tt <- function(x) { - m <- meta(x) - - out <- x - - # format data before drawing the table - for (l in m$lazy_format) { - tmp <- out - class(tmp) <- "data.frame" - l[["x"]] <- tmp - out <- eval(l) - } - - # draw the table - lazy_tt <- meta(x, "lazy_tt") - lazy_tt[["x"]] <- out - out <- eval(lazy_tt) - - # TODO: group the table - - # style the table - for (l in m$lazy_style) { - l[["x"]] <- out - out <- eval(l) - } - - m <- meta(x) - m$lazy_style <- list() - attr(out, "tinytable_meta") <- m - - return(out) -} diff --git a/vignettes/tutorial.qmd b/vignettes/tutorial.qmd index a7c39c49..87d512db 100644 --- a/vignettes/tutorial.qmd +++ b/vignettes/tutorial.qmd @@ -508,20 +508,22 @@ tt(dat) |> "They love tofu" = 7)) ``` -The `group_tt()` function only includes a few arguments: `x`, `i`, `j`, and `indent`. But whenever we call `group_tt()`, the function will automatically apply a `style_tt()` call to all the new group labels, using any extra argument supplied to `group_tt()` (arguments are pushed via `...`). This means that we can apply all the usual stying options to row labels: +We can of style group rows in the same way as regular rows: ```{r} tt(dat) |> group_tt( - align = "c", - color = "white", - background = "gray", - bold = TRUE, i = list( "I like (fake) hamburgers" = 3, "She prefers halloumi" = 4, - "They love tofu" = 7)) + "They love tofu" = 7)) |> + style_tt( + i = c(3, 5, 9), + align = "c", + color = "white", + background = "gray", + bold = TRUE) ``` ## Columns @@ -537,33 +539,22 @@ tt(dat) |> "Tofu" = 7)) ``` -As above, we can pass additional styling options to the `style_tt()` function automatically via `...`. This means that all the arguments like `italic`, `bold`, `color` and friends can be used to style spanning column headers: +Here is a table with both row and column headers, as well as some styling: ```{r} dat <- mtcars[1:9, 1:8] tt(dat) |> group_tt(color = "teal", italic = TRUE, - j = list("Hamburgers" = 1:3, - "Halloumi" = 4:5, - "Tofu" = 7), i = list("I like (fake) hamburgers" = 3, "She prefers halloumi" = 4, - "They love tofu" = 7)) -``` - -Or call twice for different stylings for row and column groups: - -```{r} -dat <- mtcars[1:9, 1:8] -tt(dat) |> - group_tt(color = "teal", italic = TRUE, + "They love tofu" = 7), j = list("Hamburgers" = 1:3, "Halloumi" = 4:5, "Tofu" = 7)) |> - group_tt(align = "c", color = "white", background = "teal", bold = TRUE, - i = list("I like (fake) hamburgers" = 3, - "She prefers halloumi" = 4, - "They love tofu" = 7)) + style_tt( + i = c(3, 5, 9), + background = "teal", + color = "white") ```