blob: a258b23a609fc0330dda5957d71e794208e58bbc [file] [log] [blame]
# File src/library/utils/R/prompt.R
# Part of the R package, https://www.R-project.org
#
# Copyright (C) 1995-2015 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/
prompt <-
function(object, filename = NULL, name = NULL, ...)
UseMethod("prompt")
prompt.default <-
function(object, filename = NULL, name = NULL,
force.function = FALSE, ...)
{
is.missing.arg <- function(arg)
typeof(arg) == "symbol" && deparse(arg) == ""
if(missing(name))
name <- if(is.character(object))
object
else {
name <- substitute(object)
## <FIXME>
## This used to be:
## if(is.language(name) && !is.name(name))
## name <- eval(name)
## as.character(name)
## but what is this trying to do?
## It seems that the eval() will typically give the given
## object, and surely we cannot use that as the name (even
## if the subsequent as.character() does not fail ...)
## Better to be defensive about this, and handle only cases
## we know will make sense ...
if(is.name(name))
as.character(name)
else if(is.call(name)
&& (as.character(name[[1L]]) %in%
c("::", ":::", "getAnywhere"))) {
name <- as.character(name)
name[length(name)]
}
else
stop("cannot determine a usable name")
## </FIXME>
}
if(is.null(filename))
filename <- paste0(name, ".Rd")
x <- if(!missing(object))
object
else {
## Better than get(); works when called in fun :
x <- get(name, envir = parent.frame())
}
## <FIXME>
## If not a function or forced to document a function (?), always
## assume data set.
if(!(is.function(x) || force.function))
return(promptData(x, filename = filename, name = name))
## </FIXME>
n <- length(argls <- formals(x))
if(n) {
arg.names <- arg.n <- names(argls)
arg.n[arg.n == "..."] <- "\\dots"
}
## Construct the 'call' for \usage.
Call <- paste0(name, "(")
for(i in seq_len(n)) { # i-th argument
Call <- paste0(Call, arg.names[i],
if(!is.missing.arg(argls[[i]]))
paste0(" = ",
## need to backtick symbols
paste(deparse(argls[[i]],
backtick = TRUE,
width.cutoff = 500L),
collapse="\n")))
if(i != n) Call <- paste0(Call, ", ")
}
## Construct the definition for \examples.
x.def <- deparse(x)
if(any(br <- substr(x.def, 1L, 1L) == "}"))
x.def[br] <- paste0(" ", x.def[br])
## escape "%" :
x.def <- gsub("%", "\\\\%", x.def)
Call <- gsub("%", "\\\\%", Call)
Rdtxt <-
list(name = paste0("\\name{", name, "}"),
# version = "\\Rdversion{1.1}",
aliases = c(paste0("\\alias{", name, "}"),
paste("%- Also NEED an '\\alias' for EACH other topic",
"documented here.")),
title = "\\title{\n%% ~~function to do ... ~~\n}",
description = c("\\description{",
paste("%% ~~ A concise (1-5 lines) description of what",
"the function does. ~~"),
"}"),
usage = c("\\usage{", paste0(Call, ")"), "}",
paste("%- maybe also 'usage' for other objects",
"documented here.")),
arguments = NULL,
details = c("\\details{",
paste("%% ~~ If necessary, more details than the",
"description above ~~"),
"}"),
value = c("\\value{",
"%% ~Describe the value returned",
"%% If it is a LIST, use",
"%% \\item{comp1 }{Description of 'comp1'}",
"%% \\item{comp2 }{Description of 'comp2'}",
"%% ...",
"}"),
references = paste("\\references{\n%% ~put references to the",
"literature/web site here ~\n}"),
author = "\\author{\n%% ~~who you are~~\n}",
note = c("\\note{\n%% ~~further notes~~\n}",
"",
paste("%% ~Make other sections like Warning with",
"\\section{Warning }{....} ~"),
""),
seealso = paste("\\seealso{\n%% ~~objects to See Also as",
"\\code{\\link{help}}, ~~~\n}"),
examples = c("\\examples{",
"##---- Should be DIRECTLY executable !! ----",
"##-- ==> Define data, use random,",
"##-- or do help(data=index) for the standard data sets.",
"",
"## The function is currently defined as",
x.def,
"}"),
keywords = c(paste("% Add one or more standard keywords,",
"see file 'KEYWORDS' in the"),
"% R documentation directory.",
"\\keyword{ ~kwd1 }% use one of RShowDoc(\"KEYWORDS\")",
"\\keyword{ ~kwd2 }% __ONLY ONE__ keyword per line"))
Rdtxt$arguments <- if(n)
c("\\arguments{",
paste0(" \\item{", arg.n, "}{",
"\n%% ~~Describe \\code{", arg.n, "} here~~\n}"),
"}") ## else NULL
if(is.na(filename)) return(Rdtxt)
cat(unlist(Rdtxt), file = filename, sep = "\n")
message(gettextf("Created file named %s.", sQuote(filename)),
"\n",
gettext("Edit the file and move it to the appropriate directory."),
domain = NA)
invisible(filename)
}
prompt.data.frame <-
function(object, filename = NULL, name = NULL, ...)
{
if(missing(name))
name <-
if(is.character(object))
object
else {
name <- substitute(object)
if(is.name(name))
as.character(name)
else
stop("cannot determine a usable name")
}
if(is.null(filename))
filename <- paste0(name, ".Rd")
x <- if(!missing(object))
object
else {
## Better than get(); works when called in fun :
x <- get(name, envir = parent.frame())
}
## <FIXME>
## Always assume data set ???
promptData(x, filename = filename, name = name)
## </FIXME>
}
promptData <-
function(object, filename = NULL, name = NULL)
{
if(missing(name))
name <-
if(is.character(object))
object
else {
name <- substitute(object)
if(is.name(name))
as.character(name)
else
stop("cannot determine a usable name")
}
if(is.null(filename))
filename <- paste0(name, ".Rd")
x <- if(!missing(object))
object
else {
## Better than get(); works when called in fun :
x <- get(name, envir = parent.frame())
}
## Construct the format.
if(is.data.frame(x)) {
make_item_tag <- function(s) {
## For syntactic names, use \code; otherwise, use \samp.
if(grepl("^([[:alpha:]]|[.][[:alpha:]._])[[:alnum:]._]*$", s)) {
paste0("\\code{", s, "}")
} else {
paste0("\\samp{", gsub("([%{}])", "\\\\\\1", s), "}")
}
}
fmt <- c("\\format{",
paste(" A data frame with",
nrow(x),
"observations on the following",
ifelse(ncol(x) == 1,
"variable.",
paste(ncol(x), "variables."))),
" \\describe{")
for(i in names(x)) {
xi <- x[[i]]
fmt <-
c(fmt,
paste0(" \\item{", make_item_tag(i), "}{",
if(inherits(xi, "ordered")) {
paste("an", data.class(xi),
"factor with levels",
paste0("\\code{", levels(xi), "}",
collapse = " < "),
collapse = " ")
} else if(inherits(xi, "factor")) {
paste("a factor with levels",
paste0("\\code{", levels(xi), "}",
collapse = " "),
collapse = " ")
} else if(is.vector(xi)) {
paste("a", data.class(xi), "vector")
} else if(is.matrix(xi)) {
paste("a matrix with", ncol(xi), "columns")
} else {
paste("a", data.class(xi))
},
"}"))
}
fmt <- c(fmt, " }", "}")
}
else {
tf <- tempfile(); on.exit(unlink(tf))
sink(tf) ; str(object) ; sink()
fmt <- c("\\format{",
" The format is:",
scan(tf, "", quiet = !getOption("verbose"), sep = "\n"),
"}")
}
Rdtxt <-
list(name = paste0("\\name{", name, "}"),
# version = "\\Rdversion{1.1}",
aliases = paste0("\\alias{", name, "}"),
docType = "\\docType{data}",
title = "\\title{\n%% ~~ data name/kind ... ~~\n}",
description = c("\\description{",
"%% ~~ A concise (1-5 lines) description of the dataset. ~~",
"}"),
usage = paste0("\\usage{data(\"", name, "\")}"),
format = fmt,
details = c("\\details{",
paste("%% ~~ If necessary, more details than the",
"__description__ above ~~"),
"}"),
source = c("\\source{",
paste("%% ~~ reference to a publication or URL",
"from which the data were obtained ~~"),
"}"),
references = c("\\references{",
"%% ~~ possibly secondary sources and usages ~~",
"}"),
examples = c("\\examples{",
paste0("data(", name, ")"),
paste0("## maybe str(", name, ") ; plot(", name, ") ..."),
"}"),
keywords = "\\keyword{datasets}")
if(is.na(filename)) return(Rdtxt)
cat(unlist(Rdtxt), file = filename, sep = "\n")
message(gettextf("Created file named %s.", sQuote(filename)),
"\n",
gettext("Edit the file and move it to the appropriate directory."),
domain = NA)
invisible(filename)
}
promptPackage <-
function(package, lib.loc = NULL, filename = NULL, name = NULL, final = FALSE)
{
## Most of this should not be translated -- PR#11191
## lib.loc is not used any more
## if (is.null(lib.loc)) lib.loc <- .libPaths()
insert1 <- function(field, new) {
prev <- Rdtxt[[field]]
Rdtxt[[field]] <<- c(prev[-length(prev)], new, prev[length(prev)])
}
insert2 <- function(field, new) insert1(field, paste("~~", new, "~~"))
if(missing(name))
name <- paste0(package, "-package")
if(is.null(filename))
filename <- paste0(name, ".Rd")
Rdtxt <-
list(name = paste0("\\name{", name, "}"),
# version = "\\Rdversion{1.1}",
aliases = c(paste0("\\alias{", name, "}"),
c(paste0("\\alias{", package, "}"))),
docType = "\\docType{package}",
title = c("\\title{", "}"),
description = c("\\description{","}"),
details = c("\\details{","}"),
author = c("\\author{","}"),
references = character(0L),
keywords = c("\\keyword{ package }")
)
insert1("title", paste0("\\packageTitle{", package,"}"))
insert1("description", paste0("\\packageDescription{", package,"}"))
insert1("author", c(paste0("\\packageAuthor{", package,"}"), "",
paste("Maintainer:",paste0("\\packageMaintainer{", package,"}"))))
insert1("details", c("", "The DESCRIPTION file:"))
insert1("details", paste0("\\packageDESCRIPTION{", package, "}"))
insert1("details", paste0("\\packageIndices{", package, "}"))
if (!final) {
insert2("details", strwrap(
"An overview of how to use the package, including the most important functions"))
Rdtxt$references <-
c("\\references{",
paste("~~",
"Literature or other references for background information",
"~~"),
"}")
Rdtxt$seealso <- c("\\seealso{", "}")
insert2("seealso",
c("Optional links to other man pages, e.g.",
"\\code{\\link[<pkg>:<pkg>-package]{<pkg>}}"))
Rdtxt$examples <- c("\\examples{","}")
insert2("examples",
"simple examples of the most important functions")
insert2("keywords",
strwrap("Optionally other standard keywords, one per line, from file KEYWORDS in the R documentation directory"))
}
if(is.na(filename)) return(Rdtxt)
cat(unlist(Rdtxt), file = filename, sep = "\n")
message(gettextf("Created file named %s.", sQuote(filename)),
"\n",
gettext("Edit the file and move it to the appropriate directory."),
domain = NA)
invisible(filename)
}
promptImport <- function(object, filename = NULL, name = NULL, importedFrom = NULL,
importPage = name, ...)
{
if(missing(name))
name <-
if(is.character(object))
object
else {
name <- substitute(object)
if(is.name(name))
as.character(name)
else if (is.language(name) && length(name) == 3 &&
identical(name[[1]], as.name("::")))
as.character(name[[3]])
else
stop("cannot determine a usable name")
}
if(is.null(filename))
filename <- paste0(name, ".Rd")
x <- if(!missing(object))
object
else {
## Better than get(); works when called in fun :
x <- get(name, envir = parent.frame())
}
if(is.null(importedFrom)) {
if (is.function(x))
importedFrom <- getNamespaceName(environment(x))
else
stop("cannot determine import name")
}
Rdtxt <-
list(name = paste0("\\name{", name, "}"),
aliases = paste0("\\alias{", name, "}"),
docType = "\\docType{import}",
title = paste0("\\title{Import from package \\pkg{", importedFrom, "}}"),
description =
c("\\description{",
paste0("The \\code{", name, "} object is imported from package \\pkg{",
importedFrom, "}."),
paste0("Help is available here: \\code{\\link[", importedFrom, ":",
importPage, "]{", importedFrom, "::", importPage, "}}."),
"}"))
if(is.na(filename)) return(Rdtxt)
cat(unlist(Rdtxt), file = filename, sep = "\n")
message(gettextf("Created file named %s.", sQuote(filename)),
"\n",
gettext("Edit the file and move it to the appropriate directory."),
domain = NA)
}