From d668dd3165630e10611fa3401c1481fd73e660a5 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Mon, 13 Mar 2023 14:54:58 -0500 Subject: [PATCH] Doc improvements (#291) * Document return argument of glue() Fixes #283 * Pass along all glue() arguments in glue_sql() Fixes #274 * Clarify the `...` overides `.x` Fixes #264. * Document more return values + general tweaks --------- Co-authored-by: Jenny Bryan --- R/color.R | 1 + R/glue.R | 20 +++++++++++++- R/quoting.R | 4 ++- R/safe.R | 1 + R/sql.R | 56 ++++++++++++++++++++++++++++++++++++--- man/as_glue.Rd | 16 +++++++++++- man/glue.Rd | 8 +++++- man/glue_col.Rd | 8 +++++- man/glue_collapse.Rd | 4 ++- man/glue_safe.Rd | 8 +++++- man/glue_sql.Rd | 62 ++++++++++++++++++++++++++++++++++++++++---- man/quoting.Rd | 9 ++++++- man/trim.Rd | 3 +++ 13 files changed, 183 insertions(+), 17 deletions(-) diff --git a/R/color.R b/R/color.R index 4dcdb88f..7e68b34b 100644 --- a/R/color.R +++ b/R/color.R @@ -22,6 +22,7 @@ #' character, specify `.literal = TRUE`. #' #' @inheritParams glue +#' @inherit glue return #' @export #' @examplesIf require(crayon) #' library(crayon) diff --git a/R/glue.R b/R/glue.R index 5df52b42..1b3254f2 100644 --- a/R/glue.R +++ b/R/glue.R @@ -8,6 +8,8 @@ #' @param ... \[`expressions`]\cr Unnamed arguments are taken to be expression #' string(s) to format. Multiple inputs are concatenated together before formatting. #' Named arguments are taken to be temporary variables available for substitution. +#' +#' For `glue_data()`, elements in `...` override the values in `.x`. #' @param .sep \[`character(1)`: \sQuote{""}]\cr Separator used to separate elements. #' @param .envir \[`environment`: `parent.frame()`]\cr Environment to evaluate each expression in. Expressions are #' evaluated from left to right. If `.x` is an environment, the expressions are @@ -38,6 +40,7 @@ #' template with [trim()] or not. #' @seealso and #' upon which this is based. +#' @returns A glue object, as created by [as_glue()]. #' @examples #' name <- "Fred" #' age <- 50 @@ -216,6 +219,7 @@ glue <- function(..., .sep = "", .envir = parent.frame(), .open = "{", .close = #' @param last String used to separate the last two items if `x` has at least #' 2 items. #' @inheritParams base::paste +#' @inherit glue return #' @examples #' glue_collapse(glue("{1:10}")) #' @@ -223,7 +227,6 @@ glue <- function(..., .sep = "", .envir = parent.frame(), .open = "{", .close = #' glue_collapse(glue("{1:10}"), width = 5) #' #' glue_collapse(1:4, ", ", last = " and ") -#' #> 1, 2, 3 and 4 #' @export glue_collapse <- function(x, sep = "", width = Inf, last = "") { if (length(x) == 0) { @@ -258,6 +261,7 @@ glue_collapse <- function(x, sep = "", width = Inf, last = "") { #' to the minimum indentation of all non-blank lines after the first. #' - Lines can be continued across newlines by using `\\`. #' @param x A character vector to trim. +#' @returns A character vector. #' @export #' @examples #' glue(" @@ -297,9 +301,23 @@ print.glue <- function(x, ..., sep = "\n") { } #' Coerce object to glue +#' +#' A glue object is a character vector with S3 class `"glue"`. The `"glue"` +#' class implements a print method that shows the literal contents (rather than +#' the string implementation) and a `+` method, so that you can concatenate with +#' the addition operator. +#' #' @param x object to be coerced. #' @param ... further arguments passed to methods. +#' @returns A character vector with S3 class `"glue"`. #' @export +#' @examples +#' x <- as_glue(c("abc", "\"\\\\", "\n")) +#' x +#' +#' x <- 1 +#' y <- 3 +#' glue("x + y") + " = {x + y}" as_glue <- function(x, ...) { UseMethod("as_glue") } diff --git a/R/quoting.R b/R/quoting.R index 97a1e9a4..b1079708 100644 --- a/R/quoting.R +++ b/R/quoting.R @@ -1,9 +1,11 @@ #' Quoting operators #' #' These functions make it easy to quote each individual element and are useful -#' in conjunction with [glue_collapse()]. +#' in conjunction with [glue_collapse()]. These are thin wrappers around +#' [base::encodeString()]. #' @param x A character to quote. #' @name quoting +#' @inherit base::encodeString return #' @export #' @examples #' x <- 1:5 diff --git a/R/safe.R b/R/safe.R index db62bc9d..9f496612 100644 --- a/R/safe.R +++ b/R/safe.R @@ -6,6 +6,7 @@ #' with untrusted input, such as inputs in a Shiny application, where using the #' normal functions would allow an attacker to execute arbitrary code. #' @inheritParams glue +#' @inherit glue return #' @export #' @examples #' "1 + 1" <- 5 diff --git a/R/sql.R b/R/sql.R index 8a8c2738..3b300637 100644 --- a/R/sql.R +++ b/R/sql.R @@ -1,5 +1,6 @@ #' Interpolate strings with SQL escaping #' +#' @description #' SQL databases often have custom quotation syntax for identifiers and strings #' which make writing SQL queries error prone and cumbersome to do. `glue_sql()` and #' `glue_data_sql()` are analogs to [glue()] and [glue_data()] which handle the @@ -134,14 +135,61 @@ #' #' DBI::dbDisconnect(con) #' @export -glue_sql <- function(..., .con, .envir = parent.frame(), .na = DBI::SQL("NULL")) { - DBI::SQL(glue(..., .envir = .envir, .na = .na, .transformer = sql_quote_transformer(.con, .na))) +glue_sql <- function(..., + .con, + .sep = "", + .envir = parent.frame(), + .open = "{", + .close = "}", + .na = DBI::SQL("NULL"), + .null = character(), + .comment = "#", + .literal = FALSE, + .trim = TRUE + ) { + DBI::SQL(glue( + ..., + .sep = .sep, + .envir = .envir, + .open = .open, + .close = .close, + .na = .na, + .null = .null, + .comment = .comment, + .literal = .literal, + .transformer = sql_quote_transformer(.con, .na), + .trim = .trim + )) } #' @rdname glue_sql #' @export -glue_data_sql <- function(.x, ..., .con, .envir = parent.frame(), .na = DBI::SQL("NULL")) { - DBI::SQL(glue_data(.x, ..., .envir = .envir, .na = .na, .transformer = sql_quote_transformer(.con, .na))) +glue_data_sql <- function(.x, + ..., + .con, + .sep = "", + .envir = parent.frame(), + .open = "{", + .close = "}", + .na = DBI::SQL("NULL"), + .null = character(), + .comment = "#", + .literal = FALSE, + .trim = TRUE) { + DBI::SQL(glue_data( + .x, + ..., + .sep = .sep, + .envir = .envir, + .open = .open, + .close = .close, + .na = .na, + .null = .null, + .comment = .comment, + .literal = .literal, + .transformer = sql_quote_transformer(.con, .na), + .trim = .trim + )) } #' @rdname glue_collapse diff --git a/man/as_glue.Rd b/man/as_glue.Rd index f424be98..8e9cc66a 100644 --- a/man/as_glue.Rd +++ b/man/as_glue.Rd @@ -11,6 +11,20 @@ as_glue(x, ...) \item{...}{further arguments passed to methods.} } +\value{ +A character vector with S3 class \code{"glue"}. +} \description{ -Coerce object to glue +A glue object is a character vector with S3 class \code{"glue"}. The \code{"glue"} +class implements a print method that shows the literal contents (rather than +the string implementation) and a \code{+} method, so that you can concatenate with +the addition operator. +} +\examples{ +x <- as_glue(c("abc", "\"\\\\\\\\", "\n")) +x + +x <- 1 +y <- 3 +glue("x + y") + " = {x + y}" } diff --git a/man/glue.Rd b/man/glue.Rd index 64520498..64a87939 100644 --- a/man/glue.Rd +++ b/man/glue.Rd @@ -39,7 +39,10 @@ glue( \item{...}{[\code{expressions}]\cr Unnamed arguments are taken to be expression string(s) to format. Multiple inputs are concatenated together before formatting. -Named arguments are taken to be temporary variables available for substitution.} +Named arguments are taken to be temporary variables available for substitution. + +\if{html}{\out{
}}\preformatted{For `glue_data()`, elements in `...` override the values in `.x`. +}\if{html}{\out{
}}} \item{.sep}{[\code{character(1)}: \sQuote{""}]\cr Separator used to separate elements.} @@ -78,6 +81,9 @@ evaluation. For example transformers see \code{vignette("transformers")}.} \item{.trim}{[\code{logical(1)}: \sQuote{TRUE}]\cr Whether to trim the input template with \code{\link[=trim]{trim()}} or not.} } +\value{ +A glue object, as created by \code{\link[=as_glue]{as_glue()}}. +} \description{ Expressions enclosed by braces will be evaluated as R code. Long strings are broken by line and concatenated together. Leading whitespace and blank lines diff --git a/man/glue_col.Rd b/man/glue_col.Rd index f1ccf302..715fd113 100644 --- a/man/glue_col.Rd +++ b/man/glue_col.Rd @@ -12,7 +12,10 @@ glue_data_col(.x, ..., .envir = parent.frame(), .na = "NA", .literal = FALSE) \arguments{ \item{...}{[\code{expressions}]\cr Unnamed arguments are taken to be expression string(s) to format. Multiple inputs are concatenated together before formatting. -Named arguments are taken to be temporary variables available for substitution.} +Named arguments are taken to be temporary variables available for substitution. + +\if{html}{\out{
}}\preformatted{For `glue_data()`, elements in `...` override the values in `.x`. +}\if{html}{\out{
}}} \item{.envir}{[\code{environment}: \code{parent.frame()}]\cr Environment to evaluate each expression in. Expressions are evaluated from left to right. If \code{.x} is an environment, the expressions are @@ -30,6 +33,9 @@ syntactic elements), when parsing the expression string. Setting \code{.literal \item{.x}{[\code{listish}]\cr An environment, list, or data frame used to lookup values.} } +\value{ +A glue object, as created by \code{\link[=as_glue]{as_glue()}}. +} \description{ The \link[crayon:crayon]{crayon} package defines a number of functions used to color terminal output. \code{glue_col()} and \code{glue_data_col()} functions provide diff --git a/man/glue_collapse.Rd b/man/glue_collapse.Rd index 57465d05..2a2008de 100644 --- a/man/glue_collapse.Rd +++ b/man/glue_collapse.Rd @@ -20,6 +20,9 @@ glue_sql_collapse(x, sep = "", width = Inf, last = "") \item{last}{String used to separate the last two items if \code{x} has at least 2 items.} } +\value{ +A glue object, as created by \code{\link[=as_glue]{as_glue()}}. +} \description{ \code{glue_collapse()} collapses a character vector of any length into a length 1 vector. \code{glue_sql_collapse()} does the same but returns a \verb{[DBI::SQL()]} @@ -32,5 +35,4 @@ glue_collapse(glue("{1:10}")) glue_collapse(glue("{1:10}"), width = 5) glue_collapse(1:4, ", ", last = " and ") -#> 1, 2, 3 and 4 } diff --git a/man/glue_safe.Rd b/man/glue_safe.Rd index 86ee072a..e7c30574 100644 --- a/man/glue_safe.Rd +++ b/man/glue_safe.Rd @@ -12,7 +12,10 @@ glue_data_safe(.x, ..., .envir = parent.frame()) \arguments{ \item{...}{[\code{expressions}]\cr Unnamed arguments are taken to be expression string(s) to format. Multiple inputs are concatenated together before formatting. -Named arguments are taken to be temporary variables available for substitution.} +Named arguments are taken to be temporary variables available for substitution. + +\if{html}{\out{
}}\preformatted{For `glue_data()`, elements in `...` override the values in `.x`. +}\if{html}{\out{
}}} \item{.envir}{[\code{environment}: \code{parent.frame()}]\cr Environment to evaluate each expression in. Expressions are evaluated from left to right. If \code{.x} is an environment, the expressions are @@ -20,6 +23,9 @@ evaluated in that environment and \code{.envir} is ignored. If \code{NULL} is pa \item{.x}{[\code{listish}]\cr An environment, list, or data frame used to lookup values.} } +\value{ +A glue object, as created by \code{\link[=as_glue]{as_glue()}}. +} \description{ \code{glue_safe()} and \code{glue_data_safe()} differ from \code{\link[=glue]{glue()}} and \code{\link[=glue_data]{glue_data()}} in that the safe versions only look up symbols from an environment using diff --git a/man/glue_sql.Rd b/man/glue_sql.Rd index 45d53508..616f7796 100644 --- a/man/glue_sql.Rd +++ b/man/glue_sql.Rd @@ -5,27 +5,80 @@ \alias{glue_data_sql} \title{Interpolate strings with SQL escaping} \usage{ -glue_sql(..., .con, .envir = parent.frame(), .na = DBI::SQL("NULL")) +glue_sql( + ..., + .con, + .sep = "", + .envir = parent.frame(), + .open = "{", + .close = "}", + .na = DBI::SQL("NULL"), + .null = character(), + .comment = "#", + .literal = FALSE, + .trim = TRUE +) -glue_data_sql(.x, ..., .con, .envir = parent.frame(), .na = DBI::SQL("NULL")) +glue_data_sql( + .x, + ..., + .con, + .sep = "", + .envir = parent.frame(), + .open = "{", + .close = "}", + .na = DBI::SQL("NULL"), + .null = character(), + .comment = "#", + .literal = FALSE, + .trim = TRUE +) } \arguments{ \item{...}{[\code{expressions}]\cr Unnamed arguments are taken to be expression string(s) to format. Multiple inputs are concatenated together before formatting. -Named arguments are taken to be temporary variables available for substitution.} +Named arguments are taken to be temporary variables available for substitution. + +\if{html}{\out{
}}\preformatted{For `glue_data()`, elements in `...` override the values in `.x`. +}\if{html}{\out{
}}} \item{.con}{[\code{DBIConnection}]: A DBI connection object obtained from \code{\link[DBI:dbConnect]{DBI::dbConnect()}}.} +\item{.sep}{[\code{character(1)}: \sQuote{""}]\cr Separator used to separate elements.} + \item{.envir}{[\code{environment}: \code{parent.frame()}]\cr Environment to evaluate each expression in. Expressions are evaluated from left to right. If \code{.x} is an environment, the expressions are evaluated in that environment and \code{.envir} is ignored. If \code{NULL} is passed, it is equivalent to \code{\link[=emptyenv]{emptyenv()}}.} +\item{.open}{[\code{character(1)}: \sQuote{\\\{}]\cr The opening delimiter. Doubling the +full delimiter escapes it.} + +\item{.close}{[\code{character(1)}: \sQuote{\\\}}]\cr The closing delimiter. Doubling the +full delimiter escapes it.} + \item{.na}{[\code{character(1)}: \code{DBI::SQL("NULL")}]\cr Value to replace \code{NA} values with. If \code{NULL} missing values are propagated, that is an \code{NA} result will cause \code{NA} output. Otherwise the value is replaced by the value of \code{.na}.} +\item{.null}{[\code{character(1)}: \sQuote{character()}]\cr Value to replace +NULL values with. If \code{character()} whole output is \code{character()}. If +\code{NULL} all NULL values are dropped (as in \code{paste0()}). Otherwise the +value is replaced by the value of \code{.null}.} + +\item{.comment}{[\code{character(1)}: \sQuote{#}]\cr Value to use as the comment +character.} + +\item{.literal}{[\code{boolean(1)}: \sQuote{FALSE}]\cr Whether to treat single or +double quotes, backticks, and comments as regular characters (vs. as +syntactic elements), when parsing the expression string. Setting \code{.literal = TRUE} probably only makes sense in combination with a custom +\code{.transformer}, as is the case with \code{glue_col()}. Regard this argument +(especially, its name) as experimental.} + +\item{.trim}{[\code{logical(1)}: \sQuote{TRUE}]\cr Whether to trim the input +template with \code{\link[=trim]{trim()}} or not.} + \item{.x}{[\code{listish}]\cr An environment, list, or data frame used to lookup values.} } \value{ @@ -36,8 +89,7 @@ SQL databases often have custom quotation syntax for identifiers and strings which make writing SQL queries error prone and cumbersome to do. \code{glue_sql()} and \code{glue_data_sql()} are analogs to \code{\link[=glue]{glue()}} and \code{\link[=glue_data]{glue_data()}} which handle the SQL quoting. \code{glue_sql_collapse()} can be used to collapse \code{\link[DBI:SQL]{DBI::SQL()}} objects. -} -\details{ + They automatically quote character results, quote identifiers if the glue expression is surrounded by backticks '\verb{`}' and do not quote non-characters such as numbers. If numeric data is stored in a character diff --git a/man/quoting.Rd b/man/quoting.Rd index a6b65a8a..6aaddca3 100644 --- a/man/quoting.Rd +++ b/man/quoting.Rd @@ -16,9 +16,16 @@ backtick(x) \arguments{ \item{x}{A character to quote.} } +\value{ +A character vector of the same length as \code{x}, with the same + attributes (including names and dimensions) but with no class set. + + Marked UTF-8 encodings are preserved. +} \description{ These functions make it easy to quote each individual element and are useful -in conjunction with \code{\link[=glue_collapse]{glue_collapse()}}. +in conjunction with \code{\link[=glue_collapse]{glue_collapse()}}. These are thin wrappers around +\code{\link[base:encodeString]{base::encodeString()}}. } \examples{ x <- 1:5 diff --git a/man/trim.Rd b/man/trim.Rd index 1c475682..8aff4652 100644 --- a/man/trim.Rd +++ b/man/trim.Rd @@ -9,6 +9,9 @@ trim(x) \arguments{ \item{x}{A character vector to trim.} } +\value{ +A character vector. +} \description{ This trims a character vector according to the trimming rules used by glue. These follow similar rules to \href{https://www.python.org/dev/peps/pep-0257/}{Python Docstrings},