Skip to content

Commit c80627d

Browse files
authored
Merge pull request #2101 from thebioengineer/latex_stub_separator
Add option latex.stub_separate
2 parents dbc92e9 + f08de28 commit c80627d

File tree

11 files changed

+291
-51
lines changed

11 files changed

+291
-51
lines changed

.Rbuildignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ tests/testthat/test-rtf_summary_rows.R
164164
tests/testthat/_snaps/rtf_summary_rows.md
165165

166166
tests/testthat/test-stub.R
167+
168+
tests/testthat/test-stub_separate.R
169+
tests/testthat/_snaps/stub_separate.md
170+
167171
tests/testthat/test-substitution.R
168172

169173
tests/testthat/test-summary_rows.R

NEWS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# gt (development version)
22

3-
* Update how long text that has a line break or is horizontally aligned in a cell (stubs, labels, table body).
3+
* Update how long text that has a line break or is horizontally aligned in a cell (stubs, labels, table body). (@thebioengineer)
4+
5+
* Added `stub.separate` option to control if vertical bars/borders are added for stubs (#2096). (@thebioengineer)
46

57
# gt 1.2.0
68

R/compile_scss.R

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ compile_scss <- function(data, id = NULL) {
3131
gt_options_tbl <-
3232
gt_options_tbl[gt_options_tbl$scss & !is.na(gt_options_tbl$value), ]
3333

34+
# If stub.separate is FALSE, override stub border style to "none"
35+
stub_separate <- dt_options_get_value(data = data, option = "stub_separate")
36+
37+
if (!is.na(stub_separate) && !stub_separate) {
38+
39+
stub_border_idx <-
40+
which(gt_options_tbl$parameter == "stub_border_style")
41+
42+
if (length(stub_border_idx) > 0) {
43+
gt_options_tbl$value[[stub_border_idx]] <- "none"
44+
}
45+
46+
stub_row_group_border_idx <-
47+
which(gt_options_tbl$parameter == "stub_row_group_border_style")
48+
49+
if (length(stub_row_group_border_idx) > 0) {
50+
gt_options_tbl$value[[stub_row_group_border_idx]] <- "none"
51+
}
52+
}
53+
3454
color_rows <- grepl("_color", gt_options_tbl$parameter, fixed = TRUE)
3555

3656
gt_options_tbl <-

R/dt_options.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ dt_options_tbl <-
274274
"quarto_use_bootstrap", FALSE, "quarto", "logical", FALSE,
275275
"latex_use_longtable", FALSE, "latex", "logical", FALSE,
276276
"latex_header_repeat", FALSE, "latex", "logical", FALSE,
277+
"stub_separate", FALSE, "stub", "logical", TRUE,
277278
"latex_toprule", FALSE, "latex", "logical", TRUE,
278279
"latex_bottomrule", FALSE, "latex", "logical", TRUE,
279280
"latex_tbl_pos", FALSE, "latex", "value", "t",

R/tab_options.R

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,14 @@
237237
#'
238238
#' The style, width, and color properties for the vertical border of the table
239239
#' stub.
240+
#'
241+
#' @param stub.separate
242+
#' *Specify whether the stub should have a separating vertical bar or not*
243+
#'
244+
#' Vertical bars typically separate the stub from the rest of the table columns.
245+
#' Setting this parameter to `FALSE` will remove that vertical separator line
246+
#' from the stub/body interface. Currently supported for HTML and LaTeX output
247+
#' formats. The default is `TRUE`.
240248
#'
241249
#' @param stub_row_group.font.size,stub_row_group.font.weight,stub_row_group.text_transform,stub_row_group.border.style,stub_row_group.border.width,stub_row_group.border.color
242250
#' *Properties of the row group column in the table stub*
@@ -542,7 +550,6 @@
542550
#' use the `longtable` environment which will not float and may span multiple
543551
#' pages.
544552
#'
545-
#'
546553
#' @param latex.header_repeat
547554
#'
548555
#' * Specify if the header should repeat or not across pages*
@@ -551,7 +558,7 @@
551558
#' every page. Setting this parameter to `TRUE` will add a `\endhead` command
552559
#' after the table headers so LaTeX knows where the headers end and will
553560
#' repeat them on every page.
554-
#'
561+
#'
555562
#' @param latex.toprule,latex.bottomrule
556563
#'
557564
#' * Specify if an hrule should be put in the table at the top (latex.toprule) or bottom (latex.bottomrule)*
@@ -561,7 +568,6 @@
561568
#' parameters to `FALSE` will instead not have these commands added, which
562569
#' lets the tables be produced without the top and bottom lines.
563570
#'
564-
#'
565571
#' @param latex.tbl.pos
566572
#'
567573
#' *Specify latex floating position*
@@ -812,6 +818,7 @@ tab_options <- function(
812818
stub.border.width = NULL,
813819
stub.border.color = NULL,
814820
stub.indent_length = NULL,
821+
stub.separate = NULL,
815822
stub_row_group.font.size = NULL,
816823
stub_row_group.font.weight = NULL,
817824
stub_row_group.text_transform = NULL,

R/utils_render_latex.R

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ create_table_start_l <- function(data, colwidth_df) {
196196
# - `>{\centering\arraybackslash}` <- center alignment
197197
# the `\arraybackslash` command is used to restore the behavior of the
198198
# `\\` command in the table (all of this uses the CTAN `array` package)
199+
199200
if (any(colwidth_df_visible$unspec < 1L)) {
200201

201202
col_defs <- NULL
@@ -234,7 +235,7 @@ create_table_start_l <- function(data, colwidth_df) {
234235
}
235236

236237
# # Add borders to the right of any columns in the stub
237-
if (length(stub_layout) > 0) {
238+
if (length(stub_layout) > 0 && dt_options_get_value(data, "stub_separate")) {
238239

239240
# Count the actual number of stub columns
240241
# When we have both group_label and rowname, we have 2 columns
@@ -1247,21 +1248,28 @@ summary_rows_for_group_l <- function(
12471248
##? TODO: GET COLUMN WIDTH TO ADD TO ALIGNMENT
12481249

12491250
if (stub_is_2) {
1251+
1252+
rowsplit_alignment <- "l"
1253+
1254+
if (dt_options_get_value(data, "stub_separate")) {
1255+
rowsplit_alignment <- paste0(rowsplit_alignment, "|")
1256+
}
1257+
12501258
row_splits_summary <-
12511259
lapply(
12521260
row_splits_summary,
12531261
function(x) {
12541262
x <- c("", x)
12551263
x[1] <- latex_multicolumn_cell(
12561264
x = x[1],
1257-
alignment = "l|",
1265+
alignment = rowsplit_alignment,
12581266
ncols = 1,
12591267
override_ncols = TRUE,
12601268
override_alignment = FALSE
12611269
)
12621270
x[2] <- latex_multicolumn_cell(
12631271
x = x[2],
1264-
alignment = "l|",
1272+
alignment = rowsplit_alignment,
12651273
ncols = 1,
12661274
override_ncols = TRUE,
12671275
override_alignment = FALSE
@@ -1317,7 +1325,7 @@ create_table_end_l <- function(data) {
13171325

13181326

13191327
paste0(
1320-
if(include_bottomrule){"\\bottomrule\n"},
1328+
if (include_bottomrule){"\\bottomrule\n"},
13211329
ifelse(dt_options_get_value(data = data, option = "latex_use_longtable"),
13221330
"\\end{longtable}\n",
13231331
"\\end{tabular*}\n"),
@@ -1385,11 +1393,11 @@ create_footer_component_l <- function(data) {
13851393
if(grepl("\\\\shortstack", footnote_latex)){
13861394

13871395
## remove linewidth parbox within a shortstack for footnotes, already within a parbox
1388-
footnote_latex <- gsub("(?<=\\\\shortstack\\[.\\]\\{)\\\\parbox\\{.+?\\}\\{(.+?)\\}","\\1",footnote_latex, perl = TRUE)
1396+
footnote_latex <- gsub("(?<=\\\\shortstack\\[.\\]\\{)\\\\parbox\\{.+?\\}\\{(.+?)\\}","\\1", footnote_latex, perl = TRUE)
13891397

13901398
## add footmark within shortstack
13911399
if(nzchar(footmark)){
1392-
footnote_latex <- gsub("(\\\\shortstack\\[.\\]\\{)(.+?\\})",paste0("\\1",gsub("\\","\\\\",footmark, fixed=TRUE),"\\2"), footnote_latex, perl = TRUE)
1400+
footnote_latex <- gsub("(\\\\shortstack\\[.\\]\\{)(.+?\\})",paste0("\\1",gsub("\\","\\\\", footmark, fixed=TRUE),"\\2"), footnote_latex, perl = TRUE)
13931401
}
13941402

13951403
}else{
@@ -1597,6 +1605,7 @@ create_body_rows_l <- function(
15971605
identical(colname_i, "::stub::") ||
15981606
grepl("^::stub_.*::$", colname_i)
15991607
) {
1608+
16001609
colwidth_i <- dplyr::filter(
16011610
colwidth_df,
16021611
type == "stub",
@@ -1609,16 +1618,17 @@ create_body_rows_l <- function(
16091618
)
16101619
}
16111620

1612-
if(sum(colwidth_i$unspec < 1) > 0){
1621+
if (sum(colwidth_i$unspec < 1) > 0) {
16131622
cell_width <- create_singlecolumn_width_text_l(pt = colwidth_i$pt, lw = colwidth_i$lw)
1614-
}else{
1623+
} else {
16151624
cell_width <- ""
16161625
}
16171626

1618-
content[i] <- apply_cell_styles_l(
1619-
content_i,
1620-
styles_body,
1621-
width = cell_width
1627+
content[i] <-
1628+
apply_cell_styles_l(
1629+
content_i,
1630+
styles_body,
1631+
width = cell_width
16221632
) |>
16231633
remove_footnote_encoding()
16241634

@@ -1640,12 +1650,11 @@ create_body_rows_l <- function(
16401650
)
16411651
}
16421652

1643-
if(isFALSE(sum(colwidth_i$unspec < 1) > 0)){
1644-
content_i <- gsub("\\\\parbox\\{\\\\linewidth\\}\\{(.+?)\\}","\\1",content_i)
1653+
if (isFALSE(sum(colwidth_i$unspec < 1) > 0)) {
1654+
content_i <- gsub("\\\\parbox\\{\\\\linewidth\\}\\{(.+?)\\}", "\\1", content_i)
16451655
}
16461656

1647-
## if styling set, remove the parbox if it is set to line width
1648-
1657+
# If styling set, remove the parbox if it is set to line width
16491658
content[i] <- remove_footnote_encoding(content_i)
16501659

16511660
}
@@ -1665,48 +1674,48 @@ create_body_rows_l <- function(
16651674
# cells not modified by tab_style calls.
16661675
remove_footnote_encoding <- function(x) {
16671676

1668-
## if no footnotes, move along
1669-
if((sum(grepl("%%%(right|left):",x)) == 0)){
1677+
# If no footnotes, move along
1678+
if ((sum(grepl("%%%(right|left):",x)) == 0)) {
16701679
return(x)
16711680
}
16721681

1673-
## if there are footnotes, loop through
1674-
1675-
for( i in seq_along(x)){
1682+
# If there are footnotes, loop through
1683+
for (i in seq_along(x)) {
16761684

16771685
x_i <- x[i]
16781686

1679-
if(grepl("\\\\(shortstack|parbox)",x_i)){
1687+
if (grepl("\\\\(shortstack|parbox)", x_i)) {
16801688

1681-
if(grepl("%%%right:",x_i)){
1689+
if (grepl("%%%right:", x_i)) {
16821690
footmark_text <- regmatches(x_i, regexec("(?<=%%%right:).+$", x_i, perl = TRUE))[[1]]
1683-
if(grepl("%%%left:", footmark_text)){
1691+
if (grepl("%%%left:", footmark_text)) {
16841692
footmark_text <- regmatches(footmark_text, regexec(".+?(?=%%%left:)", footmark_text, perl = TRUE))[[1]]
16851693
}
16861694
content_x <- regmatches(x_i, regexec(".+?(?=%%%right:)", x_i, perl = TRUE))[[1]]
16871695

1688-
if(grepl("\\\\shortstack", content_x)){
1689-
x_i <- gsub("(\\\\shortstack\\[.\\]\\{(\\\\parbox\\{.+?\\}\\{)*.+?)((\\}\\s*)+$)",paste0("\\1",gsub("\\","\\\\",footmark_text, fixed=TRUE)," \\3"), content_x, perl = TRUE)
1690-
}else{
1691-
x_i <- gsub("((\\\\parbox\\{.+?\\}\\{).+?)((\\}\\s*)+$)",paste0("\\1",gsub("\\","\\\\",footmark_text, fixed=TRUE)," \\3"), content_x, perl = TRUE)
1696+
if (grepl("\\\\shortstack", content_x)) {
1697+
x_i <- gsub("(\\\\shortstack\\[.\\]\\{(\\\\parbox\\{.+?\\}\\{)*.+?)((\\}\\s*)+$)", paste0("\\1", gsub("\\", "\\\\", footmark_text, fixed=TRUE), " \\3"), content_x, perl = TRUE)
1698+
} else {
1699+
x_i <- gsub("((\\\\parbox\\{.+?\\}\\{).+?)((\\}\\s*)+$)", paste0("\\1", gsub("\\", "\\\\", footmark_text, fixed=TRUE), " \\3"), content_x, perl = TRUE)
16921700
}
1693-
} else if(grepl("%%%left:",x_i)){
1701+
} else if (grepl("%%%left:",x_i)) {
16941702
footmark_text <- regmatches(x_i, regexec("(?<=%%%left:).+?$", x_i, perl = TRUE))[[1]]
16951703
content_x <- regmatches(x_i, regexec(".+?(?=%%%left:)", x_i, perl = TRUE))[[1]]
1696-
## add footmark within shortstack
1697-
if(grepl("\\\\shortstack", content_x)){
1698-
x_i <- gsub("(\\\\shortstack\\[.\\]\\{(\\\\parbox\\{.+?\\}\\{)*)(.+?\\})",paste0("\\1",gsub("\\","\\\\",footmark_text, fixed=TRUE)," \\3"), content_x, perl = TRUE)
1699-
}else{
1700-
x_i <- gsub("((\\\\parbox\\{.+?\\}\\{).+?)\\s(.+?((\\}\\s*)+$))",paste0("\\1",gsub("\\","\\\\",footmark_text, fixed=TRUE)," \\3"), content_x, perl = TRUE)
1704+
1705+
# Add footmark within shortstack
1706+
if (grepl("\\\\shortstack", content_x)) {
1707+
x_i <- gsub("(\\\\shortstack\\[.\\]\\{(\\\\parbox\\{.+?\\}\\{)*)(.+?\\})", paste0("\\1", gsub("\\", "\\\\", footmark_text, fixed=TRUE), " \\3"), content_x, perl = TRUE)
1708+
} else {
1709+
x_i <- gsub("((\\\\parbox\\{.+?\\}\\{).+?)\\s(.+?((\\}\\s*)+$))", paste0("\\1", gsub("\\", "\\\\", footmark_text, fixed=TRUE), " \\3"), content_x, perl = TRUE)
17011710
}
17021711

17031712
}
17041713

1705-
}else{
1706-
if(grepl("%%%right:",x_i)){
1714+
} else {
1715+
if (grepl("%%%right:",x_i)) {
17071716
x_i <- gsub("%%%(right):", "", x_i)
17081717
}
1709-
if(grepl("%%%left:", x_i)){
1718+
if (grepl("%%%left:", x_i)) {
17101719

17111720
footmark_text <- regmatches(x_i, regexec("(?<=%%%left:).+?$", x_i, perl = TRUE))[[1]]
17121721
content_x <- regmatches(x_i, regexec(".+?(?=%%%left:)", x_i, perl = TRUE))[[1]]
@@ -1734,11 +1743,13 @@ convert_font_size_l <- function(x) {
17341743
`default` = ""
17351744
)
17361745

1746+
if (as.character(x) %in% names(size_map)) {
17371747

1738-
if (as.character(x) %in% names(size_map)){
17391748
return(size_map[[x]])
1740-
}else if(grepl("(pt|%|px|in|cm|emu|em)",x)){
1741-
return(.apply_style_fontsize_l(list('cell_text' = list('size' = round(parse_font_size_l(x))))))
1749+
1750+
} else if (grepl("(pt|%|px|in|cm|emu|em)", x)) {
1751+
1752+
return(.apply_style_fontsize_l(list("cell_text" = list("size" = round(parse_font_size_l(x))))))
17421753
}
17431754

17441755
NULL
@@ -1806,6 +1817,11 @@ create_summary_rows_l <- function(
18061817

18071818
if (stub_width > 1) {
18081819

1820+
rowsplit_alignment <- "l"
1821+
if (dt_options_get_value(data, "stub_separate")) {
1822+
rowsplit_alignment <- paste0(rowsplit_alignment, "|")
1823+
}
1824+
18091825
row_splits_summary <-
18101826
lapply(
18111827
row_splits_summary,
@@ -1814,8 +1830,8 @@ create_summary_rows_l <- function(
18141830
x <- c(rep("", stub_width - 1), x)
18151831

18161832
x[seq_len(stub_width)] <- sapply(x[seq_len(stub_width)], function(x) {
1817-
latex_multicolumn_cell(x, ncols = 1, alignment = "l|", override_alignment = FALSE)
1818-
})
1833+
latex_multicolumn_cell(x, ncols = 1, alignment = rowsplit_alignment, override_alignment = FALSE)
1834+
})
18191835

18201836
x
18211837
}
@@ -1877,10 +1893,12 @@ derive_table_width_statement_l <- function(data) {
18771893

18781894
# Bookends are not required if a table width is not specified
18791895
# of if using floating table
1880-
if (table_width == "auto" ||
1881-
!dt_options_get_value(data = data, option = "latex_use_longtable")) {
1896+
if (
1897+
table_width == "auto" ||
1898+
!dt_options_get_value(data = data, option = "latex_use_longtable")
1899+
) {
18821900

1883-
statement <- ''
1901+
statement <- ""
18841902

18851903
} else if (endsWith(table_width, "%")) {
18861904

@@ -1916,7 +1934,6 @@ derive_table_width_statement_l <- function(data) {
19161934
}
19171935

19181936
statement
1919-
19201937
}
19211938

19221939
#' Consolidate Cell Styles

man/tab_options.Rd

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)