Nothing
.latex_macros <- new.env(parent = emptyenv())
.latex_macros$defs <- list()
#' Define a user-level LaTeX macro
#'
#' Registers a zero-argument shorthand that is expanded by text
#' substitution before the expression reaches the MicroTeX parser.
#' Useful for domain-specific notation (e.g. \code{\\RR} for
#' \code{\\mathbb\{R\}}) you reuse across many plots.
#'
#' @param name Macro name \strong{without} the leading backslash. For
#' \code{clear_macros}, the macro name to drop, or \code{NULL}
#' (default) to clear all.
#' @param definition LaTeX source the macro expands to.
#' @return
#' \itemize{
#' \item \code{define_macro}: Invisibly returns \code{NULL}.
#' \item \code{clear_macros}: Invisibly returns \code{NULL}.
#' \item \code{list_macros}: A named character vector mapping
#' macro names to their expansions. Empty if no macros are defined.
#' }
#' @seealso \code{\link{latex_grob}}, \code{\link{latex_options}}
#' @export
#'
#' @examples
#' \donttest{
#' define_macro("RR", "\\mathbb{R}")
#' define_macro("eps", "\\varepsilon")
#' grid::grid.newpage()
#' grid.latex("\\forall \\eps > 0, \\eps \\in \\RR")
#' clear_macros()
#' }
define_macro <- function(name, definition) {
stopifnot(is.character(name), length(name) == 1L, nzchar(name))
stopifnot(is.character(definition), length(definition) == 1L)
if (grepl("[^A-Za-z]", name)) {
stop("Macro name must contain only letters (ASCII a-z, A-Z).",
call. = FALSE)
}
.latex_macros$defs[[name]] <- definition
invisible(NULL)
}
#' @rdname define_macro
#' @export
clear_macros <- function(name = NULL) {
if (is.null(name)) {
.latex_macros$defs <- list()
} else {
.latex_macros$defs[[name]] <- NULL
}
invisible(NULL)
}
#' @rdname define_macro
#' @export
list_macros <- function() {
defs <- .latex_macros$defs
if (length(defs) == 0L) return(character(0))
unlist(defs)
}
# Apply macro expansion to a tex string. Matches \name where the next
# character is not a letter (so `\RR` matches but `\RRend` does not),
# in iteration until a fixed point so nested macros expand.
.expand_macros <- function(tex) {
defs <- .latex_macros$defs
if (length(defs) == 0L) return(tex)
for (depth in seq_len(8L)) {
before <- tex
for (name in names(defs)) {
pattern <- paste0("\\\\", name, "(?![A-Za-z])")
# Escape backslashes in the replacement so gsub treats them
# literally rather than as backreference escapes.
replacement <- gsub("\\\\", "\\\\\\\\", defs[[name]])
tex <- gsub(pattern, replacement, tex, perl = TRUE)
}
if (identical(tex, before)) break
}
tex
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.