Rev 86016 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
# File src/library/utils/R/question.R# Part of the R package, https://www.R-project.org## Copyright (C) 1995-2024 The R Core Team## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## A copy of the GNU General Public License is available at# https://www.R-project.org/Licenses/`?` <-function(e1, e2){if (missing(e2)) {type <- NULLtopicExpr <- substitute(e1)} else {type <- substitute(e1)topicExpr <- substitute(e2)}search <- (is.call(topicExpr) && topicExpr[[1L]] == quote(`?`))if(search) { # ??foo is parsed as `?`(`?`(foo))topicExpr <- topicExpr[[2L]]if (is.call(te <- topicExpr ) && te[[1L]] == quote(`?`) &&is.call(te <- topicExpr[[2L]]) && te[[1L]] == quote(`?`)) {cat("Contacting Delphi...")flush.console()Sys.sleep(2 + stats::rpois(1,2))cat("the oracle is unavailable.\nWe apologize for any inconvenience.\n")return(invisible())}}if (is.call(topicExpr) && (topicExpr[[1L]] == quote(`::`) ||topicExpr[[1L]] == quote(`:::`))) {package <- as.character(topicExpr[[2L]])topicExpr <- topicExpr[[3L]]}elsepackage <- NULLif (search) {if(is.null(type))return(eval(substitute(help.search(TOPIC, package = PACKAGE),list(TOPIC = as.character(topicExpr),PACKAGE = package))))elsereturn(eval(substitute(help.search(TOPIC, fields = FIELD,package = PACKAGE),list(TOPIC = as.character(topicExpr),FIELD = as.character(type),PACKAGE = package))))} else {if (is.null(type)) {if (is.call(topicExpr))return(.helpForCall(topicExpr, parent.frame()))topic <-if(is.name(topicExpr)) as.character(topicExpr) else e1return(eval(substitute(help(TOPIC, package = PACKAGE),list(TOPIC = topic,PACKAGE = package))))} else {## interpret e1 as a type, but to allow customization, do NOT## force arbitrary expressions to be single character strings## (so that methods can be defined for topicName).type <-if(is.name(type)) as.character(type) else e1topic <-if(is.name(topicExpr)) as.character(topicExpr)else {if (is.call(topicExpr) && identical(type, "method"))return(.helpForCall(topicExpr, parent.frame(), FALSE))e2}if (type == "package")package <- topich <- .tryHelp(topicName(type, topic), package = package)if(is.null(h)) {if(is.language(topicExpr))topicExpr <- deparse(topicExpr)stop(gettextf("no documentation of type %s and topic %s (or error in processing help)",sQuote(type), sQuote(topicExpr)),domain = NA)}h}}}topicName <-function(type, topic){if((length(type) == 0L) || (length(topic) == 0L))character(0L)elsepaste(paste(topic, collapse = ","), type, sep = "-")}.helpForCall <-function(expr, envir, doEval = TRUE){## There should really be a common way of formatting signatures.sigFormat <- function(sigNames, sigClasses) {paste(sprintf("%s = \"%s\"", sigNames, sigClasses),collapse = ", ")}f <- expr[[1L]] # the function specifierif (is.call(f) && (f[[1L]] == quote(`::`) || f[[1L]] == quote(`:::`))) {package <- f[[2L]]where <- paste0("package:", package)if (!(where %in% search()))where <- NULLf <- f[[3L]]} else {package <- NULLwhere <- topenv(envir) # typically .GlobalEnv}if(is.name(f))f <- as.character(f)if(is.null(where) || !.isMethodsDispatchOn() || !methods::isGeneric(f, where = where)) {if(!is.character(f) || length(f) != 1L)stop(gettextf("the object of class %s in the function call %s could not be used as a documentation topic",dQuote(class(f)), sQuote(deparse(expr))),domain = NA)h <- .tryHelp(f, package = package)if(is.null(h))stop(gettextf("no methods for %s and no documentation for it as a function",sQuote(f)),domain = NA)}else {## allow generic function objects or namesif(methods::is(f, "genericFunction")) {fdef <- ff <- fdef@generic}elsefdef <- methods::getGeneric(f, where = where)sigClasses <- .signatureFromCall(fdef, expr, envir, doEval)sigNames <- names(sigClasses)method <- methods::selectMethod(f, sigClasses, optional=TRUE,fdef = fdef)if(methods::is(method, "MethodDefinition")) {sigClasses <- method@definedif(length(sigClasses) < length(sigNames))sigClasses <-c(sigClasses,rep.int("ANY", length(sigNames) - length(sigClasses)))}elsewarning(gettextf("no method defined for function %s and signature %s",sQuote(f),sQuote(sigFormat(sigNames, sigClasses))),domain = NA)topic <- topicName("method", c(f, sigClasses))h <- .tryHelp(topic, package = package)if(is.null(h))stop(gettextf("no documentation for function %s and signature %s",sQuote(f),sQuote(sigFormat(sigNames, sigClasses))),domain = NA)}h}.tryHelp <-function(topic, package = NULL){## Try finding help.## Return NULL (nothing) in case we found no help pages, or an## error.## (Earlier versions showed what they found via print(), or gave## an error.)h <- tryCatch(do.call(help, list(topic, package = package)),error = identity)if(inherits(h, "error") || !length(h)) NULL else h}