[Rd] package.skeleton.S4
Christophe Genolini
cgenolin at u-paris10.fr
Sun Mar 30 15:49:23 CEST 2008
Hi the devel list.
I am adapting the package.skeleton to S4 classes and methods
I would have been very proud to post a new working function on this list.
Unfortunately, I do not manage to solve all the problems. Mainly
- sys.source does not compile a file with setClass
- dumpMethod does not exists yet
In the following code, thise two problems are notified by a line
#################
Still with this two issues, it is possible to use package.skeleton.S4 in
the following way:
- first run package.skeleton (in the classical way, on a file or in the
console).
This creates the directories and the files
- then run package.skeleton.S4.
It has to be done
* using the code_files option (since dumpMethod does not exists)
* providing the list of the class (since sys.source does not
compile setClass)
* using the same path than package.skeleton
At this three conditions, package.skeleton.S4 will :
- modify the DESCRIPTION package,
- run promptClass on the classes gived in the list,
- run promptMethod on all the methods related to the classes gives in
the list.
I tryed to solve the sys.source problem, but I am not good enough in R
to do it myself.
I do not even know if it is something hard to do or very easy. So I post
this uncompleted function...
If someone is interested in fixing it and then adding it somewhere,
I then will write the package.skeleton.S4.Rd
sincerly
Christophe
--- 8< ----------------- package.skeleton.S4 ---------------------------
package.skeleton.S4 <- function(name = "anRpackage", list, environment =
.GlobalEnv,
path = ".", force = FALSE, namespace = FALSE, code_files =
character(),S4=FALSE)
{
cat(missing(list)," EEE\n")
### If pakage.skeleton has not been run, run it on false data
dir <- file.path(path, name)
code_dir <- file.path(dir, "R")
docs_dir <- file.path(dir, "man")
data_dir <- file.path(dir, "data")
if (!file.exists(dir)){
environment <- new.env()
assign("falseData-ToErase",NULL,environment)
package.skeleton(name=name,environment=environment,path=path,namespace=namespace)
}else{}
### Build up the list_S4
### If list_S4 is empty :
### If code_files_S4 is not empty, the file in code_file_S4 are
source.
### then list receive ls() after removing ".__C__" (either if
code_files is empty or not)
if (!is.character(code_files)){stop("'code_files S4' should be a
character vector")}else{}
use_code_files <- length(code_files) > 0
if (missing(list)){
################################################################################
# Has to be false
# since sys.source does not work :-(
if (use_code_files){
environment <- new.env()
for (cf in code_files){sys.source(cf, envir = environment)}
}else{}
list <- ls(pattern=".__C__",all.names=TRUE)
list <- substr(list,7,nchar(list))
}else{}
### Check that the parameters are of correct type
if (!is.character(list)){stop("'list' should be a character vector
naming R objects")}else{}
if (!is.logical(namespace) || (length(namespace) !=
1)){stop("'namespace' should be a single logical")}else{}
curLocale <- Sys.getlocale("LC_CTYPE")
on.exit(Sys.setlocale("LC_CTYPE", curLocale), add = TRUE)
if (Sys.setlocale("LC_CTYPE", "C") != "C"){warning("cannot turn off
locale-specific chars via LC_CTYPE")}else{}
### Remove non existing object from the list
have <- sapply(list, isClass, where = environment)
if (any(!have))
warning(sprintf(ngettext(sum(!have), "class '%s' not found",
"class '%s' not found"), paste(sQuote(list[!have]),
collapse = ", ")), domain = NA)
list <- list[have]
if (!length(list))
stop("no R classes specified or available")
### Addition to DESCRIPTION
message("Adding to DESCRIPTION ...")
description <- file(file.path(dir, "DESCRIPTION"), "a+b")
cat("\nDepends: methods\nLazyLoad: yes\nCollate: gives the order in
which file shall be sourced\n",append=TRUE,file = description,sep = "")
close(description)
### Remove elements starting with "." from the list
internalObjInds <- grep("^\\.", list)
internalObjs <- list[internalObjInds]
if (any(internalObjInds)){list <- list[-internalObjInds]}else{}
### Remplace strange char by "_" and check the name validity (but
only if code_file is user define)
if (!use_code_files){
list0 <- gsub("[[:cntrl:]\"*/:<>?\\|]", "_", list)
wrong <-
grep("^(con|prn|aux|clock\\$|nul|lpt[1-3]|com[1-4])(\\..*|)$",list0)
if (length(wrong)){list0[wrong] <- paste("zz", list0[wrong], sep
= "")}else{}
ok <- grep("^[[:alnum:]]", list0)
if (length(ok) < length(list0)){list0[-ok] <- paste("z",
list0[-ok], sep = "")}else{}
list1 <- tolower(list0)
list2 <- make.unique(list1, sep = "_")
changed <- (list2 != list1)
list0[changed] <- list2[changed]
}else{
list0 <- list
}
names(list0) <- list
### If code_file is empty, it save all invisible in pack-internal.R
and all the function one by one in its file
### If code_file is not empty, is save the code_file
if (!use_code_files){
message("Saving functions and data ...")
warning("*** Does not work: dumpClass and dumpMethod are not
implemented yet ***")
warning("*** Use code_file instead ***")
###########################################################################
# if (any(internalObjInds)){dump(internalObjs, file =
file.path(code_dir, sprintf("%s-internal.R",name)))}else{}
# for (item in list) {
# if (is.function(get(item, envir = environment))){
# dump(item, file = file.path(code_dir,
sprintf("%s.R",list0[item])))
# }else{
# try(save(list = item, file =
file.path(data_dir,sprintf("%s.rda", item))))
# }
}else{
message("Copying code files ...")
file.copy(code_files, code_dir)
}
### Help file
### For all the internal, a single help file saying "not for user"
message("Making help files ...")
if (any(internalObjInds)) {
Rdfile <- file(file.path(docs_dir,
sprintf("%s-internal-S4.Rd",name)), "wt")
cat("\\name{", name, "-internal}\n", "\\title{Internal ",name, "
objects}\n", file = Rdfile, sep = "")
for (item in internalObjs) {cat("\\alias{", item, "}\n", file =
Rdfile, sep = "")}
cat("\\description{Internal ", name, " classes.}\n",
"\\details{These are not to be called by the user.}\n",
"\\keyword{internal}", file = Rdfile, sep = "")
close(Rdfile)
}
yy <- try(suppressMessages({
sapply(list,function(item){
promptClass(item,filename = file.path(docs_dir,
sprintf("%s.Rd",list0[item])))
})
listMethod <- unclass(getGenerics())
sapply(listMethod,function(metho){
if(any(sapply(list,function(lis){existsMethod(metho,lis)}))){
promptMethods(metho,filename = file.path(docs_dir,
sprintf("%s.Rd",metho)))
}else{}
return(invisible())
})
}))
if (inherits(yy, "try-error")){stop(yy)}else{}
if (length(list.files(code_dir)) == 0){unlink(code_dir, recursive =
TRUE)}else{}
if (length(list.files(data_dir)) == 0){unlink(data_dir, recursive =
TRUE)}else{}
message("Done.")
message(gettextf("Further steps are described in
'%s'.",file.path(dir, "Read-and-delete-me")), domain = NA)
}
# Example
# Save in myPack.r
---- 8< ---------------File myPack.r -----------------
`f1` <- function(x){cat("\nXXX F1 = ",x,"XXX\n")}
`.f2` <- function(x){cat("\nXXX F2 = ",f1(x^2),"XXX\n")}
# Save in myPackS4.r
---- 8< ---------------File myPackS4.r ---------------
setClass("AA",representation(a="numeric"))
setGeneric("aze",function(z){standardGeneric("aze")})
setMethod("print","AA",function(x){cat("C'est cool")})
setMethod("aze","AA",function(z){cat("C'est hyper cool")})
setClass("BB",representation(b="numeric"),validity=function(object){object at b>0})
setMethod("plot","BB",function(x,y){cat("CCC'est cool")})
setMethod("aze","BB",function(z){cat("CCC'est hyper cool")})
---- 8< -----------------------------------------------
# Example of use :
package.skeleton("pack",code_files="pack.r")
package.skeleton.S4("pack",list=c("AA","BB"),code_files="packS4.r")
More information about the R-devel
mailing list