ellipsis/0000755000176200001440000000000014042524442012077 5ustar liggesusersellipsis/NAMESPACE0000644000176200001440000000034414042477043013323 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) useDynLib(ellipsis, .registration = TRUE) ellipsis/LICENSE0000644000176200001440000000005614042034520013076 0ustar liggesusersYEAR: 2020 COPYRIGHT HOLDER: ellipsis authors ellipsis/README.md0000644000176200001440000000475114042520376013367 0ustar liggesusers # ellipsis [![Lifecycle: maturing](https://img.shields.io/badge/lifecycle-maturing-blue.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) [![Travis build status](https://travis-ci.org/r-lib/ellipsis.svg?branch=master)](https://travis-ci.org/r-lib/ellipsis) [![Codecov test coverage](https://codecov.io/gh/r-lib/ellipsis/branch/master/graph/badge.svg)](https://codecov.io/gh/r-lib/ellipsis?branch=master) 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_used()` 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: 3 components of `...` were not used. #> #> We detected these problematic arguments: #> * `..1` #> * `..2` #> * `..3` #> #> Did you misspecify an argument? ``` ellipsis/man/0000755000176200001440000000000014042477130012653 5ustar liggesusersellipsis/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/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/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/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/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/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/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/DESCRIPTION0000644000176200001440000000166714042524442013617 0ustar liggesusersPackage: ellipsis Version: 0.3.2 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 (>= 0.3.0) Suggests: covr, testthat NeedsCompilation: yes Packaged: 2021-04-29 12:06:44 UTC; lionel Author: Hadley Wickham [aut, cre], RStudio [cph] Maintainer: Hadley Wickham Repository: CRAN Date/Publication: 2021-04-29 12:40:02 UTC ellipsis/tests/0000755000176200001440000000000014024376575013255 5ustar liggesusersellipsis/tests/testthat/0000755000176200001440000000000014042524442015101 5ustar liggesusersellipsis/tests/testthat/test-check.R0000644000176200001440000000353413541226740017266 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/test-dots.R0000644000176200001440000000115613536242052017156 0ustar liggesuserscontext("test-dots") capture_dots <- function(..., auto_name = TRUE) dots(auto_name = auto_name) test_that("errors with bad inputs", { expect_error(dots(), "No ... found") expect_error(dots(1), "not an environment") }) test_that("no dots yields empty list", { expect_equal(capture_dots(), list()) }) test_that("captures names if present", { expect_named(capture_dots(x = 1, y = 2), c("x", "y")) }) test_that("constructs names if absent", { expect_named(capture_dots(1, 2), c("..1", "..2")) }) test_that("unless auto_name = FALSE", { expect_named(capture_dots(x = 1, 2, auto_name = FALSE), c("x", NA)) }) ellipsis/tests/testthat.R0000644000176200001440000000007413536242052015226 0ustar liggesuserslibrary(testthat) library(ellipsis) test_check("ellipsis") ellipsis/src/0000755000176200001440000000000014042520524012663 5ustar liggesusersellipsis/src/init.c0000644000176200001440000000134213570000620013765 0ustar liggesusers#include #include #include // for NULL #include /* .Call calls */ extern SEXP ellipsis_promise_forced(SEXP); extern SEXP ellipsis_dots(SEXP, SEXP); extern SEXP ellipsis_eval_bare(SEXP, SEXP); extern SEXP ellipsis_dots_used(SEXP); static const R_CallMethodDef CallEntries[] = { {"ellipsis_dots", (DL_FUNC) &ellipsis_dots, 2}, {"ellipsis_promise_forced", (DL_FUNC) &ellipsis_promise_forced, 1}, {"ellipsis_eval_bare", (DL_FUNC) &ellipsis_eval_bare, 2}, {"ellipsis_dots_used", (DL_FUNC) &ellipsis_dots_used, 1}, {NULL, NULL, 0} }; void R_init_ellipsis(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } ellipsis/src/dots.c0000644000176200001440000000374313576671152014026 0ustar liggesusers#define R_NO_REMAP #include #include #include #include static SEXP find_dots(SEXP env) { if (TYPEOF(env) != ENVSXP) { Rf_errorcall(R_NilValue, "`env` is a not an environment"); } SEXP dots = PROTECT(Rf_findVarInFrame3(env, R_DotsSymbol, TRUE)); if (dots == R_UnboundValue) { Rf_errorcall(R_NilValue, "No ... found"); } UNPROTECT(1); return dots; } SEXP ellipsis_dots(SEXP env, SEXP auto_name_) { int auto_name = Rf_asLogical(auto_name_); SEXP dots = PROTECT(find_dots(env)); // Empty dots if (dots == R_MissingArg) { UNPROTECT(1); return Rf_allocVector(VECSXP, 0); } R_len_t n = Rf_length(dots); SEXP out = PROTECT(Rf_allocVector(VECSXP, n)); SEXP names = PROTECT(Rf_allocVector(STRSXP, n)); Rf_setAttrib(out, R_NamesSymbol, names); for (R_len_t i = 0; i < n; ++i) { SET_VECTOR_ELT(out, i, CAR(dots)); SEXP name = TAG(dots); if (TYPEOF(name) == SYMSXP) { SET_STRING_ELT(names, i, PRINTNAME(name)); } else { if (auto_name) { char buffer[20]; snprintf(buffer, 20, "..%i", i + 1); SET_STRING_ELT(names, i, Rf_mkChar(buffer)); } else { SET_STRING_ELT(names, i, NA_STRING); } } dots = CDR(dots); } UNPROTECT(3); return out; } static bool promise_forced(SEXP x) { if (TYPEOF(x) != PROMSXP) { return true; } else { return PRVALUE(x) != R_UnboundValue; } } SEXP ellipsis_promise_forced(SEXP x) { return Rf_ScalarLogical(promise_forced(x)); } SEXP ellipsis_dots_used(SEXP env) { SEXP dots = PROTECT(find_dots(env)); if (dots == R_MissingArg) { UNPROTECT(1); return Rf_ScalarLogical(true); } while (dots != R_NilValue) { SEXP elt = CAR(dots); if (!promise_forced(elt)) { UNPROTECT(1); return Rf_ScalarLogical(false); } dots = CDR(dots); } UNPROTECT(1); return Rf_ScalarLogical(true); } SEXP ellipsis_eval_bare(SEXP expr, SEXP env) { return Rf_eval(expr, env); } ellipsis/R/0000755000176200001440000000000014042477130012301 5ustar liggesusersellipsis/R/check.R0000644000176200001440000000714214042477130013505 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 <- function(env = parent.frame(), action = abort) { eval_bare(exit_handler(action), env) invisible() } on_load({ check_dots_used <- replace_from("check_dots_used", "rlang") }) check_dots <- function(env = parent.frame(), action) { if (.Call(ellipsis_dots_used, env)) { return(invisible()) } proms <- dots(env) used <- vapply(proms, promise_forced, logical(1)) unused <- names(proms)[!used] action_dots( action = action, message = paste0(length(unused), " components of `...` were not used."), dot_names = unused, .subclass = "rlib_error_dots_unused", ) } exit_handler <- function(action) { expr( on.exit((!!check_dots)(environment(), !!action), add = TRUE) ) } #' 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 <- function(env = parent.frame(), action = abort) { proms <- dots(env, auto_name = FALSE) if (length(proms) == 0) { return() } unnamed <- is.na(names(proms)) if (all(unnamed)) { return(invisible()) } named <- names(proms)[!unnamed] action_dots( action = action, message = paste0(length(named), " components of `...` had unexpected names."), dot_names = named, .subclass = "rlib_error_dots_named", ) } on_load({ check_dots_unnamed <- replace_from("check_dots_unnamed", "rlang") }) #' 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 <- function(env = parent.frame(), action = abort) { dots <- dots(env) if (length(dots) == 0) { return() } action_dots( action = action, message = "`...` is not empty.", dot_names = names(dots), note = "These dots only exist to allow future extensions and should be empty.", .subclass = "rlib_error_dots_nonempty" ) } on_load({ check_dots_empty <- replace_from("check_dots_empty", "rlang") }) action_dots <- function(action, message, dot_names, note = NULL, .subclass = NULL, ...) { message <- paste_line( message, "", "We detected these problematic arguments:", paste0("* `", dot_names, "`"), "", note, "Did you misspecify an argument?" ) action(message, .subclass = c(.subclass, "rlib_error_dots"), ...) } ellipsis/R/utils.R0000644000176200001440000000010213536242052013555 0ustar liggesusers paste_line <- function(...) { paste(c(...), collapse = "\n") } ellipsis/R/ellipsis-package.R0000644000176200001440000000014014042471050015627 0ustar liggesusers#' @keywords internal #' @import rlang "_PACKAGE" .onLoad <- function(...) { run_on_load() } ellipsis/R/aaa.R0000644000176200001440000000116314042471063013146 0ustar liggesuserson_load <- function(expr, env = parent.frame()) { ns <- topenv(env) expr <- substitute(expr) callback <- function() eval_bare(expr, env) ns$.__rlang_hook__. <- c(ns$.__rlang_hook__., list(callback)) } run_on_load <- function(env = parent.frame()) { ns <- topenv(env) hook <- ns$.__rlang_hook__. env_unbind(ns, ".__rlang_hook__.") for (callback in hook) { callback() } ns$.__rlang_hook__. <- NULL } replace_from <- function(what, pkg, to = topenv(caller_env())) { if (what %in% getNamespaceExports(pkg)) { env <- ns_env(pkg) } else { env <- to } env_get(env, what, inherit = TRUE) } 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/R/dots.R0000644000176200001440000000151714042467056013407 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 #' @useDynLib ellipsis, .registration = TRUE dots <- function(env = parent.frame(), auto_name = TRUE) { .Call(ellipsis_dots, env, auto_name) } promise_forced <- function(x) { .Call(ellipsis_promise_forced, x) } eval_bare <- function(expr, env) { .Call(ellipsis_eval_bare, expr, env) } ellipsis/NEWS.md0000644000176200001440000000240614042477633013210 0ustar liggesusers# 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/MD50000644000176200001440000000226314042524442012412 0ustar liggesusersfd24e488d0b67e1f936ac2b64e4c6304 *DESCRIPTION 597e2bb79d625f8b9139bf5c89728dea *LICENSE deb6ceef8d8275f3c277fa8e6e486688 *NAMESPACE 7f3e7b0fe90761464f7b976c21545d3f *NEWS.md dab9f51fdddc6fb25a4824ebfe631a91 *R/aaa.R bfeee254b61b43ef57ff8dcf66f3bf47 *R/check.R 01e9def3508b208afb3692ccb469ede2 *R/dots.R 3d397a45a7d9798d467ea3629cf5ce2d *R/ellipsis-package.R 3321d65ecd14911f5e0c6b5e897d90e5 *R/safe.R 4b9d33407534c5d3d09eae3e63470800 *R/utils.R fb18454b7a5be36b6edf6c8701b29d9f *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 3de51f9eef2bceede82b2688ea26aac2 *src/dots.c bc81ff628a54a830af9295c7e3d56041 *src/init.c d03f7b327e2ac7a03a1a7b095a590e62 *tests/testthat.R 7ec2cf883faab777bdc554a024c8c44a *tests/testthat/test-check.R 9fb33f388a456f8b6fd96d0e34a4209d *tests/testthat/test-dots.R 01a0faa5ace36debf2203da07380e4ae *tests/testthat/test-safe.R