[Roxygen-commits] r92 - in pkg: . R sandbox tests/runit
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Sat Jul 26 05:19:39 CEST 2008
Author: pcd
Date: 2008-07-26 05:19:39 +0200 (Sat, 26 Jul 2008)
New Revision: 92
Modified:
pkg/DESCRIPTION
pkg/R/Rd.R
pkg/R/list.R
pkg/R/parse.R
pkg/R/roclet.R
pkg/R/roxygenize.R
pkg/R/string.R
pkg/README
pkg/sandbox/Rd.R
pkg/tests/runit/runit.Rd.R
Log:
add roxygenize to collation; fix infelicitous tags; de-TeXed, first-sentence titles; @method for S3; fix argument docs; BUGS
Modified: pkg/DESCRIPTION
===================================================================
--- pkg/DESCRIPTION 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/DESCRIPTION 2008-07-26 03:19:39 UTC (rev 92)
@@ -7,4 +7,5 @@
Manuel Eugster <Manuel.Eugster at stat.uni-muenchen.de>
Maintainer: Peter Danenberg <pcd at roxygen.org>
URL: http://roxygen.org
-Collate: 'functional.R' 'string.R' 'parse.R' 'collate.R' 'list.R' 'roclet.R' 'namespace.R' 'Rd.R'
+Collate: 'functional.R' 'string.R' 'parse.R' 'collate.R' 'list.R' 'roclet.R' 'namespace.R' 'Rd.R' 'roxygenize.R'
+Suggests: R.utils
Modified: pkg/R/Rd.R
===================================================================
--- pkg/R/Rd.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/Rd.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -6,12 +6,15 @@
#' Make an Rd roclet which parses the given files and writes the Rd
#' format to standard out (TODO: write to the file designated by
-#' \code{@@name}). Tries to guess \name and \usage unless explicitly
-#' given.
+#' \code{@@name}). Tries to guess \code{@@name} and \code{@@usage} unless
+#' explicitly given.
#'
#' Contains the member function \code{parse} which parses the result
#' of \code{parse.files}.
#'
+#' If \code{@@title} isn't present, substitutes \code{@@name} or
+#' equivalent.
+#'
#' @param subdir directory into which to place the Rd files; if
#' \code{NULL}, standard out.
#' @return Rd roclet
@@ -36,7 +39,7 @@
#' @param \dots the arguments
#' @return \code{NULL}
parse.expression <- function(key, ...)
- cat(Rd.expression(key, c(...)), file=filename, append=T)
+ cat(Rd.expression(key, c(...)), file=filename, append=TRUE)
filename <- ''
@@ -49,11 +52,58 @@
getSrcLines(srcfile, first.line, first.line)
}
- NULL.STATEMENT <- 'roxygen()'
+ #' What does the noop look like?
+ NULL.STATEMENT <- 'roxygen[[:space:]]*()'
+ #' Does the statement contain a noop-like?
+ #' @param source.line the line of source code
+ #' @return Whether the statement contains a noop
is.null.statement <- function(source.line)
length(grep(NULL.STATEMENT, source.line) > 0)
+ de.tex <- function(string)
+ gsub('\\\\[^{]*\\{([^}]*)(}|)',
+ '\\1',
+ string,
+ perl=T)
+
+ #' First sentence of a string, defined as first
+ #' period, question mark or newline.
+ #' @param description the string to be first-sentenced
+ #' @return The first sentence
+ first.sentence <- function(description) {
+ description <- de.tex(description)
+ r <- regexpr('[^.?\n]*(\\.(?!\\w)|\\?|\n|)',
+ description,
+ perl=T)
+ sentence <- substr(description, r, attr(r, 'match.length'))
+ if (is.null.string(sentence))
+ NULL
+ else {
+ chars <- nchar(sentence)
+ last.char <- substr(sentence, chars, chars)
+ if (last.char == '.' || last.char == '?')
+ sentence
+ else
+ paste(trim(sentence), '\\dots', sep='')
+ }
+ }
+
+ #' If \code{@@title} is specified, use it; or
+ #' take the first sentence of the description;
+ #' or, lastly, take the name.
+ #' @param partitum the parsed elements
+ #' @param name the calculated name-fallback
+ #' @return The parsed title
+ parse.title <- function(partitum, name) {
+ if (!is.null(partitum$title))
+ partitum$title
+ else if (!is.null(partitum$description))
+ first.sentence(partitum$description)
+ else
+ name
+ }
+
#' Reconstruct the \name directive from amongst
#' \code{@@name}, \code{@@setMethod}, \code{@@setClass},
#' \code{@@setGeneric}, \code{@@assignee}, etc.
@@ -77,7 +127,7 @@
filename,
first.line,
first.source.line),
- immediate.=T)
+ immediate.=TRUE)
} else if (!is.null(name)) {
name <- trim(name)
if (!is.null(subdir)) {
@@ -87,10 +137,22 @@
cat(sprintf('Writing %s to %s\n', name, filename))
unlink(filename)
}
+ parse.expression('title', parse.title(partitum, name))
parse.expression('name', name)
+ if (is.null(partitum$aliases))
+ parse.expression('alias', name)
}
}
+ parse.function.name <- function(partitum) {
+ if (!is.null(partitum$method))
+ Rd.expression('method',
+ car(partitum$method),
+ cadr(partitum$method))
+ else
+ partitum$assignee
+ }
+
#' Turn a list of formal arguments into a human-readable
#' function-like.
#' @param partitum the pre-parsed elements
@@ -112,10 +174,11 @@
sep=', '))
parse.expression('usage',
do.call(paste,
- c(as.list(strwrap(sprintf('%s(%s)',
- partitum$assignee,
- args),
- exdent=4)),
+ c(as.list(strwrap
+ (sprintf('%s(%s)',
+ parse.function.name(partitum),
+ args),
+ exdent=4)),
sep='\n')))
}
}
Modified: pkg/R/list.R
===================================================================
--- pkg/R/list.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/list.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -86,7 +86,7 @@
#' Zip \emph{n} lists together into tuplets of
#' length \emph{n}.
#' @param zipper the zipping function
-#' @param dots the lists to be zipped
+#' @param \dots the lists to be zipped
#' @return A list of tuplets
zip <- function(zipper, ...) {
m <- mapply(zipper, ...)
Modified: pkg/R/parse.R
===================================================================
--- pkg/R/parse.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/parse.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -1,7 +1,12 @@
#' @include string.R
#' @include list.R
#' @include functional.R
+NULL
+
+#' Sequence that distinguishes roxygen comment from normal comment.
LINE.DELIMITER <- '#\''
+
+#' Symbol that delimits tags.
TAG.DELIMITER <- '@'
#' No-op for sourceless files
@@ -218,7 +223,8 @@
#' @aliases slot param
register.preref.parsers(parse.name.description,
'slot',
- 'param')
+ 'param',
+ 'method')
#' Parse an element containing a single name and only a name;
#' extra material will be ignored and a warning issued.
@@ -315,12 +321,15 @@
#' Parse either srcrefs, prerefs or pairs of the same.
#' @param ref the srcref, preref or pair of the same
+#' @param \dots ignored
#' @return List containing the parsed srcref/preref
parse.ref <- function(ref, ...)
UseMethod('parse.ref')
#' Parse a preref/srcrefs pair
+#' @method parse.ref list
#' @param ref the preref/srcref pair
+#' @param \dots ignored
#' @return List combining the parsed preref/srcref
parse.ref.list <- function(ref, ...)
append(parse.ref(car(ref)),
@@ -328,7 +337,9 @@
#' Parse a preref
+#' @method parse.ref preref
#' @param ref the preref to be parsed
+#' @param \dots ignored
#' @return List containing the parsed preref
parse.ref.preref <- function(ref, ...) {
lines <- Map(trim.left, getSrcLines(attributes(ref)$srcfile,
@@ -461,7 +472,9 @@
}
#' Parse a srcref
+#' @method parse.ref srcref
#' @param ref the srcref to be parsed
+#' @param \dots ignored
#' @return List containing the parsed srcref
parse.ref.srcref <- function(ref, ...) {
srcfile <- attributes(ref)$srcfile
Modified: pkg/R/roclet.R
===================================================================
--- pkg/R/roclet.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/roclet.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -5,11 +5,11 @@
#' Abstract roclet that serves as a rudimentary API.
#'
#' Contains the following member functions:
-#' \item{register.parser}{takes \code{key} and \code{parser}}
+#' \itemize{\item{register.parser}{takes \code{key} and \code{parser}}
#' \item{register.parsers}{takes \code{parser} and \code{keys}}
#' \item{register.default.parser}{takes a \code{key}}
#' \item{register.default.parsers}{take \code{parsers}}
-#' \item{parse}{parses material contained in files}
+#' \item{parse}{parses material contained in files}}
#'
#' @param parse.default the default parser taking \code{key}
#' and \code{value}
@@ -107,4 +107,3 @@
#' @return The first non-null argument
first.non.null <- function(...)
append(NULL, c(...))[[1]]
-
Modified: pkg/R/roxygenize.R
===================================================================
--- pkg/R/roxygenize.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/roxygenize.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -1,17 +1,38 @@
#' @include Rd.R
#' @include namespace.R
#' @include collate.R
+roxygen()
+
+#' Whither to copy package
ROXYGEN.DIR <- '%s.roxygen'
+
+#' Whither to copy Rds
MAN.DIR <- 'man'
+
+#' Whence to copy source code
R.DIR <- 'R'
-roxygenize <- function(package.dir) {
+#' Process a package with the Rd, namespace and collate roclets.
+#' @param package.dir the package's top directory
+#' @param copy.package if R.utils is present, copies the package
+#' over before adding/manipulating files.
+#' @return \code{NULL}
+roxygenize <- function(package.dir,
+ copy.package=TRUE) {
roxygen.dir <- sprintf(ROXYGEN.DIR, package.dir)
man.dir <- file.path(roxygen.dir, MAN.DIR)
skeleton <- c(roxygen.dir, man.dir)
- for (dir in skeleton) dir.create(dir, showWarnings=F)
+
+### if (copy.package) {
+### if (require('R.utils', quietly=T))
+### copyDirectory(package.dir, roxygen.dir, overwrite=TRUE)
+### else
+### warning('`R.utils\' package not present; not copying package.')
+### }
+
+ for (dir in skeleton) dir.create(dir, showWarnings=FALSE)
r.dir <- file.path(package.dir, R.DIR)
- source.files <- list.files(r.dir, recursive=T, full.names=T)
+ source.files <- list.files(r.dir, recursive=TRUE, full.names=TRUE)
Rd <- make.Rd.roclet(man.dir)
do.call(Rd$parse, as.list(source.files))
}
Modified: pkg/R/string.R
===================================================================
--- pkg/R/string.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/R/string.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -1,7 +1,14 @@
#' @include functional.R
#' @include list.R
+NULL
+
+#' Absense of words
SPACE <- '[[:space:]]+'
+
+#' Anti-anti-words
MATTER <- '[^[:space:]]+'
+
+#' Analogue to the empty list
NIL.STRING <- ''
#' Trim [:space:] to the left of a string.
Modified: pkg/README
===================================================================
--- pkg/README 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/README 2008-07-26 03:19:39 UTC (rev 92)
@@ -31,8 +31,20 @@
1.2. TODO
-Create a driver (possibly used by `R CMD roxygen') which farms out the
-results of each roclet to appropriate files in a package skeleton.
+* Create a driver (possibly used by `R CMD roxygen') which farms out
+ the results of each roclet to appropriate files in a package
+ skeleton.
+1.3. BUGS
+
+* parse.formals doesn't distinguish between no default argument and
+ NULL; need a special value?
+
+* Skeletal Rds are created for assignments without Roxygen-blocks;
+ desirable?
+
+* first.sentence is fooled by infix periods, whereupon it resorts to
+ \dots.
+
-----------
* Hail, Hephaistos! Grant skill and weal.
Modified: pkg/sandbox/Rd.R
===================================================================
--- pkg/sandbox/Rd.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/sandbox/Rd.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -13,4 +13,6 @@
files <- if (argc > 0) as.list(argv) else FILES
roclet <- make.Rd.roclet()
-do.call(roclet$parse, files)
+## do.call(roclet$parse, files)
+roclet$parse.parsed(parse.text("#' Is a number odd?
+ a <- 2"))
Modified: pkg/tests/runit/runit.Rd.R
===================================================================
--- pkg/tests/runit/runit.Rd.R 2008-07-25 18:40:08 UTC (rev 91)
+++ pkg/tests/runit/runit.Rd.R 2008-07-26 03:19:39 UTC (rev 92)
@@ -33,29 +33,39 @@
test.name.from.assignment <- function()
check.Rd.output('a <- 2',
- output='\\name{a}')
+ output=c('\\title{a}',
+ '\\name{a}',
+ '\\alias{a}'))
test.name.overriding.assignment <- function()
check.Rd.output("#' @name b
a <- 2",
- output='\\name{b}')
+ output=c('\\title{b}',
+ '\\name{b}',
+ '\\alias{b}'))
test.implicit.usage.from.formals <- function()
check.Rd.output("a <- function(a=1) {}",
- output=c("\\name{a}",
+ output=c("\\title{a}",
+ "\\name{a}",
+ "\\alias{a}",
"\\usage{a(a=1)}"))
test.explicit.usage <- function()
check.Rd.output("#' @usage a(a=2)
a <- function(a=1) {}",
- output=c("\\name{a}",
+ output=c("\\title{a}",
+ "\\name{a}",
+ "\\alias{a}",
"\\usage{a(a=2)}"))
test.params <- function()
check.Rd.output("#' @param a an incipit letter
#' @param z a terminal letter
a <- function(a=1, z=2) {}",
- output=c("\\name{a}",
+ output=c("\\title{a}",
+ "\\name{a}",
+ "\\alias{a}",
"\\usage{a(a=1, z=2)}",
"\\arguments{\\item{a}{an incipit letter}",
"\\item{z}{a terminal letter}}"))
@@ -96,3 +106,30 @@
"\\author{test}",
"\\seealso{test}",
"\\concept{test}"))
+
+test.title.from.description <- function()
+ check.Rd.output("#' Description with sentence. That continueth.
+ a <- 2",
+ output=c("\\title{Description with sentence}",
+ "\\name{a}",
+ "\\alias{a}",
+ paste("\\description{Description with sentence.",
+ "That continueth.}")))
+
+test.question.mark.end.of.sentence <- function()
+ check.Rd.output("#' Is a number odd?
+ is.odd <- function(a) {}",
+ output=c('\\title{Is a number odd?}',
+ '\\name{is.odd}',
+ '\\alias{is.odd}',
+ '\\usage{is.odd(a)}',
+ '\\description{Is a number odd?}'))
+
+test.ellipsis.on.no.period <- function()
+ check.Rd.output("#' Whether a number is odd
+ is.odd <- function(a) {}",
+ output=c('\\title{Whether a number is odd\dots}',
+ '\\name{is.odd}',
+ '\\alias{is.odd}',
+ '\\usage{is.odd(a)}',
+ '\\description{Whether a number is odd}'))
More information about the Roxygen-commits
mailing list