ellipsis/0000755000176200001440000000000015164116560012103 5ustar liggesusersellipsis/tests/0000755000176200001440000000000014024376575013255 5ustar liggesusersellipsis/tests/testthat/0000755000176200001440000000000015164116560015105 5ustar liggesusersellipsis/tests/testthat/test-check.R0000644000176200001440000000353414204222741017260 0ustar liggesuserscontext("test-check") test_that("error if dots not used", { f <- function(x, y, ...) { check_dots_used() x + y } expect_error(f(1, 2), NA) expect_error(f(1, 2, 3), class = "rlib_error_dots_unused") }) test_that("error if dots not used by another function", { g <- function(a = 1, b = 1, ...) { a + b } f <- function(x = 1, ...) { check_dots_used() x * g(...) } expect_error(f(x = 10, a = 1), NA) expect_error(f(x = 10, c = 3), class = "rlib_error_dots_unused") }) test_that("error if dots named", { f <- function(..., xyz = 1) { check_dots_unnamed() } expect_error(f(xyz = 1), NA) expect_error(f(1, 2, 3), NA) expect_error(f(1, 2, 3, xyz = 4), NA) expect_error(f(1, 2, 3, xy = 4), class = "rlib_error_dots_named") }) test_that("error if if dots not empty", { f <- function(..., xyz = 1) { check_dots_empty() } expect_error(f(xyz = 1), NA) expect_error(f(xy = 4), class = "rlib_error_dots_nonempty") }) test_that("can control the action", { f <- function(action, check, ..., xyz = 1) { check(action = action) } expect_error(f(abort, check_dots_used, xy = 4), class = "rlib_error_dots_unused") expect_warning(f(warn, check_dots_used, xy = 4), class = "rlib_error_dots_unused") expect_message(f(inform, check_dots_used, xy = 4), class = "rlib_error_dots_unused") expect_error(f(abort, check_dots_unnamed, xy = 4), class = "rlib_error_dots_named") expect_warning(f(warn, check_dots_unnamed, xy = 4), class = "rlib_error_dots_named") expect_message(f(inform, check_dots_unnamed, xy = 4), class = "rlib_error_dots_named") expect_error(f(abort, check_dots_empty, xy = 4), class = "rlib_error_dots_nonempty") expect_warning(f(warn, check_dots_empty, xy = 4), class = "rlib_error_dots_nonempty") expect_message(f(inform, check_dots_empty, xy = 4), class = "rlib_error_dots_nonempty") }) ellipsis/tests/testthat/test-safe.R0000644000176200001440000000034113541226740017120 0ustar liggesuserscontext("test-safe") test_that("warn if unused dots", { expect_error(safe_median(1:10), NA) expect_error(safe_median(1:10, na.rm = TRUE), NA) expect_error(safe_median(1:10, y = 1), class = "rlib_error_dots_unused") }) ellipsis/tests/testthat.R0000644000176200001440000000007413536242052015226 0ustar liggesuserslibrary(testthat) library(ellipsis) test_check("ellipsis") ellipsis/MD50000644000176200001440000000170615164116560012417 0ustar liggesusers8be4248d9c2944512050d2f5ee4b83ae *DESCRIPTION 597e2bb79d625f8b9139bf5c89728dea *LICENSE 86a4edf8c0326196b6142f74aa60d217 *NAMESPACE 92a48f51f1c37b974ef48f1bbc56c968 *NEWS.md 8c9c922e033e62c9a3094436abfe7ae4 *R/check.R 05e6a05842c5ad21b39747ce66eceb3d *R/dots.R 75f170821d691ca9fb6bb99a8d9c8f3c *R/ellipsis-package.R 3321d65ecd14911f5e0c6b5e897d90e5 *R/safe.R ec3f1050d51fd6c6b88658ee4dea2ec6 *README.md d89718cc8577d3f8267e857f8abcfdfd *man/check_dots_empty.Rd 9b2d23760e22f0907a0f20ea11f1e641 *man/check_dots_unnamed.Rd 8fcb14f66d076399878fa0742287ba17 *man/check_dots_used.Rd 9f82ff2096aefac16916f96d509f6abe *man/dots_empty.Rd 4e4eb4889a9ac4c92ce7070e57f98e8f *man/dots_used.Rd 21b77e043a0192ecee3e7600ffb4cd1c *man/ellipsis-package.Rd 2bfb7193d77664dce5eda8f79380925f *man/safe_median.Rd d03f7b327e2ac7a03a1a7b095a590e62 *tests/testthat.R 7ec2cf883faab777bdc554a024c8c44a *tests/testthat/test-check.R 01a0faa5ace36debf2203da07380e4ae *tests/testthat/test-safe.R ellipsis/R/0000755000176200001440000000000015163663662012315 5ustar liggesusersellipsis/R/dots.R0000644000176200001440000000105115163663662013406 0ustar liggesusers#' Helper for consistent documentation of empty dots #' #' Use `@inheritParams ellipsis::dots_empty` in your package #' to consistently document an unused `...` argument. #' #' @param ... These dots are for future extensions and must be empty. #' @name dots_empty #' @keywords internal NULL #' Helper for consistent documentation of used dots #' #' Use `@inheritParams ellipsis::dots_used` in your package #' to consistently document an unused `...` argument. #' #' @param ... Arguments passed to methods. #' @name dots_used #' @keywords internal NULL ellipsis/R/check.R0000644000176200001440000000333715163661140013510 0ustar liggesusers#' Check that all dots have been used #' #' Automatically sets exit handler to run when function terminates, checking #' that all elements of `...` have been evaluated. If you use [on.exit()] #' elsewhere in your function, make sure to use `add = TRUE` so that you #' don't override the handler set up by `check_dots_used()`. #' #' @usage NULL #' @param action The action to take when the dots have not been used. One of #' [rlang::abort()], [rlang::warn()], [rlang::inform()] or [rlang::signal()]. #' @param env Environment in which to look for `...` and to set up handler. #' @export #' @examples #' f <- function(...) { #' check_dots_used() #' g(...) #' } #' #' g <- function(x, y, ...) { #' x + y #' } #' f(x = 1, y = 2) #' #' try(f(x = 1, y = 2, z = 3)) #' try(f(x = 1, y = 2, 3, 4, 5)) check_dots_used <- NULL # Assigned at load time #' Check that all dots are unnamed #' #' Named arguments in ... are often a sign of misspelled argument names. #' #' @usage NULL #' @inheritParams check_dots_used #' @param env Environment in which to look for `...`. #' @export #' @examples #' f <- function(..., foofy = 8) { #' check_dots_unnamed() #' c(...) #' } #' #' f(1, 2, 3, foofy = 4) #' try(f(1, 2, 3, foof = 4)) check_dots_unnamed <- NULL # Assigned at load time #' Check that dots are unused #' #' Sometimes you just want to use `...` to force your users to fully name #' the details arguments. This function warns if `...` is not empty. #' #' @usage NULL #' @inheritParams check_dots_used #' @param env Environment in which to look for `...`. #' @export #' @examples #' f <- function(x, ..., foofy = 8) { #' check_dots_empty() #' x + foofy #' } #' #' try(f(1, foof = 4)) #' f(1, foofy = 4) check_dots_empty <- NULL # Assigned at load time ellipsis/R/ellipsis-package.R0000644000176200001440000000033715163663662015660 0ustar liggesusers#' @keywords internal #' @import rlang "_PACKAGE" .onLoad <- function(...) { check_dots_used <<- rlang::check_dots_used check_dots_unnamed <<- rlang::check_dots_unnamed check_dots_empty <<- rlang::check_dots_empty } ellipsis/R/safe.R0000644000176200001440000000132513536242052013343 0ustar liggesusers#' Safe version of median #' #' `safe_median()` works [stats::median()] but warns if some elements of `...` #' are never used. #' #' @param x Numeric vector #' @param ... Additional arguments passed on to methods. #' @param na.rm For numeric method, should missing values be removed? #' @export #' @examples #' x <- c(1:10, NA) #' safe_median(x, na.rm = TRUE) #' median(x, na.rm = TRUE) #' #' try(median(x, na.mr = TRUE)) #' try(safe_median(x, na.mr = TRUE)) #' #' try(median(1, 2, 3)) #' try(safe_median(1, 2, 3)) safe_median <- function(x, ...) { check_dots_used() UseMethod("safe_median") } #' @export #' @rdname safe_median safe_median.numeric <- function(x, ..., na.rm = TRUE) { stats::median(x, na.rm = na.rm) } ellipsis/NAMESPACE0000644000176200001440000000027215163661140013321 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(safe_median,numeric) export(check_dots_empty) export(check_dots_unnamed) export(check_dots_used) export(safe_median) import(rlang) ellipsis/LICENSE0000644000176200001440000000005614042034520013076 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: ellipsis authors ellipsis/NEWS.md0000644000176200001440000000247315163663752013220 0ustar liggesusers# ellipsis 0.3.3 * Now unconditionally uses rlang # ellipsis 0.3.2 * Compatibility with next version of rlang. * Changed license to MIT (#39). # ellipsis 0.3.1 * Fixed an incompatibility with R devel. * New `?dots_used` topic from which you can inherit documentation for `...` documentation when the dots are passed to methods. # ellipsis 0.3.0 * `check_dots_used()`, `check_dots_unnamed()`, and `check_dots_empty()` gain an `action` argument, to specify if they should error, warn, message or signal when the dots meet the condition. # ellipsis 0.2.0 ellipsis has officially graduated from experimental to maturing in the package lifecycle. * The main change of this release is that `check_()` functions now throw custom errors, rather than warnings. * `check_` functions have been optimised for the most common case of no problems. This means that you use it in more places without worrying about the performance cost. * New `check_dots_empty()` that checks that `...` is empty (#11). * Improved error message suggesting that you check for mispecified argument names. # ellipsis 0.1.0 * New `check_dots_unnamed()` that checks that all components of `...` are unnamed (#7). * Fix a bug that caused `check_dots_used()` to emit many false positives (#8) # ellipsis 0.0.2 * Fix a `PROTECT`ion error ellipsis/README.md0000644000176200001440000000525615163661140013370 0ustar liggesusers # ellipsis [![Lifecycle: superseded](https://lifecycle.r-lib.org/articles/figures/lifecycle-superseded.svg)](https://lifecycle.r-lib.org/articles/stages.html) [![CRAN status](https://www.r-pkg.org/badges/version/ellipsis)](https://cran.r-project.org/package=ellipsis) [![R-CMD-check](https://github.com/r-lib/ellipsis/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-lib/ellipsis/actions/workflows/R-CMD-check.yaml) [![Codecov test coverage](https://codecov.io/gh/r-lib/ellipsis/graph/badge.svg)](https://app.codecov.io/gh/r-lib/ellipsis) Superseded by rlang. All the functionality in ellipsis is now provided by rlang. ------------------------------------------------------------------------ Adding `...` to a function is a powerful technique because it allows you to accept any number of additional arguments. Unfortunately it comes with a big downside: any misspelled or extraneous arguments will be silently ignored. This package provides tools for making `...` safer: - `check_dots_evaluated()` errors if any components of `...` are not evaluated. This allows an S3 generic to state that it expects every input to be evaluated. - `check_dots_unnamed()` errors if any components of `...` are named. This allows you to collect arbitrary unnamed arguments, warning if the user misspells a named argument. - `check_dots_empty()` errors if `...` is used. This allows you to use `...` to force the user to supply full argument names, while still warning if an argument name is misspelled. Thanks to [Jenny Bryan](https://github.com/jennybc) for the idea, and [Lionel Henry](https://github.com/lionel-) for the heart of the implementation. ## Installation Install the released version from CRAN: ``` r install.packages("ellipsis") ``` Or the development version from GitHub: ``` r devtools::install_github("r-lib/ellipsis") ``` ## Example `mean()` is a little dangerous because you might expect it to work like `sum()`: ``` r sum(1, 2, 3, 4) #> [1] 10 mean(1, 2, 3, 4) #> [1] 1 ``` This silently returns the incorrect result because `mean()` has arguments `x` and `...`. The `...` silently swallows up the additional arguments. We can use `ellipsis::check_dots_used()` to check that every input to `...` is actually used: ``` r safe_mean <- function(x, ..., trim = 0, na.rm = FALSE) { ellipsis::check_dots_used() mean(x, ..., trim = trim, na.rm = na.rm) } safe_mean(1, 2, 3, 4) #> Error in `safe_mean()`: #> ! Arguments in `...` must be used. #> ✖ Problematic arguments: #> • ..1 = 2 #> • ..2 = 3 #> • ..3 = 4 #> ℹ Did you misspell an argument name? ``` ellipsis/man/0000755000176200001440000000000014042477130012653 5ustar liggesusersellipsis/man/ellipsis-package.Rd0000644000176200001440000000153013541226740016360 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ellipsis-package.R \docType{package} \name{ellipsis-package} \alias{ellipsis} \alias{ellipsis-package} \title{ellipsis: Tools for Working with ...} \description{ The ellipsis is a powerful tool for extending functions. Unfortunately this power comes at a cost: misspelled arguments will be silently ignored. The ellipsis package provides a collection of functions to catch problems and alert the user. } \seealso{ Useful links: \itemize{ \item \url{https://ellipsis.r-lib.org} \item \url{https://github.com/r-lib/ellipsis} \item Report bugs at \url{https://github.com/r-lib/ellipsis/issues} } } \author{ \strong{Maintainer}: Hadley Wickham \email{hadley@rstudio.com} Other contributors: \itemize{ \item RStudio [copyright holder] } } \keyword{internal} ellipsis/man/check_dots_empty.Rd0000644000176200001440000000140714042477130016470 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check.R \name{check_dots_empty} \alias{check_dots_empty} \title{Check that dots are unused} \arguments{ \item{env}{Environment in which to look for \code{...}.} \item{action}{The action to take when the dots have not been used. One of \code{\link[rlang:abort]{rlang::abort()}}, \code{\link[rlang:abort]{rlang::warn()}}, \code{\link[rlang:abort]{rlang::inform()}} or \code{\link[rlang:abort]{rlang::signal()}}.} } \description{ Sometimes you just want to use \code{...} to force your users to fully name the details arguments. This function warns if \code{...} is not empty. } \examples{ f <- function(x, ..., foofy = 8) { check_dots_empty() x + foofy } try(f(1, foof = 4)) f(1, foofy = 4) } ellipsis/man/dots_used.Rd0000644000176200001440000000060113657421222015132 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dots.R \name{dots_used} \alias{dots_used} \title{Helper for consistent documentation of used dots} \arguments{ \item{...}{Arguments passed to methods.} } \description{ Use \verb{@inheritParams ellipsis::dots_used} in your package to consistently document an unused \code{...} argument. } \keyword{internal} ellipsis/man/check_dots_used.Rd0000644000176200001440000000200014042477130016260 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check.R \name{check_dots_used} \alias{check_dots_used} \title{Check that all dots have been used} \arguments{ \item{env}{Environment in which to look for \code{...} and to set up handler.} \item{action}{The action to take when the dots have not been used. One of \code{\link[rlang:abort]{rlang::abort()}}, \code{\link[rlang:abort]{rlang::warn()}}, \code{\link[rlang:abort]{rlang::inform()}} or \code{\link[rlang:abort]{rlang::signal()}}.} } \description{ Automatically sets exit handler to run when function terminates, checking that all elements of \code{...} have been evaluated. If you use \code{\link[=on.exit]{on.exit()}} elsewhere in your function, make sure to use \code{add = TRUE} so that you don't override the handler set up by \code{check_dots_used()}. } \examples{ f <- function(...) { check_dots_used() g(...) } g <- function(x, y, ...) { x + y } f(x = 1, y = 2) try(f(x = 1, y = 2, z = 3)) try(f(x = 1, y = 2, 3, 4, 5)) } ellipsis/man/safe_median.Rd0000644000176200001440000000140113536242052015371 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/safe.R \name{safe_median} \alias{safe_median} \alias{safe_median.numeric} \title{Safe version of median} \usage{ safe_median(x, ...) \method{safe_median}{numeric}(x, ..., na.rm = TRUE) } \arguments{ \item{x}{Numeric vector} \item{...}{Additional arguments passed on to methods.} \item{na.rm}{For numeric method, should missing values be removed?} } \description{ \code{safe_median()} works \code{\link[stats:median]{stats::median()}} but warns if some elements of \code{...} are never used. } \examples{ x <- c(1:10, NA) safe_median(x, na.rm = TRUE) median(x, na.rm = TRUE) try(median(x, na.mr = TRUE)) try(safe_median(x, na.mr = TRUE)) try(median(1, 2, 3)) try(safe_median(1, 2, 3)) } ellipsis/man/check_dots_unnamed.Rd0000644000176200001440000000131314042477130016755 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check.R \name{check_dots_unnamed} \alias{check_dots_unnamed} \title{Check that all dots are unnamed} \arguments{ \item{env}{Environment in which to look for \code{...}.} \item{action}{The action to take when the dots have not been used. One of \code{\link[rlang:abort]{rlang::abort()}}, \code{\link[rlang:abort]{rlang::warn()}}, \code{\link[rlang:abort]{rlang::inform()}} or \code{\link[rlang:abort]{rlang::signal()}}.} } \description{ Named arguments in ... are often a sign of misspelled argument names. } \examples{ f <- function(..., foofy = 8) { check_dots_unnamed() c(...) } f(1, 2, 3, foofy = 4) try(f(1, 2, 3, foof = 4)) } ellipsis/man/dots_empty.Rd0000644000176200001440000000064013751012017015324 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/dots.R \name{dots_empty} \alias{dots_empty} \title{Helper for consistent documentation of empty dots} \arguments{ \item{...}{These dots are for future extensions and must be empty.} } \description{ Use \verb{@inheritParams ellipsis::dots_empty} in your package to consistently document an unused \code{...} argument. } \keyword{internal} ellipsis/DESCRIPTION0000644000176200001440000000166615164116560013622 0ustar liggesusersPackage: ellipsis Version: 0.3.3 Title: Tools for Working with ... Description: The ellipsis is a powerful tool for extending functions. Unfortunately this power comes at a cost: misspelled arguments will be silently ignored. The ellipsis package provides a collection of functions to catch problems and alert the user. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = "cph") ) License: MIT + file LICENSE Encoding: UTF-8 RoxygenNote: 7.1.1 URL: https://ellipsis.r-lib.org, https://github.com/r-lib/ellipsis BugReports: https://github.com/r-lib/ellipsis/issues Depends: R (>= 3.2) Imports: rlang (>= 1.1.7) Suggests: covr, testthat NeedsCompilation: no Packaged: 2026-04-03 07:11:22 UTC; lionel Author: Hadley Wickham [aut, cre], RStudio [cph] Maintainer: Hadley Wickham Repository: CRAN Date/Publication: 2026-04-04 05:11:12 UTC