| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 1 | #' Put a few rows of a table into one category | 
 | 2 | #' | 
| Hao Zhu | bd95bb2 | 2017-05-22 16:08:49 -0400 | [diff] [blame] | 3 | #' @description Group a few rows in a table together under a label. | 
 | 4 | #' | 
 | 5 | #' @param kable_input Output of `knitr::kable()` with `format` specified | 
 | 6 | #' @param group_label A character string for the name of the group | 
 | 7 | #' @param start_row A numeric value that tells the function in which row the | 
 | 8 | #' group starts. Note that the counting excludes header rows and other group | 
 | 9 | #' labeling rows | 
 | 10 | #' @param end_row A numeric value that tells the function in which row the group | 
 | 11 | #' ends. | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 12 | #' @param index A named vector providing the index for robust row-grouping tasks. | 
 | 13 | #' Basically, you can use it in the same way as `add_header_above()`. | 
| Hao Zhu | bd95bb2 | 2017-05-22 16:08:49 -0400 | [diff] [blame] | 14 | #' @param label_row_css A character string for any customized css used for the | 
 | 15 | #' labeling row. By default, the labeling row will have a solid black line | 
 | 16 | #' underneath. Only useful for HTML documents. | 
 | 17 | #' @param latex_gap_space A character value telling LaTeX how large the gap | 
 | 18 | #' between the previous row and the group labeling row. Only useful for LaTeX | 
 | 19 | #' documents. | 
| Hao Zhu | ac7e70f | 2017-08-02 00:18:36 -0400 | [diff] [blame] | 20 | #' @param escape A T/F value showing whether special characters should be | 
 | 21 | #' escaped. | 
| Salzer | 8f49eb6 | 2018-02-12 22:19:06 -0500 | [diff] [blame] | 22 | #' @param latex_align Adjust justification of group_label in latex only. Value should be "c" for | 
| Salzer | 1555085 | 2018-02-12 22:09:14 -0500 | [diff] [blame] | 23 | #' centered on row, "r" for right justification, or "l" for left justification. Default | 
 | 24 | #' Value is "l"  If using html, the alignment can be set by using the label_row_css | 
 | 25 | #' parameter. | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 26 | #' @param latex_wrap_text T/F for wrapping long text. Default is off. Whenever | 
 | 27 | #' it is turned on, the table will take up the entire line. It's recommended | 
 | 28 | #' to use this with full_width in kable_styling. | 
| bsalzer | 8593327 | 2018-02-12 17:26:46 -0500 | [diff] [blame] | 29 | #' @param colnum A numeric that determines how many columns the text should span. | 
 | 30 | #' The default setting will have the text span the entire length. | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 31 | #' @param bold A T/F value to control whether the text should be bolded. | 
 | 32 | #' @param italic A T/F value to control whether the text should to be emphasized. | 
| Brian Salzer | a3f43ad | 2018-03-04 15:03:20 -0500 | [diff] [blame] | 33 | #' @param hline_before A T/F value that addes a horizontal line before the group_row label.  Default | 
 | 34 | #' value is False. | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 35 | #' @param hline_after A replicate of `hline.after` in xtable. It | 
| Hao Zhu | 6191e74 | 2018-03-01 13:09:08 -0500 | [diff] [blame] | 36 | #' addes a hline after the row | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 37 | #' @param extra_latex_after Extra LaTeX text to be added after the row. | 
| Hao Zhu | ebdb3c2 | 2020-08-12 08:27:38 -0400 | [diff] [blame] | 38 | #' @param indent A T/F value to control whether list items are indented. | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 39 | #' @param monospace T/F value to control whether the text of the | 
 | 40 | #' selected column need to be monospaced (verbatim) | 
| Hao Zhu | 718fa3f | 2020-08-19 08:23:28 -0400 | [diff] [blame] | 41 | #' @param underline T/F value to control whether the text of the | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 42 | #' selected row need to be underlined | 
 | 43 | #' @param strikeout T/F value to control whether the text of the | 
 | 44 | #' selected row need to be striked out. | 
 | 45 | #' @param color A character string for column text color. Here please | 
 | 46 | #' pay attention to the differences in color codes between HTML and LaTeX. | 
 | 47 | #' @param background A character string for column background color. Here please | 
 | 48 | #' pay attention to the differences in color codes between HTML and LaTeX. | 
| Hao Zhu | bd95bb2 | 2017-05-22 16:08:49 -0400 | [diff] [blame] | 49 | #' | 
| Hao Zhu | 9399dcc | 2020-08-26 17:27:38 -0400 | [diff] [blame] | 50 | #' @examples | 
 | 51 | #' \dontrun{ | 
 | 52 | #' x <- knitr::kable(head(mtcars), "html") | 
| Hao Zhu | 78e6122 | 2017-05-24 20:53:35 -0400 | [diff] [blame] | 53 | #' # Put Row 2 to Row 5 into a Group and label it as "Group A" | 
| Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame] | 54 | #' pack_rows(x, "Group A", 2, 5) | 
| Hao Zhu | 9399dcc | 2020-08-26 17:27:38 -0400 | [diff] [blame] | 55 | #' } | 
| Hao Zhu | 78e6122 | 2017-05-24 20:53:35 -0400 | [diff] [blame] | 56 | #' | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 57 | #' @export | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 58 | group_rows <- function(kable_input, group_label = NULL, | 
 | 59 |                        start_row = NULL, end_row = NULL, | 
 | 60 |                        index = NULL, | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 61 |                        label_row_css = "border-bottom: 1px solid;", | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 62 |                        latex_gap_space = "0.3em", | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 63 |                        escape = TRUE, latex_align = "l", | 
 | 64 |                        latex_wrap_text = FALSE, | 
 | 65 |                        colnum = NULL, | 
| Hao Zhu | 2742ffc | 2018-10-17 11:23:44 -0400 | [diff] [blame] | 66 |                        bold = TRUE, | 
 | 67 |                        italic = FALSE, | 
 | 68 |                        hline_before = FALSE, | 
 | 69 |                        hline_after = FALSE, | 
 | 70 |                        extra_latex_after = NULL, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 71 |                        indent = TRUE, | 
 | 72 |                        monospace = FALSE, underline = FALSE, strikeout = FALSE, | 
 | 73 |                        color = NULL, background = NULL) { | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 74 |  | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 75 |   kable_format <- attr(kable_input, "format") | 
 | 76 |   if (!kable_format %in% c("html", "latex")) { | 
| Hao Zhu | 401ebd8 | 2018-01-14 17:10:20 -0500 | [diff] [blame] | 77 |     warning("Please specify format in kable. kableExtra can customize either ", | 
 | 78 |             "HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ ", | 
 | 79 |             "for details.") | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 80 |     return(kable_input) | 
 | 81 |   } | 
| Adrien Le Guillou | fdffec6 | 2019-09-04 00:03:52 +0200 | [diff] [blame] | 82 |  | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 83 |   if (is.null(index)) { | 
 | 84 |     if (kable_format == "html") { | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 85 |       if (!missing(latex_align)) warning("latex_align parameter is not used in HTML Mode, | 
| Salzer | 1555085 | 2018-02-12 22:09:14 -0500 | [diff] [blame] | 86 |                                     use label_row_css instead.") | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 87 |       return(group_rows_html(kable_input, group_label, start_row, end_row, | 
| Adrien Le Guillou | fdffec6 | 2019-09-04 00:03:52 +0200 | [diff] [blame] | 88 |                              label_row_css, escape, colnum, indent, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 89 |                              bold, italic, monospace, underline, strikeout, | 
 | 90 |                              color, background))} | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 91 |     if (kable_format == "latex") { | 
 | 92 |       return(group_rows_latex(kable_input, group_label, start_row, end_row, | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 93 |                               latex_gap_space, escape, latex_align, colnum, | 
| Hao Zhu | 2742ffc | 2018-10-17 11:23:44 -0400 | [diff] [blame] | 94 |                               bold, italic, hline_before, hline_after, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 95 |                               extra_latex_after, indent, latex_wrap_text, | 
 | 96 |                               monospace, underline, strikeout, | 
 | 97 |                               color, background)) | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 98 |     } | 
 | 99 |   } else { | 
 | 100 |     index <- group_row_index_translator(index) | 
 | 101 |     out <- kable_input | 
 | 102 |     if (kable_format == "html") { | 
 | 103 |       for (i in 1:nrow(index)) { | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 104 |         if (!missing(latex_align)) warning("latex_align parameter is not used in HTML Mode, | 
| Salzer | 1555085 | 2018-02-12 22:09:14 -0500 | [diff] [blame] | 105 |                                     use label_row_css instead.") | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 106 |         out <- group_rows_html(out, index$header[i], | 
 | 107 |                                index$start[i], index$end[i], | 
| Adrien Le Guillou | fdffec6 | 2019-09-04 00:03:52 +0200 | [diff] [blame] | 108 |                                label_row_css, escape, colnum, indent, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 109 |                                bold, italic, monospace, underline, strikeout, | 
 | 110 |                                color, background) | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 111 |       } | 
 | 112 |     } | 
 | 113 |     if (kable_format == "latex") { | 
 | 114 |       for (i in 1:nrow(index)) { | 
 | 115 |         out <- group_rows_latex(out, index$header[i], | 
 | 116 |                                index$start[i], index$end[i], | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 117 |                                latex_gap_space, escape, latex_align, colnum, | 
| Hao Zhu | 2742ffc | 2018-10-17 11:23:44 -0400 | [diff] [blame] | 118 |                                bold, italic, hline_before, hline_after, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 119 |                                extra_latex_after, indent, latex_wrap_text, | 
 | 120 |                                monospace, underline, strikeout, | 
 | 121 |                                color, background) | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 122 |       } | 
 | 123 |     } | 
 | 124 |     return(out) | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 125 |   } | 
| Hao Zhu | 49483bf | 2017-09-12 11:21:00 -0400 | [diff] [blame] | 126 | } | 
 | 127 |  | 
 | 128 | group_row_index_translator <- function(index) { | 
 | 129 |   index <- standardize_header_input(index) | 
 | 130 |   index$start <- cumsum(c(1, index$colspan))[1:length(index$colspan)] | 
 | 131 |   index$end <- cumsum(index$colspan) | 
 | 132 |   index$header <- trimws(index$header) | 
 | 133 |   index <- index[index$header != "", ] | 
 | 134 |   return(index) | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 135 | } | 
 | 136 |  | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 137 | group_rows_html <- function(kable_input, group_label, start_row, end_row, | 
| Hao Zhu | cedf90e | 2020-08-12 08:45:34 -0400 | [diff] [blame] | 138 |                             label_row_css, escape, colnum, indent, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 139 |                             bold, italic, monospace, underline, strikeout, | 
 | 140 |                             color, background) { | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 141 |   kable_attrs <- attributes(kable_input) | 
| Hao Zhu | 558c72f | 2017-07-24 15:12:00 -0400 | [diff] [blame] | 142 |   kable_xml <- read_kable_as_xml(kable_input) | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 143 |   kable_tbody <- xml_tpart(kable_xml, "tbody") | 
 | 144 |  | 
| Hao Zhu | ac7e70f | 2017-08-02 00:18:36 -0400 | [diff] [blame] | 145 |   if (escape) { | 
 | 146 |     group_label <- escape_html(group_label) | 
 | 147 |   } | 
 | 148 |  | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 149 |   group_header_rows <- attr(kable_input, "group_header_rows") | 
 | 150 |   group_seq <- seq(start_row, end_row) | 
 | 151 |   if (!is.null(group_header_rows)) { | 
 | 152 |     group_seq <- positions_corrector(group_seq, group_header_rows, | 
 | 153 |                                      length(xml_children(kable_tbody))) | 
| jokorn | 69c8bd5 | 2019-06-29 11:11:11 +0200 | [diff] [blame] | 154 |     # Update the old group_header_rows attribute with their new positions | 
 | 155 |     kable_attrs$group_header_rows <- ifelse(kable_attrs$group_header_rows > group_seq[1], | 
 | 156 |                                             kable_attrs$group_header_rows+1, | 
 | 157 |                                             kable_attrs$group_header_rows) | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 158 |   } | 
 | 159 |  | 
 | 160 |   # Insert a group header row | 
 | 161 |   starting_node <- xml_child(kable_tbody, group_seq[1]) | 
| bsalzer | 8593327 | 2018-02-12 17:26:46 -0500 | [diff] [blame] | 162 |   kable_ncol <- ifelse(is.null(colnum), | 
 | 163 |                        length(xml_children(starting_node)), | 
 | 164 |                        colnum) | 
| Adrien Le Guillou | fdffec6 | 2019-09-04 00:03:52 +0200 | [diff] [blame] | 165 |  | 
 | 166 |   if (bold) group_label <- paste0("<strong>", group_label, "</strong>") | 
 | 167 |   if (italic) group_label <- paste0("<em>", group_label, "</em>") | 
 | 168 |  | 
| Hao Zhu | 8b16a6c | 2020-08-18 16:59:20 -0400 | [diff] [blame] | 169 |   if (label_row_css == "border-bottom: 1px solid;") { | 
 | 170 |     if (!is.null(attr(kable_input, "lightable_class"))) { | 
 | 171 |       lightable_class <- attr(kable_input, "lightable_class") | 
 | 172 |       if (lightable_class %in% c( | 
 | 173 |         "lightable-classic", "lightable-classic-2", "lightable-minimal")) { | 
 | 174 |         label_row_css <- "border-bottom: 0;" | 
 | 175 |       } | 
 | 176 |       if (lightable_class %in% c("lightable-paper")) { | 
 | 177 |         label_row_css <- "border-bottom: 1px solid #00000020;" | 
 | 178 |       } | 
 | 179 |       if (lightable_class %in% c("lightable-material")) { | 
 | 180 |         label_row_css <- "border-bottom: 1px solid #eee; " | 
 | 181 |       } | 
 | 182 |       if (lightable_class %in% c("lightable-material-dark")) { | 
 | 183 |         label_row_css <- "border-bottom: 1px solid #FFFFFF12; color: #FFFFFF60;" | 
 | 184 |       } | 
 | 185 |     } | 
 | 186 |   } | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 187 |   if (monospace) { | 
 | 188 |     label_row_css <- paste0(label_row_css, "font-family: monospace;") | 
 | 189 |   } | 
 | 190 |   if (underline) { | 
 | 191 |     label_row_css <- paste0(label_row_css, "text-decoration: underline;") | 
 | 192 |   } | 
 | 193 |   if (strikeout) { | 
 | 194 |     label_row_css <- paste0(label_row_css, "text-decoration: line-through;") | 
 | 195 |   } | 
 | 196 |   if (!is.null(color)) { | 
 | 197 |     label_row_css <- paste0(label_row_css, "color: ", html_color(color), | 
 | 198 |                             " !important;") | 
 | 199 |   } | 
 | 200 |   if (!is.null(background)) { | 
 | 201 |     label_row_css <- paste0(label_row_css, "background-color: ", | 
 | 202 |                             html_color(background), " !important;") | 
 | 203 |   } | 
| Hao Zhu | 8b16a6c | 2020-08-18 16:59:20 -0400 | [diff] [blame] | 204 |  | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 205 |   group_header_row_text <- paste0( | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 206 |     '<tr groupLength="', length(group_seq), '"><td colspan="', kable_ncol, | 
| Adrien Le Guillou | fdffec6 | 2019-09-04 00:03:52 +0200 | [diff] [blame] | 207 |     '" style="', label_row_css, '">', group_label, "</td></tr>") | 
 | 208 |  | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 209 |   group_header_row <- read_xml(group_header_row_text, options = "COMPACT") | 
 | 210 |   xml_add_sibling(starting_node, group_header_row, .where = "before") | 
 | 211 |  | 
 | 212 |   # add indentations to items | 
| Hao Zhu | f2dfd14 | 2017-07-24 14:43:28 -0400 | [diff] [blame] | 213 |   out <- as_kable_xml(kable_xml) | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 214 |   attributes(out) <- kable_attrs | 
 | 215 |   attr(out, "group_header_rows") <- c(attr(out, "group_header_rows"), group_seq[1]) | 
| Hao Zhu | 2742ffc | 2018-10-17 11:23:44 -0400 | [diff] [blame] | 216 |   if (indent) { | 
 | 217 |     out <- add_indent_html(out, positions = seq(start_row, end_row)) | 
 | 218 |   } | 
| Hao Zhu | 62cdde5 | 2017-05-20 22:16:03 -0400 | [diff] [blame] | 219 |   return(out) | 
 | 220 | } | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 221 |  | 
| Hao Zhu | fc14c9b | 2017-05-22 14:03:22 -0400 | [diff] [blame] | 222 | group_rows_latex <- function(kable_input, group_label, start_row, end_row, | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 223 |                              gap_space, escape, latex_align, colnum, | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 224 |                              bold = T, italic = F, hline_before = F, hline_after = F, | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 225 |                              extra_latex_after = NULL, indent, latex_wrap_text = F, | 
 | 226 |                              monospace = F, underline = F, strikeout = F, | 
 | 227 |                              color = NULL, background = NULL) { | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 228 |   table_info <- magic_mirror(kable_input) | 
| Hao Zhu | 3fc0e88 | 2018-04-03 16:06:41 -0400 | [diff] [blame] | 229 |   out <- solve_enc(kable_input) | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 230 |  | 
| Hao Zhu | 064990d | 2017-10-17 18:08:42 -0400 | [diff] [blame] | 231 |   if (table_info$duplicated_rows) { | 
 | 232 |     dup_fx_out <- fix_duplicated_rows_latex(out, table_info) | 
 | 233 |     out <- dup_fx_out[[1]] | 
 | 234 |     table_info <- dup_fx_out[[2]] | 
 | 235 |   } | 
 | 236 |  | 
| Hao Zhu | ac7e70f | 2017-08-02 00:18:36 -0400 | [diff] [blame] | 237 |   if (escape) { | 
| Hao Zhu | f94a26f | 2018-04-05 17:42:55 -0400 | [diff] [blame] | 238 |     group_label <- input_escape(group_label, latex_align) | 
| Hao Zhu | 718fa3f | 2020-08-19 08:23:28 -0400 | [diff] [blame] | 239 |   } else { | 
 | 240 |     group_label <- sim_double_escape(group_label) | 
| Hao Zhu | ac7e70f | 2017-08-02 00:18:36 -0400 | [diff] [blame] | 241 |   } | 
 | 242 |  | 
| Hao Zhu | f94a26f | 2018-04-05 17:42:55 -0400 | [diff] [blame] | 243 |   if (bold) { | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 244 |     group_label <- paste0("\\\\textbf{", group_label, "}") | 
 | 245 |   } | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 246 |  | 
| Hao Zhu | f94a26f | 2018-04-05 17:42:55 -0400 | [diff] [blame] | 247 |   if (italic) group_label <- paste0("\\\\textit{", group_label, "}") | 
| Hao Zhu | 03e3333 | 2020-08-19 01:09:43 -0400 | [diff] [blame] | 248 |  | 
 | 249 |   if (monospace) { | 
 | 250 |     group_label <- paste0("\\\\ttfamily\\{", group_label, "\\}") | 
 | 251 |   } | 
 | 252 |   if (underline) { | 
 | 253 |     group_label <- paste0("\\\\underline\\{", group_label, "\\}") | 
 | 254 |   } | 
 | 255 |   if (strikeout) { | 
 | 256 |     group_label <- paste0("\\\\sout\\{", group_label, "\\}") | 
 | 257 |   } | 
 | 258 |   if (!is.null(color)) { | 
 | 259 |     group_label <- paste0("\\\\textcolor", latex_color(color), "\\{", | 
 | 260 |                               group_label, "\\}") | 
 | 261 |   } | 
 | 262 |   if (!is.null(background)) { | 
 | 263 |     group_label <- paste0("\\\\cellcolor", latex_color(background), "\\{", | 
 | 264 |                               group_label, "\\}") | 
 | 265 |   } | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 266 |   # Add group label | 
| Hao Zhu | 779569e | 2019-04-26 17:06:33 -0400 | [diff] [blame] | 267 |   if (latex_wrap_text) { | 
 | 268 |     latex_align <- switch( | 
 | 269 |       latex_align, | 
 | 270 |       "l" = "p{\\\\linewidth}", | 
 | 271 |       "c" = ">{\\\\centering\\\\arraybackslash}p{\\\\linewidth}", | 
 | 272 |       "r" = ">{\\\\centering\\\\arraybackslash}p{\\\\linewidth}" | 
 | 273 |     ) | 
 | 274 |   } | 
 | 275 |  | 
 | 276 |  | 
| Hao Zhu | 334376d | 2020-08-19 00:45:09 -0400 | [diff] [blame] | 277 |   rowtext <- table_info$contents[start_row + table_info$position_offset] | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 278 |   if (table_info$booktabs) { | 
| Hao Zhu | 334376d | 2020-08-19 00:45:09 -0400 | [diff] [blame] | 279 |     pre_rowtext <- paste0("\\\\addlinespace[", gap_space, "]\n") | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 280 |   } else { | 
| Hao Zhu | 334376d | 2020-08-19 00:45:09 -0400 | [diff] [blame] | 281 |     pre_rowtext <- '' | 
 | 282 |     hline_after <- TRUE | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 283 |   } | 
| Hao Zhu | 334376d | 2020-08-19 00:45:09 -0400 | [diff] [blame] | 284 |   pre_rowtext <- paste0( | 
 | 285 |     pre_rowtext, | 
 | 286 |     ifelse(hline_before,"\\\\hline\n", ""), | 
 | 287 |     "\\\\multicolumn{", ifelse(is.null(colnum), | 
 | 288 |                                table_info$ncol, | 
 | 289 |                                colnum), | 
 | 290 |     "}{", latex_align,"}{", group_label, | 
 | 291 |     "}\\\\\\\\\n", ifelse(hline_after, "\\\\hline\n", '') | 
 | 292 |   ) | 
| georgegui | 4cc925b | 2018-03-01 12:02:45 -0600 | [diff] [blame] | 293 |   if(!is.null(extra_latex_after)){ | 
 | 294 |     pre_rowtext <- paste0(pre_rowtext, | 
 | 295 |                       regex_escape(extra_latex_after, double_backslash = TRUE)) | 
 | 296 |   } | 
 | 297 |   new_rowtext <- paste0(pre_rowtext, rowtext) | 
| Hao Zhu | 9c3007e | 2020-08-03 13:52:38 -0400 | [diff] [blame] | 298 |   if (start_row + 1 == table_info$nrow & | 
| Hao Zhu | 334376d | 2020-08-19 00:45:09 -0400 | [diff] [blame] | 299 |       !is.null(table_info$repeat_header_latex) & table_info$booktabs) { | 
| Hao Zhu | 9c3007e | 2020-08-03 13:52:38 -0400 | [diff] [blame] | 300 |     out <- sub(paste0(rowtext, "\\\\\\\\\\*\n"), | 
 | 301 |                paste0(new_rowtext, "\\\\\\\\\\*\n"), | 
 | 302 |                out) | 
 | 303 |   } else { | 
 | 304 |     out <- sub(paste0(rowtext, "\\\\\\\\\n"), | 
 | 305 |                paste0(new_rowtext, "\\\\\\\\\n"), | 
 | 306 |                out) | 
 | 307 |   } | 
 | 308 |  | 
| Hao Zhu | 8f20299 | 2017-07-15 02:20:18 -0400 | [diff] [blame] | 309 |   out <- gsub("\\\\addlinespace\n", "", out) | 
| Hao Zhu | d2c0f73 | 2017-08-26 10:40:14 -0400 | [diff] [blame] | 310 |   out <- structure(out, format = "latex", class = "knitr_kable") | 
| Hao Zhu | 32f43f7 | 2017-06-20 18:24:54 -0400 | [diff] [blame] | 311 |   table_info$group_rows_used <- TRUE | 
 | 312 |   attr(out, "kable_meta") <- table_info | 
| Hao Zhu | 2742ffc | 2018-10-17 11:23:44 -0400 | [diff] [blame] | 313 |   if (indent) { | 
 | 314 |     out <- add_indent_latex(out, seq(start_row, end_row)) | 
 | 315 |   } | 
| Hao Zhu | d972e7f | 2017-05-22 13:27:15 -0400 | [diff] [blame] | 316 |   return(out) | 
 | 317 | } | 
| Hao Zhu | be853f7 | 2018-05-20 18:52:26 -0400 | [diff] [blame] | 318 |  | 
 | 319 | #' Automatically figuring out the group_row index | 
 | 320 | #' | 
 | 321 | #' @description This helper function allows users to build the `group_row` | 
 | 322 | #' index more quickly and use `group_rows` in a way that is similar with | 
 | 323 | #' `collapse_rows`. | 
 | 324 | #' | 
 | 325 | #' @param x The index column. A vector. For example `c("a", "a", "b", "b", "b")`` | 
 | 326 | #' | 
 | 327 | #' @export | 
 | 328 | auto_index <- function(x) { | 
| Hao Zhu | 6adba33 | 2020-08-19 11:48:51 -0400 | [diff] [blame] | 329 |   if (is.factor(x)) x <- as.character(x) | 
| Hao Zhu | be853f7 | 2018-05-20 18:52:26 -0400 | [diff] [blame] | 330 |   x_rle <- rle(x) | 
 | 331 |   index <- x_rle$lengths | 
 | 332 |   names(index) <- x_rle$values | 
 | 333 |   return(index) | 
 | 334 | } | 
| Hao Zhu | 72917f9 | 2019-03-15 18:41:42 -0400 | [diff] [blame] | 335 |  | 
 | 336 | #' @rdname group_rows | 
 | 337 | #' @export | 
 | 338 | pack_rows <- group_rows |