1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
|
.onLoad <- function(libname, pkgname) {
## pander settings
options('pander' = list(
'digits' = 4,
'decimal.mark' = '.',
'formula.caption.prefix' = 'Formula: ',
'big.mark' = '',
'round' = Inf,
'keep.trailing.zeros' = FALSE,
'keep.line.breaks' = FALSE,
'missing' = NA,
'date' = '%Y/%m/%d %X',
'header.style' = 'atx',
'list.style' = 'bullet',
'table.style' = ifelse(
getOption('jupyter.in_kernel', FALSE),
## The jupyter notebook does not understand the multiline table format
'rmarkdown',
'multiline'),
'table.emphasize.rownames' = TRUE,
'table.split.table' = 80,
'table.split.cells' = 30,
'table.caption.prefix' = 'Table: ',
'table.continues' = 'Table continues below',
'table.continues.affix' = '(continued below)',
'table.alignment.default' = 'centre',
'table.alignment.rownames' = 'centre',
'use.hyphening' = FALSE,
'evals.messages' = TRUE,
'p.wrap' = '_',
'p.sep' = ', ',
'p.copula' = ' and ',
'plain.ascii' = FALSE,
'graph.nomargin' = TRUE,
'graph.fontfamily' = 'sans',
'graph.fontcolor' = 'black',
'graph.fontsize' = 12,
'graph.grid' = TRUE,
'graph.grid.minor' = TRUE,
'graph.grid.color' = 'grey',
'graph.grid.lty' = 'dashed',
'graph.boxes' = FALSE,
'graph.legend.position' = 'right',
'graph.background' = 'white',
'graph.panel.background' = 'transparent',
'graph.colors' = c("#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7", "#999999", "#E69F00"), #nolint
'graph.color.rnd' = FALSE,
'graph.axis.angle' = 1,
'graph.symbol' = 1,
'knitr.auto.asis' = TRUE,
'pandoc.binary' = Sys.which('pandoc')
))
## evals options
options('evals' = list(
'parse' = TRUE,
'cache' = TRUE,
'cache.mode' = 'environment',
'cache.dir' = '.cache',
'cache.time' = 0.1,
'cache.copy.images' = FALSE,
'classes' = NULL,
'hooks' = NULL,
'length' = Inf,
'output' = 'all',
'graph.unify' = FALSE,
'graph.name' = '%t',
'graph.dir' = 'plots',
'graph.output' = 'png',
'width' = 480,
'height' = 480,
'res' = 72,
'hi.res' = FALSE,
'hi.res.width' = 960,
'graph.env' = FALSE,
'graph.recordplot' = FALSE,
'graph.RDS' = FALSE,
'log' = NULL
))
}
## general (temporary) storage for pander's stuff
storage <- new.env()
storage$caption <- NULL
storage$alignment <- NULL
debug <- new.env()
debug$nested <- 0
debug$nestedID <- 0
## cache storage
cached.results <- new.env() # cache of results from evals
cached.environments <- new.env() # cache of changes to the environment (assignments in particular)
## cache hash storage
hash.cache.obj <- new.env() # raw R objects of which hash was computed before
hash.cache.hash <- new.env() # the computed hash of the above R objects
hash.cache.last.used <- new.env() # when was the hash last queried
## masked plots
masked.plots <- new.env()
masked.plots$plot <- masked.plots$barplot <- masked.plots$lines <- masked.plots$pie <- masked.plots$boxplot <- masked.plots$polygon <- masked.plots$points <- masked.plots$legend <- masked.plots$hist <- masked.plots$pairs <- masked.plots$stripchart <- masked.plots$clusplot <- masked.plots$text <- function (...) { #nolint
mc <- match.call()
fn <- deparse(mc[[1]])
fn.pkg <- gsub('.*library/|/help.*', '', help(fn)[1])
fn.orig <- parse(text = paste0(fn.pkg, '::', fn))[[1]]
mc <- match.call(get(fn, envir = .GlobalEnv))
if (!(!is.null(mc$plot) && !mc$plot)) {
## pander options
fc <- panderOptions('graph.fontcolor')
fbs <- panderOptions('graph.fontsize')
bc <- panderOptions('graph.background')
gc <- panderOptions('graph.grid.color')
cex <- fbs / 12
cs <- panderOptions('graph.colors')
if (panderOptions('graph.color.rnd'))
cs <- sample(cs)
cb <- cs[1]
## global par update
if (!fn %in% c('text')) {
par(
family = panderOptions('graph.fontfamily'),
cex = cex, cex.axis = cex * 0.8, cex.lab = cex, cex.main = cex * 1.2, cex.sub = cex,
bg = bc, # nolint TODO: how could we color only the inner plot area globally? Not like: https://stat.ethz.ch/pipermail/r-help/2003-May/033971.html
las = panderOptions('graph.axis.angle'),
lwd = 2,
pch = panderOptions('graph.symbol'),
col.axis = fc, col.lab = fc, col.main = fc, col.sub = fc)
}
## remove margins
if (panderOptions('graph.nomargin') & !fn %in% c('text')) {
par(mar = c(4.1, 4.3, 2.1, 0.1))
}
## default: grid is added to all plots
doAddGrid <- TRUE
## update colors
if (is.null(mc$col) & is.null(mc$color))
mc$col <- cb
if (fn == 'boxplot')
mc$border <- 'black'
if (fn == 'clusplot') {
mc$col <- NULL
if (is.null(mc$color))
mc$color <- TRUE
if (is.null(mc$shade))
mc$shade <- TRUE
if (is.null(mc$labels))
mc$labels <- 4
if (is.null(mc$col.p))
mc$col.p <- 'black'
if (is.null(mc$col.clus))
mc$col.clus <- cs
}
## remove boxes
if (fn %in% c('pairs', 'stripchart')) {
doAddGrid <- FALSE
par(fg = fc)
} else {
if (panderOptions('graph.boxes'))
par(fg = gc)
else
par(fg = bc)
}
if (fn == 'pie')
mc$col <- cs
}
## call
mc[[1]] <- fn.orig
eval(mc, envir = parent.frame())
## grid
if (all(par()$mfrow == 1) & panderOptions('graph.grid') & doAddGrid & !(!is.null(mc$plot) && !mc$plot)) {
g <- tryCatch(grid(lty = panderOptions('graph.grid.lty'),
col = panderOptions('graph.grid.color'),
lwd = 0.5),
error = function(e) e)
if (!inherits(g, 'error')) {
if (panderOptions('graph.grid.minor'))
g <- tryCatch(add.minor.ticks(2, 2, grid = TRUE), error = function(e) e)
}
if (inherits(g, 'error'))
warning('Applying default formatting to image is somehow compromised (the result could differ from what you specified in `panderOptions`). Hints: printing `lattice`/`ggplot2` is not needed and tweaking `base` plots with `par` might have some side-effects!') #nolint
}
}
#' Querying/setting pander option
#'
#' To list all \code{pander} options, just run this function without any parameters provided. To query only one value, pass the first parameter. To set that, use the \code{value} parameter too.
#'
#' The following \code{pander} options are available:
#'
#' \itemize{
#' \item \code{digits}: numeric (default: \code{2}) passed to \code{format}. Can be a vector specifying values for each column (has to be the same length as number of columns). Values for non-numeric columns will be disregarded.
#' \item \code{decimal.mark}: string (default: \code{.}) passed to \code{format}
#' \item \code{formula.caption.prefix}: string (default: \code{'Formula: '}) passed to \code{\link{pandoc.formula}} to be used as caption prefix. Be sure about what you are doing if changing to other than \code{'Formula: '} or \code{':'}.
#' \item \code{big.mark}: string (default: '') passed to \code{format}.
#' \item \code{round}: numeric (default: \code{Inf}) passed to \code{round}. Can be a vector specifying values for each column (has to be the same length as number of columns). Values for non-numeric columns will be disregarded.
#' \item \code{keep.trailing.zeros}: boolean (default: \code{FALSE}) to show or remove trailing zeros in numbers
#' \item \code{keep.line.breaks}: boolean (default: \code{FALSE}) to keep or remove line breaks from cells in a table
#' \item \code{missing}: string (default: \code{NA}) to replace missing values in vectors, tables etc.
#' \item \code{date}: string (default: \code{'\%Y/\%m/\%d \%X'}) passed to \code{format} when printing dates (\code{POSIXct} or \code{POSIXt})
#' \item \code{header.style}: \code{'atx'} or \code{'setext'} passed to \code{\link{pandoc.header}}
#' \item \code{list.style}: \code{'bullet'}, \code{'ordered'} or \code{'roman'} passed to \code{\link{pandoc.list}}. Please not that this has no effect on \code{pander} methods.
#' \item \code{table.style}: \code{'multiline'}, \code{'grid'}, \code{'simple'} or \code{'rmarkdown'} passed to \code{\link{pandoc.table}}
#' \item \code{table.emphasize.rownames}: boolean (default: \code{TRUE}) if row names should be highlighted
#' \item \code{table.split.table}: numeric passed to \code{\link{pandoc.table}} and also affects \code{pander} methods. This option tells \code{pander} where to split too wide tables. The default value (\code{80}) suggests the conventional number of characters used in a line, feel free to change (e.g. to \code{Inf} to disable this feature) if you are not using a VT100 terminal any more :)
#' \item \code{table.split.cells}: numeric or numeric vector (default: \code{30}) passed to \code{\link{pandoc.table}} and also affects \code{pander} methods. This option tells \code{pander} where to split too wide cells with line breaks. Numeric vector specifies values for cells separately. Set \code{Inf} to disable.
#' \item \code{table.caption.prefix}: string (default: \code{'Table: '}) passed to \code{\link{pandoc.table}} to be used as caption prefix. Be sure about what you are doing if changing to other than \code{'Table: '} or \code{':'}.
#' \item \code{table.continues}: string (default: \code{'Table continues below'}) passed to \code{\link{pandoc.table}} to be used as caption for long (split) without a use defined caption
#' \item \code{table.continues.affix}: string (default: \code{'(continued below)'}) passed to \code{\link{pandoc.table}} to be used as an affix concatenated to the user defined caption for long (split) tables
#' \item \code{table.alignment.default}: string (default: \code{centre}) that defines the default alignment of cells. Can be \code{left}, \code{right} or \code{centre} that latter can be also spelled as \code{center}.
#' \item \code{table.alignment.rownames}: string (default: \code{centre}) that defines the alignment of rownames in tables. Can be \code{left}, \code{right} or \code{centre} that latter can be also spelled as \code{center}.
#' \item \code{use.hyphening}: boolean (default: \code{FALSE}) if try to use hyphening when splitting large cells according to table.split.cells. Requires \pkg{sylly}.
#' \item \code{evals.messages}: boolean (default: \code{TRUE}) passed to \code{evals}' \code{pander} method specifying if messages should be rendered
#' \item \code{p.wrap}: a string (default: \code{'_'}) to wrap vector elements passed to \code{p} function
#' \item \code{p.sep}: a string (default: \code{', '}) with the main separator passed to \code{p} function
#' \item \code{p.copula}: a string (default: \code{' and '}) with ending separator passed to \code{p} function
#' \item \code{plain.ascii}: boolean (default: \code{FALSE}) to define if output should be in plain ascii or not
#' \item \code{graph.nomargin}: boolean (default: \code{TRUE}) if trying to keep plots' margins at minimal
#' \item \code{graph.fontfamily}: string (default: \code{'sans'}) specifying the font family to be used in images. Please note, that using a custom font on Windows requires \code{grDevices:::windowsFonts} first.
#' \item \code{graph.fontcolor}: string (default: \code{'black'}) specifying the default font color
#' \item \code{graph.fontsize}: numeric (default: \code{12}) specifying the \emph{base} font size in pixels. Main title is rendered with \code{1.2} and labels with \code{0.8} multiplier.
#' \item \code{graph.grid}: boolean (default: \code{TRUE}) if a grid should be added to the plot
#' \item \code{graph.grid.minor}: boolean (default: \code{TRUE}) if a miner grid should be also rendered
#' \item \code{graph.grid.color}: string (default: \code{'grey'}) specifying the color of the rendered grid
#' \item \code{graph.grid.lty}: string (default: \code{'dashed'}) specifying the line type of grid
#' \item \code{graph.boxes}: boolean (default: \code{FALSE}) if to render a border around of plot (and e.g. around strip)
#' \item \code{graph.legend.position}: string (default: \code{'right'}) specifying the position of the legend: 'top', 'right', 'bottom' or 'left'
#' \item \code{graph.background}: string (default: \code{'white'}) specifying the plots main background's color
#' \item \code{graph.panel.background}: string (default: \code{'transparent'}) specifying the plot's main panel background. Please \emph{note}, that this option is not supported with \code{base} graphics.
#' \item \code{graph.colors}: character vector of default color palette (defaults to a colorblind theme: \url{http://jfly.iam.u-tokyo.ac.jp/color/}). Please \emph{note} that this update work with \code{base} plots by appending the \code{col} argument to the call if not set.
#' \item \code{graph.color.rnd}: boolean (default: \code{FALSE}) specifying if the palette should be reordered randomly before rendering each plot to get colorful images
#' \item \code{graph.axis.angle}: numeric (default: \code{1}) specifying the angle of axes' labels. The available options are based on \code{par(les)} and sets if the labels should be:
#' \itemize{
#' \item \code{1}: parallel to the axis,
#' \item \code{2}: horizontal,
#' \item \code{3}: perpendicular to the axis or
#' \item \code{4}: vertical.
#' }
#' \item \code{graph.symbol}: numeric (default: \code{1}) specifying a symbol (see the \code{pch} parameter of \code{par})
#' \item \code{knitr.auto.asis}: boolean (default: \code{TRUE}) if the results of \code{pander} should be considered as \code{'asis'} in \code{knitr}. Equals to specifying \code{results='asis'} in the R chunk, so thus there is no need to do so if set to \code{TRUE}.
#' \item \code{pandoc.binary}: full path of \code{pandoc}'s binary. By default, \code{pandoc} is in the path.
#' }
#' @param o option name (string). See below.
#' @param value value to assign (optional)
#' @export
#' @seealso \code{\link{evalsOptions}}
#' @examples \dontrun{
#' panderOptions()
#' panderOptions('digits')
#' panderOptions('digits', 5)
#' }
panderOptions <- function(o, value) {
res <- getOption('pander')
## just querying
if (missing(value)) {
if (missing(o))
return(res)
if (o %in% names(res))
return(res[[o]])
pandoc.header('Possible `pander` options:', style = 'setext')
pandoc.list(names(res))
stop('Wrong option queried.')
} else {
if (!o %in% names(res))
stop(paste('Invalid option name:', o))
## fix assigning NULL to a list element
if (is.null(value)) {
res[o] <- list(NULL)
} else {
res[[o]] <- value
}
options('pander' = res)
}
}
#' Querying/setting evals option
#'
#' To list all \code{evals} options, just run this function without any parameters provided. To query only one value, pass the first parameter. To set that, use the \code{value} parameter too.
#'
#' The following \code{evals} options are available:
#'
#' \itemize{
#' \item \code{parse}: if \code{TRUE} the provided \code{txt} elements would be merged into one string and parsed to logical chunks. This is useful if you would want to get separate results of your code parts - not just the last returned value, but you are passing the whole script in one string. To manually lock lines to each other (e.g. calling a \code{plot} and on next line adding an \code{abline} or \code{text} to it), use a plus char (\code{+}) at the beginning of each line which should be evaluated with the previous one(s). If set to \code{FALSE}, \code{evals} would not try to parse R code, it would get evaluated in separate runs - as provided. Please see examples of \code{\link{evals}}.
#' \item \code{cache}: caching the result of R calls if set to \code{TRUE}
#' \item \code{cache.mode}: cached results could be stored in an \code{environment} in \emph{current} R session or let it be permanent on \code{disk}.
#' \item \code{cache.dir}: path to a directory holding cache files if \code{cache.mode} set to \code{disk}. Default to \code{.cache} in current working directory.
#' \item \code{cache.time}: number of seconds to limit caching based on \code{proc.time}. If set to \code{0}, all R commands, if set to \code{Inf}, none is cached (despite the \code{cache} parameter).
#' \item \code{cache.copy.images}: copy images to new files if an image is returned from cache? If set to \code{FALSE} (default) the "old" path would be returned.
#' \item \code{classes}: a vector or list of classes which should be returned. If set to \code{NULL} (by default) all R objects will be returned.
#' \item \code{hooks}: list of hooks to be run for given classes in the form of \code{list(class = fn)}. If you would also specify some parameters of the function, a list should be provided in the form of \code{list(fn, param1, param2=NULL)} etc. So the hooks would become \code{list(class1=list(fn, param1, param2=NULL), ...)}. See examples of \code{\link{evals}}. A default hook can be specified too by setting the class to \code{'default'}. This can be handy if you do not want to define separate methods/functions to each possible class, but automatically apply the default hook to all classes not mentioned in the list. You may also specify only one element in the list like: \code{hooks=list('default' = pander_return)}. Please note, that nor error/warning messages, nor stdout is captured (so: updated) while running hooks!
#' \item \code{length}: any R object exceeding the specified length will not be returned. The default value (\code{Inf}) does not filter out any R objects.
#' \item \code{output}: a character vector of required returned values. This might be useful if you are only interested in the \code{result}, and do not want to save/see e.g. \code{messages} or \code{print}ed \code{output}. See examples of \code{\link{evals}}.
#' \item \code{graph.unify}: boolean (default: \code{FALSE}) that determines if \code{evals} should try to unify the style of (\code{base}, \code{lattice} and \code{ggplot2}) plots? If set to \code{TRUE}, some \code{panderOptions()} would apply.
#' \item \code{graph.name}: set the file name of saved plots which is \code{\link{tempfile}} by default. A simple character string might be provided where \code{\%d} would be replaced by the index of the generating \code{txt} source, \code{\%n} with an incremented integer in \code{graph.dir} with similar file names and \code{\%t} by some random characters. A function's name to be \code{eval}uated can be passed here too.
#' \item \code{graph.dir}: path to a directory where to place generated images. If the directory does not exist, \code{\link{evals}} try to create that. Default set to \code{plots} in current working directory.
#' \item \code{graph.output}: set the required file format of saved plots. Currently it could be any of \code{grDevices}: \code{png}, \code{bmp}, \code{jpeg}, \code{jpg}, \code{tiff}, \code{svg} or \code{pdf}. Set to \code{NA} not to save plots at all and tweak that setting with \code{capture.plot()} on demand.
#' \item \code{width}: width of generated plot in pixels for even vector formats
#' \item \code{height}: height of generated plot in pixels for even vector formats
#' \item \code{res}: nominal resolution in \code{ppi}. The height and width of vector images will be calculated based in this.
#' \item \code{hi.res}: generate high resolution plots also? If set to \code{TRUE}, each R code parts resulting an image would be run twice.
#' \item \code{hi.res.width}: width of generated high resolution plot in pixels for even vector formats. The \code{height} and \code{res} of high resolution image is automatically computed based on the above options to preserve original plot aspect ratio.
#' \item \code{graph.env}: save the environments in which plots were generated to distinct files (based on \code{graph.name}) with \code{env} extension?
#' \item \code{graph.recordplot}: save the plot via \code{recordPlot} to distinct files (based on \code{graph.name}) with \code{recodplot} extension?
#' \item \code{graph.RDS}: save the raw R object returned (usually with \code{lattice} or \code{ggplot2}) while generating the plots to distinct files (based on \code{graph.name}) with \code{RDS} extension?
#' \item \code{log}: \code{NULL} or an optionally passed \emph{logger name} from \pkg{futile.logger} to record all info, trace, debug and error messages.
#' }
#' @param o option name (string). See below.
#' @param value value to assign (optional)
#' @export
#' @seealso \code{\link{evals}} \code{\link{panderOptions}}
#' @examples
#' evalsOptions()
#' evalsOptions('cache')
#' evalsOptions('cache', FALSE)
evalsOptions <- function(o, value) {
res <- getOption('evals')
## just querying
if (missing(value)) {
if (missing(o))
return(res)
if (o %in% names(res))
return(res[[o]])
pandoc.header('Possible `evals` options:', style = 'setext')
pandoc.list(names(res))
stop('Wrong option queried.')
} else {
if (!o %in% names(res))
stop(paste('Invalid option name:', o))
## fix assigning NULL to a list element
if (is.null(value)) {
res[o] <- list(NULL)
} else {
res[[o]] <- value
}
options('evals' = res)
}
}
|