Allow no colnames with PDF output when booktabs enabled
diff --git a/DESCRIPTION b/DESCRIPTION
index f4eab25..8d7bbdd 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -31,6 +31,7 @@
 Imports:
     knitr (>= 1.16),
     magrittr,
+    stringi,
     stringr (>= 1.0),
     xml2,
     rvest,
diff --git a/R/add_indent.R b/R/add_indent.R
index de6fc32..c0e1c1e 100644
--- a/R/add_indent.R
+++ b/R/add_indent.R
@@ -39,15 +39,23 @@
     table_info <- dup_fx_out[[2]]
   }
 
-  if (max(positions) > table_info$nrow - 1) {
+  if (table_info$booktabs & is.null(table_info$colnames)) {
+    max_position <- table_info$nrow
+    position_offset <- 0
+  } else {
+    max_position <- table_info$nrow - 1
+    position_offset <- 1
+  }
+
+  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 + 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..d3871f7 100644
--- a/R/group_rows.R
+++ b/R/group_rows.R
@@ -162,8 +162,12 @@
   }
   if (italic) group_label <- paste0("\\\\textit{", group_label, "}")
   # Add group label
-  rowtext <- table_info$contents[start_row + 1]
   if (table_info$booktabs) {
+    if (is.null(table_info$colnames)) {
+      rowtext <- table_info$contents[start_row]
+    } else {
+      rowtext <- table_info$contents[start_row + 1]
+    }
     pre_rowtext <- paste0(
       "\\\\addlinespace[", gap_space, "]\n",
       ifelse(hline_before,"\\\\hline\n", ""),
@@ -174,6 +178,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/kableExtra-package.R b/R/kableExtra-package.R
index 7b4b72b..67d8558 100644
--- a/R/kableExtra-package.R
+++ b/R/kableExtra-package.R
@@ -55,6 +55,7 @@
 #' vanilla rmarkdown. For customized rmarkdown templates, it is recommended to
 #' load related LaTeX packages manually.
 #'
+#' @importFrom stringi stri_replace_all_fixed
 #' @importFrom stringr str_count str_split str_match str_detect str_match_all
 #' str_extract str_replace_all str_trim str_extract_all str_sub str_replace
 #' @importFrom xml2 read_xml xml_attr xml_has_attr xml_attr<- read_html
diff --git a/R/kable_styling.R b/R/kable_styling.R
index b7677df..c80b3d5 100644
--- a/R/kable_styling.R
+++ b/R/kable_styling.R
@@ -281,15 +281,27 @@
 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)
+    if (table_info$booktabs & is.null(table_info$colnames)) {
+      row_color <- sprintf("\\rowcolors{1}{white}{%s}", color)
+    } else {
+      row_color <- sprintf("\\rowcolors{2}{white}{%s}", color)
+    }
   } else {
-    row_color <- sprintf("\\rowcolors{2}{%s}{white}", color)
+    if (table_info$booktabs & is.null(table_info$colnames)) {
+      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 +356,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 e6503b4..927aaec 100644
--- a/R/magic_mirror.R
+++ b/R/magic_mirror.R
@@ -90,7 +90,15 @@
   }
   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) {
+    if (is.na(which(read_lines(kable_input) == "\\midrule")[1])) {
+      kable_info$colnames <- NULL
+    } else {
+      kable_info$colnames <- str_split(kable_info$contents[1], " \\& ")[[1]]
+    }
+  } else {
+    kable_info$colnames <- str_split(kable_info$contents[1], " \\& ")[[1]]
+  }
   # Row names
   kable_info$rownames <- str_extract(kable_info$contents, "^[^ &]*")
 
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'))
+```