diff --git a/DESCRIPTION b/DESCRIPTION
index cddade8..d17e341 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: tables
Title: Formula-Driven Table Generation
-Version: 0.9.32
+Version: 0.9.33
Authors@R: person(given = "Duncan",
family = "Murdoch",
role = c("aut", "cre"),
diff --git a/NEWS.md b/NEWS.md
index 117dfc5..875fd7c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,12 @@
-# tables 0.9.32
+
+# tables 0.9.33
- The fix for issue #30 was incomplete for some reason.
+- `table_options()` now returns the value of options if called
+with a character argument.
+- An option `escape` has been added to `table_options()`. If `TRUE`,
+any special characters in HTML or LaTeX output are escaped so they
+appear as-is.
# tables 0.9.31
diff --git a/R/All.R b/R/All.R
index 3483858..e6475bd 100644
--- a/R/All.R
+++ b/R/All.R
@@ -9,7 +9,7 @@ All <- function(df,
texify = getOption("tables.texify", FALSE)) {
names <- colnames(df)
if (texify)
- names <- Hmisc::latexTranslate(names)
+ names <- texify(names)
f <- NULL
for (i in seq_along(names)) {
diff --git a/R/escapes.R b/R/escapes.R
new file mode 100644
index 0000000..9eb259e
--- /dev/null
+++ b/R/escapes.R
@@ -0,0 +1,37 @@
+texify <- function(x) {
+ # Based on knitr function
+ x <- gsub("\\\\", "\\\\textbackslash", x)
+ x <- gsub("([#$%&_{}])", "\\\\\\1", x)
+ x <- gsub("\\\\textbackslash", "\\\\textbackslash{}", x)
+ x <- gsub("~", "\\\\textasciitilde{}", x)
+ x <- gsub("\\^", "\\\\textasciicircum{}", x)
+ x
+}
+
+htmlify <- function (x)
+ # Taken from the tools package
+{
+ fsub <- function(pattern, replacement, x)
+ gsub(pattern,
+ replacement,
+ x,
+ fixed = TRUE,
+ useBytes = TRUE)
+
+ x <- fsub("&", "&", x)
+ x <- fsub("---", "—", x)
+ x <- fsub("--", "–", x)
+ x <- fsub("``", "“", x)
+ x <- fsub("''", "”", x)
+ x <- gsub("`([^']+)'",
+ "‘\\1’",
+ x,
+ perl = TRUE,
+ useBytes = TRUE)
+ x <- fsub("`", "'", x)
+ x <- fsub("<", "<", x)
+ x <- fsub(">", ">", x)
+ x <- fsub("\"\\{\"", "\"{\"", x)
+ x <- fsub("\"", """, x)
+ x
+}
diff --git a/R/html.tabular.R b/R/html.tabular.R
index f9cf233..072e617 100644
--- a/R/html.tabular.R
+++ b/R/html.tabular.R
@@ -1,75 +1,74 @@
-htmlify <- function (x) # Taken from the tools package
-{
- fsub <- function(pattern, replacement, x)
- gsub(pattern, replacement, x, fixed=TRUE, useBytes=TRUE)
-
- x <- fsub("&", "&", x)
- x <- fsub("---", "—", x)
- x <- fsub("--", "–", x)
- x <- fsub("``", "“", x)
- x <- fsub("''", "”", x)
- x <- gsub("`([^']+)'", "‘\\1’", x, perl=TRUE, useBytes=TRUE)
- x <- fsub("`", "'", x)
- x <- fsub("<", "<", x)
- x <- fsub(">", ">", x)
- x <- fsub("\"\\{\"", "\"{\"", x)
- x <- fsub("\"", """, x)
- x
-}
-
-htmlNumeric <- function(chars, minus=TRUE, leftpad=TRUE, rightpad=TRUE) {
- regexp <- "^( *)([-]?)([^ -][^ ]*)( *)$"
- leadin <- sub(regexp, "\\1", chars)
- sign <- sub(regexp, "\\2", chars)
- rest <- sub(regexp, "\\3", chars)
- tail <- sub(regexp, "\\4", chars)
-
- figurespace <- " "
- minussign <- "−"
-
- if (minus && any(neg <- sign == "-")) {
- if (any(leadin[!neg] == ""))
- leadin <- sub("^", " ", leadin)
- leadin[!neg] <- sub(" ", "", leadin[!neg])
- sign[!neg] <- figurespace
- sign[neg] <- minussign
- }
- if (leftpad && any(ind <- leadin != ""))
- leadin[ind] <- gsub(" ", figurespace, leadin[ind])
-
- if (rightpad && any(ind <- tail != ""))
- tail[ind] <- gsub(" ", figurespace, tail[ind])
-
- paste(leadin, sign, rest, tail, sep="")
+htmlNumeric <- function(chars,
+ minus = TRUE,
+ leftpad = TRUE,
+ rightpad = TRUE) {
+ regexp <- "^( *)([-]?)([^ -][^ ]*)( *)$"
+ leadin <- sub(regexp, "\\1", chars)
+ sign <- sub(regexp, "\\2", chars)
+ rest <- sub(regexp, "\\3", chars)
+ tail <- sub(regexp, "\\4", chars)
+
+ figurespace <- " "
+ minussign <- "−"
+
+ if (minus && any(neg <- sign == "-")) {
+ if (any(leadin[!neg] == ""))
+ leadin <- sub("^", " ", leadin)
+ leadin[!neg] <- sub(" ", "", leadin[!neg])
+ sign[!neg] <- figurespace
+ sign[neg] <- minussign
+ }
+ if (leftpad && any(ind <- leadin != ""))
+ leadin[ind] <- gsub(" ", figurespace, leadin[ind])
+
+ if (rightpad && any(ind <- tail != ""))
+ tail[ind] <- gsub(" ", figurespace, tail[ind])
+
+ paste(leadin, sign, rest, tail, sep = "")
}
-CSSclassname <- function(just)
- ifelse(just == "l", "left",
- ifelse(just == "c", "center",
- ifelse(just == "r", "right", just)))
-
-toHTML <- function(object, file = "",
- options = NULL, id = NULL,
- append = FALSE,
- browsable = TRUE, ...) {
+CSSclassname <- function(just)
+ ifelse(just == "l", "left", ifelse(just == "c", "center", ifelse(just == "r", "right", just)))
+toHTML <- function(object,
+ file = "",
+ options = NULL,
+ id = NULL,
+ append = FALSE,
+ browsable = TRUE,
+ ...) {
if (!is.null(options)) {
saveopts <- do.call(table_options, options)
- on.exit(table_options(saveopts), add=TRUE)
+ on.exit(table_options(saveopts), add = TRUE)
}
opts <- table_options()
output <- character()
- mycat <- function(...) output <<- c(output, unlist(list(...)))
+ mycat <- function(...)
+ output <<- c(output, unlist(list(...)))
+
+ escape <- opts$escape
+
+ do_escape <- function(x) {
+ if (escape)
+ x <- htmlify(x)
+ x
+ }
defjust <- opts$justification
blankhead <- "
| \n"
- classes <- chars <- format(object, html = TRUE, minus = opts$HTMLminus,
- leftpad = opts$HTMLleftpad,
- rightpad = opts$HTMLrightpad, ...) # format without justification
+ classes <- chars <- format(
+ object,
+ html = TRUE,
+ minus = opts$HTMLminus,
+ leftpad = opts$HTMLleftpad,
+ rightpad = opts$HTMLrightpad,
+ escape = escape,
+ ...
+ ) # format without justification
classes[] <- ""
vjust <- attr(object, "justification")
@@ -79,7 +78,7 @@ toHTML <- function(object, file = "",
chars[chars == ""] <- " "
chars[] <- sprintf(" %s | \n", classes, chars)
- rowClasses <- rowLabels <- attr(object, "rowLabels")
+ rowClasses <- rowLabels <- do_escape(attr(object, "rowLabels"))
rowClasses[] <- ""
nleading <- ncol(rowLabels)
rowLabels[is.na(rowLabels)] <- " "
@@ -87,19 +86,19 @@ toHTML <- function(object, file = "",
rjust[is.na(rjust)] <- opts$rowlabeljustification
ind <- rjust != defjust
rowClasses[ind] <- sprintf(' class="%s"', CSSclassname(rjust[ind]))
- rowLabels[] <- sprintf( " %s | \n", rowClasses, rowLabels)
+ rowLabels[] <- sprintf(" %s | \n", rowClasses, rowLabels)
colnamejust <- attr(rowLabels, "colnamejust")
- colnamejust <- rep(colnamejust, length.out=nleading)
+ colnamejust <- rep(colnamejust, length.out = nleading)
colnameClasses <- colnames(rowLabels)
colnameClasses[] <- ""
ind <- is.na(colnamejust)
colnamejust[ind] <- defjust
ind <- colnamejust != defjust
colnameClasses[ind] <- sprintf(' class="%s"', CSSclassname(colnamejust[ind]))
- colnames(rowLabels) <- sprintf(" %s | \n", colnameClasses, colnames(rowLabels))
+ colnames(rowLabels) <- sprintf(" %s | \n", colnameClasses, do_escape(colnames(rowLabels)))
- clabels <- attr(object, "colLabels")
+ clabels <- do_escape(attr(object, "colLabels"))
cjust <- attr(clabels, "justification")
ind <- is.na(cjust)
cjust[ind] <- defjust
@@ -107,29 +106,34 @@ toHTML <- function(object, file = "",
multi <- matrix(0, nrow(clabels), ncol(clabels))
prevmulti <- rep(0, nrow(multi))
for (i in rev(seq_len(ncol(multi)))) {
- ind <- is.na(clabels[,i])
+ ind <- is.na(clabels[, i])
multi[!ind, i] <- 1 + prevmulti[!ind]
prevmulti[ind] <- 1 + prevmulti[ind]
prevmulti[!ind] <- 0
}
colspan <- ifelse(multi < 2, "", sprintf(' colspan="%d"', multi))
- class <- ifelse(cjust == defjust | multi == 0, "", sprintf(' class="%s"', CSSclassname(cjust)))
+ class <- ifelse(cjust == defjust |
+ multi == 0,
+ "",
+ sprintf(' class="%s"', CSSclassname(cjust)))
clabels[clabels == ""] <- " "
- clabels <- ifelse(multi == 0, "", sprintf(' %s | \n', colspan, class, clabels))
+ clabels <- ifelse(multi == 0,
+ "",
+ sprintf(' %s | \n', colspan, class, clabels))
rowLabelHeadings <- matrix(blankhead, nrow(clabels), ncol(rowLabels))
- rowLabelHeadings[nrow(clabels),] <- colnames(rowLabels)
+ rowLabelHeadings[nrow(clabels), ] <- colnames(rowLabels)
if (opts$doHTMLheader) {
- head <- sub("CHARSET", localeToCharset(), opts$HTMLhead, fixed=TRUE)
+ head <- sub("CHARSET", localeToCharset(), opts$HTMLhead, fixed = TRUE)
mycat(head)
}
if (opts$doCSS) {
- if (is.null(id))
- css <- gsub("#ID ", "", opts$CSS, fixed=TRUE)
+ if (is.null(id))
+ css <- gsub("#ID ", "", opts$CSS, fixed = TRUE)
else
- css <- gsub("#ID", paste0("#", id), opts$CSS, fixed=TRUE)
+ css <- gsub("#ID", paste0("#", id), opts$CSS, fixed = TRUE)
mycat(css)
}
@@ -137,7 +141,7 @@ toHTML <- function(object, file = "",
mycat(opts$HTMLbody)
if (opts$doBegin) {
- if (is.null(id))
+ if (is.null(id))
id <- ""
else
id <- sprintf(' id="%s"', id)
@@ -147,7 +151,7 @@ toHTML <- function(object, file = "",
mycat(sprintf('%s\n', opts$HTMLcaption))
if (opts$doHeader) {
- rows <- apply(cbind(rowLabelHeadings, clabels), 1, paste0, collapse="")
+ rows <- apply(cbind(rowLabelHeadings, clabels), 1, paste0, collapse = "")
mycat('\n')
mycat(sprintf('\n%s
\n', CSSclassname(defjust), rows))
mycat('\n')
@@ -158,7 +162,7 @@ toHTML <- function(object, file = "",
mycat('\n')
}
if (opts$doBody) {
- rows <- apply(cbind(rowLabels, chars), 1, paste0, collapse="")
+ rows <- apply(cbind(rowLabels, chars), 1, paste0, collapse = "")
mycat('\n')
mycat(sprintf('\n%s
\n', CSSclassname(defjust), rows))
mycat('\n')
@@ -169,7 +173,10 @@ toHTML <- function(object, file = "",
result <- browsable(HTML(output), value = browsable)
if (!identical(file, "")) {
if (is.character(file)) {
- file <- file(file, open = if (append) "at" else "wt")
+ file <- file(file, open = if (append)
+ "at"
+ else
+ "wt")
on.exit(close(file))
}
writeLines(output, file)
@@ -179,14 +186,13 @@ toHTML <- function(object, file = "",
}
html.tabular <- function(object, ...) {
- toHTML(object, ...)
+ toHTML(object, ...)
}
writeCSS <- function(CSS = htmloptions()$CSS, id = NULL) {
- if (is.null(id))
- css <- gsub("#ID ", "", CSS, fixed=TRUE)
+ if (is.null(id))
+ css <- gsub("#ID ", "", CSS, fixed = TRUE)
else
- css <- gsub("#ID", paste0("#", id), CSS, fixed=TRUE)
+ css <- gsub("#ID", paste0("#", id), CSS, fixed = TRUE)
cat(css)
}
-
diff --git a/R/latex.tabular.R b/R/latex.tabular.R
index f9ed28b..202afec 100644
--- a/R/latex.tabular.R
+++ b/R/latex.tabular.R
@@ -1,12 +1,7 @@
-texify <- function(x) {
- x <- gsub("\\", "\\textbackslash{}", x, fixed = TRUE)
- if (requireNamespace("Hmisc"))
- x <- Hmisc::latexTranslate(x)
- x
-}
toLatex.tabular <- function(object, file = "", options = NULL,
- append = FALSE, ...) {
+ append = FALSE,
+ ...) {
if (!is.null(options)) {
saveopts <- do.call(table_options, options)
@@ -24,9 +19,18 @@ toLatex.tabular <- function(object, file = "", options = NULL,
output <<- paste0(output, paste(args, collapse = sep))
}
+ escape <- opts$escape
+
+ do_escape <- function(x) {
+ if (escape)
+ x <- texify(x)
+ x
+ }
+
chars <- format(object, latex = TRUE, minus = opts$latexminus,
leftpad = opts$latexleftpad,
- rightpad = opts$latexrightpad,...) # format without justification
+ rightpad = opts$latexrightpad,
+ ...) # format without justification
vjust <- attr(object, "justification")
vjustdefs <- rep(opts$justification, length.out=ncol(object))
@@ -34,7 +38,7 @@ toLatex.tabular <- function(object, file = "", options = NULL,
chars[ind] <- sprintf("\\multicolumn{1}{%s}{%s}",
vjust[ind], chars[ind])
- rowLabels <- attr(object, "rowLabels")
+ rowLabels <- do_escape(attr(object, "rowLabels"))
nleading <- ncol(rowLabels)
rowLabels[is.na(rowLabels)] <- ""
rjust <- attr(rowLabels, "justification")
@@ -49,8 +53,8 @@ toLatex.tabular <- function(object, file = "", options = NULL,
colnamejust[ind] <- rjustdefs[ind]
ind <- colnamejust != rjustdefs
colnames(rowLabels)[ind] <- sprintf("\\multicolumn{1}{%s}{%s}",
- colnamejust[ind], colnames(rowLabels)[ind])
- clabels <- attr(object, "colLabels")
+ colnamejust[ind], do_escape(colnames(rowLabels)[ind]))
+ clabels <- do_escape(attr(object, "colLabels"))
leadin <- paste(rep("&", max(nleading - 1, 0)), collapse=" ")
cjust <- attr(clabels, "justification")
ind <- is.na(cjust)
diff --git a/R/options.R b/R/options.R
index 6ae7f59..871e570 100644
--- a/R/options.R
+++ b/R/options.R
@@ -11,7 +11,7 @@ CSSdefault <- '\n"
+[1] "\n"
$HTMLhead
[1] "\n\n\n\n"
@@ -164,6 +164,9 @@ $HTMLrightpad
$HTMLminus
[1] FALSE
+$escape
+[1] FALSE
+
> table_options()[c("toprule", "midrule", "bottomrule",
+ "titlerule")]
@@ -780,7 +783,6 @@ $i$ & Sepal.Length & Sepal.Width & Petal.Length & Petal.Width & \multicolumn{1}
> options(tables.texify = TRUE)
> toLatex(tabular(mean ~ Factor(A) * All(df), data = df))
-Loading required namespace: Hmisc
\begin{tabular}{lcc}
\toprule
& \multicolumn{2}{c}{A} \\ \cmidrule(lr){2-3}
@@ -983,4 +985,4 @@ All & $150$ & $5.84$ & $0.83$ & $3.06$ & $0.44$ \\
*** Run successfully completed ***
> proc.time()
user system elapsed
- 0.688 0.030 0.718
+ 0.561 0.024 0.584