Merge pull request #197 from leovan/master

Allow no colnames with PDF output when booktabs enabled
diff --git a/DESCRIPTION b/DESCRIPTION
index f4eab25..eba392d 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -14,7 +14,8 @@
     person('Rob', 'Shepherd', role = 'ctb'),
     person('Yoni', 'Sidi', role = 'ctb'), 
     person('Brian', 'Salzer', role = 'ctb'),
-    person('George', 'Gui', role = 'ctb')
+    person('George', 'Gui', role = 'ctb'),
+    person('Yeliang', 'Fan', role = 'ctb')
     )
 Description: Build complex HTML or 'LaTeX' tables using 'kable()' from 'knitr' 
     and the piping syntax from 'magrittr'. Function 'kable()' is a light weight 
diff --git a/R/add_indent.R b/R/add_indent.R
index de6fc32..a8a455e 100644
--- a/R/add_indent.R
+++ b/R/add_indent.R
@@ -39,15 +39,17 @@
     table_info <- dup_fx_out[[2]]
   }
 
-  if (max(positions) > table_info$nrow - 1) {
+  max_position <- table_info$nrow - table_info$position_offset
+
+  if (max(positions) > max_position) {
     stop("There aren't that many rows in the table. Check positions in ",
          "add_indent_latex.")
   }
 
-  for (i in positions) {
-    rowtext <- table_info$contents[i + 1]
+  for (i in positions + table_info$position_offset) {
+    rowtext <- table_info$contents[i]
     out <- sub(rowtext, latex_indent_unit(rowtext), out, perl = TRUE)
-    table_info$contents[i + 1] <- latex_indent_unit(rowtext)
+    table_info$contents[i] <- latex_indent_unit(rowtext)
   }
   out <- structure(out, format = "latex", class = "knitr_kable")
   attr(out, "kable_meta") <- table_info
diff --git a/R/group_rows.R b/R/group_rows.R
index 85962cf..4352105 100644
--- a/R/group_rows.R
+++ b/R/group_rows.R
@@ -162,8 +162,8 @@
   }
   if (italic) group_label <- paste0("\\\\textit{", group_label, "}")
   # Add group label
-  rowtext <- table_info$contents[start_row + 1]
   if (table_info$booktabs) {
+    rowtext <- table_info$contents[start_row + table_info$position_offset]
     pre_rowtext <- paste0(
       "\\\\addlinespace[", gap_space, "]\n",
       ifelse(hline_before,"\\\\hline\n", ""),
@@ -174,6 +174,7 @@
       "}\\\\\\\\\n", ifelse(hline_after, "\\\\hline\n", '')
     )
   } else {
+    rowtext <- table_info$contents[start_row + 1]
     rowtext <- paste0("\\\\hline\n", rowtext)
     pre_rowtext <- paste0(
       "\\\\hline\n\\\\multicolumn{", table_info$ncol, "}{", latex_align,"}{",
diff --git a/R/kable_styling.R b/R/kable_styling.R
index 3be1202..f3f9136 100644
--- a/R/kable_styling.R
+++ b/R/kable_styling.R
@@ -281,15 +281,24 @@
 styling_latex_striped <- function(x, table_info, color) {
   # gray!6 is the same as shadecolor ({RGB}{248, 248, 248}) in pdf_document
   if (table_info$tabular == "longtable" & !is.na(table_info$caption)) {
-    row_color <- sprintf("\\rowcolors{2}{white}{%s}", color)
+    row_color <- sprintf("\\rowcolors{%s}{white}{%s}",
+                         1 + table_info$position_offset, color)
   } else {
-    row_color <- sprintf("\\rowcolors{2}{%s}{white}", color)
+    if (table_info$position_offset == 0) {
+      row_color <- sprintf("\\rowcolors{1}{white}{%s}", color)
+    } else {
+      row_color <- sprintf("\\rowcolors{2}{%s}{white}", color)
+    }
   }
 
   x <- read_lines(x)
   if (table_info$booktabs) {
     header_rows_start <- which(x == "\\toprule")[1]
-    header_rows_end <- which(x == "\\midrule")[1]
+    if (is.null(table_info$colnames)) {
+      header_rows_end <- header_rows_start
+    } else {
+      header_rows_end <- which(x == "\\midrule")[1]
+    }
   } else {
     header_rows_start <- which(x == "\\hline")[1]
     header_rows_end <- which(x == "\\hline")[2]
@@ -344,7 +353,11 @@
   x <- read_lines(x)
   if (table_info$booktabs) {
     header_rows_start <- which(x == "\\toprule")[1]
-    header_rows_end <- which(x == "\\midrule")[1]
+    if (is.null(table_info$colnames)) {
+      header_rows_end <- header_rows_start
+    } else {
+      header_rows_end <- which(x == "\\midrule")[1]
+    }
   } else {
     header_rows_start <- which(x == "\\hline")[1]
     header_rows_end <- which(x == "\\hline")[2]
diff --git a/R/magic_mirror.R b/R/magic_mirror.R
index 5cc2337..09eea05 100644
--- a/R/magic_mirror.R
+++ b/R/magic_mirror.R
@@ -89,7 +89,13 @@
   kable_info$nrow <- length(kable_info$contents)
   kable_info$duplicated_rows <- (sum(duplicated(kable_info$contents)) != 0)
   # Column names
-  kable_info$colnames <- str_split(kable_info$contents[1], " \\& ")[[1]]
+  if (kable_info$booktabs & !grepl("\\\\midrule", kable_input)) {
+    kable_info$colnames <- NULL
+    kable_info$position_offset <- 0
+  } else {
+    kable_info$colnames <- str_split(kable_info$contents[1], " \\& ")[[1]]
+    kable_info$position_offset <- 1
+  }
   # Row names
   kable_info$rownames <- str_extract(kable_info$contents, "^[^ &]*")
 
diff --git a/R/row_spec.R b/R/row_spec.R
index 47832eb..638c611 100644
--- a/R/row_spec.R
+++ b/R/row_spec.R
@@ -190,7 +190,7 @@
     table_info <- dup_fx_out[[2]]
   }
 
-  row <- row + 1
+  row <- row + table_info$position_offset
   for (i in row) {
     target_row <- table_info$contents[i]
     new_row <- latex_new_row_builder(target_row, table_info,
diff --git a/R/util.R b/R/util.R
index 57e58b5..446cb2e 100644
--- a/R/util.R
+++ b/R/util.R
@@ -124,10 +124,11 @@
   for (i in which(dup_index != 1)) {
     dup_row <- table_info$contents[i]
     empty_times <- dup_index[i] - 1
+    # insert empty_times before last non whitespace characters
     new_row <- str_replace(
-      dup_row, "&",
-      paste0("& \\\\\\\\vphantom\\\\{", empty_times, "\\\\}"))
-    kable_input <- str_replace(kable_input, dup_row, new_row)
+      dup_row, "(?<=\\s)([\\S]+[\\s]*)$",
+      paste0("\\\\\\\\vphantom\\\\{", empty_times, "\\\\} \\1"))
+    kable_input <- sub(dup_row, new_row, kable_input)
     table_info$contents[i] <- new_row
   }
   table_info$duplicated_rows <- FALSE
diff --git a/tests/visual_tests/no_colnames_booktabs_pdf.Rmd b/tests/visual_tests/no_colnames_booktabs_pdf.Rmd
new file mode 100644
index 0000000..b0d1b58
--- /dev/null
+++ b/tests/visual_tests/no_colnames_booktabs_pdf.Rmd
@@ -0,0 +1,172 @@
+---
+title: "no_colnames_booktabs_pdf"
+author: "Leo"
+date: "5/10/2018"
+output: pdf_document
+---
+
+# Create some test data
+
+```{r, include=F}
+library(tidyverse)
+library(knitr)
+library(kableExtra)
+```
+
+```{r}
+simple_df_one_column <- data.frame(
+  text = paste0('TEXT ', seq(1, 6))
+)
+
+simple_df_one_column_math <- data.frame(
+  math = paste0('$\\text{Math:} x = ', seq(1, 6), '$ TEXT')
+)
+
+simple_df_multi_columns <- data.frame(
+  text = paste0('TEXT ', seq(1, 6)),
+  desc = paste0('DESCRIPTION ', seq(1, 6))
+)
+
+simple_df_multi_columns_math <- data.frame(
+  text = paste0('TEXT ', seq(1, 6)),
+  math = paste0('$\\text{Math:} x = ', seq(1, 6), '$ TEXT')
+)
+
+simple_df_longtable_one_column <- data.frame(
+  text = paste0('TEXT ', seq(1, 50))
+)
+
+simple_df_longtable_one_column_math <- data.frame(
+  math = paste0('$\\text{Math:} x = ', seq(1, 50), '$ TEXT')
+)
+
+simple_df_longtable_multi_columns <- data.frame(
+  text = paste0('TEXT ', seq(1, 50)),
+  desc = paste0('DESCRIPTION ', seq(1, 50))
+)
+
+simple_df_longtable_multi_columns_math <- data.frame(
+  text = paste0('TEXT ', seq(1, 50)),
+  math = paste0('$\\text{Math:} x = ', seq(1, 50), '$ TEXT')
+)
+```
+
+# Simple Table with One Column
+
+```{r}
+simple_df_one_column %>%
+  kable("latex", escape = F, booktabs = T) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+```{r}
+simple_df_one_column %>%
+  kable("latex", escape = F, booktabs = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+# Simple Table with One Column and Math
+
+```{r}
+simple_df_one_column_math %>%
+  kable("latex", escape = F, booktabs = T) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+```{r}
+simple_df_one_column_math %>%
+  kable("latex", escape = F, booktabs = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+# Simple Table with Multi Columns
+
+```{r}
+simple_df_multi_columns %>%
+  kable("latex", escape = F, booktabs = T) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+```{r}
+simple_df_multi_columns %>%
+  kable("latex", escape = F, booktabs = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+# Simple Table with Multi Columns and Math
+
+```{r}
+simple_df_multi_columns_math %>%
+  kable("latex", escape = F, booktabs = T) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+```{r}
+simple_df_multi_columns_math %>%
+  kable("latex", escape = F, booktabs = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped'))
+```
+
+# Simple Long Table with One Column
+
+```{r}
+simple_df_longtable_one_column %>%
+  kable("latex", caption = 'Long Table with One Column',
+        escape = F, booktabs = T, longtable = T) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+```{r}
+simple_df_longtable_one_column %>%
+  kable("latex", caption = 'Long Table with One Column without Colnames',
+        escape = F, booktabs = T, longtable = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+# Simple Long Table with One Column and Math
+
+```{r}
+simple_df_longtable_one_column_math %>%
+  kable("latex", caption = 'Long Table with One Column',
+        escape = F, booktabs = T, longtable = T) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+```{r}
+simple_df_longtable_one_column_math %>%
+  kable("latex", caption = 'Long Table with One Column without Colnames',
+        escape = F, booktabs = T, longtable = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+# Simple Long Table with Multi Columns
+
+```{r}
+simple_df_longtable_multi_columns %>%
+  kable("latex", caption = 'Long Table with One Column',
+        escape = F, booktabs = T, longtable = T) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+```{r}
+simple_df_longtable_multi_columns %>%
+  kable("latex", caption = 'Long Table with One Column without Colnames',
+        escape = F, booktabs = T, longtable = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+# Simple Long Table with Multi Columns and Math
+
+```{r}
+simple_df_longtable_multi_columns_math %>%
+  kable("latex", caption = 'Long Table with One Column',
+        escape = F, booktabs = T, longtable = T) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```
+
+```{r}
+simple_df_longtable_multi_columns_math %>%
+  kable("latex", caption = 'Long Table with One Column without Colnames',
+        escape = F, booktabs = T, longtable = T, col.names = NULL) %>%
+  kable_styling(latex_options = c('striped', 'repeat_header'))
+```