Nothing
# This is package mvbutils
"%!in%" <-
function (a, b)
!(a %in% b)
"%&%" <-
function (a, b)
paste(a, b, sep = "")
"%**%" <-
function (x, y)
{
dimnames(x) <- NULL
dimnames(y) <- NULL
if (length(dim(x)) == 2 && length(dim(y)) == 2 && dim(x)[2] ==
1 && dim(y)[1] == 1)
return(c(x) %o% c(y))
if ((!is.null(dim(x)) && any(dim(x) == 1)))
dim(x) <- NULL
if ((!is.null(dim(y)) && any(dim(y) == 1)))
dim(y) <- NULL
if (is.null(dim(x)) && is.null(dim(y))) {
if (length(x) == length(y))
x <- x %*% y
else {
if ((length(x) != 1) && (length(y) != 1))
stop("lengths of x (" %&% length(x) %&% ") and y (" %&%
length(y) %&% ") are incompatible")
else x <- x * y
}
}
else x <- x %*% y
if ((!is.null(dim(x)) && any(dim(x) == 1)))
dim(x) <- NULL
x
}
"%<-%" <-
function( a, value){
# a must be of the form '{thing1;thing2;...}'
a <- as.list( substitute( a))[-1]
e <- parent.frame()
stopifnot( length( value) == length( a))
stopifnot( all( sapply( a, is.name)))
for( i in seq_along( a))
assign( as.character( a[[i]]), value[[i]], envir=e)
# eval( call( '<-', a[[ i]], value[[i]]), envir=e)
NULL
}
"%downto%" <-
function( from, to) if( from >= to) from:to else numeric( 0)
"%except%" <-
function (vector, condition)
vector[match(vector, condition, 0) == 0]
"%grepling%" <-
function( x, patt) grepl( patt, x)
"%in.range%" <-
function (a, b)
(a >= min(b)) & (a <= max(b))
"%is.a%" <-
function (x, what)
inherits(x, what, FALSE)
"%is.an%" <-
function (x, what)
inherits(x, what, FALSE)
"%is.not.a%" <-
function (x, what)
!inherits(x, what, FALSE)
"%is.not.an%" <-
function (x, what)
!inherits(x, what, FALSE)
"%matching%" <-
function( x, patt)
unique( unlist( lapply( patt, grep, x=as.character( x), value=TRUE)))
"%not.in%" <-
function (a, b)
!(a %in% b)
"%not.in.range%" <-
function( a, b) {
(a < min( b)) | (a > max( b))
}
"%perling%" <-
function( x, patt) grepl( patt, x, perl=TRUE)
"%such.that%" <-
function( a, b)
a[ eval( do.call( 'substitute', list( substitute( b), list( '.'=quote( a)))), list( a=a), enclos=sys.frame( mvb.sys.parent()) )]
"%SUCH.THAT%" <-
function( a, b) {
if( !length( a))
return( a)
fun <- function( .) .
body( fun) <- substitute( b)
environment( fun) <- sys.frame( sys.parent())
ind <- logical( length( a))
for( i in seq( along=a))
ind[ i] <- fun( a[[ i]])
a[ ind]
}
"%that.are.in%" <-
function( a, b)
a[ a %in% b]
"%that.dont.match%" <-
function( x, patt) {
if( !length( patt))
stop( "invalid pattern argument")
x[ seq_along( x) %except% unlist( lapply( patt, grep, x=as.character( x)))]
}
"%that.match%" <-
function( x, patt) {
if( !length( patt))
stop( "invalid pattern argument")
unique( unlist( lapply( patt, grep, x=as.character( x), value=TRUE)))
}
"%upto%" <-
function (from, to)
if (from <= to) from:to else numeric(0)
"%where%" <-
function( x, cond) {
# x is coerced to data.frame; cond is expression to evaluate, subbing first in x then in caller
# Example: if x has a column 'stuff'
# x %where% (stuff < 3)
# is the same as x[ x$stuff<3,]
# Note the brackets, required by operator precedence rules
mum <- mvb.sys.parent()
if( mum==0)
mum <- .GlobalEnv
else
mum <- sys.frames()[[ mum]]
cond <- eval( substitute( cond), as.data.frame( x), enclos=mum)
cond[ is.na( cond)] <- FALSE
x[ cond,]
}
"%where.warn%" <-
function( x, cond) {
# x is data.frame; cond is expression to evaluate, subbing first in x then in caller
# Example: if x has a column 'stuff'
# x %where.warn% (stuff < 3)
# is the same as x[ x$stuff<3,]
# but if any of the conditions is NA or FALSE, a warning is given for those rows
# Note the brackets, required by operator precedence rules
sub.cond <- deparse( substitute( cond), nlines=1, width.cutoff=50)
sub.x <- deparse( substitute( x), nlines=1, width.cutoff=20)
rx <- row.names( x)
mum <- mvb.sys.parent()
if( mum==0)
mum <- .GlobalEnv
else
mum <- sys.frames()[[ mum]]
cond <- eval( substitute( cond), x, enclos=mum)
cond[ is.na( cond)] <- FALSE
if( !all( cond))
warning( sprintf( 'Check of %s fails on row(s) [%s] of %s', sub.cond,
paste( rx[ !cond], collapse=','), sub.x))
x[ cond,]
}
"%without.name%" <-
function( x, what) {
new.names <- names( x) %except% what
x[ new.names]
}
".onLoad" <-
function( libname, pkgname) {
if( 'mvb.session.info' %in% search())
return() # create only once per session
wd <- getwd()
# Attach "mvb.session.info". Bloody CRAN pedantry gets worse and bloody worse
# Not sure if I need to do this before defining ATTACH, but whatever...
a.bloody.ttach <- get( 'at' %&% 'tach', baseenv())
a.bloody.ttach( pos = 2, name = "mvb.session.info", list( .First.top.search = wd,
.Path = c( ROOT=wd), session.start.time = Sys.time(), partial.namespaces=character(0)))
rm( a.bloody.ttach)
nsenv <- environment( sys.function())
evalq( {
mvboptions <- new.env( parent=emptyenv()) # internal option-holder
# Anti CRANkiness
tools <- asNamespace( 'tools')
utils <- asNamespace( 'utils')
# To override rbind.data.frame()
body.rbind <- body( baseenv()$rbind) # for re-exporting generic rbind()
body.print.function <- body( baseenv()$print.function)
# plus, hack to allow matrices of POSIXct to rbind nicely...
# ... extends to other classes if 'length<-' provided
brdf <- local({ # to avoid temp var clutter
brdf <- base::rbind.data.frame
e <- new.env( parent=environment( brdf))
newarray <- array
body( newarray) <- substitute( {
atts <- attributes( data)
atts$dim <- atts$dimnames <- atts$names <- NULL
data <- BODY # assignment needed in "newer" R (certainly >=3.3, perhaps younger); used to be OK just with BODY
attributes( data) <- c( attributes( data), atts)
data
}, list( BODY=body( array)))
e$array <- newarray
environment( brdf) <- e
brdf
})
# Idiotic subterfuges imposed by CRANally-retentive checks
ATTACH <- CRANky( 'hcatta')
untetherBalloon <- CRANky( 'gnidniBkcolnu')
tetherBalloon <- CRANky( 'gnidniBkcol')
balloonIsTethered <- CRANky( 'dekcoLsIgnidnib')
LLDBflush <- function( file) 0
body( LLDBflush) <- if( is.loaded( 'R_lazyLoadDBflush', PACKAGE='base'))
substitute( unmentionable( 'R_lazyLoadDBflush', as.character( file)[1], PACKAGE=bottom),
list( unmentionable=as.name( rawToChar( rev( charToRaw( 'llaC.')))), bottom='base'))
else
substitute( unmentionable( lazyLoadDBflush( as.character( file)[1])),
list( unmentionable=as.name( rawToChar( rev( charToRaw( 'lanretnI.'))))))
environment( LLDBflush) <- baseenv()
LLDBflush <- CRANky( 'hsulfBDLL', environment())
get.nsreg <- function() 0
body( get.nsreg) <- substitute( unmentionable( getNamespaceRegistry()),
list( unmentionable=as.name( rawToChar( rev( charToRaw( 'lanretnI.'))))))
environment( get.nsreg) <- baseenv()
get.nsreg <- CRANky( 'gersn.teg', environment())
maintained.packages <- originals.mp <- dont.lock.envs <- presave.hooks <- list()
mvb.base.S3.generics <- names( get.S3.generics( baseenv(), ns=FALSE))
mvb.base.S3.generics <- c( '[', '[<-', '$', '$<-', '[[', '[[<-', 'cbind', 'rbind',
'Ops', 'Math', 'Summary', 'Complex', mvb.base.S3.generics)
mvb.base.S3.generics <- structure( rep( 'base', length( mvb.base.S3.generics)),
names=mvb.base.S3.generics)
fix.list <- empty.data.frame( name= , file= , where=, where.type=, dataclass='',
has.source=FALSE, file.time=0)
dont.lock.envnames <- character(0)
# Re-register print methods in base--- otherwise autoprint messes up
REGS3M <- CRANky( 'dohtem3Sretsiger')
S3MT <- get( '.__S' %&% '3MethodsTable__.')
do.on( lsall( S3MT, patt='^print[.]') %except% 'print.default',
REGS3M( 'print', sub( 'print.', '', .), get( .), baseenv())
)
},
envir=nsenv)
eapply( nsenv, force) # no lazyload
# Bindings are only locked *after* .onLoad-- so can't unlock them here...
dont.lockBindings( 'dont.lock.envs', pkgname)
dont.lockBindings( 'dont.lock.envnames', pkgname)
# Now putting fix.list & maintained.packages into mvb.session.info, instead of package:mvbutils
# copy.ns.objects( cq( fix.list, maintained.packages), pkgname)
f <- function( val) blah-blah-blah
for( x in cq( fix.list, maintained.packages, presave.hooks)) {
body( f) <- substitute( if( missing( val)) x else x <<- val, list( x=as.name( x)))
environment( f) <- asNamespace( 'mvbutils')
makeActiveBinding( x, f, as.environment( 'mvb.session.info'))
dont.lockBindings( x, pkgname)
}
set.path.attr( pos.to.env( 1), .Path)
setup.mcache( .GlobalEnv) # in case of cached objects in ROOT, which 'load' won't understand
# assign.to.base( 'rbind.data.frame', mvb.rbind.data.frame, override.env=FALSE) # no choice on this one
my.reps <- getOption( 'mvbutils.replacements', TRUE)
# Circumvent user stuff-ups...
my.reps <- switch( typeof( my.reps),
'logical' = !identical( FALSE, my.reps[1]),
'character' = my.reps,
TRUE)
# Slimmed-down list Sep 2012; others moved to 'nicetime'
my.reps.opts <- named( cq( loadhistory, savehistory, save.image,
library, lockEnvironment, importIntoEnv, loadNamespace))
my.reps <- my.reps.opts[ my.reps] %except% NA # storm the last bastion of user stuff-ups
# Only do nominated replacements
# Next is mlocal so that ATB correctly picks up import env-- ATB limitation
assign.to.base.opt <- function( what, ..., nlocal=sys.parent())
mlocal( if( what %in% my.reps) assign.to.base( what, ...))
assign.to.base.opt( 'lockEnvironment', hack.lockEnvironment(), override.env=FALSE)
assign.to.base.opt( 'importIntoEnv', hack.importIntoEnv(), override.env=FALSE)
assign.to.base.opt( 'loadNamespace', hack( 'loadNamespace',
partial=local({
ok <- try( {
pn <- as.environment( 'mvb.session.info')$partial.namespaces
(length( pn)>0) && ((pn == "EVERY PACKAGE") || (package %in% pn))
})
!inherits(ok, 'try-error') && ok
}),
override.env=FALSE))
# Now let ME (only) maintain mvbutils itself
if( exists( 'tasks', .GlobalEnv, mode='character', inherits=FALSE)
&& !is.na( tasks[ 'mvbutils']))
load.maintained.package( 'mvbutils', full.path( tasks[ 'mvbutils'], wd), cq( ROOT, mvbutils),
autopatch=!is.null( getOption( 'autopatch.mvbutils')))
for( i in cq( load, save) %&% 'history')
assign.to.base.opt( i, hack( i,
file=if( nzchar( histfile <- Sys.getenv( 'R_HISTFILE'))) histfile else '.Rhistory'))
# Only reason for try(...) next is to avoid my stuffing mvbutils up while editing this...
try( if( ('loadhistory' %in% my.reps.opts) && !nzchar( Sys.getenv( 'R_HISTFILE')))
Sys.setenv( R_HISTFILE=file.path( .First.top.search, '.Rhistory')))
assign.to.base.opt( "library", hack( library, pos=local({
poz <- try( 1+rev( mvbutils::search.task.trees())[1])
if( inherits( poz, 'try-error'))
poz <- 2
poz
})
))
hack.save.image <- function( ...) {
# formals will be replaced by those of 'save.image'
# Evaluate args and check if they match defaults
mc <- match.call( as.environment( 'mvb.session.info')$base.save.image)
mc <- as.list( mc)[-1]
mc[] <- mget( names( mc), sys.frame( sys.nframe()))
form <- formals( base.save.image)
if( length( mc) && !identical( form[ names( mc)], mc)) {
mc <- c( quote( base.save.image), mc)
eval( as.call( mc), sys.parent())
} else # length(mc)==0 => default params anyway
mvbutils::Save()
}
formals( hack.save.image) <- formals( save.image)
assign.to.base.opt( "save.image", hack.save.image)
# Needed by 'set.pkg.and.dir' in eg 'install.pkg'
assign( 'R.rebuild.vers', numeric_version( R.rebuild.versions), nsenv)
# Things below here no longer used
if( FALSE)
old.onLoad.stuff()
# packageStartupMessage( 'MVBUTILS loaded\n') # apparently "not good practice"-- can't be bothered arguing
}
".onUnload" <-
function( libpath){
s <- try( as.environment( 'mvb.session.info'))
if( s %is.a% 'try-error')
return()
for( i in ls( s, pattern='^base\\.'))
assign.to.base( sub( '^base\\.', '', i), s[[i]])
autoedit( FALSE)
detach( 'mvb.session.info') # gulp
}
"?" <-
function ( e1, e2) {
# `?` <- get("base.?", pos = "mvb.session.info")
mc <- as.list(match.call())
mc[[1]] <- quote( asNamespace( 'utils')$'?') # anti CRANky
if( missing( e2)) {
# Set 'mvb_help_type', just in case it's needed
mvb_help_type <- mc$help_type
if( is.null( mvb_help_type))
mvb_help_type <- getOption( 'mvb_help_type', getOption( 'help_type', "text"))
h1 <- try(eval(as.call(mc), parent.frame()), silent = TRUE)
if( (h1 %is.not.a% "try-error") && (length(unclass(h1)) > 0))
return( h1)
h1 <- dochelp( as.character( mc$e1), help_type=mvb_help_type)
if( h1 %is.a% c( "pagertemp", "browsertemp"))
return(h1)
# If that failed too, just call it again & permit the crash...
}
eval(as.call(mc), parent.frame())
}
"[.dull" <-
function( x, ...) {
res <- NextMethod( '[', x)
oldClass( res) <- 'dull'
return( res)
}
"add.flatdoc.to" <-
function( x=NULL, char.x=NULL, pkg=NULL, env=NULL, convert.to.source=FALSE) {
if( is.null( env))
env <- if( !is.null( pkg)) maintained.packages[[ pkg]] else parent.frame()
if( is.null( char.x))
char.x <- as.character( substitute( x))
if( is.function( x)) { # TRUE except for fixr( existing.general.object)
text <- docskel( x=x, char.x=char.x, env=env)
class( text) <- 'docattr'
if( is.null( x))
x <- env[[ char.x]]
} else
text <- as.cat( '# Your scriptlet goes here...')
if( !is.null( srcref <- attr( x, 'srcref'))){
# Turn into 'source' attribute, so that it's handled by write.sourceable.function
attr( x, 'source') <- if( attr( srcref, 'srcfile')$filename=='dummyfile') # ie from previous fixr
attr( srcref, 'srcfile')$lines
else
capture.output( print( srcref))
attr( x, 'srcref') <- NULL
}
attr( x, 'doc') <- text
x
}
"as.cat" <-
function( x) { stopifnot( is.character( x)); oldClass( x) <- 'cat'; x}
"as.docattr" <-
function( x) {
stopifnot( is.character( x))
class( x) <- 'docattr'
x
}
"as.env" <-
function ( x) UseMethod( 'as.env')
"as.env.character" <-
function( x) {
glob <- names( attr( .GlobalEnv, 'path'))
if( is.character( glob) && (length( glob)==1) && (x==glob))
return( .GlobalEnv)
return( as.environment( x)) # will trigger error if invalid
}
"as.env.default" <-
function( x)
as.environment( x)
"assign.to.base" <-
function( x, what=lapply( named( x),
function( x, where) get( 'replacement.' %&% x, pos=where), where=where),
where=-1,
in.imports=sys.parent() != 0 && exists( '.__NAMESPACE__.', environment( sys.function( sys.parent()))),
override.env=TRUE) {
############
if( !is.list( what))
what <- list( what)
if( is.null( names( what)))
names( what) <- x
reassign <- function( obj, value, env) {
if( tethered <- balloonIsTethered( obj, env))
untetherBalloon( obj, env)
if( override.env)
environment( value) <- environment( get( obj, env))
assign( obj, value, env)
if( tethered) {
w <- options("warn")
on.exit(options(w))
options(warn = -1)
tetherBalloon( obj, env)
}
}
penv <- if( in.imports) # ? extra parent.env 15/11/2010
parent.env( environment( sys.function( sys.parent())))
else
NULL
get.S3.methods.tables <- function( wherestr, meth) {
# generic <- sub( '.* for +([# ]+) +from.*', '\\1', wherestr)
# where.gen <- do.call( 'getAnywhere', list( generic))$where
# where.gen <- unique( sub( '(namespace|package):', '', where.gen))
# scatn( 'Looking for "%s" in: %s', meth, paste( where.gen, collapse=', '))
where.gen <- lapply( wherestr, function( x) asNamespace( x)$.__S3MethodsTable__.)
has.meth <- sapply( where.gen, function( x) exists( meth, x, inherits=FALSE))
return( where.gen[ has.meth])
}
for( xi in x) {
this <- what[[ xi]]
if( !is.null( penv) && exists( xi, penv, inherits=FALSE))
reassign( xi, this, penv)
# Hidden S3 methods will be duplicated in the package namespace
where.xi <- do.call( 'getAnywhere', list( xi))$where
# pkgs <- unique( sub( 'namespace:', 'package:', where.xi))
# # sub( 'registered S3 method for .* from namespace ', 'package:', where.xi)))
# pkgs <- sub( 'package:', '', grep( 'package:', pkgs, value=TRUE))
# ?Should this search parent-envs of namespaces too? That seems a bit forward...
if( !length( where.xi))
next
system.xi <- NULL
envs.xi <- unlist( c(
FOR( where.xi %that.match% '^registered S3', get.S3.methods.tables(
sub( ' +.*', '', sub( '.*namespace *', '', .)), meth=xi)),
FOR( where.xi %that.match% '^package:', as.environment(.)),
FOR( where.xi %that.match% '^namespace:', asNamespace( sub( 'namespace:', '', .)))
))
envs.xi <- unique( unlist( envs.xi))
for( ienv in envs.xi) {
if( exists( xi, ienv, inherits=FALSE)) {
if( is.null( system.xi)) {
system.xi <- ienv[[ xi]]
}
reassign( xi, this, ienv)
}
}
# Keep original-- only the first one found though, which is a bit random
if( !exists( 'base.' %&% xi, where='mvb.session.info', inherits=FALSE))
assign( 'base.' %&% xi, system.xi, 'mvb.session.info')
}
invisible( NULL)
}
"attach.mlazy" <-
function( dir, pos=2,
name='data:' %&% attr( .GlobalEnv, 'name') %&% ':' %&% basename( dir)) {
ATTACH( list(), pos=pos, name=name)
e <- pos.to.env( pos)
attr( e, 'path') <- dir <- task.home( dir)
load.refdb( envir=e) # does nothing if no file
}
"autoedit" <-
function( do=TRUE){
s <- as.environment( 'mvb.session.info')
if( do) {
if( !exists( 'autoedit.callback', envir=s, inherits=FALSE) ||
is.null( s$autoedit.callback))
assign( 'autoedit.callback', addTaskCallback(
function( ...) {
try( FF())
TRUE
}),
envir=s)
} else if( !is.null( s$autoedit.callback)) {
removeTaskCallback( s$autoedit.callback)
s$autoedit.callback <- NULL
}
}
"build.pkg" <-
function( pkg, character.only=FALSE, flags=character(0), cull.old.builds=TRUE){
# In case of path arg
if( missing( pkg)) {
orig.pkg <- character.only
} else {
thing <- substitute( pkg)
orig.pkg <- if( thing %is.a% 'name') as.character( thing) else pkg
}
set.pkg.and.dir( TRUE)
result <- rcmdgeneric.pkg2( pkg=pkg, outdir=outdir, indir=sourcedir,
cmd='build', flags=flags)
if( cull.old.builds) {
cull.old.builds( orig.pkg, character.only=TRUE) # pkg reset to string
}
invisible( result)
}
"build.pkg.binary" <-
function( pkg, character.only=FALSE, flags=character(0), cull.old.builds=TRUE, multiarch=NA, preclean=TRUE){
i <- 1
repeat{
temp.inst.lib <- file.path( tempdir(), 'templib' %&% i)
if( !file.exists( temp.inst.lib))
break
i <- i+1
}
mkdir( temp.inst.lib)
on.exit( unlink( temp.inst.lib, recursive=TRUE))
# In case of path arg
if( missing( pkg)) {
orig.pkg <- character.only
} else {
thing <- substitute( pkg)
orig.pkg <- if( thing %is.a% 'name') as.character( thing) else pkg
}
set.pkg.and.dir( TRUE)
if( preclean) {
flags <- c( '--preclean', flags) # good idea
}
if( is.na( multiarch)) {
check_multiarch()
}
if( !multiarch) {
flags <- c( '--no-multiarch', flags)
} else { # R (3.3) is buggy here; see install.pkg for workaround
flags <- c( '--compile-both', '--force-biarch', flags)
}
result <- rcmdgeneric.pkg2( pkg, outdir=outdir, indir=sourcedir, cmd='INSTALL',
flags=c( flags, '--build -l ' %&% temp.inst.lib))
if( cull.old.builds) {
cull.old.builds( orig.pkg, character.only=TRUE) # pkg reset to string
}
invisible( result)
}
"cachefile.path" <-
function (..., fsep = .Platform$file.sep)
{
if (any(sapply(list(...), length) == 0))
return(character())
paste(..., sep = fsep)
}
"called.by" <-
function( fname, can.match, where) {
where <- if( is.environment( where)) list( where) else as.list( where)
which <- unlist( lapply( where, exists, x=fname), use.names=FALSE)
if( !any( which)) {
f <- if( exists( fname)) get( fname) else list() }
else
f <- get( fname, pos=where[[ index( which)[ 1] ]])
# flist_ as.character( unlist( f[length(f)], use=FALSE))
flist <- char.unlist( f)
if( !length( flist))
return( numeric( 0))
# Check for functions occurring in default parameters!
# R version does this automatically
# everything_ unique( c( flist, as.character( unlist( as.list( f)[-length(f)], use=FALSE))))
everything <- flist
# Main task:
everything <- match( everything, can.match, nomatch=0)
everything <- everything[ everything>0]
# Check for generic functions:
# Ignore for now in R
# if( mode(f[[length(f)]])=='internal' | flist[1]=='UseMethod')
# everything_ c( everything, index(substring( can.match, 1, nchar( fname)+1) == fname %&% '.'))
everything
}
"callees.of" <-
function( funs, fw, recursive=FALSE) {
if( fw %is.a% 'foodweb')
fw <- fw[[1]]
all <- dimnames( fw)[[1]]
orig.funs <- funs
out <- character()
while( length( funs)) {
vec <- all %in% funs
these <- all[ vec %*% fw > 0] # ie: these <- callees.of( funs, fw)
funs <- these %except% c( out, orig.funs) # orig.funs to cut off loops
out <- unique( c( out, these))
if( !recursive)
break
}
sort( out)
}
"callers.of" <-
function( funs, fw, recursive=FALSE) {
if( fw %is.a% 'foodweb')
fw <- fw[[1]]
all <- dimnames( fw)[[1]]
orig.funs <- funs
out <- character()
while( length( funs)) {
vec <- all %in% funs
these <- all[ fw %*% vec > 0] # ie: these <- callers.of( funs, fw)
funs <- these %except% c( out, orig.funs) # orig.funs to cut off loops
out <- unique( c( out, these))
if( !recursive)
break
}
sort( out)
}
"cd" <-
function ( to, execute.First = TRUE, execute.Last = TRUE) {
######################
# This to allow cd(..) from task "mvbutils" itself or a subtask...
penv <- environment( sys.function())
if( identical( penv, .GlobalEnv) || identical( penv, pos.to.env( 2))) {
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( mvbutils::cd) # anti CRANky
return( eval( mc, sys.frame( sys.parent())))
}
need.to.promote.on.failure <- FALSE
on.exit({
if (need.to.promote.on.failure) promote.2.to.1()
if (!is.null(wd <- attr(.GlobalEnv, "path"))) setwd(wd)
if (.Path[length(.Path)] != wd) {
.Path <<- if (any(.Path == wd))
.Path[1:max(index(.Path == wd))]
else
c("??" = character(0), "??" = wd)
}
cdprompt()
})
orig.path <- attr(.GlobalEnv, "path")
if (is.null(orig.path) || !my.all.equal(orig.path, .Path[length(.Path)]))
stop("problem with taskly status of .GlobalEnv!")
if (missing(to))
to <- get.cd.from.menu()
else to <- substitute(to)
to <- strsplit(deparse(to), "/", fixed=TRUE)[[1]]
if (to[1] == "0")
to <- c(rep("..", length(.Path) - 1), to[-1])
to <- to %except% "."
if (!length(to))
return(invisible())
ii <- to[-length(to)] != ".." & to[-1] == ".."
ii <- c(ii, FALSE) | c(FALSE, ii)
to <- to[!ii]
if (!length(to))
return(invisible())
if (to[1] == ".." && length(.Path) == 1)
stop("Can't move backwards from ROOT!")
# Tedious temporaries...
if( getOption( 'mvbutils.quick.cd', FALSE))
suppressWarnings(
mlazy( what=cq( .Random.seed, last.warning, .Traceback, .Saved.plots)
%SUCH.THAT% exists( ., where=1, inherits=FALSE)))
#save.image() # replaced by...
Save.pos( 1) # 12/04, to work with all.rda & lazy-Load
if( !nzchar( Sys.getenv( 'R_HISTFILE')))
Sys.setenv( R_HISTFILE=file.path( .First.top.search, '.Rhistory'))
if( getOption( 'mvbutils.update.history.on.cd', TRUE))
try( savehistory(), silent=TRUE) # won't work if embedded; never mind
need.to.promote.on.failure <- TRUE
if (to[1] == "..") {
cd..(1)
for (i in 1 %upto% sum(to == ".."))
cd..(2)
} else
load.mvb( file.path( orig.path, '.RData'), names(orig.path),
pos = 2, attach.new = TRUE, path = orig.path)
remove(list = lsall(pos = 1), pos = 1)
attributes(.GlobalEnv) <- list()
if (length(to)) {
for (i in 2 %upto% length( to)) {
cd.load(to[1], pos = 2, attach.new = TRUE)
to <- to[-1]
}
cd.load(to[1], pos = 1, attach.new = FALSE)
if( getOption( 'mvbutils.update.history.on.cd', TRUE))
try( loadhistory(), silent=TRUE) # won't work if embedded; never mind
need.to.promote.on.failure <- FALSE
}
}
"cd.." <-
function( pos, nlocal=sys.parent()) mlocal({
# Do .Last before checking move, because this might detach rubbish
if( execute.Last) {
.Last.task <- if( exists( '.Last.task', where=pos, inherits=FALSE))
get( '.Last.task', pos=pos)
else
function( pos) {}
try( .Last.task( 1))
}
# For MPs with loaded namespaces:
if( regexpr( '^temp.nsobj:', search()[pos+1])>0)
detach( pos=pos+1)
can.go.up <- !is.null( names( attr( as.environment( pos+1), 'path')))
if( can.go.up)
update.maintained.package( names( .Path)[ length( .Path)])
else {
need.to.promote.on.failure <- pos>1
stop( "Can't cd up; there's a non-task in position 2", call.=FALSE)
}
if( pos>1) {
need.to.promote.on.failure <- TRUE
detach( pos=pos)
}
to <- to[-1]
orig.cd.path <- paste( names( .Path), collapse='/')
.Path <<- .Path[ -length( .Path)]
setwd( .Path[ length( .Path)])
# All good; change fix.list if cd'ing up from a maintained package
if( (names( orig.path) %in% names( maintained.packages)) &&
(attr( maintained.packages[[ names( orig.path)]], 'path') == orig.path)) {
fixing.in.pkg <- fix.list$where==orig.cd.path
fix.list$where.type[ fixing.in.pkg] <<- 'package'
}
})
"cd.change.all.paths" <-
function( from.text='0', old.path, new.path) {
case <- if( .Platform$OS=='windows')
upper.case
else
function( x) x # case-sensitive
cditerate( from.text, cd.change.all.paths.guts, '', old.path=case( old.path),
new.path=case( new.path), case=case)
}
"cd.change.all.paths.guts" <-
function( found, task.dir, task.name='??', env, old.path, new.path, case) {
cat( task.name, '\n')
if( exists( 'tasks', envir=env, inherits=FALSE) && is.character( tasks)) {
tasks <- get( 'tasks', envir=env)
tasks[] <- otasks <- gsub( '\\\\', '/', tasks) # [] to keep names
tasks[] <- gsub( old.path, new.path, case( tasks))
if( any( tasks != otasks)) {
assign( 'tasks', tasks, envir=env)
save.refdb( env, file=file.path( task.dir, '.RData'))
if( getOption( 'write.mvb.tasks', FALSE))
write.mvb.tasks( env=env, dir=task.dir)
}
}
found
}
"cd.load" <-
function (taskname, pos, attach.new, nlocal = sys.parent()) mlocal({
if( taskname %in% names( maintained.packages))
stop( "No longer allowed to 'cd' into maintained packages-- if you must, then first use 'unmaintain.package'")
if (!exists("tasks", where = 2, inherits = FALSE))
tasks <- character(0)
full.path <- tasks[taskname]
if (is.na(full.path)) {
if (yes.no("Task " %&% taskname %&% " does not exist yet. Create it? "))
full.path <- make.new.cd.task(taskname)
else {
cat("No ")
stop("Just exiting cd", call.=FALSE)
}
}
if( regexpr( '^[.]{1,2}/', full.path)>0) # rel paths OK; 24/6/2005
full.path <- file.path( getwd(), full.path)
# Strip out .. and .
full.path <- gsub( '/\\./', '/', full.path)
full.path <- gsub( '[^/]*/\\.\\./', '', full.path)
names( full.path) <- taskname
filename <- file.path( full.path, '.RData')
if( is.na( filename) || !file.exists( full.path)) # || added 1/7/2005
stop( "Can't find an image file to load for '" %&% taskname %&% "'!")
# Will *assume* there is just one possible package
# Make sure saved image is up-to-date
# save.refdb OK because can't mtrace in m.p. itself
if( any( names( maintained.packages)==taskname)) {
save.refdb( file=filename, envir=maintained.packages[[ taskname]])
fixing.in.pkg <- index( fix.list$where == paste( c( names(.Path), taskname), collapse='/'))
fix.list$where.type[ fixing.in.pkg] <<- 'task'
}
load.mvb( filename, name = taskname,
pos = pos, attach.new = attach.new, path = full.path)
.Path <<- c(.Path, full.path)
setwd( full.path) # new 24/6/2005, to allow rel paths
epos <- as.env( pos)
if( any( names( maintained.packages)==taskname)) {
if( packageHasNamespace( taskname, full.path)
&& (taskname %not.in% loadedNamespaces()))
warning( "Package version of '" %&% taskname %&% "' not loaded yet-- may behave slightly differently")
else if( taskname %in% loadedNamespaces()) {
# Make "copies" of all extra stuff that's in namespace, using active bindings to ensure namespace
# is synchronized. Copies go into a new search environment just below task
ns <- asNamespace( taskname)
etemp <- ATTACH( NULL, pos=pos+1, name='temp.nsobj:' %&% taskname)
# Don't copy weird stuff
extroids <- lsall( ns) %except% lsall( epos)
extroids <- extroids %such.that% (regexpr( '^\\.__.*__\\.$', .)<0)
for( x in extroids) {
# f <- substitute( if( missing( val)) x else x <<- val, list( x=as.name( x)))
# makeActiveBinding( x, as.function( alist( val=, f), envir=ns), etemp)
f <- function( val) 0
body( f) <- substitute( if( missing( val)) x else x <<- val, list( x=as.name( x)))
environment( f) <- ns
makeActiveBinding( x, f, etemp)
}
} # if loaded namespace
# Change fix list to point to here rather than m.p.
repfl <- index( fix.list$where==search.task.trees()[1])
if( length( repfl))
fix.list[ repfl, 'where.type'] <<- 'task'
} # if maintained
if (execute.First && exists(".First.task", where = pos, inherits = FALSE)) {
.First.task <- epos$.First.task # reassign for clarity of any error msg
try(.First.task(pos))
}
})
"cd.write.mvb.tasks" <-
function( from=., from.text=substitute( from))
invisible( cditerate( from.text, cd.write.mvb.tasks.guts, vector( 'list', 0)))
"cd.write.mvb.tasks.guts" <-
function( found, task.dir, task.name, env) {
# cat( task.name, task.dir); print( env)
if( exists( 'tasks', envir=env, inherits=FALSE))
write.mvb.tasks( env=env, dir=task.dir)
found
}
"cdfind" <-
function( pattern, from=., from.text, show.task.name=FALSE) {
if( missing( from.text))
from.text <- substitute( from)
answer <- cditerate( from.text, cdfind.guts, vector( 'list', 0), pattern, show.task.name=show.task.name)
attributes( answer) <- list( names=names( answer))
answer
}
"cdfind.guts" <-
function (found, task.dir, task.name, pattern, env) {
if (length( o <- lsall(envir = env))) {
o <- o %that.match% pattern
if (length(o)) {
a <- match(o, names(found), 0)
if (sum(a))
found[names(found)[a]] <- lapply(found[names(found)[a]],
c, task.name)
if (sum(a == 0))
found <- c(found, structure(.Data = rep(task.name,
sum(a == 0)), names = o[a == 0], mode = "list"))
}
}
found
}
"cditerate" <-
function( from.text, what.to.do, so.far=vector('NULL',0), ..., show.task.name=FALSE) {
assign( '[[', my.index, envir=sys.frame( sys.nframe()))
assign( '[[<-', my.index.assign, envir=sys.frame( sys.nframe()))
nodes <- find.path( char.rel.path=from.text)
if( dos.or.windows())
nodes <- upper.case( nodes)
node.list <- list(1)
names( node.list) <- names( nodes)
parents <- 0
is.task <- function( x) {
if( !is.null( x <- attr( pos.to.env( x), 'path')) && !is.null( x <- names( x)[1]))
x
else
''
}
attached.tasks <- sapply( 1:length( search()), is.task)
orig.env <- env <- new.env()
i <- 1
while( my.index.exists( i, node.list)) { # length( node.list[[i]])) {
# Look first to see if task is attached
this.name <- names( nodes[ node.list[[ i]]])
if( show.task.name)
cat( '\n' %&% names( unlist( node.list))[ match( node.list[[ i]], unlist( node.list))])
m <- match( this.name, attached.tasks, 0)
if( m)
env <- as.environment( m)
else if( file.access( this.file <- file.path( nodes[ node.list[[i]] ], '.RData'))==0) {
# was: this.file <- file.path( nodes[ node.list[[i]] ], '.RData')
# Clear last batch of objects
env <- orig.env
remove( list=lsall( env), envir=env)
attr( env, 'path') <- dirname( this.file)
checko <- suppressWarnings( try( load.mvb( this.file, envir=env, name=this.name), silent=TRUE))
if( checko %is.a% 'try-error') # hopefully things will just work anyway...
warning( "Problem loading " %&% this.file)
} else {
warning( "Can't find " %&% this.file)
env <- NULL # flag
}
if( !is.null( env)) {
so.far <- what.to.do( found=so.far, task.dir=nodes[ node.list[[i]]],
task.name=find.prefix( node.list[[i]], nodes, parents), env=env, ...)
deeper <- exists( 'tasks', envir=env, inherits=FALSE)
} else
deeper <- FALSE # couldn't find, don't even try
if( deeper) {
new.nodes <- get( 'tasks', envir=env)
deeper <- length( new.nodes) > 0 }
if( deeper) {
new.nodes <- sapply( new.nodes, full.path, start=nodes[[ node.list[[i]]]])
if( dos.or.windows())
new.nodes <- upper.case( new.nodes)
# Eliminate self-referential subtasks!
if( any( drop <- !is.na( sr <- match( new.nodes, nodes)))) {
prefix <- find.prefix( node.list[[i]], nodes, parents)
other.prefix <- character( sum( drop))
for( j in 1:sum( drop))
cat( 'Loop or self-reference in task hierarchy: ',
prefix %&% '/' %&% names(new.nodes)[drop][ j], '=',
find.prefix( sr[ drop][j], nodes, parents), '\n')
new.nodes <- new.nodes[ !drop]
} #self-reference
nodes <- c( nodes, new.nodes)
parents <- c( parents, rep( node.list[[i]], length( new.nodes)))
new.nodes[] <- seq( to=length(nodes), by=1, length=length(new.nodes))
mode( new.nodes) <- 'numeric'
mode( new.nodes) <- 'list'
node.list[[i]] <- c( node.list[[i]], new.nodes)
i <- c( i, 2)
} else { # !deeper
# Move up while no more sibs.
while( length( i)>1 && i[ length(i)] == length( node.list[[ i[-length(i)] ]]))
i <- i[ -length(i)]
# Move to next sib, if any.
i[ length(i)] <- i[ length(i)] + 1
} # deeper or not
} # of master loop
if( show.task.name)
cat( '\n')
attr( so.far, 'nodes') <- nodes
attr( so.far, 'node.list') <- node.list
so.far
}
"cdprompt" <-
function() {
opened <- what.is.open()
if( length( opened))
opened <- paste( c( '', opened), collapse='<')
prompt <- names( .Path)[-1]
if( length( prompt)>1 && (abbr.char <- getOption( 'abbreviate.cdprompt', 0)) > 0)
prompt[ -length( prompt)] <- substring( prompt[ -length( prompt)], 1, abbr.char)
invisible( options( prompt = paste( prompt, collapse = "/") %&% opened %&% "> "))
}
"cdregexpr" <-
function( regexp, from=., from.text, ..., show.task.name=FALSE) {
if( missing( from.text))
from.text <- substitute( from)
answer <- cditerate( from.text, cdregexpr.guts, vector( 'list', 0), regexp,
show.task.name=show.task.name, ...)
attributes( answer) <- list( names=names( answer))
answer
}
"cdregexpr.guts" <-
function (found, task.dir, task.name, regexp, env, ...) {
if (length(o <- search.for.regexpr(regexp, where = env, ...))) {
found <- c(found, structure(.Data = rep(task.name, length(o)),
names = o, mode = "list"))
}
found
}
"cdtree" <-
function( from=., from.text=substitute( from), charlim=90) {
indices <- cditerate( from.text, cdtree.guts, empty.data.frame( full.name=, own.name='', parent=0))
# Now produce function matrix etc.
funs <- indices$own.name
n <- length( funs)
# Avoid problems with duplicated names
pre.X <- rep( 1, n)
while( !is.na( d <- index( duplicated( funs))[1])) {
pre.X[ d] <- pre.X[ d]+1
funs[ d] <- 'X' %&% funs[ d] }
funmat <- matrix( 0, n, n, dimnames=list( funs, funs))
funmat[ cbind( indices$parent[-1], 2 %upto% n)] <- 1
organize.web.display()
funs <- substring( funs, pre.X, nchar( funs))
dimnames( funmat) <- list( funs, funs)
names( level) <- funs
answer <- list( funmat=funmat, level=level, x=x, nodes=attr( indices, 'nodes'),
node.list=attr( indices, 'node.list'))
class( answer) <- cq( cdtree, foodweb)
answer
}
"cdtree.guts" <-
function (found, task.dir, task.name, env)
{
task.info <- strsplit(task.name, "/")[[1]]
this.task.name <- task.info[length(task.info)]
parent <- paste(task.info[-length(task.info)], collapse = "/")
i <- match(parent, found$full.name, 0)
rbind(found, list(full.name = task.name, parent = i, own.name = this.task.name))
}
"changed.funs" <-
function( egood, ebad, topfun=NULL, fw=NULL){
if( is.null( fw))
fw <- foodweb( egood, plotting=FALSE)
if( is.null( topfun))
topfun
to.do <- topfun
fchanges <- character( 0)
done <- 0
while( done < length( to.do)) {
fun <- to.do[ done+1]
if( fun %not.in% lsall( ebad)) {
fchanges <- c( fchanges, fun)
} else {
changed <- !my.all.equal( egood[[ fun]], ebad[[ fun]])
if( changed) {
fchanges <- c( fchanges, fun)
more <- callees.of( fun, fw) %except% c( to.do, fchanges)
to.do <- c( to.do, more)
}
}
done <- done + 1
}
return( fchanges)
}
"char.unlist" <-
function (x) {
if (!(listable <- is.list(x))) {
if( isS4( x) && ('.Data' %in% names( getSlots( class( x)))))
x <- x@.Data
if (listable <- (!is.atomic(x) && !is.symbol(x))) {
# x <- as.list( x) worked well for years, but weird sh*t like externalptr can occur, so...
xx <- try( as.list(x), silent=TRUE)
if( x %is.a% 'try-error') {
listable <- FALSE
} else {
x <- xx
}
}
}
if (listable)
unlist(lapply(x, char.unlist), use.names = FALSE)
else
paste(deparse(x), collapse = "\n")
}
"check.patch.versions" <-
function( care=NULL) {
nmp <- names( maintained.packages)
instances <- cq( MP, installed, source, tarball, binary)
mat <- matrix( NA_character_, length( nmp), length( instances),
dimnames=list( nmp, instances))
character.only <- FALSE
for( pkg in nmp) {
pv <- maintained.packages[[ pkg]][[ pkg %&% '.VERSION']]
if( !is.null( pv)) {
mat[ pkg, 'MP'] <- as.character( pv)
}
try( mat[ pkg, 'installed'] <- as.character( packageVersion( pkg)), silent=TRUE)
set.pkg.and.dir( TRUE, FALSE) # want outdir calculated, but not created
try( mat[ pkg, 'source'] <- read.dcf( file.path( sourcedir,
'DESCRIPTION'))[1,'Version'], silent=TRUE)
try({
tarballs <- dir( outdir, pattern=sprintf( '^%s_[0-9]+([.][0-9]+)*[.]tar[.]gz$', pkg),
full.names=FALSE)
mat[ pkg, 'tarball'] <- as.character( max( numeric_version( sub( '.*_', '',
sub( '.tar.gz$', '', tarballs)))))
}, silent=TRUE)
try({
binaries <- dir( outdir, pattern=sprintf( '^%s_[0-9]+([.][0-9]+)*[.]zip$', pkg),
full.names=FALSE)
mat[ pkg, 'binary'] <- as.character( max( numeric_version( sub( '.*_', '',
sub( '.zip$', '', binaries)))))
}, silent=TRUE)
}
keep <- rep( TRUE, length( nmp))
for( icare in care) {
keep <- keep | (mat[ ,icare] != mat[ , 'MP'])
}
return( mat[ keep,])
}
"check.pkg" <-
function( pkg, character.only=FALSE, build.flags=character(0), check.flags=character(0), CRAN=FALSE) {
# Advice is to build into tarball first, then RCMD CHECK that
orig.pkg <- substitute( pkg)
set.pkg.and.dir( TRUE)
force( build.flags)
force( check.flags)
force( CRAN)
mc <- match.call()
mc[[1]] <- build.pkg
mc$pkg <- orig.pkg # in case of path arg
mc$build.flags <- mc$check.flags <- mc$CRAN <- NULL
mc$flags <- build.flags
extract.named( eval.parent( mc)) # dir. etc
i <- 1
repeat{
temp.inst.lib <- file.path( tempdir(), 'templib' %&% i)
if( !file.exists( temp.inst.lib))
break
i <- i+1
}
mkdir( temp.inst.lib)
on.exit( unlink( temp.inst.lib, recursive=TRUE))
rcmdgeneric.pkg2( orig.pkg, outdir=outdir, indir=file.path( outdir, pkg), cmd='check',
postfix= '_' %&% read.dcf( file.path( sourcedir, 'DESCRIPTION'))[,'Version'] %&% '.tar.gz',
flags=c( check.flags, if( CRAN) '--as-cran', '-l ' %&% temp.inst.lib))
}
"check_multiarch" <-
function( nlocal=sys.parent()) mlocal({
multiarch <- TRUE # default sans biarch
dcf <- read.dcf( file.path( dir., pkg, 'DESCRIPTION'))
biarch_field <- match( 'BIARCH', toupper( colnames( dcf)), 0)
if( biarch_field) {
multiarch <- as.logical( dcf[1,biarch_field])
if( is.na( multiarch)) {
warning( "Malformed BIARCH field; trying multiarch=TRUE")
multiarch <- TRUE
}
}
})
"clip" <-
function( x, n=1) x[ 1 %upto% ( length( x) - n)]
"close.selfdeleting.file" <-
function( con, ...) {
fname <- summary( con)$description
NextMethod( 'close')
unlink( fname)
}
"copy.ns.objects" <-
function( objects, pkgname) {
objects <- objects # force
icns <- function( pkgname, pkgpath){
senv <- as.environment( 'package:' %&% pkgname)
cat( 'Locked?\n')
print( environmentIsLocked( senv))
print( objects)
ns <- asNamespace( pkgname)
f <- function( val) blah-blah-blah
for( x in objects) {
body( f) <- substitute( if( missing( val)) x else x <<- val, list( x=as.name( x)))
environment( f) <- ns
makeActiveBinding( x, f, senv)
}
}
setHook( packageEvent( pkgname, 'attach'), icns)
}
"cq" <-
function( ...) {
# Saves putting in quotes!
# E.G.: quoted( first, second, third) is the same as c( 'first', 'second', 'third')
# wrapping by as.character means cq() returns character(0) not list()
as.character( sapply( as.list( match.call( expand.dots=TRUE))[-1], as.character))
}
"CRANky" <-
function( blurb, env=baseenv()){
# Returns an undetectable synonym of an unmentionable function in baseenv() or elsewhere
# Sigh........
fun <- env[[ rawToChar( rev( charToRaw( blurb)))]]
e <- new.env( parent=env)
e$fun <- fun
environment( fun) <- e
body( fun) <- quote( {
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- environment( sys.function())$fun
eval.parent( mc)
})
return( fun)
}
"create.backups" <-
function( pos=1) {
pos <- as.env( pos)
if( is.null( t <- attr( pos, 'path')))
stop( "Don't know what path to use for search environment:" %&% pos)
mkdir( file.path( t, '.Backup.mvb'))
fob <- read.bkind( t)
# changed 5/4/2005 for speed with mcache
cand <- lsall( pos) %SUCH.THAT% !bindingIsActive( ., env=pos)
cand <- cand %SUCH.THAT% (mode(.)=='function')
sapply( cand %except% fob$object.names, deal.with.backups, where=pos)
invisible( NULL)
}
"create.bkind.if.needed" <-
function( dir) {
dir <- file.path( dir, '.Backup.mvb')
if( !is.dir( dir ))
try( mkdir( dir))
if( !is.dir( dir))
return('') # mucho problemo
index.file <- file.path( dir, "index")
if(!file.exists(index.file))
file.create(index.file)
index.file
}
"create.wrappers.for.dll" <-
function( this.dll.info, ns=new.env( parent=parent.frame(2))) {
###################
# 'ns' is normally a namespace, but can be any old env for devel purposes
dll.name <- unclass( this.dll.info)$name
dll.env <- new.env( parent=ns) # will return empty if no registrands
routs <- getDLLRegisteredRoutines( this.dll.info)
n.routs.by.callmech <- sapply( routs, length)
if( sum( n.routs.by.callmech)) {
for( irout.class in names( n.routs.by.callmech %except% 0)) {
# eg C_myrout; prefix is C or Call or F or Ext
rout.class.prefix <- sub( 'ortran|ernal', '', sub( '.', '', irout.class)) %&% '_'
for( irout in seq_along( routs[[ irout.class]])) {
# Might be slightly faster to just use this.un$address, but limiting
this.un <- routs[[ irout.class]][[ irout]]
dll.env[[ rout.class.prefix %&% this.un$name]] <- this.un
}
}
}
return( dll.env)
}
"cull.old.builds" <-
function( pkg, character.only=FALSE) {
##################
set.pkg.and.dir( FALSE) # just to deal with 'pkg'
zipdirs <- dir( dir., # dir( attr( maintained.packages[[ pkg]], 'path'),
pattern='^[rR][0-9]+', full.names=TRUE, include.dirs=TRUE) %such.that% is.dir( .)
for( izipdir in zipdirs) {
tarballs <- dir( izipdir, pattern=sprintf( '^%s_([0-9]+[.])+tar[.]gz$', pkg))
tarver <- numeric_version( sub( '.*_', '', sub( '.tar.gz', '', tarballs, fixed=TRUE)))
zippos <- dir( izipdir, pattern=sprintf( '^%s_([0-9]+[.])+zip$', pkg))
zipver <- numeric_version( sub( '.*_', '', sub( '.zip', '', zippos, fixed=TRUE)))
maxver <- max( c( zipver, tarver))
unlink( file.path( izipdir, zippos[ zipver < maxver]))
unlink( file.path( izipdir, tarballs[ tarver < maxver]))
}
invisible()
}
"current.source" <-
function() {
cs <- stdin()
if (exists("source.list", "mvb.session.info")) {
sl <- get("source.list", "mvb.session.info")
if( length( sl)) {
cs <- sl[[ length( sl)]]
attr( cs, 'source.list.num') <- length( sl) # so we know..!
}
}
return( cs)
}
"deal.with.backups" <-
function( name, where) {
infeasible.R.line <- "'\"@\"@'@ START OF BACKUP @'@\"@\"'"
backup.fix <- getOption( "backup.fix", c( 0, 0))
if( backup.fix[1] == 0)
return()
where <- as.env( where)
bdd <- attr( where, "path")
if( !nchar( create.bkind.if.needed( bdd))) {
warning( "Can't create backup directory!")
return() }
filename <- get.bkfile( name, bdd, create = TRUE)
ow <- options( warn = -1)
previous.backups <- readLines( filename)
options( ow)
char.type <- !has.source( where[[name]])
if( length( previous.backups)) {
line.breaks <- index( previous.backups == infeasible.R.line)
if( char.type) {
# Line after infeasible is number of lines until next infeasible
next.break <- line.breaks <- line.breaks[ 1]
repeat{
next.break <- next.break + 3 +
as.numeric( previous.backups[ next.break+2])
if( next.break > length( previous.backups))
break
if( previous.backups[ next.break] != infeasible.R.line) {
warning( "Stuffed backup for " %&% name %&% "; keeping extra stuff")
break
}
line.breaks <- c( line.breaks, next.break)
}
}
if( !length( line.breaks))
previous.backups <- character( 0)
else
discard.mouldering.backups()
}
cat( c( previous.backups, infeasible.R.line, "SESSION=" %&% unclass( session.start.time)),
file = filename, sep = "\n")
if( where[[name]] %is.a% 'function')
write.sourceable.function( where[[ name]], filename, append = TRUE,
print.name = TRUE, xn=name)
else if( char.type)
cat( length( where[[name]]), where[[name]], file=filename, sep='\n', append=TRUE)
else # general
cat( '`' %&% name %&% '` <- local(',
attr( where[[name]], 'source'), ') # end local', file=filename, sep='\n', append=TRUE)
}
"demlazy" <-
function( ..., what, envir=.GlobalEnv) {
if( missing( what))
what <- sapply( match.call( expand.dots=FALSE)$..., deparse)
envir <- as.env( envir)
mcache <- attr( envir, 'mcache')
what <- what %such.that% (. %in% names( mcache))
if( !length( what))
return()
for( i in what) {
temp <- envir[[ i]]
remove( list=i, envir=envir)
envir[[ i]] <- temp
}
fp <- attr( envir, 'path')
if( getOption( 'mlazy.subdir', TRUE))
fp <- file.path( fp, 'mlazy')
file.remove( file.path( fp, 'obj' %&% abs( mcache[ what]) %&% '.rda'))
attr( envir, 'mcache') <- mcache %without.name% what
invisible( NULL)
}
"deparse.names.parsably" <-
function( x) {
if( typeof( x)=='symbol')
'as.name("' %&% as.character( x) %&% '")'
else
deparse( x)
}
"discard.mouldering.backups" <-
function (nlocal = sys.parent())
mlocal({
if (line.breaks[1] > 1) {
previous.backups <- previous.backups[line.breaks[1]:length(previous.backups)]
line.breaks <- line.breaks - line.breaks[1] + 1
}
keepo <- rep(TRUE, length(line.breaks))
prev.times <- sapply(strsplit(previous.backups[line.breaks +
1], "=", fixed=TRUE), function(x) as.numeric(paste(x[-1],
collapse = "")))
old.sessions <- unique(prev.times) %except% session.start.time
if (length(old.sessions) > backup.fix[2])
old.sessions <- rev(sort(old.sessions))[1 %upto% backup.fix[2]]
keepo <- keepo & (prev.times %in% c(old.sessions, session.start.time))
is.this.session <- prev.times == session.start.time
if (sum(is.this.session) >= backup.fix[1])
keepo <- keepo & (!is.this.session | (cumsum(is.this.session) >
sum(is.this.session) + 1 - backup.fix[1]))
copy.lengths <- diff(c(line.breaks, length(previous.backups) +
1))
keepo <- rep(keepo, copy.lengths)
previous.backups <- previous.backups[keepo]
})
"ditto.list" <-
function( ...){
mc <- as.list( match.call( expand.dots=TRUE)[-1])
nondit <- sapply( mc, function( x) !is.name( x) || nzchar( x))
mc[ nondit] <- lapply( mc[ nondit], eval, envir=parent.frame())
mc[ !nondit] <- unname( mc[ findInterval( index( !nondit), index( nondit))])
return( mc)
}
"do.in.envir" <-
function( fbody, envir=parent.frame(2)) {
ff <- sys.function( sys.parent())
body( ff) <- substitute( fbody)
environment( ff) <- envir
cc <- sys.call( sys.parent())
cc[[1]] <- ff
eval.parent( cc, 2)
}
"do.on" <-
function( x, expr, ..., simplify=TRUE){
fungo <- function( .) bod
l <- list( ...)
environment( fungo) <- if( length( l))
list2env( l, parent=parent.frame())
else
parent.frame()
body( fungo) <- substitute( expr)
if( is.atomic( x) && is.null( names( x)))
x <- named( x)
sapply( x, fungo, simplify=simplify)
}
"doc2Rd" <-
function( text, file=NULL, append=formals(cat)$append, warnings.on=TRUE, Rd.version=NULL,
def.valids=NULL, check.legality=TRUE) {
###############################
if( is.function( text)) {
forig <- text
text <- attr( text, 'doc')
stopifnot( is.character( text))
} else
forig <- NULL
class( text) <- NULL
# Enforce PERL syntax in regexes
for( regexo in cq( grep, grepl, sub, gsub, regexpr, gregexpr)) {
ff <- get( regexo)
formals( ff)$perl <- quote( !fixed)
formals( ff)$useBytes <- TRUE
assign( regexo, ff, envir=sys.frame( sys.nframe()))
}
if( is.null( Rd.version))
Rd.version <- if( getRversion() >= '2.10.0') '2' else '1'
is.Rd2 <- numeric_version( Rd.version) >= '2'
# Fucken syntax fucken change, thanks R
if( 'keep.source' %not.in% names( formals( parse))) {
formals( parse) <- c( formals( parse), alist( keep.source=TRUE))
}
# ... and for 'subco' (which uses Rd.version, for example)
subco <- subco
environment( subco) <- sys.frame( sys.nframe())
# Strip EOL whitespace
text <- sub( ' +$', '', text)
# ... and tabs...
text <- gsub( '\t', ' ', text)
# Pre-empt backslash and brace woes-- Rdoc 1 is very buggy about this
notcom <- grep( '^[^%]', text)
# if( !is.Rd2) ??
text[notcom] <- gsub( '\\', '\016', text[notcom], fixed=TRUE) # now leave til end
text[notcom] <- gsub( '{', '\020', text[notcom], fixed=TRUE)
text[notcom] <- gsub( '}', '\021', text[notcom], fixed=TRUE)
# Code blocks first: indent all contents by 2. This stops capitalized words in codeblocks from becoming sections
cbstart <- index( text=='%%#')+1
if( length( cbstart)) {
cbend <- index( !nzchar( text))
cbend <- cbend[ findInterval( cbstart, cbend)+1]-1
cblines <- unlist( mapply( seq, from=cbstart, to=cbend, SIMPLIFY=FALSE))
text[ cblines] <- ' ' %&% text[ cblines]
}
# Check for completely informal doco...
if( !match( 'DESCRIPTION', text, 0) && !match( 'Description:', text, 0)) {
if( warnings.on)
cat( "Looks like informal doco to 'doc2Rd', in " %&% text[1] %&% '\n')
if( !nzchar( sub( ' +', '', text[1])))
text <- c( 'INFORMAL DOCO', text)
first.blank <- index( !nzchar( text))[1]
if( is.na( first.blank)) {
if( warnings.on)
warning( "No blank lines-- so no aliasses will be set")
text <- c( text[ 1], '', text[-1])
first.blank <- 2
}
# Prepare to ignore other section-like lines-- just bold them
seclines <- grep( '^([.]*[A-Z][a-z0-9 ]*[a-zA-Z0-9])(\\([Ss]\\))?:$', text)
text[ seclines] <- '*' %&% seclines %&% '*'
seclines <- grep( '^[.]*[A-Z][A-Z0-9.]+(\\(S\\))?$', text)
text[ seclines] <- '*' %&% seclines %&% '*'
# Add DESCRIPTION field, containing everything:
text <- multinsert( text, first.blank, list( c( 'Documentation for ' %&% text[1], '',
'DESCRIPTION', '')))
if( !is.null( forig)) {
text <- c( text, '', 'USAGE', '', '# This section is machine-generated...',
sub( '^ *([^ ]+) .*', '\\1', text[1]) %&% sub( '^NULL$', '()',
sub( 'list', '', deparse( formals( forig)))))
if( length( formals( forig)))
text <- c( text, '', 'ARGUMENTS', '', 'This section is machine-generated...',
paste( ' ', names( formals( forig)), ': ???', sep=''))
}
}
# Global sub of colonized section & subsection titles to caps
first.blank <- index( !nzchar( text))[1]
seclines <- grep( '^[.]*[A-Z][a-zA-Z0-9.]*[a-zA-Z0-9](\\([Ss]\\))?:$', text)
seclines <- c( seclines, grep(
'^[.]*[A-Z][A-Z0-9.-][A-Z0-9]+(\\([Ss]\\))?$', text)) %such.that% (. > first.blank)
text[ seclines] <- toupper( sub( '(\\([Ss]\\))?:?$', '', text[ seclines]))
# Global sub of refs to (sub)section titles-- AUTHOR(S) as well as AUTHOR
# .. subsections are like sections, but the line starts with 1 or more periods
sectitles <- grep( '^[.]*[A-Z][A-Z0-9.-]+[A-Z0-9]$', text, value=TRUE)
for( secti in sectitles) {
# No leading dots
short.secti <- sub( '^[.]*', '', secti)
# How xref appears in flat-format doco
rss <- '\\b' %&% to.regexpr( short.secti) %&% '($|\\W)'
# How it will look in Rd; bolded, first char Upper, rest lower
xref <- '*' %&% toupper( substring( short.secti, 1, 1)) %&%
tolower( gsub( '.', ' ', substring( short.secti, 2), fixed=TRUE)) %&%
'*\\2'
xref2 <- sub( '2$', '3', xref) # cases when a 2nd optional paren is used
# "in MYSECTION"
text <- gsub( '\\b([Ii])n ' %&% rss,
'\\1n ' %&% xref,
text)
# "under MYSECTION"
text <- gsub( '\\b([Uu])nder ' %&% rss,
'\\1nder ' %&% xref,
text)
# "as per MYSECTION"
text <- gsub( '\\b([Aa])s per ' %&% rss,
'\\1s per ' %&% xref,
text)
# "See MYSECTION" and "see also MYSECTION"
text <- gsub( '\\b([Ss])ee (also )?' %&% rss,
'\\1ee \\2' %&% xref2,
text)
# "The MYSECTION section"; NB no afterspace because of \\W
text <- gsub( '\\b([Tt])he ' %&% rss %&% 'section',
'\\1he ' %&% xref %&% 'section',
text)
# "Section MYSECTION" and "section on MYSECTION"
text <- gsub( '\\b([Ss])ection (on )?' %&% rss,
'\\1ection \\2' %&% xref2,
text)
# "MYSECTION (qv)"; NB no afterspace
text <- gsub( rss %&% ' *\\(qv\\)',
xref,
text)
# "MYSECTION (see below)"; NB no afterspace
text <- gsub( rss %&% ' *\\(see below\\)',
xref %&% '[(]see below[)]',
text)
} # for sectitles
#tcon <- textConnection( text)
#on.exit( close( tcon))
lptr <- 0
nlines <- length( text)
Rd <- character( 0)
EOF <- FALSE
# Definitions:
verbatim <- function( string) {
string <- gsub( '\\', '\001', string, fixed=TRUE)
string <- gsub( '{', '\\{', string, fixed=TRUE)
string <- gsub( '}', '\\}', string, fixed=TRUE)
string <- gsub( '%', '\\%', string, fixed=TRUE)
string <- gsub( '\001', '\\\\', string, fixed=TRUE)
string
}
maxchar <- c( usage=80, synopsis=80, examples=100)
out <- function( string, string2, strip.spaces.at.start=FALSE) {
# length( string)>1 with keyword blocks
if( length( string)==1 && grepl( '^subsection[{]', string)) {
new.nesting <- nchar( sub( 'subsection[{]([.]*).*', '\\1', string))
new.nesting <- min( new.nesting, nesting + 1)
string <- sub( '[{][.]*', '{', string)
} else
new.nesting <- 0
if( new.nesting <= nesting)
Rd <<- c( Rd, rep( '}', 1+nesting-new.nesting))
nesting <<- new.nesting
if( !missing( string2)) {
if( strip.spaces.at.start)
string2 <- sub( '^ +', '', string2)
string <- if( length( string2)==1)
paste( '\\', string, '{', string2, sep='') # no closing brace
else
c( '\\' %&% string %&% '{', string2) # no closing brace
} else
string[ length( string)] <- sub( '[}] *$', '', string[ length( string)]) # final keyword
Rd <<- c( Rd, string)
} # out function
line <- function( skip.blanks=TRUE, do.subs=TRUE, auto.link=FALSE, uncomment=TRUE, valid.links=NULL) {
repeat{
# line <- readLines( tcon, 1)
# if( !length( line)) {
# return( line)
# }
if( lptr==nlines) {
EOF <<- TRUE
return( character(0))
}
lptr <<- lptr+1
line <- text[ lptr]
if( uncomment && substring( line, 1, 1)=='%')
return( substring( line, 2)) # unmodified apart from removing %
line <- sub( ' +$', '', line) # strip spaces at the end
if( uncomment)
line <- gsub( '%', '\\%', line, fixed=TRUE)
if( !skip.blanks || nzchar( line))
break
}
if( do.subs)
line <- subco( line, auto.link=auto.link, valid.links=def.valids)
line
}
block <- function( do.subs=TRUE, bs17=FALSE, blank.stop=FALSE, auto.link=FALSE, Rd2.Rlike=FALSE,
width=NA, methodize=FALSE) {
#############
block <- character( 0)
repeat{
new.line <- line( do.subs=do.subs, skip.blanks=!blank.stop, auto.link=auto.link,
valid.links=def.valids)
if( EOF)
break
if( blank.stop && !nzchar( new.line))
break
# Check for field names
if( length( grep( '^[.]*[A-Z][A-Z0-9.-]+(\\(S\\))?$', new.line))) {
# replace AUTHOR(S) by AUTHOR
#pushBack( sub( '(S)', '', new.line, fixed=TRUE), tcon)
text[ lptr] <- sub( '(S)', '', new.line, fixed=TRUE)
lptr <<- lptr-1
break
}
# Pre-formatted?
if( !bs17 && substring( new.line, 1, 2)=='%#') {
pref.block <- block( do.subs=FALSE, bs17=TRUE, blank.stop=TRUE)
# All into one line for now...
block <- c( block, paste( c( '\\preformatted{', pref.block, '}'), collapse='\n'))
} else
block <- c( block, new.line)
}
if( bs17) {
# Flag backslashes and braces for different treatment in verbatim-style bits
# Same thing happens in 'line' inside code blocks
block <- gsub( '\016', '\017', block, fixed=TRUE)
block <- gsub( '\020', '\022', block, fixed=TRUE)
block <- gsub( '\021', '\023', block, fixed=TRUE)
}
if( Rd2.Rlike) {
block <- gsub( '\016', '\\', block, fixed=TRUE) # now leave til end
block <- gsub( '\020', '{', block, fixed=TRUE)
block <- gsub( '\021', '}', block, fixed=TRUE)
block <- make.Rd2( block, width=width, methodize=methodize)
}
block
}
insert.para.breaks <- function( block) {
if( length( block)>1) {
n <- length( block)
block <- rep( block, each=2)
block[ 2*(1:n)] <- ''
block <- block[ -2*n]
}
block
}
itemize <- function( block) {
# Unlabelled (bulleted) lists
while( length( block) && length( items <- index( grepl( '^ +[*-] ', block)))) {
n.items <- min( index( diff( c( items, length(block)+5)) %!in% 1:2))
# Start \itemize{
block <- multinsert( block, items[1]-1, '\\itemize{')
items <- items + 1 # to allow for the new \\itemize{ line
if( n.items>1) # zap any blank lines between items
block <- block[ -( items[1]:items[n.items] %except% items[1:n.items])]
# Add \item
items <- items[1]+(1:n.items)-1
block[ items] <- '\\item ' %&% sub( '^ +[*-] ', '', block[ items])
# End with back-brace for \itemize
block <- multinsert( block, items[ n.items], '}')
}
# Labelled lists, e.g. value: result
while( length( block) && length( items <- index( grepl( '^ +[^:]*: ', block)))) {
n.items <- min( index( diff( c( items, length(block)+5)) %!in% 1:2))
# Start \describe{
block <- multinsert( block, items[1]-1, '\\describe{')
items <- items + 1 # to allow for the new \\describe{ line
if( n.items>1) # zap any blank lines between items
block <- block[ -( items[1]:items[n.items] %except% items[1:n.items])]
# Add \item{label}{body}
items <- items[1]+(1:n.items)-1
block[ items] <- '\\item{' %&% sub( '^ +([^:]*): +', '\\1}{', block[ items]) %&% '}'
# End with back-brace for \describe
block <- multinsert( block, items[ n.items], '}')
}
block
}
list.block <- function( sub.item.names=FALSE, auto.link=FALSE) {
block <- character( 0)
repeat{
new.line <- line( do.subs=FALSE) # subs done later
if( EOF)
break
# Check for field names
if( length( grep( '^[.]*[A-Z][A-Z0-9.-]+$', new.line))) {
#pushBack( new.line, tcon)
text[ lptr] <- new.line
lptr <<- lptr-1
break
}
# Check for list item: line starts with space, then comma-separated words ending with a colon
if( grepl( '^ ', new.line)) {
# NB: whole item text is assumed to be on one line
item <- strsplit( new.line, ': ')[[1]]
item[1] <- if( sub.item.names) subco( item[1]) else gsub( "'", '', item[1])
new.line <- paste( '\\item{', item[1], '}{',
subco( paste( item[ -1], collapse=':')), '}', sep='')
} else
new.line <- subco( new.line, auto.link=auto.link, valid.links=def.valids)
block <- c( block, new.line)
}
block
}
seealso.block <- function() {
block <- ' ' %&% block() %&% ','
block <- block[ !grepl( '^%', block)] # comment lines
# Strip out anything already in \code{}...
block <- gsub( '\\\\code\\{([^}]*)\\}', "'\\1'", block)
# ...and put single words ended by comma or semicolon into \code{\link{}}
block <- gsub( " ([a-zA-Z.][---a-zA-Z.0-9]*)('*)[,;]",
' \\\\code\\{\\\\link\\{\\1\\}\\}\\2,', block)
# ...and strip quotes around these
block <- gsub( "'(\\\\code\\{\\\\link\\{[^}]*\\}\\})'", '\\1', block)
# ... and any remaining quotes back into \code{}
block <- gsub( " '([^']+)'", " \\\\code\\{\\1\\}", block)
block <- substring( block, 1, nchar( block)-1)
block
}
keyword.block <- function() {
block <- block()
block <- grep( '^[^%]', block, value=TRUE) # drop comment lines
block <- paste( block, collapse=' ')
block <- gsub( '[,;]', ' ', block)
block <- gsub( ' +', ' ', block)
block <- strsplit( block, ' ')[[ 1]]
block[ nchar( block) > 0]
}
nice.title <- function( section.title) {
# Now handles subsections too, which start with a sequence of periods
# section.title <- gsub( '\\.', ' ', section.title)
# substring( section.title, 1, 1) <- upper.case( substring( section.title, 1, 1))
section.title <- sub( '^([.]*)(.)', '\\1\\U\\2', section.title, perl=TRUE)
section.title <- sub( '^([.]*).*', '\\1', section.title) %&%
gsub( '.', ' ', sub( '^[.]*', '', section.title), fixed=TRUE)
section.title
}
sectionize <- function( niced.up.title) {
field.name <- if( substring( niced.up.title, 1, 1) == '.') 'subsection' else 'section'
sprintf( '%s{%s}', field.name, niced.up.title)
}
# fields <- cq( description, usage, synopsis, arguments, arguments., value, details, examples,
# author, references, note, see.also, keywords)
# fields <- c( fields, 'author(s)')
# Code starts here
nesting <- -1
name <- strsplit( line(), ' ')[[1]][1]
out( 'name', name)
overall.name <- name
if( is.package <- grepl( '\\-package', name))
out( 'alias', sub( '\\-package.*', '', name))
while( nzchar( name)){
if( !is.null( def.valids))
def.valids <- def.valids %except% name # don't link to myself
out( 'alias', verbatim( name), strip.spaces.at.start=TRUE)
name <- line( FALSE, FALSE, uncomment=FALSE)
}
if( is.package)
out( 'docType', 'package')
if( is.data <- match( 'FORMAT', text, 0)>0)
out( 'docType', 'data')
out( 'title', line( do.subs=FALSE)) # no special stuff allowed in title
# Itemizing rules are:
# - don't use \code subs in item names in VALUE or ARGUMENTS
# - optional to use it in other fields
# - don't use \itemize except for unnamed bullet-point lists (like this para)
while( !EOF) {
next.field <- tolower( line())
if( EOF)
break
switch( next.field,
description=,
details=,
author=,
"author(s)"=,
references=,
format=,
source=,
note= out( next.field, itemize( insert.para.breaks( block( auto.link=!is.null( def.valids))))),
examples=,
synopsis=,
usage= out( next.field,
block( do.subs=FALSE, Rd2.Rlike=is.Rd2, bs17=!is.Rd2, width=maxchar[ 'usage'],
methodize=(next.field=='usage'))),
see.also= out( 'seealso', insert.para.breaks(
block( auto.link=!is.null( def.valids)))), #seealso.block())),
value=,
arguments= out( next.field, list.block(FALSE, auto.link=!is.null( def.valids))),
keywords= out( '\\keyword{' %&% keyword.block() %&% '}'),
out( sectionize( nice.title( next.field)),
#out( 'section{' %&% nice.title( next.field) %&% '}',
itemize( insert.para.breaks( block( auto.link=!is.null( def.valids)))))
)
# For user's own sections, used to have
# if( regexpr( '\\.$', next.field)<0)
# itemize( insert.para.breaks( block()))
# else
# list.block(TRUE))
# but it didn't work with funny characters anyway
} # while new field
Rd <- c( Rd, rep( '}', 1+nesting))
# Rd <- Rd[ nchar( Rd)>0]
Rd <- setup.dontruns( Rd)
# Already methodized USAGE
# methodize.USAGE() # sigh
# \keywords{} is mandatory...
if( !length( grep( '^\\\\keyword\\{', Rd)))
Rd <- c( Rd, '\\keyword{' %&% (if( is.data) 'data' else 'misc') %&% '}')
# Split \preformatted; don't zap blanks
preflines <- grep( '\n', Rd, fixed=TRUE)
Rd <- multirep( Rd, preflines, strsplit( Rd[ preflines], '\n'))
if( is.Rd2) {
Rd <- gsub( '\016', '\\\\', Rd, fixed=TRUE)
Rd <- gsub( '\020', '\\{', Rd, fixed=TRUE)
Rd <- gsub( '\021', '\\}', Rd, fixed=TRUE)
# ... and in verbatim bits:
Rd <- gsub( '\017', '\\\\', Rd, fixed=TRUE)
Rd <- gsub( '\022', '{', Rd, fixed=TRUE)
Rd <- gsub( '\023', '}', Rd, fixed=TRUE)
# Fix split one-liners-- not that they need fixing-- this is "improvement" in R 2.12
one.liners <- cq( name, alias, docType, title, author)
olsplit <- grep( '^\\\\(' %&% paste( one.liners, collapse='|') %&% ') *\\{[^}]*$', Rd)
if( length( olsplit))
olsplit <- olsplit[ grepl( '^ *\\} *$', Rd[ olsplit+1])]
if( length( olsplit)){
Rd[ olsplit] <- Rd[ olsplit] %&% '}'
Rd <- Rd[ -(olsplit+1)]
}
} else {
# Old format Rd had problems with some weird-but-legal sequences...
# Restore backslashes & braces in normal text -- get round buggy Rd
Rd <- gsub( '\016', '\\\\\\enc{}{}', Rd, fixed=TRUE)
Rd <- gsub( '\020', '\\{\\enc{}{}', Rd, fixed=TRUE)
Rd <- gsub( '\021', '\\}\\enc{}{}', Rd, fixed=TRUE)
# ... and in verbatim bits:
Rd <- gsub( '\017', '\\\\\\link{}', Rd, fixed=TRUE)
Rd <- gsub( '\022', '\\{\\link{}', Rd, fixed=TRUE)
Rd <- gsub( '\023', '\\}\\link{}', Rd, fixed=TRUE)
reduce.empty.links() # minimize offence to Rcmd check...
}
if( !is.null( file))
cat( Rd, sep='\n', file=file, append=append)
Rd <- as.cat( Rd)
if( is.Rd2 && check.legality && getRversion() >= '2.10.0') {
# parse_Rd unreliable in 2.9.x so only do this in 2.10 onwards, regardless of Rd.version
ow <- options( warn=2)
check.file <- tempfile( legal.filename( overall.name))
on.exit( { options( ow); unlink( check.file)}, add=TRUE)
cat( Rd, sep='\n', file=check.file)
p1 <- try( parse_Rd( check.file)) # warning => error
if( p1 %is.a% 'try-error')
class( Rd) <- c( 'try-error', class( Rd))
}
return( Rd)
}
"dochelp" <-
function( topic, doc, help_type=c( 'text', 'html')) {
# "doc" might point to another object. Start by looping til we have a character "doc".
current.topic <- topic
if( missing( doc)) { # TRUE unless this is being used as a pager
doc <- 0
while( !is.character( doc) && exists( current.topic) &&
length( doc <- attr( get( current.topic), 'doc')))
if( is.list( doc))
current.topic <- doc[[1]] # unwrap list
# If no functions/things with such doco, look for a 'thing.doc' character object
if( !is.character( doc)) {
for( ext in c( '', '.doc')) {
t1 <- topic %&% ext
if( exists( t1, mode='character'))
doc <- get( t1, mode='character')
break
}
}
}
fff <- FALSE # default
if( has.doc <- is.character( doc)) {
help_type <- try( match.arg( help_type))
if( help_type %is.a% 'try-error')
help_type <- 'text'
if( help_type=='html') {
help_type <- 'text' # in case we fail
if( !nzchar( sub( ' +', '', doc[1])))
doc <- c( topic, doc)
drd <- try( doc2Rd( doc, warnings.on=FALSE))
if( drd %is.not.a% 'try-error') {
tf1 <- tempfile()
fff <- tf1 %&% '.html' # will get class 'browsertemp', and be autoprinted
tf1 <- tf1 %&% '.Rd'
on.exit( try( unlink( tf1)), add=TRUE)
cat( drd, file=tf1, sep='\n')
drd <- try( Rd2HTML( tf1, fff))
if( drd %is.not.a% 'try-error') {
# All good-- no need for pager fallback
help_type <- 'html'
}
}
}
if( help_type=='text') {
fff <- tempfile()
doc <- doc[ regexpr( '^%', doc) < 0] # drop "%" lines
doc <- strsplit( doc, '\n')
doc[ !sapply( doc, length)] <- ''
doc <- strwrap( unlist( doc), simplify=FALSE)
doc[ !sapply( doc, length)] <- ''
# writeLines( paste( unlist( doc), collapse='\n'), con=fff) # writelines seems to zap empty lines
cat( paste( unlist( doc), collapse='\n'), file=fff)
names( fff) <- topic
}
class( fff) <- if( help_type=='text') 'pagertemp' else 'browsertemp'
}
# invisible( has.doc) changed for 2.x
invisible( fff)
}
"docotest" <-
function( fun.or.text, ...) {
doco <- doc2Rd( fun.or.text)
tf <- tempfile( fileext='.Rd')
tf2 <- tempfile( fileext='.html')
on.exit( unlink( tf)) # can't unlink tf2 because browser might still need it
cat( doco, file=tf, sep='\n')
ok <- try( Rd2HTML( tf, tf2, ...))
if( ok %is.not.a% 'try-error') {
browseURL( tf2)
} else {
unlink( tf2) # might as well
}
invisible( NULL)
}
"docskel" <-
structure( function( x=NULL, char.x=NULL, env=.GlobalEnv, assign.=FALSE){
if( !identical( env, .GlobalEnv)) {
env <- as.environment( env)
pkg <- sub( 'package:', '', attr( env, 'name'))
} else
pkg <- 'not-yet-a-package'
if( is.null( char.x)) {
sx <- substitute( x)
if( is.call( sx)) {
x <- as.character( sx)
if( x[1] %not.in% c( '::', ':::') || length( x)<3)
stop( "Don't know how to fixr '" %&% deparse( sx) %&% "'")
pkg <- x[2]
char.x <- x[3]
if( any( search()==pkg))
env <- as.environment( pkg)
else if( is.null( env <- maintained.packages[[ pkg]])) {
if( any( search()=='package:' %&% pkg))
env <- as.environment( 'package:' %&% pkg)
else if( pkg %in% loadedNamespaces())
env <- asNamespace( pkg)
else
stop( "Package '" %&% pkg %&% "' not available")
}
} else
char.x <- deparse( sx)[1]
}
if( is.null( x))
x <- env[[ char.x]]
text <- c( paste( char.x, " package:", pkg, "\n", sep=''), attr( sys.function(), 'att1'),
make.usage.section( char.x, NULL, env))
if( length( formals( x)))
text <- c( text, attr( sys.function(), 'att2'), make.arguments.section( char.x, NULL, env))
text <- c( text, attr( sys.function(), 'att3'))
#text <- unlist( strsplit( text, '\n'))
if( assign.) {
class( text) <- 'docattr'
attr( x, 'doc') <- text
env[[ char.x]] <- x # will do the assign for real...
}
class( text) <- 'cat'
text
}
, att1 = structure(c("", "Do something-or-other", "", "DESCRIPTION", "", "A splendid function that does something jolly useful", "", "", "USAGE", "", "# This section is a formal requirement, and as such often isn't useful...", "# ...in showing how to use the function(s). You can show more realistic usages...", "# ...in comment lines, and/or refer to the EXAMPLES section.", ""), class = "docattr")
, att2 = structure(c("", "ARGUMENTS", "", "You can put normal text in ARGUMENTS, too, like this. Remember to indent all arguments, as below.", ""), class = "docattr")
, att3 = structure(c("", "VALUE", "", "Immense. NB this section isn't compulsory.", "", "", "DETAILS", "", "Not compulsory. Other section headings, e.g. AUTHOR, should also go here. Use *single* quotes around object names and code fragments, e.g. 'bit.of.code()'. Use *double* quotes for \"text\" or \"file.name\". See 'doc2Rd' for full details of format.", "", "", "SEE.ALSO", "", "'doc2Rd', 'flatdoc'", "", "", "EXAMPLES ", "", "# Not compulsory to have an EXAMPLES -- you can put examples into other sections.", "# Here's how to make a \"don't run\" example:", "", "## Don't run", "reformat.my.hard.drive()", "## End don't run", "", "", "KEYWORDS", "", "%% You can delete the KEYWORDS section-- it will be auto-added by 'doc2Rd'", "%% These lines starting with \"%%\" won't appear in user-visible help.", "", "misc"), class = "docattr")
)
"dont.lock.me" <-
function( env=environment( sys.function( -1))){
assign.to.base( 'lockEnvironment', hack.lockEnvironment())
attr( env, 'dont.lock.me') <- TRUE
}
"dont.lockBindings" <-
function( what, pkgname, namespace.=TRUE) {
# cat( 'dlb on ', what, 'in', pkgname, 'with namespace=', namespace., '\n')
what <- what # force ??
# Used to have mvbutils:::untetherBalloon below, but u.B. should be found automatically
# ... now putting it back in because that didn't seem to work, but in a CRANpatible way
f <- function( pkgname, pkgpath) 99
if( namespace.)
body( f) <- substitute( sapply( what, untetherBalloon, env=asNamespace( pkgname)),
list( what=what, untetherBalloon=asNamespace( 'mvbutils')$untetherBalloon))
else
body( f) <- substitute( sapply( what, untetherBalloon,
env=as.environment( paste( 'package:', pkgname, sep=''))),
list( what=what, untetherBalloon=asNamespace( 'mvbutils')$untetherBalloon))
environment( f) <- baseenv()
setHook.once( pkgname, if( namespace.) "onLoad" else "attach", f, 'append')
}
"dont.save" <-
function()
getOption("dont.Save", cq( .packageName, .SavedPlots, last.warning, .Last.value, .Traceback))
"dos.or.windows" <-
function ()
.Platform$OS.type == "windows"
"empty.data.frame" <-
function (...) {
mc <- as.list(match.call()[-1])
m <- sapply(mc, mode)
is.a.name <- m == "name"
is.a.name[is.a.name] <- !nzchar(as.character(mc[is.a.name]))
mc[is.a.name] <- mc[!is.a.name][(cumsum(!is.a.name) + 1)[is.a.name]]
df <- do.call("list", mc)
# df <- do.call("list", mc)
# df <- as.data.frame.I(df)
mc$stringsAsFactors <- FALSE
df <- do.call( 'data.frame', mc)
df <- df[-(1:nrow(df)), , drop = FALSE]
df
}
"env.name.string" <-
function( env){
stopifnot( env %is.an% 'environment')
namio <- attr( env, 'name')
if( is.null( namio))
namio <- names( attr( env, 'path'))
namio <- if( is.null( namio) || !is.character( namio) || length( namio)<1) '' else namio[1]
namio <- namio %&% capture.output( print( env))[1]
return( namio)
}
"eval.scriptlet" <-
function (expr, envir = parent.frame(), enclos = if (is.list(envir) ||
is.pairlist(envir)) parent.frame() else baseenv()){
force( envir)
force( enclos)
eval( expr, envir, enclos)
}
"everyth" <-
function( x, by=1, from=1)
x[ seq( from=from, by=by, length=(length( x)-from+by) %/% by)]
"expand.match" <-
function( short, long, any.case=FALSE) {
# Expands unique partial matches of 'short' in 'long'.
# Leaves non-matches or non-uniques alone
if( any.case)
i <- pmatch( toupper( short), toupper( long), duplicates.ok=TRUE)
else
i <- pmatch( short, long, duplicates.ok=TRUE)
short[ !is.na( i)] <- long[ i[ !is.na(i)]]
# short[ is.na( i)] <- NA
short
}
"expanded.call" <-
function( nlocal=sys.parent()) mlocal(
lapply( named( names( formals( sys.function( mvb.sys.nframe())))), function( x) eval( as.name( x)))
)
"extract.named" <-
function( l, to=parent.frame()) {
n <- names( l)
for( i in n[ nchar( n)>0])
assign( i, l[[ i]], envir=to)
}
"fast.read.fwf" <-
function( file, width,
col.names=if( !is.null( colClasses)) names( colClasses) else 'V' %&% 1:ncol( fields),
colClasses=character(0), na.strings=character(0L), tz='', ...) {
fs <- file.info( file)$size
if( is.na( tail( width, 1))) {
# Determine padding at EOL experimentally
lengo <- 2*sum( abs( width))
repeat {
if( lengo > fs)
stop( "Can't find enough newlines")
reado <- readChar( file, lengo)
fullw <- regexpr( '\\n', reado, 0)
if( fullw > 0)
break
lengo <- lengo * 2
}
width <- c( clip( width), -( fullw - sum( abs( clip( width)))))
} else if( tail( width, 1) < 0)
width <- c( clip( width), tail( width, 1) - 1) # EOL char
else
width <- c( width, -1) # 1 char for EOL
acw <- abs( width)
nl <- fs %/% sum( acw)
if( fs %% sum( acw) != 0)
stop( "Line length mismatch")
fields <- readChar( file, rep( acw, nl))
dim( fields) <- c( length( width), nl)
fields <- t( fields[ width>0,])
dimnames( fields)[[2]] <- col.names
df <- data.frame( matrix( 0, nl, 0)) # must have correct number of rows
# For col classes, methods package may be needed, but
# ...if so will usually have been loaded already, and
# ...if not we don't want to bother
# Defeat the RCMD CHECK NANNY which is getting a bit bloody above itself
libr.sodding.ary <- library
methas <- if( 'package:methods' %in% search()) get( 'as', 'package:methods') else
function( x, y) { libr.sodding.ary( methods); {get( 'as', 'package:methods')}(x, y) }
for( fi in col.names)
df[[fi]] <- if (is.na(colClasses[fi]))
type.convert(fields[,fi], as.is = TRUE, dec = '.', na.strings = na.strings)
else if (colClasses[fi] == "factor")
as.factor(fields[,fi])
else if (colClasses[fi] == "Date")
as.Date(fields[,fi])
else if ( grepl( '^POSIXct', colClasses[fi]))
as.POSIXct(fields[,fi], tz=tz, format=sub( '^POSIXct', '', colClasses[fi]))
else methas(data[[fi]], colClasses[fi])
df
}
"FF" <-
function() {
# Check list of filenames to see if they've been updated
new.file.times <- unclass( file.info( fix.list$file)[,'mtime'])
modified <- is.na( new.file.times) | new.file.times!= fix.list$file.time
if( !any( modified))
return( structure( character( 0), for.info='No modifications'))
FF.find.homes() # check that the homes are attached...
if( !any( modified))
return( structure( character( 0), for.info='No modifications (but some updated files)'))
set.srcfilecopy <- function( x, lines) {
sc <- attr( x, 'srcref')
if( !is.null( sc)) {
attr( sc, 'srcfile') <- srcfilecopy( 'dummyfile', lines)
last.line <- max( index( nzchar( lines)))
last.char <- nchar( lines[ last.line])
sc[] <- as.integer( c( 1, 1, last.line, last.char, 1, last.char, 1, last.line))
attr( x, 'srcref') <- sc
}
return( x)
}
old.warn <- options( 'warn')[[1]]
on.exit( options( warn=old.warn))
for( mod in index( modified)) {
name <- unclass( fix.list$name)[ mod]
cat( name, ': ')
stuffed <- FALSE
if( !fix.list$has.source[ mod]) { # grepl( '\\<character\\>', fix.list$dataclass[ mod])) {
ff <- readLines( fix.list$file[ mod])
the.class <- strsplit( fix.list$dataclass[ mod], ',', fixed=TRUE)[[1]] %except% 'character'
if( !length( the.class))
the.class <- 'cat' # print.as.cat
class( ff) <- the.class
cat( 'OK\n')
} else {
# Could be anything...
should.be.func <- grepl( '\\<function\\>', fix.list$dataclass[ mod])
source.code <- readLines( fix.list$file[ mod]) # everything incl. any errors
mt <- new.env( parent=.GlobalEnv) # asNamespace( 'mvbutils')) # limit damage
# code <- try( list( value=source.mvb( fix.list$file[ mod], max.n.expr=1, envir=mt,
# debug.script=!should.be.func)))
code <- try( list( value=source.mvb( fix.list$file[ mod], max.n.expr=1, envir=mt)))
if( code %is.a% 'try-error') {
stuffed <- TRUE
if( should.be.func) {
fftext <- sub( 'I', to.regexpr( name), "function( ...) stop( 'I failed to parse')")
ff <- eval( parse( text=fftext, keep.source=TRUE))
ff <- set.srcfilecopy( ff, source.code) # all lines
environment( ff) <- mt
} else
ff <- list( 'Scriptlet for "' %&% name %&% '" failed to parse')
attr( ff, 'source') <- source.code # otherwise code is lost!!!
} else {
ff <- code$value
if( is.null( ff)) {
warning( 'Scriptlet for "' %&% name %&% '" generates NULL; replacing with list()')
ff <- list()
}
if( !is.function( ff)) {
class( ff) <- c( 'thing.with.source', oldClass( ff))
attr( ff, 'source') <- as.cat( source.code)
}
# Shouldn't need to set srcref or source attributes
cat( 'OK\n')
}
}
# Reset environment of functions. Modified 5/11/2011, to allow 'local()' defs to keep their own envir
if( is.function( ff) && identical( environment( ff), mt) ) {
# Use old environment if available
if( exists( name, mode='function', w[[ mod]], inherits=FALSE))
environment( ff) <- environment( w[[ mod]][[ name]])
else
environment( ff) <- .GlobalEnv # why not?
}
assign(name, ff, w[[ mod]])
if( has.source( ff) || is.character( ff)) # should now work with charvecs too
try( deal.with.backups( name, w[[ mod]])) # ought not to crash, but...
if( !stuffed && mods.in.packages[ mod])
update.loaded.pkg( attr( w[[mod]], 'name'), name, ff)
} # loop over modifiees
autosave <- getOption( 'FF.autosave', FALSE)
for( i in unique( w[ mods.in.tasks | mods.in.packages]))
if( !identical( i, .GlobalEnv) &&
( autosave || yes.no( "Save task '" %&% attr( i, 'name') %&% "'? ")))
Save.pos( i)
answer <- unclass( fix.list$name[ modified])
if( 'package:debug' %in% search() && any( is.traced <- (answer %in% names( tracees)))) {
cat( 'Reapplying trace(s)...')
lapply( answer[ is.traced], mtrace, fname=NULL, # fname=NULL forces char.fname
from=.GlobalEnv, # NOT ideal--- but until "from" is added to trace info, better than the alternative, which goes straight to baseenv
tracing=TRUE)
cat( 'done\n')
}
# fix.list <<- fix.list[ !modified,]
fix.list$file.time <<- new.file.times # doesn't seem to work in one step
answer
}
"FF.find.homes" <-
function( nlocal=sys.parent()) mlocal({
w <- vector( 'list', nrow( fix.list))
mods.in.tasks <- modified & fix.list$where.type=='task'
if( any( mods.in.tasks)) {
stt <- search.task.trees()
where.tasks <- match( fix.list$where, names( stt))
not.here <- mods.in.tasks & is.na( where.tasks) # nowhere to go. Warn?
modified[ not.here] <- FALSE
where.tasks[ not.here] <- NA
use <- modified & !is.na( where.tasks)
w[ use] <- lapply( stt[ where.tasks[ use]], as.env)
}
mods.in.packages <- modified & fix.list$where.type=='package'
if( any( mods.in.packages)) {
task.trees <- sapply( lapply( maintained.packages, attr, which='task.tree'), paste, collapse='/')
where.packs <- match( fix.list$where, task.trees, NA)
not.here <- mods.in.packages & is.na( where.packs)
modified[ not.here] <- FALSE
where.packs[ not.here] <- NA
use <- modified & !is.na( where.packs)
w[ use] <- maintained.packages[ where.packs[ use]]
}
mods.in.attached <- modified & fix.list$where.type=='attached'
if( any( mods.in.attached)) {
where.att <- match( fix.list$where, search(), NA)
not.here <- mods.in.attached & is.na( where.att)
modified[ not.here] <- FALSE
where.att[ not.here] <- NA
use <- modified & !is.na( where.att)
w[ use] <- lapply( where.att[ use], pos.to.env)
}
})
"file.path.as.absolute" <-
function( x) {
# file_path_as_absolute rejects nonexistent paths-- ANNOYING, UNNECESSARY!!
# Another hack required
fpa <- file_path_as_absolute
e <- new.env( parent=environment( fpa))
e$stop <- function( ...) 0
environment( fpa) <- e
fpa( x)
}
"find.and.get" <-
function( nlocal=sys.parent()) mlocal({
if( is.null( pkg)) {
if( new)
num.load.from <- 1
else {
num.load.from <- find( name, numeric=TRUE)[1]
if( is.na( num.load.from)) {
if( length( maintained.packages)) {
mpls <- lapply( maintained.packages, lsall)
m <- sapply( mpls, match, x=name, nomatch=0)
if( sum( m>0)==1)
pkg <- names( maintained.packages)[ m>0] # handle below
else if( sum( m>0)>1)
stop( "'" %&% name %&% "' found in more than one live package ('" %&%
paste( names( maintained.packages)[ m>0], collapse="', '") %&% "'): must specify which one")
}
if( is.null( pkg)) { # can't find anywhere
new <- TRUE
num.load.from <- 1
}
} else if( regexpr( '^package:', search()[ num.load.from])>0) {
# check for maintained version
pkg <- substring( search()[ num.load.from], nchar( 'package:')+1) # handle below
if( is.null( maintained.packages[[ pkg]])) {
if( fixing)
warning( "Reluctantly fixing '" %&% name %&% "' directly in 'package:" %&% pkg %&%
"'-- won't affect any namespace copies and won't be saved",
immediate.=TRUE)
pkg <- NULL
}
}
}
}
if( !is.null( pkg)) { # could be set during last
num.load.from <- NA
if( pkg %is.an% 'environment') # eg ..mypack
pkg <- attr( pkg, 'name')
load.from <- maintained.packages[[ pkg]]
if( is.null( load.from)) {
if( fixing)
stop( "Package '" %&% pkg %&% "' not set up for editing-- see 'maintain.packages'")
else { # just readr something from a loaded package
load.from <- asNamespace( pkg)
name.load.from <- 'package:' %&% pkg
type.load.from <- 'attached'
}
} else {
name.load.from <- paste( attr( load.from, 'task.tree'), collapse='/')
type.load.from <- 'package'
}
new <- new || !exists( name, load.from, inherits=FALSE)
} else { # num.load.from cannot be NA
load.from <- pos.to.env( num.load.from)
if( !is.null( names( attr( pos.to.env( num.load.from), 'path')))) {
name.load.from <- rev( unlist( lapply( num.load.from:length( search()),
function( x) names( attr( pos.to.env( x), 'path')))))
type.load.from <- 'task'
} else {
name.load.from <- search()[ num.load.from]
type.load.from <- 'attached'
}
}
name.load.from <- paste( name.load.from, collapse='/')
trace.was.on <- FALSE
if(!new) {
x <- get( name, load.from)
trace.was.on <- exists( 'tracees', 'mvb.session.info') && (name %in% names( tracees)) }
else {
x <- what
attributes( x) <- list() # ****ing srcref...
}
})
"find.derefs" <-
function( envir) {
if( is.null( mcache <- attr( envir, 'mcache')))
attr( envir, 'mcache') <- mcache <- named( integer( 0))
names( mcache) %SUCH.THAT% ( envir[[.]] %is.not.a% 'promise')
}
"find.docholder" <-
function( what, pos=find( what[1])){
pos <- as.env( pos)
o <- lsall( pos) %except% mcachees( pos)
searchfun.Rd <- function( x) {
if( is.function( xo <- pos[[x]]))
doco <- attr( xo, 'doc')
else if( length( grep( '\\.doc$', x)) && is.character( xo))
doco <- xo
else
doco <- character(0)
what %in% named.in.doc( doco)
} # searchfun.Rd
searchfun.casual <- function( x) if( !is.null( doc <- attr( pos[[x]], 'doc')) &&
is.list( doc)) doc[[1]] else character(0)
searchfun.own <- function( x) if( !is.null( doc <- attr( pos[[x]], 'doc')) &&
is.character( doc)) x else character(0)
keepo1 <- list( length( what))
Rds <- sapply( o, searchfun.Rd)
dim( Rds) <- c( length( what), length( o))
# apply over-simplifies, so...
keepo <- lapply( split( Rds, row( Rds)), function( ins) o[ins])
keepo2 <- lapply( named( what), searchfun.own) # what not o
keepo <- mapply( c, keepo, keepo2, SIMPLIFY=FALSE)
keepo3 <- lapply( named( what), searchfun.casual) # what not o
keepo <- mapply( c, keepo, keepo3, SIMPLIFY=FALSE)
names( keepo) <- what
lapply( keepo, unique)
}
"find.documented" <-
function( pos=1, doctype=c( 'Rd', 'casual', 'own', 'any'),
only.real.objects=TRUE) {
# 'pos' can have length > 1-- so guts live inside function
findo <- function( pos) {
pos <- as.env( pos)
oallall <- lsall( pos)
oall <- oallall %except% mcachees( pos)
ofuns <- oall %SUCH.THAT% exists( ., mode='function', envir=pos)
odoc <- (oall %except% ofuns) %that.match% '\\.doc$'
searchfun.docobj.Rd <- function( x) named.in.doc( pos[[x]])
searchfun.Rd <- function( x) named.in.doc( attr( pos[[x]], 'doc'))
searchfun.casual <- function( x) x[ !is.null( attr( pos[[x]], 'doc')) ]
searchfun.own <- function( x) x[ !is.null( doc <- attr( pos[[x]], 'doc')) &&
is.character( doc) ]
keepo <- character( 0)
for( dt in doctype)
keepo <- c( keepo, unlist( lapply( ofuns, FUN='searchfun.' %&% dt)))
if( 'Rd' %in% doctype)
keepo <- c( keepo, unlist( lapply( odoc, searchfun.docobj.Rd)))
returnList( keepo=unique( keepo), oall=oallall)
} # findo
doctype <- match.arg( doctype)
if( doctype=='any')
doctype <- c( 'Rd', 'casual')
if( is.environment( pos))
pos <- list( pos)
res <- lapply( pos, findo)
keepo <- unique( unlist( lapply( res, '[[', x='keepo')))
obs <- unlist( lapply( res, '[[', x='oall'))
if( only.real.objects)
keepo <- keepo %that.are.in% obs
return( keepo)
}
"find.funs" <-
function( pos=1, ..., exclude.mcache=TRUE, mode='function') {
# In this version, "pos" can have length > 1
findo <- function( pos2) {
o <- named( lsall( pos=pos2, ...))
if( exclude.mcache)
o <- o %except% mcachees( pos2)
if( !length( o))
return( character( 0))
old.warn <- options( warn=-1)$warn
on.exit( options( warn=old.warn))
keep <- sapply( o, exists, where=pos2, mode=mode, inherits=FALSE)
if( !any( keep))
return( character( 0))
names( o) <- NULL
o[keep]
}
if( is.environment( pos))
pos <- list( pos)
else
pos <- lapply( pos, as.env)
unlist( lapply( pos, findo), use.names=FALSE)
}
"find.lurking.envs" <-
function( obj, delve=FALSE, trace=FALSE){
listo <- list( quote( obj))
out.str <- character(0)
out.size <- numeric( 0)
while( length( listo)) {
if( trace)
print( listo[[1]])
thing <- eval( listo[[1]])
out.str <- c( out.str, deparse( listo[[1]])[1])
if( missing( thing)) {
out.size <- c( out.size, object.size( formals( sys.function())$obj))
} else if( is.environment( thing)) {
out.str[ length( out.str)] <- paste( out.str[ length( out.str)],
sub( 'environment', '', format( thing)))
out.size <- c( out.size, Inf)
# do not add environments to this list...
} else {
# process it, and add to list...
thing <- unclass( thing)
out.size <- c( out.size, object.size( thing))
if( is.recursive( thing)) {
if( is.function( thing)) {
listo <- c( listo, substitute( environment( x), list( x=listo[[1]])))
if( delve)
listo <- c( listo,
substitute( body( x), list( x=listo[[1]])),
substitute( formals( x), list( x=listo[[1]])))
} else {
# Label list-like elts with $name if avail, or [[num]] if not
if( is.null( namio <- names( thing)))
namio <- rep( '', length( thing))
listo <- c( listo, lapply( seq_along( thing),
function( x) if( nzchar( namio[x]))
substitute( a$b, list( a=listo[[1]], b=as.name( namio[x])))
else
substitute( a[[b]], list( a=listo[[1]], b=x))))
} # if recursive nonfunc
}
attro <- names( attributes( thing)) %except%
cq( dim, dimnames, class, levels, names, comment, row.names, tsp)
if( length( attro))
listo <- c( listo, lapply( attro,
function( x) substitute( attr( a, b), list( a=listo[[1]], b=x))))
}
listo <- listo[-1]
}
o <- order( out.size)
data.frame( what=out.str[o], size=out.size[o])
}
"find.mp" <-
function( x, mode='any'){
sx <- find( x, mode=mode, numeric=TRUE)[1]
if( is.na( sx)) {
sx <- index( sapply( maintained.packages,
function( env) exists( x, env, mode=mode, inherits=FALSE))[1])
if( is.na( sx))
stop( "Can't find '" %&% x %&% "' in search path or maintained packages")
sx <- maintained.packages[[ sx]]
} else
sx <- as.environment( sx)
sx
}
"find.path" <-
function( rel.path, char.rel.path, return.all=FALSE) {
if( !missing( char.rel.path))
rel.path <- as.character( char.rel.path) # in case of the number 0
else
rel.path <- deparse( substitute( rel.path))
if( substring( rel.path, 1, 2)=='..' &&
exists( rel.path, as.environment( 'mvb.session.info'), mode='environment', inherits=FALSE))
return( as.environment( 'mvb.session.info')[[ rel.path]])
# Parse input string: NB that R interprets a/b/c as function calls!
rel.path <- strsplit( rel.path, '/', fixed=TRUE)[[1]]
rel.path <- as.character( unlist( rel.path))
rel.path <- rel.path[ rel.path!="/"]
search.list <- sapply( seq( search()),
function( x) {
x <- names( attr( pos.to.env( x), 'path'))
if( is.null( x))
x <- ''
x }
)
get.tasks.if.present <- function( env.or.pos) {
env.or.pos <- as.env( env.or.pos)
if( exists( 'tasks', envir=env.or.pos, inherits=FALSE))
get( 'tasks', envir=env.or.pos)
else
character( 0)
}
env <- new.env()
wp <- get( '.Path', pos='mvb.session.info')
for( igo in seq( rel.path)) {
go <- rel.path[ igo]
if( go=='..') {
if( length( wp))
wp <- wp[-length(wp)] }
else if( go=='0')
wp <- .Path['ROOT']
else if( go!='.') {
if( identical( wp, .Path[ 1:length( wp)]))
ctasks <- get.tasks.if.present( names( .Path)[ length( wp)])
else {
# cat( 'loading tasks from', wp[ length( wp)], '\n')
load( file.path( wp[ length( wp)], '.RData'), envir=env)
ctasks <- get.tasks.if.present( env)
remove( list=lsall( env), envir=env)
}
if( !any( go==names( ctasks)))
stop( 'can\'t find task named ' %&% go %&% ' in ' %&% wp[length(wp)])
else {
old.wd <- getwd()
actual.ctask <- try( {
setwd( wp[ length( wp)])
setwd( ctasks[ go])
getwd()
})
setwd( old.wd)
if( actual.ctask %is.a% 'try-error')
stop( "can't find dir of task named '" %&% go %&% "' in '" %&% wp[ length( wp)])
names( actual.ctask) <- go
wp <- c( wp, actual.ctask)
}
} # if: different types of 'go'
} # for
if( !return.all)
wp <- wp[ length( wp)]
wp
}
"find.prefix" <-
function (j, nodes, parents)
{
s <- names(nodes[j])
while ((j <- parents[j]) > 0) s <- names(nodes[j]) %&% "/" %&%
s
s
}
"find.web" <-
function( nlocal=sys.parent()) mlocal({
funs <- unique( c( funs, generics))
n <- length( funs)
if( !n)
stop( 'Nothing there!')
funmat <- matrix( 0, n, n, dimnames=list( MASTER=funs, SLAVE=funs))
master.of <- lapply( funs, called.by, can.match=funs, where=where)
n.master <- unlist( lapply( master.of, length))
if( !sum( n.master))
stop( 'Bo-RING! No food chain here!')
setup <- c( rep( 1:length(funs), n.master), unlist( master.of))
dim( setup) <- c( sum( n.master), 2)
funmat[ setup] <- 1
diag( funmat) <- 0 # to drop self-references
# Not interested in calls TO generic functions:
funmat[ ,generics] <- 0
# check whether any methods of generic functions:
drop.generics <- funmat[ generics, ] %**% rep( 1, n) == 0
if( any( drop.generics)) {
funs <- funs[ -match( generics[drop.generics], funs)]
funmat <- funmat[ funs, funs]
n <- n-sum( drop.generics) }
color <- rep( textcolor, n)
if( length( prune)) {
prunio <- matrix( 0, length( prune), n)
prunio <- sapply( to.regexpr( prune), regexpr, text=funs) # to.regexpr(): oct 2011
prunio <- as.logical( (prunio != -1) %**% rep( 1, length( prune)))
color[ prunio] <- highlight
# Everything descended from a prune
if( descendents) {
old.descendents <- rep( FALSE, n)
descendents <- prunio
while( sum( descendents)!=sum( old.descendents)) {
old.descendents <- descendents
descendents <- descendents | (descendents %**% funmat > 0) } }
else
descendents <- prunio
# All ancestors of a prune
if( ancestors) {
old.ancestors <- rep( FALSE, n)
ancestors <- prunio
while( sum( ancestors) != sum( old.ancestors)) {
old.ancestors <- ancestors
ancestors <- ancestors | (funmat %**% ancestors > 0) } }
else
ancestors <- prunio
color <- color[ ancestors | descendents]
funs <- funs[ ancestors | descendents]
funmat <- funmat[ funs, funs, drop=FALSE]
n <- length( funs)
}
# Now we have to figure out what level in the hierarchy each fn. belongs at.
# Simple-minded approach: anything NOT called by any other function is top-
# level; anything called only by top-levels is second-level; etc.
if( !n)
stop( 'Nothing there!')
level <- rep(0, n); names( level) <- funs
current.level <- 1
while( any( level==0)) {
tops <- rep( 1, sum( level==0)) %**% funmat[level==0, level==0] == 0
if( !any( tops)) # we have to sort out functions that call each other
tops <- least.mutual.dependency( funmat, funs, level)
level[ dimnames( funmat)[[1]] [ level==0] [tops] ] <- current.level
current.level <- current.level+1
}
})
"fix.order" <-
function( env=1) {
oenv <- env
env <- as.env( env)
if( is.null( path <- attr( env, 'path')) || is.null( names( path)))
stop( 'Not a task')
fob <- read.bkind( path)
if( !length( fob[[1]]))
stop( 'Can\'t deduce fix.order')
fdates <- file.info( file.path( path, '.Backup.mvb', fob$files))$mtime
o <- order( fdates)
fob <- fob$object.names[ o]
fob <- fob[ fob %in% find.funs( oenv) ] # remove deleted functions still with backups
fob
}
"fixr" <-
function( x, new=FALSE, install=FALSE, what=list( function(){}, '')[[1]], fixing=TRUE,
pkg=NULL, character.only=FALSE, new.doc=FALSE, force.srcref=FALSE) {
#############################################################
if( missing( x) && missing( character.only))
return( 'Nothing to edit!')
prog <- 'program.' %&% ifelse( fixing, 'editor', 'reader')
proged <- getOption( prog)
if( is.null( proged) || install)
proged <- install.proged( option.name=prog)
if( is.character( character.only)) {
x <- character.only
character.only <- TRUE
}
if( !character.only) {
sx <- substitute( x)
if( is.call( sx)) {
x <- as.character( sx)
if( x[1] %not.in% c( '::', ':::', '$') || length( x)<3)
stop( "Don't know how to fixr '" %&% deparse( sx) %&% "'")
pkg <- x[2]
if( substring( pkg, 1, 2)=='..') { # ..mypack$fun
pkg <- substring( pkg, 3)
if( pkg %not.in% names( maintained.packages))
stop( "Package '" %&% pkg %&% "' is not a 'maintained package'!")
}
name <- x[3]
} else
name <- deparse( substitute( x), width.cutoff=30, nlines=1)
} else
name <- x
find.and.get()
if( is.function( x))
environment( x) <- .GlobalEnv # to prevent the environment string being printed after the definition.
# ...mostly for new functions; bad practice to set environments otherwise.
if( new.doc)
x <- add.flatdoc.to( x, char.x=name, env=load.from)
dir <- c( getOption( 'edit.scratchdir'), Sys.getenv( 'TMP'), Sys.getenv( 'TEMP'))
dir <- dir[ nchar( dir)>0][1]
if( is.na( dir))
stop( "Don't know where to put scratch files:" %&%
" none of options( 'edit.scratchdir') or TMP or TEMP are set!")
# Filename including "version" number if required
exact.same <- index( name==fix.list$name & name.load.from==fix.list$where)[1]
if( !is.na( exact.same))
filename <- fix.list$file[ exact.same]
else {
if( !length( partial <- index( name==fix.list$name)))
version.suffix <- ''
else {
ofnames <- fix.list$file[ partial]
versions <- suppressWarnings( as.integer( sub( '(.*)#([0-9]+)\\.R$', '\\2', ofnames)))
versions[ is.na( versions)] <- 0
new.version <- min( (1:max( versions)) %except% versions)
version.suffix <- '#' %&% new.version
}
# Changed 1/2017 to allow other objects to get dot-R suffix instead of dot-txt; good for syntax-highlighting
fsuffix <- if( has.source( x)) {
'.R'
} else {
getOption( 'fixr.suffices', character())[ file_ext( name)]
}
if( is.na( fsuffix)) { # default for texty things
fsuffix <- '.txt'
}
filename <- file.path( dir, legal.filename( name %&% version.suffix %&% fsuffix))
}
old.warn <- options(warn = -1, width = 180)[1:2] # wide to avoid line breaks
failed.to.edit <- TRUE # usual pessimism
on.exit({
if( failed.to.edit && file.exists( filename))
unlink(filename)
if( trace.was.on)
mtrace( char.fname=name)
options(old.warn) })
# Do backup only if task
if( fixing && !new && type.load.from %in% cq( package, task) && has.source( x))
deal.with.backups( name, load.from) # takes env or number
if( x %is.a% 'function') {
if( !is.null( sr <- attr( x, 'srcref')) && !is.null( src <- attr( sr, 'srcfile')$lines)) {
# Might want entire original source if func didn't parse
if( force.srcref) { # added 2018 to resolve messed-up cases with attributes
write.sourceable.function( x, filename)
} else if( attr( sr, 'srcfile')$filename=='dummyfile') { # produced by 'fixr' before; print all
cat( src, file=filename, sep='\n')
} else { # standard R srcref; just take what's there
capture.output( print( x, useSource=TRUE), file=filename)
}
} else
write.sourceable.function( x, filename)
} else if( has.source( x))
cat( attr( x, 'source'), file=filename, sep='\n')
else # text object
cat( x, file=filename, sep='\n')
# OK <- shell( proged(name, filename), translate=TRUE, wait = FALSE) # shell doesn't work on Linux
cmd <- proged( name, filename)
if( dos.or.windows())
cmd <- gsub( '([^ ])/', '\\1\\\\', cmd)
OK <- system( cmd, wait=FALSE) # before 12/2005 'wait' was only set FALSE on Windows; dunno why
if(OK != 0)
stop("Couldn't launch editor")
# Avoid returning focus to console
put.in.session( just.created.window=TRUE)
# Zap duplicates
if( fixing) {
fix.list <<- fix.list[ fix.list$name != name | fix.list$where != name.load.from,]
fix.list <<- rbind(fix.list,
list( name = name, file = filename, where = name.load.from, where.type= type.load.from,
has.source=!is.character( x),
dataclass = paste( unique( c( class( x),
if( is.character( x)) 'character')), collapse=','),
file.time=unclass( file.info( filename)[1,'mtime'])))
}
failed.to.edit <- FALSE
invisible(NULL)
}
"fixr.guts" <-
function( name, new=FALSE, proged, fixing=TRUE, what=list( function(){}, '')[[1]], obj) {
# Just like
if( missing( name))
return( "Nothing to edit!")
trace.was.on <- FALSE
# Function to edit, and its name (may be different from 'name' if method)
if( !missing( obj)) {
load.from <- 1
x <- obj
is.new <- trace.was.on <- FALSE
} else {
load.from <- if( new) NA else find( name, numeric=TRUE)[1] # mode check removed 28/7/2005
is.new <- is.na( load.from)
if(!is.new) {
x <- if( missing( obj)) get( name, pos=load.from) else obj
trace.was.on <- exists( 'tracees', 'mvb.session.info') && (name %in% names( tracees)) }
else {
x <- what
load.from <- 1 }
}
if( is.function( x))
environment( x) <- .GlobalEnv # to prevent the environment string being printed after the definition.
# ...mostly for new functions; bad practice to set environments otherwise.
try.load.from <- NULL
num.load.from <- load.from
if( load.from>1) {
try.load.from <- names( attr( pos.to.env( load.from), 'path'))
if( is.null( try.load.from))
load.from <- search()[ load.from]
else
load.from <- try.load.from
} else {
load.from <- try.load.from <- names( attr( pos.to.env( 1), 'path')) # else ".GlobalEnv" will cause problems if there's a "cd"
if( is.null( load.from)) {
warning( search()[ load.from] %&% ' doesn\'t seem to be a task: object will be saved into .GlobalEnv')
load.from <- '.GlobalEnv' }
}
dir <- options('edit.scratchdir')[1]
if( is.null( dir)) {
dir <- Sys.getenv( 'TMP')
if( !nchar( dir))
dir <- Sys.getenv( 'TEMP')
if( !nchar( dir))
stop( "Don't know where to put scratch files: none of options( 'edit.scratchdir') or TEMP or TMP are set!")
}
filename <- file.path( dir, legal.filename( name)) # used to append.R to avoid...
#... editors loading e.g. .First.lib as a binary file! Now assuming this is done outside
old.warn <- options(warn = -1, width = 180)[1:2] # wide to avoid line breaks
failed.to.edit <- TRUE # usual pessimism
on.exit({
if( failed.to.edit && file.exists( filename))
unlink(filename)
if( trace.was.on)
mtrace( char.fname=name)
options(old.warn) })
if( fixing && !is.new && !is.null( try.load.from) && is.function( x)) # only do backup if task
deal.with.backups( name, num.load.from)
if( is.function( x))
write.sourceable.function( x, filename)
else
cat( x, file=filename, sep='\n')
# OK <- shell( proged(name, filename), translate=TRUE, wait = FALSE) # shell doesn't work on Linux
cmd <- proged( name, filename)
callo <- quote( system( cmd))
if( 'wait' %in% names( formals( system)))
callo$wait <- FALSE
OK <- eval( callo)
if(OK != 0)
stop("Couldn't launch editor")
# Avoid returning focus to console
put.in.session( just.created.window=TRUE)
# Zap duplicates
if( fixing) {
fix.list <<- fix.list[ fix.list$name != name,]
fix.list <<- rbind(fix.list,
list( name = name, file = filename, where = load.from,
dataclass = paste( class( x), collapse=','), file.time=unclass( file.info( filename)[1,'mtime'])))
}
failed.to.edit <- FALSE
invisible(NULL)
}
"fixtext" <-
function( x, ...) {
mc <- match.call( expand.dots=TRUE)
mc$what <- ''
mc[[1]] <- quote( fixr)
eval( mc, parent.frame())
}
"fixup.DLLs" <-
function( in.memory, ipath, rpath, spath, pkg, use.newest=FALSE, nlocal=sys.parent()) mlocal({
suffix <- '[.]' %&% (if( .Platform$OS.type=='windows') '(dll|DLL)' else 'so') %&% '$'
dlls1 <- sort( dir( rpath, pattern=suffix))
libs <- 'libs'
dlls2 <- suppressWarnings( sort( dir( file.path( rpath, 'inst', libs), pattern=suffix)))
# R 2.12: DLLs in arch subfolder under "/libs" which...
# ... will be ref'd by 'libs' object, which controls installation dir...
# ... Otherwise (pre 2.12), 'libs' is just "libs" folder
# Allow any storage arrangement in task package
# 2.12+: If task DLLs found *not* in subarch, assume the installed versions go to the current subarch
if( nzchar( .Platform$r_arch)) {
libs <- file.path( libs, .Platform$r_arch)
dlls3 <- suppressWarnings( sort( dir( file.path( rpath, 'inst', libs), pattern=suffix)))
} else
dlls3 <- character( 0)
dlls <- c( dlls1, dlls2, dlls3)
dll.paths <- c( file.path( rpath, dlls1), file.path( rpath, 'inst', 'libs', dlls2),
file.path( rpath, 'inst', libs, dlls3))
names( dll.paths) <- dlls
# Definitely overwrite the versions in the source package
if( length( dll.paths)) {
mkdir( file.path( spath, 'inst', libs)) # probably should build into mvb.file.copy
mvb.file.copy( dll.paths, file.path( spath, 'inst', libs, dlls))
}
if( !is.null( ipath)) {
if( is.dir( ipath.libs <- file.path( ipath, libs)))
idlls <- sort( dir( ipath.libs, pattern=suffix))
else
idlls <- character(0)
inst.dll.paths <- file.path( ipath.libs, idlls)
names( inst.dll.paths) <- idlls
# New DLLs in raw get copied; new DLLs in inst get deleted
use.raw <- dlls %except% idlls # provisionally, ones to replace
if( length( both <- intersect( idlls, dlls))) {
time.raw <- file.info( dll.paths[ both])$mtime
time.inst <- file.info( inst.dll.paths[ both])$mtime
md5.raw <- md5sum( dll.paths[ both])
md5.inst <- md5sum( inst.dll.paths[ both])
names( time.raw) <- names( time.inst) <-
names( md5.raw) <- names( md5.inst) <- both
if( use.newest) { # also make sure files have different contents
if( length( newer.inst <- both[ (time.raw < time.inst) & (md5.raw != md5.inst) ])) {
mvb.file.copy( inst.dll.paths[ newer.inst], dll.paths[ newer.inst], overwrite=TRUE)
# raw package-- in case overwritten already by older vers in raw task package!
mvb.file.copy( inst.dll.paths[ newer.inst],
file.path( spath, 'inst', libs, newer.inst), overwrite=TRUE)
}
}
# If raw is newer, handle below via 'use.raw'
use.raw <- c( use.raw, both[ time.raw > time.inst])
} # if duplicated
not.installed.yet <- use.raw %except% names( inst.dll.paths)
inst.dll.paths[ not.installed.yet] <- file.path( ipath.libs, not.installed.yet)
# in.memory=TRUE for reloading DLLs as appropriate-- always TRUE in current code
# Unload / unlink
try.dyn.load <- function( x) try( dyn.load( x))
try.dyn.unload <- function( x) try( dyn.unload( x))
try.library.dynam.load <- function( x) try( library.dynam(
sub( '[.]' %&% file_ext( x) %&% '$', '', basename( x)), package=pkg, lib.loc=dirname( ipath)))
try.library.dynam.unload <- function( x) try( library.dynam.unload(
sub( '[.]' %&% file_ext( x) %&% '$', '', basename( x)), libpath=ipath))
# DLLs could be loaded either via dyn.load or library.dynam; the latter is now recommended.
# ... Assume 'library.dynam' for new DLLs, and only assume 'dyn.load' if there's definite evidence!
ldlist <- sapply( library.dynam(), '[[', i='path')
loadeds <- sapply( getLoadedDLLs(), '[[', i='path')
if( length( use.raw)) {
# Unload, replace, reload
cat( "Updating DLLs in source of '", pkg, "' from newer installed DLLs...", sep='')
flush.console()
via.dyn.loads <- (loadeds %that.are.in% inst.dll.paths[ use.raw]) %except% ldlist
via.library.dynams <- inst.dll.paths[ use.raw] %except% via.dyn.loads
if( in.memory) {
lapply( via.dyn.loads %that.are.in% loadeds, try.dyn.unload)
lapply( via.library.dynams %that.are.in% loadeds, try.library.dynam.unload)
} # if in.memory
mvb.file.copy( dll.paths[ use.raw], inst.dll.paths[ use.raw], overwrite=TRUE)
if( in.memory) {
lapply( via.library.dynams, try.library.dynam.load)
lapply( via.dyn.loads, try.dyn.load)
}
cat( 'done\n')
} # if changed dlls in raw package
# DLLs in inst that now shouldn't be (because not in raw):
inxs.dlls <- idlls %except% dlls
# Ones with source shouldn't be zapped either
if( is.dir( file.path( rpath, 'src'))) {
src.files <- dir( file.path( rpath, 'src'), pattern='[.](c|cc|cpp|C|f|f90|f95|m|mm|M|pas|lpr)$')
if( length( src.files)) {
# Include mypack.c-- though I recommend naming your dynlibs specifically, not with pkgname
src.files <- c( src.files, pkg %&% '.c')
src.dlls <- to.regexpr( sub( '[.][^.]*$', '', src.files)) # strip ext
src.dlls <- src.dlls %&% suffix # prepare for match
inxs.dlls <- inxs.dlls %that.dont.match% src.dlls
}
}
lapply( inst.dll.paths[ inxs.dlls] %that.are.in% (loadeds %except% ldlist), try.dyn.unload)
lapply( inst.dll.paths[ inxs.dlls] %that.are.in% ldlist, try.library.dynam.unload)
file.remove( inst.dll.paths[ inxs.dlls])
}
})
"fixup.exports" <-
function( pkg) {
# Make sure exported functions are visible
ns <- asNamespace( pkg)
# Export list must be read directly from the NAMESPACE file, ugggh
things.to.export <- parseNamespaceFile( pkg,
package.lib=dirname( getNamespaceInfo( ns, 'path')))$exports
expenv <- ns$.__NAMESPACE__.$exports
unexportees <- lsall( expenv) %except% things.to.export
rm( list=unexportees, envir=expenv)
for( new.exportee in things.to.export %except% lsall( expenv))
assign( new.exportee, structure( new.exportee, names=new.exportee), envir=expenv)
visible <- list()
if( ('package:' %&% pkg) %in% search())
visible <- list( list( env=as.environment( 'package:' %&% pkg),
can.reset=FALSE)) # see below for can.reset
loaded.users <- getNamespaceUsers( pkg)
loaded.users <- loaded.users %SUCH.THAT% (("package:" %&% .) %in% search())
loaded.users <- loaded.users %SUCH.THAT% (try( asNamespace( .)) %is.not.a% 'try-error')
for( lu in loaded.users)
visible <- c( visible, list( list( env=parent.env( asNamespace( lu)), can.reset=FALSE)))
# Space for code to look thru importing environments of other packages that
# might import this one; should add the parent.env of the namespace of the
# importing package to the list 'visible'
# These might be locked, in which case it would be possible to fudge by
# resetting their parent.env to a new environment to contain these exports,
# and whose own parent is the original parent.env. That is a bit RISKY
# so if I do code this, be sure to make it optional. The 'can.reset' field
# is used to indicate whether this is OK; it isn't OK for the search path copy,
# but that shouldn't be locked in the first place.
for( vis in visible) {
things.to.make.vis <- things.to.export %except% lsall( vis$env)
things.to.zap <- unexportees %that.are.in% lsall( vis$env)
if( length( c( things.to.make.vis, things.to.zap))) {
assenv <- NULL # default: can't do it
if( environmentIsLocked( vis$env)) {
if( vis$can.reset && identical( parent.env( vis$env), asNamespace( 'base'))) {
assenv <- new.env( parent=parent.env( vis$env))
parent.env( vis$env) <- assenv # scary...
} else if( environmentIsLocked( parent.env( vis$env)))
warning( "Can't or daren't add to imports for " %&% format( vis$env))
else
assenv <- parent.env( vis$env) # not locked; probably fudged like this already
} else # not locked
assenv <- vis$env
if( !is.null( assenv)) {
rm( list=things.to.zap, envir=assenv)
for( thing in things.to.make.vis)
assign( thing, ns[[ thing]], assenv)
}
} # if anything to assign
} # loop over places where the funcs should be visible
}
"fixup.help" <-
function( nlocal=sys.parent()) mlocal({
# Work out which Rd files are new
# md5sum is incredibly fast for this!
manpath <- file.path( spath, 'man')
Rd.files <- dir( manpath, pattern='[.]Rd$')
new.Rd.info <- md5sum( file.path( manpath, Rd.files))
names( new.Rd.info) <- Rd.files
alias <- matrix( scan( file.path( ipath, 'help', 'AnIndex'), what='', sep='\t', quiet=TRUE),
ncol=2, byrow=TRUE)
uaf <- unique( alias[,2])
alias.files <- alias[,2] %&% '.Rd'
alias <- alias[,1]
# In theory, could check against the man/pkg.Rd.gz file in the installation
# ...but no guaranteed unzip method available. Instead, use a from-last-time file.
Rd.info.file <- file.path( ipath, 'Meta', 'Rd.info.rda')
if( !force.all.docs && file.exists( Rd.info.file))
load( Rd.info.file) # creates old.Rd.info
else {
old.Rd.info <- rep( -1, length( uaf))
# Next reflects fossilized bug in %&%: should return ch(0) if any arg is len 0
names( old.Rd.info) <- if( length( uaf)) uaf %&% '.Rd' else uaf
}
zipped <- file.exists( file.path( ipath, 'help', 'Rhelp.zip'))
new.files <- names( new.Rd.info) %except% names( old.Rd.info)
changed.files <- names( new.Rd.info) %that.are.in% names( old.Rd.info)
changed.files <- changed.files[ old.Rd.info[ changed.files] != new.Rd.info[ changed.files]]
gone.files <- names( old.Rd.info) %except% names( new.Rd.info)
# Fudge for R2.10 to get round parse_Rd/lazyLoad bugs: force re-parsing
if( dynamic.help && !file.exists( file.path( ipath, 'help', 'patched'))) {
new.files <- names( new.Rd.info)
changed.files <- character( 0)
}
# Function to prepare shell & then run commands in it
log <- character( 0)
system2 <- function( commands, intern=TRUE, ...) {
bf <- tempfile()
on.exit( unlink( bf))
if( .Platform$OS.type=='windows') {
commands <- sub( '\\bR CMD\\b', 'RCMD', commands, perl=TRUE)
bf <- bf %&% '.bat'
} else
commands <- sub( '\\bRCMD\\b', 'R CMD', commands, perl=TRUE)
cat( getOption( 'rcmd.shell.setup', character( 0)), # 'CALL SET-R-BUILD-PATH.BAT'
commands, sep='\n', file=bf)
if( !is.null( mvboptions$debug_fixup_help)) {
cat( c( readLines( bf), '...'), sep='\n', file=stderr())
flush.console()
}
log <<- c( log, system( bf, intern=intern, ...))
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'done\n', file=stderr())
flush.console()
}
}
if( length( gone.files)) {
fzap <- sub( '[.]Rd$', '', gone.files)
if( !zipped)
try( suppressWarnings( file.remove( file.path( ipath, 'help', fzap))), silent=TRUE)
else
system2( 'zip -d ' %&% file.path( ipath, 'help', 'Rhelp.zip') %&% fzap)
try( suppressWarnings( file.remove( file.path( ipath, 'html', fzap %&% '.html'))), silent=TRUE)
}
dealias.files <- c( changed.files, gone.files)
if( length( dealias.files)) {
alias <- alias[ alias.files %not.in% dealias.files]
alias.files <- alias.files %except% dealias.files
uaf <- unique( alias.files)
}
files.to.update <- c( new.files, changed.files)
if( length( files.to.update)) {
fnew <- sub( '[.]Rd$', '', files.to.update)
full.fnew <- file.path( spath, 'man', fnew %&% '.Rd')
# from .build_Rd_db:
enco <- try( tools$.get_package_metadata( ipath, FALSE)["Encoding"])
if( (enco %is.a% 'try-error') || is.na(enco))
enco <- "unknown"
if( dynamic.help) {
# Magic to avoid lazyLoad trouble:
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'flushing cache in help.rdb...', file=stderr())
flush.console()
}
LLDBflush( file.path( ipath, 'help', pkg %&% '.rdb'))
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'done\n', file=stderr())
flush.console()
}
if( force.all.docs)
file.remove( file.path( ipath, 'help', pkg %&% c( '.rdb', '.rdx')))
# Next routine is smart about updating
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'installing Rd...', file=stderr())
flush.console()
}
testo <- try( tools$.install_package_Rd_objects( spath, ipath, enco=enco))
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'done\n', file=stderr())
flush.console()
}
# ...try() should only be to trap any errors with user's own Rd files..?
# Fastest to get aliases from parsed Rd
if( !is.null( mvboptions$debug_fixup_help)) {
cat( '2nd flushing cache in help.rdb...', file=stderr())
flush.console()
}
LLDBflush( file.path( ipath, 'help', pkg %&% '.rdb'))
if( !is.null( mvboptions$debug_fixup_help)) {
cat( 'done\n', file=stderr())
flush.console()
}
Rdlist <- tools$fetchRdDB( file.path( ipath, 'help', pkg))
aliases <- lapply( Rdlist, tools$.Rd_get_metadata, kind='alias')
alias <- unlist( aliases)
alias.files <- rep( names( aliases), sapply( aliases, length))
names( alias.files) <- alias
saveRDS( alias.files, file.path( ipath, 'help', 'aliases.rds'))
tools$.install_package_Rd_indices( spath, ipath)
tools$.writePkgIndices( spath, ipath)
} else {
text.fnew <- file.path( ipath, 'help', fnew)
html.fnew <- file.path( ipath, 'html', fnew %&% '.html')
Rd.fnew <- file.path( ipath, 'man', fnew %&% '.Rd')
if( is.Rd2) { # if( exists( 'Rd2txt', mode='function')) # assume Rd2HTML does, too
for( i in seq_along( fnew)) {
p1 <- try( tools$prepare_Rd( full.fnew[i], encoding=enco, defines = .Platform$OS.type,
stages = "install", warningCalls = FALSE))
# p1 <- try( parse_Rd( full.fnew[i])) doesn't do macro subs
if( p1 %is.a% 'try-error')
warning( "Can't parse_Rd " %&% fnew[ i] %&% "; no help for this one")
else {
attr( p1, 'prepared') <- 3L # from .build_rd_db
Rd2txt( p1, out=text.fnew[i], package=pkg)
Rd2HTML( p1, out=html.fnew[i], package=pkg)
} # parse_Rd OK
} # for i
} else { # Rdoc 1
cat( 'Rdconv-ing ', length( fnew), ' Rd files, twice...\n')
system2( 'RCMD Rdconv ' %&% c(
paste( '--package=', pkg, '-t=txt', '-o=' %&% text.fnew, full.fnew),
paste( '-t=html', '-o=' %&% html.fnew, full.fnew)))
if( .Platform$OS.type=='windows') { # ...then hack links
# Endless work needed to do this right for pre-2.10, so just make all point here
for( i.html in html.fnew) {
reado <- readLines( i.html)
reado <- gsub( '"[.][.]/[.][.]/[.][.]/doc/html/search/SearchObject.html[?]([^"]+)"',
'"\\1.html"', reado)
cat( reado, sep='\n', file=i.html)
}
} # windows
cat( '...done\n')
} # which Rd version
# ?Need to do something about 00index.html? (both versions)
if( zipped) {
system2( 'zip -j ' %&% file.path( ipath, 'help', 'Rhelp.zip') %&% ' ' %&% text.fnew)
try( suppressWarnings( file.remove( text.fnew)), silent=TRUE)
}
# Alias info
for( ifnew in fnew) {
filio <- readLines( file.path( spath, 'man', ifnew %&% '.Rd'))
sections <- grep( '^[\\][A-Za-z0-9]+\\{', filio) # }
namas <- sections[ grep( '^[\\](name|alias)[{]', filio[ sections])]
not.namas <- c( sections %except% namas, Inf)
namas <- namas[ namas < min( not.namas)]
this.alias <- unique( sub( '.*[{]([^}]+)[}].*', '\\1', filio[ namas]))
alias <- c( alias, this.alias)
alias.files <- c( alias.files, rep( ifnew, length( this.alias)))
}
} # if not dynamic help
# Index
alias.files <- sub( '[.]Rd$', '', alias.files)
cat( paste( alias, alias.files, sep='\t'),
sep='\n', file=file.path( ipath, 'help', 'AnIndex'))
} # if length( files.to.update)
# old.Rd.info
old.Rd.info <- new.Rd.info
save( old.Rd.info, file=Rd.info.file)
# help.search index... TO DO I guess... now obsolete post R-2.10, phew
})
"fixup.vignettes" <-
function( nlocal=sys.parent(), empty.list) mlocal({
if( !getOption( 'mvbutils.vignettes', FALSE))
return( local.return())
# Vignette index for homebrewed PDFs
if( is.dir( own.vig.dir <- file.path( sourcedir, 'inst', 'doc')) &&
length( own.vigs <- dir( own.vig.dir, pattern='[.]pdf$')) &&
!file.exists( file.path( own.vig.dir, 'index.html'))) {
## Make it up, either from mypack.VIGNETTES first, then adding other missing bits
if( is.character( vig.info <- ewhere[[ pkg %&% '.VIGNETTES']])) {
vig.info <- sub( '^ *([^ :]+) *: *', '\\1:', vig.info)
vig.info <- vig.info %that.match% '^[^ :]+:'
if( length( vig.info)) {
vig.info <- strsplit( vig.info, ':')
vig.info <- structure( sapply( vig.info, '[', i=2), names=sapply( vig.info, '[', i=1))
vig.info <- vig.info %such.that% ((names( .) %&% '.pdf') %in% own.vigs)
}
} else
vig.info <- character() # then make it up
own.vigs <- sub( '[.]pdf$', '', own.vigs)
need.rudi <- own.vigs %except% names( vig.info)
vig.info <- c( vig.info, named( need.rudi))
vig.R.files <- file.path( sourcedir, 'inst', 'doc', names( vig.info) %&% '.R')
names( vig.R.files) <- vig.info
# Create .Rnw stubs so vignettes get found: thanks to Henrik Bengtsson's nonsweave doco
for( ivig in own.vigs) {
ivig.rnw <- file.path( sourcedir, 'inst', 'doc', ivig %&% '.Rnw')
if( !file.exists( ivig.rnw)) {
stubbo <- gsub( 'VIGNAME', to.regexpr( ivig), attr( sys.function(), 'vignette.stub'))
if( file.exists( vig.R.files[ ivig])) {
last.line <- grep( 'end.*document', stubbo)
stubbo <- multinsert( stubbo, last.line-1, c( '<<>>=', readLines( vig.R.files[ ivig]), '@'))
}
scatn( '%s', stubbo, file=ivig.rnw)
} # if no stub
} # for own.vigs
empty.list <- I( rep( list( character( 0)), length( vig.info)))
vig.index <- data.frame( File=names( vig.info) %&% '.Rnw', Title=vig.info, PDF=names( vig.info) %&% '.pdf',
Depends=empty.list, Keywords=empty.list,
R=ifelse( file.exists( vig.R.files), vig.R.files, ''), stringsAsFactors=FALSE)
tools$.writeVignetteHtmlIndex( pkg, file.path( sourcedir, 'inst', 'doc', 'index.html'), vig.index)
saveRDS( vig.index, file=file.path( sourcedir, 'R', 'meta.vignette.rds'))
# so patch.installed() can copy this across to Meta
# saveRDS( vig.index, file = file.path( sourcediroutDir, "Meta", "vignette.rds"))
} else { # if no vig stuff
if( !is.dir( own.vig.dir))
own.vigs <- character( 0)
sweave.vig.dir <- file.path( sourcedir, 'vignettes')
if( is.dir( sweave.vig.dir))
own.vigs <- c( own.vigs, dir( sweave.vig.dir, pattern='[.]Rnw$'))
# Should check filedates and rebuild if required
# Maybe include pdfs in source pack even if Sweave, but use Rbuildignore
# This does not deal case of changing from homebrewed to Sweave vignettes
# but why would you?!
if( !length( own.vigs)) {
# clean out anything installed
old.pdfs <- dir( file.path( ipath, 'inst', 'doc'), pattern='[.]pdf$', full.names=TRUE)
unlink( old.pdfs)
unlink( sub( 'pdf$', 'R', old.pdfs)) # R source
unlink( sub( 'pdf$', 'Rnw', old.pdfs)) # vignette source
unlink( file.path( ipath, 'inst', 'doc', 'index.html'))
unlink( file.path( ipath, 'meta', 'vignette.rds'))
}
}
})
"flatdoc" <-
function( EOF="<<end of doc>>") {
doctext <- readLines.mvb( current.source(), EOF=EOF, line.count=TRUE)
class( doctext) <- 'docattr'
attr( doctext, 'line.count') <- NULL
doctext
}
"foodweb" <-
function( funs, where=1, charlim=80, prune=character(0), rprune,
ancestors=TRUE, descendents=TRUE,
plotting=TRUE, plotmath=FALSE,
generics=c( 'c','print','plot', '['), lwd=0.5, xblank=0.18,
border='transparent', boxcolor='white', textcolor='black', color.lines=TRUE, highlight='red', ...) {
oldpar <- par( ..., no.readonly=TRUE)
on.exit( par( oldpar))
charlim <- charlim/par('cex')
par( lwd=lwd) # lwd included as a parameter, in case this screws up
skip.computations <- FALSE
if( missing( funs)) {
if( is.environment( where))
where <- list( where)
funs <- unique( unlist( lapply( where, find.funs)))
} else if( funs %is.a% 'foodweb') { # basically redisplay
skip.computations <- TRUE
extract.named( funs)
funs <- names( level)
n <- length(level) }
if( !skip.computations) {
if( !missing( rprune))
prune <- funs %matching% rprune
funs <- unique( c( funs, prune))
if( !length( funs))
return( structure( list( funmat=matrix( 0,0,0), x=numeric( 0), level=numeric( 0)),
class='foodweb'))
find.web()
organize.web.display( plotmath=plotmath) }
answer <- list( funmat=funmat, x=x, level=level)
class( answer) <- 'foodweb'
if( plotting) {
# Dreadful Rgui-windows bug with 'ps'...
opar <- par( 'ps')
if( names( dev.cur())=='windows') {
on.exit( par( ps=opar+1L))
}
plot( answer, border=border, boxcolor=boxcolor, xblank=xblank, textcolor=textcolor,
color.lines=color.lines, plotmath=plotmath, ...)
}
invisible( answer)
}
"FOR" <-
function( x, expr, ...){
fungo <- function( .) bod
l <- list( ...)
environment( fungo) <- if( length( l))
list2env( l, parent=parent.frame())
else
parent.frame()
body( fungo) <- substitute( expr)
if( is.atomic( x) && is.null( names( x)))
x <- named( x)
lapply( x, fungo)
}
"force.assign" <-
function( x, value, envir) {
envir <- as.environment( envir)
if( bl <- exists( x, envir, inherits=FALSE) && balloonIsTethered( x, envir))
untetherBalloon( x, envir)
assign( x, value, envir=envir)
if( bl)
tetherBalloon( x, envir)
}
"format.dull" <-
function( x, ...) rep( '...', NROW( x))
"from.here" <-
function( EOF=as.character( NA)) {
f1 <- tempfile()
# cat( 'FILENAME: ', f1, '\n')
cat( readLines.mvb( current.source(), EOF=EOF), file=f1, sep='\n')
c1 <- file( f1)
class( c1) <- c( 'selfdeleting.file', class( c1))
c1
}
"full.path" <-
function( path, start='.'){
spath <- strsplit( path, '/', fixed=TRUE)[[1]]
if( spath[1] %in% c( '.', '..'))
path <- file.path( start, path)
# Eliminate . and ..
spath <- strsplit( path, '/')[[1]]
spath <- spath %except% '.'
while( !is.na( first.parent <- index( spath == '..')[1]))
spath <- spath[ -( first.parent + -1:0)]
paste( spath, collapse='/')
}
"generic.dll.loader" <-
function( libname, pkgname, ignore_error=FALSE){
# Generic DLL loader
dll.path <- file.path( libname, pkgname, 'libs')
if( nzchar( subarch <- .Platform$r_arch))
dll.path <- file.path( dll.path, subarch)
this.ext <- .Platform$dynlib.ext %&% '$' # strictly, should wrap first in 'mvbutils:::to.regexpr'
dlls <- dir( dll.path, pattern=this.ext, full.names=FALSE, ignore.case=.Platform$OS.type=='windows')
names( dlls) <- dlls
ns <- asNamespace( pkgname)
for( idll in dlls) {
dll.name <- sub( this.ext, '', idll)
this.dll.info <- try( library.dynam( dll.name, package=pkgname, lib.loc=libname))
if( this.dll.info %is.not.a% 'try-error') {
assign( 'LL_' %&% dll.name, create.wrappers.for.dll( this.dll.info, ns), ns)
} else if( !ignore_error) {
print( this.dll.info) # error message
stop()
}
} # for dlls
}
"get.backup" <-
function( name, where=1, rev=TRUE, zap.name=TRUE, unlength=TRUE) {
bdd <- get.path.from.where( where)
if( !is.dir( bdd)) {
warning( "Can't find backup directory")
return() }
filename <- get.bkfile( name, bdd, create = FALSE)
if( !nchar( filename)) {
warning( "Can't find backup file")
return() }
# Zap warnings about unterminated lines
ow <- options(warn = -1); on.exit( options( ow))
bu <- readLines(filename); options(ow); on.exit()
if( !length( bu)) {
warning( "Nothing in the backup file")
return()
}
nonblanks <- regexpr( '[^ ]', c( bu, 'x'))>0
bu <- bu[ min( index( nonblanks)) %upto% length( bu)]
# Next line must match 'get.bkfile'
infeasible.R.line <- "'\"@\"@'@ START OF BACKUP @'@\"@\"'"
line.breaks <- bu == infeasible.R.line
if( !sum(line.breaks)) {
warning( "No marker lines in the backup file")
return()
}
bu <- split( bu, cumsum( line.breaks))
bu <- lapply( bu, '[', -(1:2))
if( zap.name) {
zap.name.function <- function( x) {
x[ 1] <- sub( '"[^"]*" <- *', '', x[ 1])
x
}
bu <- lapply( bu, zap.name.function)
}
# Character object backups are preceded by one line giving the length of the object. Remove.
if( unlength)
bu <- lapply( bu, function( x) {
l <- suppressWarnings( as.numeric( x[1]))
if( !is.na( l) && length( x)==l+1)
x <- x[-1]
return( x)
})
if( rev)
bu <- rev( bu)
bu
}
"get.bkfile" <-
function (name, bkdir, create = FALSE)
{
fob <- read.bkind(bkdir)
i <- match(name, fob$object.names)
if (is.na(i)) {
if (!create)
return("")
file.nums <- as.integer(unlist(strsplit(fob$files, "BU", fixed=TRUE)))
n <- min(1:(length(file.nums) + 1) %except% file.nums)
filename <- "BU" %&% n
fob$files <- c(fob$files, filename)
fob$object.names <- c(fob$object.names, name)
cat(paste(fob$files, fob$object.names, sep = "="), sep = "\n",
file = file.path(bkdir, ".Backup.mvb", "index"))
}
else filename <- fob$files[i]
filename <- file.path(bkdir, ".Backup.mvb", filename)
if (!file.exists(filename))
file.create(filename)
filename
}
"get.cd.from.menu" <-
function() {
if(!exists( "tasks", where=1, inherits=FALSE))
tasks <- structure( character(0), names=character(0)) # avoid sort complaining about names
catstop <- function() {
cat( 'No ')
stop( 'merely quitting cd', call.=FALSE)
}
line.end <- if( getOption( 'cd.extra.CR', FALSE)) '\n' else ''
can.go.up <- ifelse( length( .Path) > 1, 1, 0)
to <- menu( c( sort(names(tasks)), if( can.go.up) '..' else NULL,
"CREATE NEW TASK"), graphics = !is.null(getOption('gui')), title = "Task menu")
if(to == 0)
catstop()
if(to == 1 + can.go.up +length(tasks)) {
cat( "Name of new task (ENTER to quit): " %&% line.end)
to <- readline()
if(to=="")
catstop() }
else if( to > length( tasks))
to <- '..'
else
to <- sort( names(tasks))[to]
return( parse( text=to)[[1]])
}
"get.info.for.mcache" <-
function( x, envir, name=TRUE) {
if( name)
x <- envir[[ x]]
lapply( named( cq( mode, class, dim, length, object.size)),
function( f) get(f)(x))
}
"get.last.R.mandatory.rebuild.version" <-
function() {
##############################
# Self-explanatory. NB R.rebuild.vers created in mvbutils:::.onLoad
last.R.major <- numeric_version( sub( '[.][0-9]+[^.]*$', '', as.character( getRversion())))
returnList(
Rrebver=max( R.rebuild.vers %such.that% (. <= last.R.major)),
last.R.major)
}
"get.mcache.reffun" <-
function( whati, envir) {
# Must avoid name clash between 'whati' and internal vars of fx
fx <- function( x) NULL
body( fx) <- substitute(
if( missing( x))
qwhati
else {
mc <- attr( envir, 'mcache')
mci <- as.list( attr( mc, 'info'))
mc[ whati] <- -abs( mc[ whati]) # signal a change
mci[[ whati]] <- get.info.for.mcache( x, name=FALSE)
attr( mc, 'info') <- mci
oldClass( mc) <- 'nullprint'
attr( envir, 'mcache') <- mc
qwhati <<- x
}, list( whati=whati, qwhati=as.name( whati), x=as.name( 'x' %&% whati),
mc=as.name( 'mc' %&% whati)))
names( formals( fx)) <- 'x' %&% whati
e <- new.env( parent=asNamespace( 'mvbutils'))
e$envir <- envir # doesn't work if I sub envir directly into body( fx)
environment( fx) <- e
fx
}
"get.mcache.store.name" <-
function( envir) {
lsnc <- lsall( envir=envir, patt='^\\.mcache[0-9]+$')
if( !length( lsnc))
cache.name <- '.mcache0'
else
cache.name <- lsnc[ order( nchar( lsnc), decreasing=TRUE)[1]]
cache.name
}
"get.new.file.numbers" <-
function( derefs, file.numbers) {
had.numbers <- derefs %such.that% (. %in% names( file.numbers))
file.numbers <- file.numbers %without.name% derefs
derefs <- derefs %except% had.numbers
new.file.numbers <- (1 %upto% max( file.numbers)) %except% file.numbers
new.file.numbers <- c( new.file.numbers, max( c( 0, file.numbers)) +
1 %upto% (length( derefs)-length(new.file.numbers)))[ 1:length(derefs)]
names( new.file.numbers) <- derefs
new.file.numbers
}
"get.path.from.where" <-
function( where){
if( is.character( where) && is.dir( where))
return( where)
if( !is.environment( where)) {
if( length( where) != 1)
stop( "'where' should be length 1")
where <- named( search())[ where] # to character
where <- index( search()==where) # to numeric
if( !is.numeric( where) || is.na( where))
stop( "'where'?")
pfw <- file.path(attr(pos.to.env(where), "path"))
} else
pfw <- attr( where, 'path')
return( pfw)
}
"get.path.list" <-
function ()
{
path.list <- search()
apfun <- function(x) {
x <- attr(pos.to.env(x), "path")
if (!is.null(x))
x <- names(x)[1]
if (is.null(x))
x <- ""
x
}
ap <- sapply(seq(path.list), apfun)
path.list[nchar(ap) > 0] <- ap[nchar(ap) > 0]
path.list
}
"get.ref.info" <-
function( envo, nlocal=sys.parent()) mlocal({
if( is.null( cache <- attr( envo, 'cache')))
attr( envo, 'cache') <- cache <- new.env( hash=TRUE, envo)
lscache <- lsall( cache)
refs <- derefs <- promises <- character(0)
file.numbers <- numeric( 0)
if( length( lscache)) {
refs <- names( which( unlist( eapply( envo, inherits, 'mref'))))
derefs <- lscache %that.are.in% (lsall( envo) %except% refs)
prom.func <- function( x) {cache[[x]] %is.a% 'promise'}
promises <- names( which( sapply( lscache, prom.func)))
fnum.func <- function( x) unclass( envo[[ x]])$nfile
if( length( refs))
file.numbers <- sapply( refs, fnum.func)
}
})
"get.S3.generics" <-
function( pack, ns=TRUE){
if( ns) {
packname <- pack
pack <- asNamespace( pack)
meths <- lsall( pack$.__S3MethodsTable__.)
} else {
packname <- '' # nameless
meths <- find.funs( pack)
}
prefixes <- character( 0)
for( imeth in meths) {
spl <- clip( strsplit( imeth, '.', fixed=TRUE)[[1]])
prefixes <- c( prefixes, sapply( 1 %upto% length( spl),
function( x) paste( spl[ 1:x], collapse='.')))
}
packgens <- unique( prefixes %that.are.in% find.funs( pack))
packgens <- packgens[ unlist( lapply( packgens,
function( f) 'UseMethod' %in% all.names( body( pack[[f]]))))]
structure( rep( packname, length( packgens)), names=packgens)
}
"group" <-
function( m, ...) {
l <- list( ...)
if( length( l)==1 && is.list( l))
l <- l[[ 1]]
rep( names( l), sapply( l, length))[ match( m, unlist( l), NA)]
}
"hack" <-
function( fun, ...){
if( is.character( fun))
fun <- get( fun)
mc <- match.call( expand.dots=FALSE)$...
for( i in names( mc))
formals( fun)[[ i]] <- mc[[ i]]
fun
}
"hack.importIntoEnv" <-
function () { # impenv, impnames, expenv, expnames) {
le <- if( exists( 'base.importIntoEnv', where='mvb.session.info', inherits=FALSE))
get( 'base.importIntoEnv', 'mvb.session.info')
else
baseenv()$importIntoEnv
# NB NB: Probably should do this with activeBinding() not delayedAssign(), to
# ... proof it against subsequent changes
# Also (though not for this function) would be nice to have on-the-fly changes to "Imports"
# ... reflected by 'patch.install'
subbo <- substitute(
{
if( environmentName( expenv) %in% names( maintained.packages)) {
for( i in seq_along( impnames))
do.call( 'delayedAssign', list( x=impnames[ i], value=call( 'get', expnames[i]),
eval.env=expenv, assign.env=impenv))
} else
default
}, list( default=body( le)))
body( le) <- subbo
environment( le) <- asNamespace( 'mvbutils')
le
}
"hack.lockEnvironment" <-
function(){
le <- if( exists( 'base.lockEnvironment', where='mvb.session.info', inherits=FALSE))
get( 'base.lockEnvironment', 'mvb.session.info')
else
baseenv()$lockEnvironment
subbo <- substitute(
{
#cat( 'Checking '); print( env)
#cat( ' '); print( exists( '.__NAMESPACE__.', env, mode='environment', inherits=FALSE))
#cat( ' '); print( exists( '.packageName', env, mode='character', inherits=FALSE))
#cat( ' '); print( sum( match( env$.packageName, names( maintained.packages), 0)))
is.mp.ns <- exists( '.__NAMESPACE__.', env, mode='environment', inherits=FALSE) &&
exists( '.packageName', env, mode='character', inherits=FALSE) &&
sum( match( env$.packageName, names( maintained.packages), 0))
if( is.mp.ns || any( sapply( dont.lock.envs, identical, y=env)) ||
!is.null( attr( env, 'dont.lock.me')) ||
sum( match( attr( env, 'name'), dont.lock.envnames, 0))) {
# cat( "Not locking\n")
if( is.mp.ns) {
dont.lock.envnames <<- c( dont.lock.envnames, 'package:' %&% env$.packageName)
dont.lock.envs <<- c( dont.lock.envs, structure( list( parent.env( env)),
names='imports:' %&% env$.packageName))
}
} else
default
}, list( default=body( le)))
body( le) <- subbo
environment( le) <- asNamespace( 'mvbutils')
le
}
"has.source" <-
function( x) is.function( x) || !is.null( attr( x, 'source'))
"help" <-
function (topic, package = NULL, lib.loc = NULL, verbose = getOption("verbose"),
try.all.packages = getOption("help.try.all.packages"), help_type = getOption("help_type")) {
# help <- get("base.help", pos = "mvb.session.info")
mc <- as.list(match.call(expand.dots = TRUE))
mc[[1]] <- quote( utils::help) # as.environment( 'mvb.session.info')$base.help)
# Set 'mvb_help_type', just in case it's needed
mvb_help_type <- mc$help_type
if( is.null( mvb_help_type))
mvb_help_type <- getOption( 'mvb_help_type', 'text')
if (!is.null(mc$topic) && !is.call(mc$topic) && is.null(mc$type) &&
is.null(mc$lib.loc)) { # && is.null(mc$try.all.packages)) {
h1 <- try(eval(as.call(mc), parent.frame()), silent = TRUE)
if( (h1 %is.not.a% "try-error") && (length(unclass(h1)) > 0))
return( h1)
h1 <- dochelp( as.character( mc$topic), help_type=mvb_help_type)
if( h1 %is.a% c( "pagertemp", "browsertemp"))
return(h1)
}
eval(as.call(mc), parent.frame())
}
"help2flatdoc" <-
function( fun.name, pkg=NULL, text=NULL, aliases=NULL){
# These were buried inside the if() below
if( is.null( text)) {
libpath <- dirname( find.package( pkg))
if( getRversion() >= "2.10") {
al <- readRDS( file.path( libpath, pkg, 'help', 'aliases.rds'))
hfilename <- al[ fun.name]
p1 <- tools$fetchRdDB( file.path( libpath, pkg, 'help', pkg), hfilename)
text <- Rd2txt_easy( p1)
} else {
# Get 'help' to create text, via fake 'pager' function
text <- character( 0)
repager <- function( file, header, title, delete.file) {
text <<- readLines( file)
if( delete.file)
unlink( file)
}
# Now 'print' will invoke 'repager'
# Non-standard treatment of 'package' arg in 'help' requires the following hack:
ufq <- options( useFancyQuotes=FALSE)
eval( substitute(
print( help( fun.name, package=pkg, htmlhelp=FALSE, chmhelp=FALSE, pager=repager,
lib.loc=libpath)),
list( pkg=pkg)))
options( ufq)
}
if( !length( text))
stop( "No help found for " %&% fun.name)
}
if( !grepl( '(?i) R Documentation', text[1])) { # new styleee
text <- c( sprintf( '%s package:%s R Documentation', fun.name, pkg), '', text)
}
text <- help2flatdoc_guts( text, aliases=unique( c( fun.name, aliases)))
class( text) <- 'cat'
text
}
"help2flatdoc_guts" <-
function( text, aliases=NULL) {
text <- gsub( '[' %&% sQuote( '') %&% ']', "'", text)
text <- gsub( '[' %&% dQuote( '') %&% ']', '"', text)
# "Things" are separated by one or more blank lines; convert to single blanks, even in usage/examples
text <- sub( '^ +$', '', text)
text <- c( text, '') # add empty line, maybe to be trimmed
blanko <- which( !nzchar( text))
consec <- diff( c( 0, blanko)) == 1
text <- text[ -blanko[ consec]]
# Headings have weird colour decorations
# Subheadings don't but start in char 1
# Sub-subs start after char 1
# All heading-lines end in a colon; AFAICS nothing else does except an argument with no documentation...
# which deserves punishment and will become a subheading...
# ... or a comment in a R-like bit that happens to end in colon. Assume things with hash can't be headings.
# Tidy up headings
iheadings <- grep( '\b', text, fixed=TRUE)
# ... but first one is the title
headings <- gsub( '_\b', '', text[ iheadings])
text[ iheadings[ 1]] <- headings[ 1]
iheadings <- iheadings[-1]
headings <- headings[-1]
# Tidy the rest of the headings
headings <- toupper( sub( ':$', '', headings))
heading_indents <- regexpr( '[^ ]', headings) # needed later
uhi <- sort( unique( heading_indents)) # 1, x+1, 2x+1, ...
nonblanks <- which( nzchar( text)) # easier to re-do after condensing multiblanks
first_typical <- ( nonblanks %such.that% (. > iheadings[ headings=='DESCRIPTION']))[1]
def_indent <- c( regexpr( '[^ ]', text[ first_typical]))
# Special sections not to be tweaked
noli_me_tangere <- 'xxx' # no indent, clearly odd
specials <- character()
special_ranges <- numeric()
for( special in cq( USAGE, EXAMPLES) %such.that% (. %in% headings)) { # non-funcs might not have this
this <- which( headings==special)
range <- (iheadings[ this]+2) %upto% ( c( iheadings, length( text)+2)[ this+1]-2) # leave blanks around headings
tr <- text[ range]
minind <- min( regexpr( '[^ ]', tr) %such.that% (.>0))
tr <- substring( tr, minind)
if( special=='USAGE') {
# Aliasses: all functions named in USAGE
alias_lmethods <- grep( '## S3( replacement)? method for class|Default S3( replacement)? method', tr)
alias_lines1 <- grep( "^[a-zA-Z0-9._]+\\(", tr, value=TRUE)
alias_funs <- sub( '^([a-zA-Z0-9._]+)\\(.*', '\\1', alias_lines1)
# If there's already an S3-type comment at the end of a method line, then just leave it
# Assume method usages are single-line
if( length( alias_lmethods)) {
subat <- 1+alias_lmethods[ !grepl( '# S3( replacement)? method for ', tr[ 1+alias_lmethods])]
tr[ subat] <- tr[ subat] %&%
sub( '##', ' #', fixed=TRUE,
sub( 'class ', '', fixed=TRUE,
sub( "''", "'", fixed=TRUE,
sub( "'", '"', fixed=TRUE,
tr[ subat-1]))))
tr[ alias_lmethods] <- '\002'
alias_methods <- alias_funs[ alias_lines1 %in% (1+alias_lmethods)]
alias_funs <- alias_funs %except% alias_methods
} else {
alias_methods <- character()
}
alias_lines2 <- grep( "^[^(]+%[a-zA-Z0-9_.]+%", tr, value=TRUE)
alias_ops <- sub( "^[^(]+(%[a-zA-Z0-9_.]+%).*", '\\1', alias_lines2)
aliases <- unique( c( aliases, alias_funs, alias_methods, alias_ops)) %except% sub( ' .*', '', text[1])
}
specials <- c( specials, tr)
special_ranges <- c( special_ranges, range)
text[ range] <- noli_me_tangere
}
# Dot-points are more indented... AFAIK dotch can only occur at start-of-line
dotch <- substring( Rd2txt_easy( options=TRUE)$itemBullet ,1, 1)
# text <- gsub( dotch, '\001', text, fixed=TRUE) # the dotch is a bit hard to manipulate in regexps... though I'm using it here, I guess
# Group adjacent lines. Stop the group either at blank line, or at "verbatim" (over-indented) text
# Don't twiddle headings
gaps <- which( !nzchar( text)) %such.that% (. > iheadings[1])
prev_iheading <- findInterval( gaps, iheadings)
# new_text <- character( length( gaps)-1)
evalq( # for debug speed
for( i in which( head( gaps, -1) %not.in% (iheadings-1))) {
range <- (gaps[i]+1) %upto% (gaps[i+1]-1)
lines <- text[ range]
# How indented do we expect?
indent <- def_indent + regexpr( '[^ ]', headings[ prev_iheading[ i]]) - 1
idot <- regexpr( sprintf( '^ *[%s]', dotch), lines[1], fixed=TRUE)
if( idot>0) {
indent <- idot
}
# Check indentation; if non-code, collapse & unindent all lines of the group
ich1 <- regexpr( '[^ ]', lines[ 1])
if( (ich1>1) && (ich1 <= indent)) { # standard para, or list item
lines <- paste( sub( '^ +', '', lines), collapse=' ')
text[ range[-1]] <- '\002' # mark to kill later
# List items should be *less* indented thx2 Rd2txt_easy
prefix <- if( ich1 < indent) ' ' else '' # list item
text[ range[1]] <- prefix %&% lines
} else if( ich1>indent) {
lines <- substring( lines, ich1)
lines[1] <- '%%#\n' %&% lines[1] # code block
text[ range] <- lines
} # else noli me tangere!
} # for gaps
)
text[ special_ranges] <- specials
text <- sub( dotch, ' -', text, fixed=TRUE) # dot-points
headings <- sub( '^ +', '', headings)
subness <- match( heading_indents, uhi)
# Precede all headings with blank line; spaces to dots; prefix subheadings
headings <- '\n' %&% do.on( subness, rawToChar( rep( charToRaw( '.'), .-1))) %&%
gsub( ' +', '.', sub( '^ +', '', headings))
text[ iheadings] <- headings
# Split lines with code blocks (and extra blank line before headings)
start_of_code <- grep( '\n', text)
text <- multirep( text, start_of_code, strsplit( text[ start_of_code], '\n'))
text <- text[ text != '\002']
text <- c( sub( ' +R Documentation *$', '', text[1]), aliases, text[-1])
return( text)
}
"hook.set.already" <-
function( pkg, hook.type, f, action=cq( append, prepend, replace)){
identical.to.f <- function( x) {
y <- x
attr( y, '.Environment') <- NULL
identical( y, f) }
mangle <- packageEvent( pkg, hook.type)
hooks <- getHook( mangle)
if( !any( sapply( hooks, identical.to.f))) {
action <- match.arg( action)
setHook( mangle, f, action)
}
}
"index" <-
function (lvector)
seq_along( lvector)[lvector]
"install.pkg" <-
function( pkg, character.only=FALSE, lib=.libPaths()[1],
flags=character(0), multiarch=NA, preclean=TRUE)
{
set.pkg.and.dir( FALSE)
# Fucking R continues to fuck up BINPREF and BINPREF64 despite bug report 16919 (from someone else)
# Only solution appears to be to hack <R>/etc/x64/Makeconf to something like this
## BINPREF ?= c:/Rtools/mingw_64/bin/
# BINPREF ?= X:/.../mingw_64/bin
# ifdef BINPREF64
# BINPREF = $(BINPREF64)
# endif
if( preclean) {
flags <- c( '--preclean', flags)
}
if( is.na( multiarch)) {
check_multiarch()
}
if( !multiarch) {
flags <- c( '--no-multiarch', flags)
}
rcmdgeneric.pkg2( pkg, '', indir=sourcedir, outdir='.', cmd='INSTALL',
flags= c( flags, '-l ' %&% shQuote( lib)))
}
"install.proged" <-
function( option.name='program.editor') {
readonly <- ifelse( option.name=='program.reader', 'in read-only mode', '')
cat( 'Must set up program editor information before "fixr" works.')
repeat {
cat( '\nType whatever you\'d type in a command window to',
'invoke your editor', readonly, 'on a file called "myfun.r".',
' For example, on Unix-like systems: myedit myfun.r &',
' In Windows, use double quotes around a path if it contains spaces,',
' and use \\ not \\\\ or / as the separator;',
'to find the path, look at Properties/Shortcut/Target of the icon or shortcut.',
' Otherwise, type <ENTER> to quit: ', sep='\n')
pe.path <- readline()
if( !nchar( pe.path))
return()
if( length( grep( 'myfun\\.r', pe.path))==1)
break
}
pe.path <- strsplit( pe.path, 'myfun.r', fixed=TRUE)[[1]]
if( length( pe.path)==1)
pe.path <- c( pe.path, '')
pe <- substitute( function( name, fname) paste( path1, fname, path2, sep=''),
list( path1=pe.path[1], path2=pe.path[2]))
edit.scratchdir <- Sys.getenv( 'TEMP')
if( !nchar( edit.scratchdir))
edit.scratchdir <- Sys.getenv( 'TMP')
repeat{
cat( 'Enter directory for scratch files (single backslashes only in Windows)')
if( nchar( edit.scratchdir))
cat( 'or <ENTER> for', edit.scratchdir)
cat( ': ')
check <- readline()
if( nchar( check))
edit.scratchdir <- check
if( !is.dir( edit.scratchdir))
mkdir( edit.scratchdir)
if( is.dir( edit.scratchdir))
break
cat( "Can't create directory", edit.scratchdir, "!")
}
edit.scratchdir <- as.vector( edit.scratchdir)[1]
if( option.name=='program.editor') {
backup.fix <- NULL # don't backup by default
repeat{
cat( 'Automatic backups #1: how many backups per session (0 for no backups)? ')
n.per.session <- as.integer( readline())
if( is.na( n.per.session) || n.per.session < 0)
next
if( n.per.session==0)
break
cat( 'Automatic backups #2: how many sessions to keep last version from? ')
n.sessions <- as.integer( readline())
if( is.na( n.sessions) || n.sessions<0)
next
backup.fix <- c( n.sessions, n.per.session)
break
}
o <- substitute( options( program.editor=pe, edit.scratchdir=edit.scratchdir, backup.fix=backup.fix))
} else
o <- substitute( options( program.reader=pe))
eval( o)
cat( 'You should use "fixr" to make sure that the following appears in your .First:',
deparse( o), 'autoedit( TRUE)', '', sep='\n')
options()[[ option.name]]
}
"integ" <-
function( expr, lo, hi, what='x', ..., args.to.integrate=list()) {
f <- function() {}
body( f) <- substitute( expr)
formals( f) <- c( list( x=NULL), as.list( match.call( expand.dots=FALSE)$...))
names( formals( f))[1] <- what
environment( f) <- parent.frame()
do.call( 'integrate', c( list( f, lo, hi), args.to.integrate))$value
}
"internal.copy.ns.objects" <-
function( pkgname, pkgpath){
senv <- as.environment( 'package:' %&% pkgname)
ns <- asNamespace( pkgname)
f <- function( val) blah-blah-blah
environment( f) <- ns
print( objects)
for( x in objects) {
body( f) <- substitute( if( missing( val)) x else x <<- val, list( x=as.name( x)))
makeActiveBinding( x, f, senv)
}
}
"is.dir" <-
function (dir)
{
ok <- file.exists(dir)
ok[ok] <- file.info(dir[ok])$isdir
ok
}
"is.nonzero" <-
function (x)
{
val <- FALSE
if (length(x) == 1) {
if (is.character(x) || is.factor(x))
val <- pmatch(x, "FALSE", 0) == 0
else if (is.logical(x))
val <- x
else if (is.numeric(x))
val <- x != 0
}
val
}
"is.package.installed" <-
function(package, ...) {
# Taken from R.utils whatever that is
# thanks to Henrik Bengtsson for the tip
path <- system.file(package=package)
(path != "")
}
"isF" <-
function( x) {
if( length( x) != 1) {
warning( 'isT/isF expect length-1 arguments; returning FALSE')
}
is.logical( x) && (length( x)==1) && (!is.na( x)) && !x
}
"isT" <-
function( x) {
if( length( x) != 1) {
warning( 'isT/isF expect length-1 arguments; returning FALSE')
}
is.logical( x) && (length( x)==1) && (!is.na( x)) && x
}
"lazify" <-
function( path, package, pkgpath) {
# Taken from tools:::makeLazyLoading
e <- new.env( hash=TRUE)
load( path, e)
file.remove( path)
tools$makeLazyLoadDB( e, file.path( dirname( path), package), compress=TRUE)
# Next line to avoid use of bad cache if reloaded:
LLDBflush( file.path( dirname( path), package %&% '.rdb'))
loaderFile <- file.path( R.home(), "share", "R",
( if( packageHasNamespace( package, dirname( pkgpath))) 'ns') %&% "packloader.R")
file.copy( loaderFile, file.path( dirname( path), package), TRUE)
}
"ldyn.tester" <-
function( chname) {
# Circumvent the package lookup mechanism: package must be a path!
package <- gsub( '[\\]', '/', dirname( chname))
package <- sub( '/libs(/[^/]*)?$', '', package)
stopifnot( is.dir( package))
chname <- file_path_sans_ext( basename( chname))
find.package <- function( package, ...) package
ldyn <- baseenv()$library.dynam
environment( ldyn) <- environment()
rezzo <- ldyn( chname, package, lib.loc='')
return( rezzo)
}
"ldyn.unload" <-
function( l1) {
##################
# l1 from previous call to ldyn.tester
patho <- unclass( l1)$path
dl <- .dynLibs()
whicho <- which( do.on( dl, unclass(.)$path==patho))
stopifnot( length( whicho)==1)
OK <- dyn.unload( patho)
.dynLibs( dl[ -whicho])
return( OK)
}
"least.mutual.dependency" <-
function (funmat, funs, level)
{
group <- funmat[level == 0, level == 0, drop = FALSE]
mode(group) <- "logical"
old.group <- group & FALSE
while (any(group != old.group)) {
old.group <- group
for (i in funs[level == 0]) {
newbies <- group[, group[, i], drop = FALSE] %*%
rep(1, sum(group[, i]))
group[, i] <- group[, i] | (newbies > 0)
}
}
nn <- sum(level == 0)
keep <- c(TRUE, rep(FALSE, nn - 1))
for (i in 2:nn) {
old.group <- matrix(as.vector(group[, i]) == as.vector(group[,
keep]), nrow = nn)
keep[i] <- !any(rep(1, nn) %*% old.group == nn)
}
group <- group[, keep, drop = FALSE]
if (ncol(group) > 1) {
nn <- ncol(group)
old.group <- matrix(0, nn, nn)
for (i in 1:nn) for (j in (1:nn)[1:nn != i]) {
old.group[i, j] <- set.test(group[, i], group[, j])
old.group[j, i] <- -old.group[i, j]
}
old.group[old.group < 0] <- 0
not.keep <- old.group %*% rep(1, nn) > 0
group <- group[, !not.keep, drop = FALSE]
}
group <- dimnames(group)[[1]][apply(group, 1, any)]
match(group, funs[level == 0])
}
"legal.filename" <-
function (name)
{
length.limit <- 250
filenames <- strsplit(substr(name, 1, length.limit), "")[[1]]
filenames[filenames %in% c(":", "*", "?", "'", "/", "\\", '|',
"\"", ">", "<", '+', ' ')] <- "."
if (!(upper.case(filenames[1]) %in% LETTERS))
filenames <- c("X", filenames)
paste(filenames, collapse = "")
}
"library.dynam.reg" <-
function( chname, package, lib.loc, ...) {
ld <- library.dynam( chname, package, lib.loc, ...)
rr <- getDLLRegisteredRoutines( ld, addNames=TRUE)
gnsym <- getNativeSymbolInfo(
c( names( rr$.C), names( rr$.Call), names( rr$.Fortran), names( rr$.External)),
PACKAGE=ld)
ns <- asNamespace( package)
chname <- 'C_' %&% chname
assign( chname, new.env( parent=emptyenv()), envir=ns)
FOR( names( gnsym), assign( ., gnsym[[.]], envir=ns[[ chname]]))
}
"load.maintained.package" <-
function( name, path, task.tree, autopatch=TRUE){
e <- new.env( parent=if( exists( 'emptyenv', mode='function')) emptyenv() else baseenv())
attr( e, 'path') <- structure( path, names=name)
attr( e, 'name') <- name
attr( e, 'task.tree') <- task.tree
# Hooks and maintained.packages[[]] are adjusted before the load,
# ... in case the latter triggers namespacing...
# ... which shouldn't happen, but will if a fun sourcepack accidentally has
# ... the namespace enviro
# Used to test for existence of .onLoad before next line, but
# 1. not sure the test was needed anyway, and
# 2. all packages should have namespaces now
# 3. can't do the test before the load
# if( exists( '.onLoad', e, mode='function'))
setHook( packageEvent( name, 'onLoad'), no.lazyLoad.hook, 'prepend')
setHook( packageEvent( name, 'attach'), no.lazyLoad.attach.hook, 'prepend')
maintained.packages[[ name]] <<- e
assign( '..' %&% name, e, as.environment( 'mvb.session.info')) # alias for ease of access
tryo <- try( load.refdb( envir=e))
if( (tryo %is.a% 'try-error') || !length( lsall( e))) {
warning( "No package '" %&% name %&% "' found during 'maintain.packages'")
rm( e)
try( rm( '..' %&% name, as.environment( mvb.session.info)), silent=TRUE)
maintained.packages <<- maintained.packages %without.name% name
} else {
# Anything being edited from that task?
editees <- fix.list$where == paste( task.tree, collapse='/')
fix.list$where.type[ editees] <<- 'package'
}
}
"load.mvb" <-
function (filename, name, pos, attach.new=is.null( envir) && pos != 1,
path=attr( envir, 'path'), envir=NULL, ...) {
if (attach.new)
envir <- ATTACH(NULL, pos = pos, name = name)
else {
if( is.null( envir))
envir <- as.env(pos)
attr( envir, "name") <- name # which won't work on .GlobalEnv in R3.0+, but never mind
}
# This stuff used to be after the load, but load.refdb needs the path attr set
if( tail( splitto <- strsplit( filename, '.', fixed=TRUE)[[1]], 1)=='rdb') {
LLDBflush( paste( clip( splitto), collapse='.') %&% '.rdb')
lazyLoad( paste( clip( splitto), collapse='.'), envir=envir)
} else
load.refdb(filename, envir = envir, fpath=path)
attr( envir, 'path') <- path
ll <- list(...)
if (length(ll))
for (attro in names(ll)) attr(envir, attro) <- ll[[attro]]
}
"load.refdb" <-
function( file=file.path( fpath, '.RData'), envir, fpath=attr( envir, 'path')) {
envir <- as.env( envir)
if( !file.exists( file))
return()
load( file, envir)
setup.mcache( envir, fpath)
invisible( lsall( envir))
}
"local.on.exit" <-
function( expr, add=FALSE) {
# Assigns expr to on.exit.code in mlocal manager. See local.return for explanation of 'where'
# Don't know what should "really" happen if expr is missing but add is TRUE
subex <- if( missing( expr)) NULL else substitute( expr)
where <- get( 'enclos', envir=parent.frame(2))
if( add) {
oldex <- get( 'on.exit.code', where)
subex <- substitute( { oldex; subex }, returnList( oldex, subex))
}
assign( 'on.exit.code', subex, envir=where)
}
"local.return" <-
function( ...) { # Returns its arguments; unnamed arguments are named using deparse & substitute
orig.mc <- mc <- as.list( match.call())[ -1]
if( length( mc)) {
if( length( mc)==1)
mc <- eval( mc[[1]], envir=parent.frame())
else { # multiple arguments, so return as named list
if( is.null( names( mc)))
which <- 1:length( mc)
else
which <- names( mc)==''
for( i in index( which))
if( is.symbol( orig.mc[[ i]]))
names( mc)[ i] <- as.character( orig.mc[[ i]] )
mc <- lapply( mc, eval, envir=parent.frame())
}
}
# R version. This uses a trick: the call to "eval" that invokes the mlocalized routine
# containing this call to "local.return", sets up a frame with 3 args including "enclos"
# which is actually ignored. However I deliberately set this argument in the final call
# to "eval" inside "mlocal", so that "local.return" knows where to put the answer. This
# is probably dependent on a quirk of implementation.
# The need to do this at all, is that loops terminated with a "break" in R _don't_ have
# the value of the last expression before the break. They do in S.
# Need to hide "override.answer" from stupid CRANiac checks
override.answer <- 'override.answer' # FFS...
assign( override.answer, mc, envir=get( 'enclos', envir=parent.frame(2)))
}
"localfuncs" <-
function( funcs) {
pf <- parent.frame()
funcs <- lapply( named( funcs), get, envir=pf, inherits=TRUE)
for( i in names( funcs)) {
f <- funcs[[ i]]
environment( f) <- pf
assign( i, f, envir=pf)
}
invisible( NULL)
}
"lsall" <-
function( ...) {
mc <- match.call( expand.dots=TRUE)
mc$all.names <- TRUE
mc[[1]] <- as.name( 'ls')
eval( mc, parent.frame())
}
"lsize" <-
function( envir=.GlobalEnv){
envir <- as.env( envir)
mcache <- attr( envir, 'mcache')
mcs <- names( mcache) %that.are.in% lsall( envir)
if( length( mcs)) {
mcfiles <- file.path( attr( envir, 'path'), 'mlazy', 'obj' %&% abs( mcache[ mcs]) %&% '.rda')
mcsize <- file.info( mcfiles)$size
names( mcsize) <- mcs
} else
mcsize <- numeric( 0)
obs <- lsall( envir=envir) %except% mcs
if( length( obs))
obsize <- sapply( named( obs), function( x) object.size( envir[[x]]))
else
obsize <- numeric( 0)
o <- order( c( obsize, mcsize))
obsize <- c( obsize, -mcsize)[o]
return( obsize)
}
"maintain.packages" <-
function( ..., character.only=FALSE, autopatch=FALSE){
if( character.only)
packs <- unlist( list(...))
else {
mc <- as.list( match.call( expand.dots=FALSE)$...)
packs <- sapply( mc, as.character)
}
# Don't reload
# packs <- packs %such.that% (. %not.in% names( maintained.packages))
packs <- packs %except% names( maintained.packages)
# Can't be retrospective
if( length( packs) && (
any( already <- packs %in% loadedNamespaces() ||
!is.na( match( 'package:' %&% packs, search()))))) {
cat( "Can't maintain package(s) {", paste( packs[ already], collapse=','),
"}: already loaded!\n")
packs <- packs[ !already]
}
# Can't be cd'ed into or below the
if( length( packs) && (
any( already <- packs %in% names( .Path)))) {
cat( "Can't maintain package(s) {", paste( packs[ already], collapse=','),
"}: already cd'ed into\n")
packs <- packs[ !already]
}
if( length( packs)) {
snames <- lapply( seq( along=search()), function( x) names( attr( pos.to.env( x), 'path'))[1])
snames[ sapply( snames, is.null)] <- ''
snames <- unlist( snames)
snames <- match( rev( names( .Path)), snames)
tasks <- lapply( snames, function( x)
if( exists( 'tasks', pos.to.env( x), mode='character')) pos.to.env( x)$tasks else character( 0))
owner <- match( packs, names( unlist( tasks)), 0)
packs <- packs[ owner>0]
owner <- rep( 1:length( tasks), sapply( tasks, length))[ owner[ owner>0]]
# Need fully qualified path name, using path attr + task thing which might be relative
for( ipkg in seq( along=packs)) {
pe <- pos.to.env( snames[ owner[ ipkg]])
task.tree <- c( names( .Path)[ 1:(length( snames) + 1 - owner[ ipkg])], packs[ ipkg])
load.maintained.package( packs[ ipkg],
full.path( pe$tasks[ packs[ ipkg]], attr( pe, 'path')),
task.tree)
} # for ipkg
} # if length( packs)
if( autopatch) {
for( ipack in packs)
try({ # eg in case not installed
instpath <- dirname( system.file( '.', package=ipack))
if( instpath=='.')
next
instdate <- file.info( file.path( instpath, 'R', ipack))$mtime
moddate <- file.info( file.path( attr( maintained.packages[[ipack]], 'path'), '.RData'))$mtime
if( moddate > instdate) {
cat( sprintf( "Updating installation of '%s'...", ipack))
try( flush.console()) # try() in case it doesn't exist on this platform
patch.installed( ipack, character.only=TRUE)
cat( 'done\n')
} else
patch.installed( ipack, character.only=TRUE, pre.inst=FALSE, DLLs.only=TRUE) # update "source" DLLs
})
}
return( names( maintained.packages))
}
"make.arguments.section" <-
function( funs=find.funs( env) %except% find.documented( env, doctype='Rd'), file=stdout(),
env=.GlobalEnv) {
arguments <- function( x) {
ax <- names( formals( env[[ x]]))
if( length( ax))
' ' %&% ax %&% ': (' %&% x %&% ')'
else
character( 0)
}
funs <- unlist( lapply( funs, arguments), use.names=FALSE)
if( !is.null( file))
cat( funs, sep='\n', file=file)
invisible( funs)
}
"make.internal.doc" <-
structure( function( funs, package, pkenv) {
if( !length( funs))
return( character( 0))
# xfuns is to cope with operators,
# whose names start with %. This is interpreted as a "don't-show-rest-of-line"
# by the standard flatdoc system, and is removed by 'doc2Rd'.
# So we need to add an extra % symbol.
xfuns <- ifelse( regexpr( '^%', funs)>0, '%', '') %&% funs
text <- c( "PACKAGE-internal package:PACKAGE",
xfuns,
attr( sys.function(), 'usage.header.text'),
make.usage.section( funs, file=NULL, env=pkenv),
attr( sys.function(), 'usage.footer.text'))
text <- gsub( 'PACKAGE', to.regexpr( package), text)
# Split CRs; dunno if there are any nowadays-- this may be fixing something that doesn't happen
# unlist( strsplit( text, '\n')) no, because zaps blank lines
if( length( embedCR <- grep( '\n', text)))
text <- massrep( text, embedCR, strsplit( text[ embedCR], '\n'))
return( unname( text))
}
, usage.header.text = structure(c("", "Internal functions for PACKAGE", "", "DESCRIPTION", "", "Internal functions for 'PACKAGE', not meant to be called directly.", "", "", "USAGE", ""), class = "docattr")
, usage.footer.text = structure(c("", "KEYWORDS", "", "internal"), class = "docattr")
)
"make.NAMESPACE" <-
function( env=1, path=attr( env, 'path'),
description=read.dcf( file.path( path, 'DESCRIPTION'))[1,], more.exports=character( 0)) {
env <- as.environment( env)
import <- paste( description[ 'Depends'], description[ 'Imports'], sep=',')
import <- gsub( '\\([^)]*\\)', '', import)
import <- gsub( ' *', '', import)
import <- strsplit( import, ',')[[1]]
import <- sub( '[<>].*', '', import)
import <- unique( import %except% c( 'R', 'NA'))
# Eliminate non-NAMESPACE packages
has.NAMESPACE <- rep( NA, length( import))
names( has.NAMESPACE) <- import
for( lp in .libPaths()) {
packs <- .packages( T, lp)
new.imps.here <- import[ is.na( has.NAMESPACE) & (import %in% packs)]
if( length( new.imps.here))
has.NAMESPACE[ new.imps.here] <- packageHasNamespace( new.imps.here, lp)
if( !any( is.na( has.NAMESPACE)))
break
}
if( any( is.na( has.NAMESPACE)))
stop( "Can't find depended package " %&% import[ is.na( has.NAMESPACE)])
import <- import[ has.NAMESPACE]
owndoc <- find.documented( env, doctype='own')
# internals <- character(0)
# for( internaldoc in owndoc[ sapply( owndoc, function( x) regexpr( '-internal', attr( get( x), 'doc')[1])>0)]) {
# tc <- unclass( attr( get( internaldoc), 'doc'))[-1]
# gap <- index( regexpr( '[^ ]', tc)<0)[1]
# internals <- c( internals, gsub( ' +', '', tc[ 1 %upto% (gap-1)]))
# }
force.exports <- possible.methods <- ffe <- find.funs( env)
force.exports <- force.exports %SUCH.THAT% !is.null( attr( env[[.]], 'export.me'))
possible.methods <- possible.methods %except% force.exports
export <- unique( c( ffe %that.are.in% find.documented( env),
force.exports, more.exports)) %that.are.in% lsall( env)
methods <- list()
group.generics <- c( "+", "-", "*", "/", "^", "%%", "%/%",
"&", "|", "!",
"==", "!=", "<", "<=", ">=", ">") # from ?S3groupGeneric
# Arguably, should also have the other Groups' group-generics
# but I've never written methods for them, and I can see confusion with eg 'all.equal'. They are:
group.generics <- c( group.generics, cq(
abs, sign, sqrt, floor, ceiling, trunc, round, signif, exp, log, expm1, log1p,
cos, sin, tan, acos, asin, atan, cosh, sinh, tanh, acosh, asinh, atanh,
lgamma, gamma, digamma, trigamma, cumsum, cumprod, cummax, cummin,
all, any, sum, prod, min, max, range,
Arg, Conj, Im, Mod, Re))
prims <- c( .S3PrimitiveGenerics, group.generics)
# Built-in version of '.knownS3Generics' is glaringly crap
.knownS3Generics <- mvb.base.S3.generics
S3.generics <- c( .knownS3Generics, structure( rep( 'base', length( prims)), names=prims))
S3.generics <- S3.generics[ !duplicated( cbind( S3.generics, names( S3.generics)))]
for( ipack in import)
S3.generics <- c( S3.generics, get.S3.generics( ipack, ns=TRUE))
S3.generics <- c( S3.generics, get.S3.generics( env, ns=FALSE))
for( gen in names( S3.generics))
methods[[ gen]] <- possible.methods %that.match% ('^' %&% to.regexpr( gen) %&% '\\.')
methods <- methods %SUCH.THAT% (length(.)>0)
generics <- rep( names( methods), sapply( methods, length))
if( length( methods)) {
# Weed out apparent non-methods
# Default env in arg1 is namespace of package where generic 'x' lives
pseudo.ns <- function( pack) if( nzchar( pack)) asNamespace( pack) else env
arg1 <- function( x, env=pseudo.ns( S3.generics[ x])) {
if( x=='Summary') # the S4 generic in base has first arg 'x', but the S3 has '...'
x <- '...'
else {
x <- names( formals( env[[x]]))[1]
if( is.null( x))
x <- ''
}
x
}
genarg1 <- sapply( named( names( methods)), arg1)
genarg1 <- rep( genarg1, sapply( methods, length))
methods <- unlist( methods, use.names=FALSE)
metharg1 <- sapply( named( methods), arg1, env=env)
is.meth <- genarg1=='' | metharg1==genarg1
methods <- methods[ is.meth]
generics <- generics[ is.meth]
if( length( methods)) {
# Check doco to see if possible methods really are methods
# ...USAGE section should not refer to specific method but to generic
# No doc => no evidence against being a method, but otherwise...
methdoc <- find.docholder( methods, env)
is.meth <- rep( TRUE, length( methods))
methdoclen <- sapply( methdoc, length)
has.doc <- index( methdoclen != 0)
for( i in has.doc) {
docobj <- get( methdoc[[ i]][1], envir=env)
docobj <- if( is.function( docobj)) attr( docobj, 'doc') else docobj
USAGE.line <- grep( '^%?USAGE$', docobj)[1]
ARGUMENTS.line <- grep( '^%?ARGUMENTS$', docobj)[1]
# Is it called by its own name?
if( !is.na( USAGE.line + ARGUMENTS.line))
is.meth[ i] <- !length( grep( '\\<' %&% to.regexpr( methods[ i]) %&% ' *\\(', #)
docobj[ (USAGE.line+1) %upto% (ARGUMENTS.line-1)]))
}
methods <- methods[ is.meth]
generics <- generics[ is.meth]
} # if any possible methods with OK args
} # if any possible methods at all
if( !length( methods)) {
methdoclen <- integer( 0) # avoid woe below
}
classes <- substring( methods, nchar( generics)+2)
# Methods not exported unless explicitly documented
export <- export %except% (methods[ methdoclen==0])
S3 <- matrix( c( generics, classes), ncol=2)
returnList( import, export, S3)
}
"make.new.cd.task" <-
function( task.name, nlocal=sys.parent(), answer, dir.name) mlocal({
# dir.name <- file.path( task.home(), legal.filename( task.name))
dir.name <- './' %&% legal.filename( task.name) # syntax for rel paths: 26/6/2005
line.end <- if( getOption( 'cd.extra.CR', FALSE)) '\n' else ''
repeat {
cat("Default directory = ", dir.name, "\n(names will be expanded relative to ", task.home(),
")\nDirectory: " %&% line.end)
answer <- readline()
if(answer == "")
answer <- dir.name
else {
answer <- gsub( '\\\\', '/', answer)
if( (.Platform$OS.type=='windows' && (substring( answer, 1, 1) != '/') &&
(substring( answer, 2, 2) != ':')) ||
(.Platform$OS.type=='unix' && (substring( answer, 1, 1) %not.in% c('~','/'))) ) {
# want relative path
if( substring( answer, 1, 2) != './')
answer <- './' %&% answer
}
}
if( file.exists( answer)) {
if( !is.dir( answer))
cat("Directory already exists, as a file!\n")
else
break }
else # if !file.exists
if( mkdir( answer))
break
else
cat( 'Failed to create directory ', answer,
'\nWarning: unwanted directories may have been created!\n')
}
dir.name <- answer
if( !exists( 'tasks', where=2, inherits=FALSE))
tasks <- character( 0)
tasks <- c( tasks, dir.name)
names( tasks)[length( tasks)] <- task.name
assign( 'tasks', tasks, pos=2)
pe2 <- pos.to.env( 2)
if( getOption( 'write.mvb.tasks', FALSE))
write.mvb.tasks( tasks, pe2)
Save.pos( 2) # save( list=objects( pos=2, all=TRUE), envir=pe2, file=file.path( attr( pe2, 'path'), '.RData'))
rdata.path <- file.path( dir.name, '.RData')
if( !file.exists( rdata.path))
save( list=character(0), file=rdata.path)
names( dir.name) <- task.name
dir.name
})
"make.Rd2" <-
function( strings, width=NA, methodize=FALSE){
####################
# width NYI: to allow autoclipping of code lines
# basic idea is strwrap, but need to watch for strings and comments
badatt <- FALSE
strings <- gsub( '\\\\%', '%', strings) # because line() will pre-insert backslash before percent
pp <- parse_and_maybe_methodize_USAGE( strings, methodize)
# Reason for {} next, is to avoid incomplete-parsing "errors" eg with if/else
# if( try( pp <- parse( text=c( '{', strings, '}')), silent=TRUE) %is.a% 'try-error') {
if( pp %is.a% 'try-error') {
warning( "Unparsable R-like text") # prolly orta indicate WHERE..!
# but that requires lots of args to be passed in
# Mostly, doc2Rd() says what it is parsing, so user can figga it
# Make everything a comment, and do escapes accordingly
strings <- '#' %&% strings # what about %-starters?
badatt <- TRUE
} else {
strings <- pp # methodized, if requested
}
# Hide escaped quotes
search.string <- "(^|[^\\])([\\\\])+\\"
strings <- gsub( search.string %&% "'", '\\1\\2\001', strings)
strings <- gsub( search.string %&% '"', '\\1\\2\002', strings)
strings <- gsub( search.string %&% "`", '\\1\\2\003', strings)
# strings <- gsub( search.string %&% "n", '\004', strings) # also special
strings <- strings %&% '\n'
sq <- charToRaw( "'")
dq <- charToRaw( '"')
bq <- charToRaw( '`')
hash <- charToRaw( '#')
eol <- charToRaw( '\n') # all hash-modes end at EOL, which is always found
brace <- charToRaw( '{')
backbrace <- charToRaw( '}')
backslash <- charToRaw( '\\')
percent <- charToRaw( '%')
rep.brace <- '\005'
rep.backbrace <- '\006'
rep.backslash <- '\007'
rep.percent <- '\010'
specials <- end.specials <- c( sq, dq, bq, hash)
end.specials[ end.specials==hash] <- eol
state <- 0 # string states are carried across lines
for( istr in seq_along( strings)) {
rch <- charToRaw( strings[ istr])
l <- length( rch)
states <- rep( state, length( rch)) # default
to.do <- rep( TRUE, length( rch))
done <- 0
while( done < length( rch)) {
if( state==0) {
# Match any special
matcho <- sapply( specials, match, table=rch[ to.do], nomatch=l+1-done) + done
next.state <- which.min( matcho)
matcho <- matcho[ next.state]
} else {
# Match only the end-special for this state
matcho <- match( end.specials[ state], rch[ to.do], nomatch=l+1-done) + done
next.state <- 0
}
states[ (done+1) %upto% (matcho-1)] <- state
done <- matcho
to.do <- (done+1) %upto% l
if( matcho <= l)
state <- next.state
}
# Flag characters in rch that need escaping
rch[ rch==backslash] <- charToRaw( rep.backslash)
rch[ rch==percent] <- charToRaw( rep.percent)
escape.braces <- states %in% c( 0, 4)
rch[ escape.braces & rch==brace] <- charToRaw( rep.brace)
rch[ escape.braces & rch==backbrace] <- charToRaw( rep.backbrace)
strings[ istr] <- rawToChar( clip( rch))
}
if( methodize) {
# String-concealing trick was used earlier to hide
# ... method{func}{class} from the semi-parser. Undo trick.
strings <- sub( '( *)"method[{]([^}]*[}])[{]([^}]*[}])"', '\\1\\\\method{\\2{\\3', strings,
perl=FALSE) # NFI why perl=FALSE is needed :/
}
strings <- gsub( '\001', "\\'", strings, fixed=TRUE)
strings <- gsub( '\002', '\\"', strings, fixed=TRUE)
strings <- gsub( '\003', '\\`', strings, fixed=TRUE)
strings <- gsub( '\004', '\\n', strings, fixed=TRUE)
strings <- gsub( rep.percent, '\\%', strings, fixed=TRUE)
strings <- gsub( rep.brace, '\\{', strings, fixed=TRUE)
strings <- gsub( rep.backbrace, '\\}', strings, fixed=TRUE)
strings <- gsub( rep.backslash, '\\\\', strings, fixed=TRUE) # ?is this correct #backslashes?
attr( strings, 'badatt') <- badatt # NULL if parsed OK
return( strings)
}
"make.usage.section" <-
function( funs=find.funs( env) %except% find.documented( env, doctype='Rd'), file=stdout(),
env=.GlobalEnv) {
usage <- function( x) {
if( regexpr( '^%[^%]*%$', x)>0) {
# Assumes binary op with no defaults
y <- names( formals( env[[ x]]))
y <- paste( y[1], x, y[2], sep=' ')
} else {
y <- clip( deparse( args( env[[x]])))
y <- sub( '^ +', ' ', y)
if( make.names( x) != x) # need backquote
x <- '`' %&% x %&% '`'
y[1] <- sub( '^function ', to.regexpr( x), y[1])
y <- paste( y, collapse='')
}
y
}
funs <- unlist( lapply( funs, usage), use.names=FALSE)
if( !is.null( file))
cat( funs, sep='\n', file=file)
invisible( funs)
}
"make_dull" <-
function( df, cols) {
for( icol in cols) {
class( df[[ icol]]) <- unique( c( 'dull', oldClass( df[[ icol]])))
}
return( df)
}
"masked" <-
function (pos) {
if( is.character( pos))
pos <- match( pos, search())
if (any(pos < 2))
return(structure(.Data = character(0), info = "Nothing in .Global.env can be masked!"))
o <- unique(unlist(lapply(pos, objects, all = TRUE)))
all.objects <- unlist(lapply(1:(min(pos) - 1), objects,
all = TRUE), use.names = FALSE)
mm <- match(all.objects, o, 0)
tabu <- tabulate(mm, nbins = length(o))
o[tabu > 0]
}
"masking" <-
function (pos = 1) {
if( is.character( pos))
pos <- match( pos, search())
if (any(pos >= (sl <- length(search()))))
return(structure(.Data = character(0), info = "Objects at the bottom can't mask anything!"))
o <- unique(unlist(lapply(pos, objects, all = TRUE)))
all.objects <- unlist(lapply((max(pos) + 1):sl, objects,
all = TRUE), use.names = FALSE)
mm <- match(all.objects, o, 0)
tabu <- tabulate(mm, nbins = length(o))
o[tabu > 0]
}
"massrep" <-
function( orig, atlist, replist, sorted.at=TRUE){
if( !length( atlist))
return( orig)
repextend <- function( a, r)
if( length( a)==1)
r
else
c( r, rep( list( character(0)), length(a)-1) )
la <- sapply( atlist, length)
rl <- rep( list( orig[0]), sum( la)) # preserves type of 'orig'
rl[ 1 + c( 0, cumsum( clip( la)))] <- replist
return( multirep( orig, unlist( atlist), rl, sorted.at))
}
"max_pkg_ver" <-
function( pkg, libroot, pattern='^[rR][ -]?[0-9]+') {
max.ver <- numeric_version( '0')
while( length( libroot)) {
lib <- libroot[ 1]
ver <- try( packageVersion( pkg, lib), silent=TRUE)
if( ver %is.not.a% 'try-error') {
max.ver <- max( ver, max.ver)
}
potlibs <- dir( lib, pattern=pattern, full.names=TRUE, include.dirs=TRUE) %such.that% is.dir(.)
libroot <- multirep( libroot, 1, list( potlibs))
}
return( max.ver)
}
"maybe.save.after.move" <-
function (to.from) {
if( is.na( to.from$saving)) {
thing.for.message <- if( !is.null( names( to.from$path)))
'"' %&% names( to.from$path) %&% '" [' %&% to.from$path %&% ']'
else
to.from$path
to.from$saving <- yes.no( 'Save workspace of ' %&% thing.for.message %&% '? ')
}
if( to.from$saving)
Save.pos( to.from$env, to.from$path)
}
"mcachees" <-
function( envir=.GlobalEnv)
if( is.null( mcache <- attr( as.environment( envir), 'mcache'))) character(0) else names( mcache)
"mcut" <-
function( x, breaks, pre.lab='', mid.lab='', post.lab='', digits=getOption( 'digits')){
lbreaks <- format( round( breaks, digits=digits)) %&% mid.lab
labs <- pre.lab %&% '[' %&% c( '<' %&% lbreaks[1],
clip( lbreaks) %&% ',' %&% lbreaks[ -1], '>=' %&% rev( lbreaks)[1]) %&% ']' %&% post.lab
if( length( breaks)==1)
labs <- labs[-2]
else if( length( breaks)==0)
labs <- labs[2]
xc <- 1+findInterval( x, breaks)
factor( labs[ xc], levels=labs, ordered=TRUE)
}
"mintcut" <-
function( x, breaks=NULL,
prefix='', all.levels=!is.null( attr( breaks, 'all.levels')), by.breaks=1) {
####################
# Labels of the form 2-7 or 3, or 8+ (for last in range)
# x<breaks[1] := NA
all.levels <- force( all.levels)
x <- as.integer( x)
breaks <- if( is.null( breaks))
seq( floor( min(x, na.rm=TRUE)), ceiling( max( x, na.rm=TRUE)), by=by.breaks)
else
sort( as.integer( breaks))
xc <- findInterval( x, breaks)
xc[ xc==0] <- NA
xlabs <- breaks %&% '-' %&% c( breaks[ -1]-1, Inf)
gap1 <- c( clip( breaks)==breaks[-1]-1, FALSE)
xlabs[ gap1] <- breaks[ gap1]
xlabs[ length( breaks)] <- breaks[ length( breaks)] %&% '+'
xlabs <- prefix %&% xlabs
factor( xlabs[ xc], levels=if( all.levels) xlabs else xlabs[ 1 %upto% max( xc, na.rm=TRUE)],
ordered=TRUE)
}
"mkdir" <-
function( dirlist) {
outcome <- logical(length(dirlist))
for (dir in 1 %upto% length(dirlist)) {
answer <- strsplit(strsplit(dirlist[dir], "/", fixed=TRUE)[[1]], "\\", fixed=TRUE)
# Deal with absolute strings starting with '/'
if( !length( answer[[1]])) {
answer <- answer[-1]
answer[[1]] <- '/' %&% answer[[1]]
}
next.dir <- character(0)
for (i in answer)
if( !is.dir( next.dir <- paste( c( next.dir, i), collapse = "/")) &&
!( substring( next.dir, nchar( next.dir), nchar( next.dir))==':'))
dir.create(next.dir)
outcome[dir] <- is.dir(next.dir)
}
outcome
}
"mlazy" <-
function( ..., what, envir=.GlobalEnv, save.now=TRUE) {
if( missing( what))
what <- sapply( match.call( expand.dots=FALSE)$..., deparse)
if( !length( what))
return()
envir <- as.environment( envir)
what <- what %such.that% (. %in% lsall( envir))
if( !length( what)) {
warning( 'nothing exists to be mlazyed')
return()
}
# Next call used to have a getfrom arg, set to sys.frame( mvb.sys.parent()) ..?
move.to.mcache( what, envir, save.now=save.now)
if( !identical( envir, .GlobalEnv))
save.refdb( envir=envir) # not until asked
}
"mlocal" <-
function( expr) {
sp <- sys.parent()
sp.env <- sys.frame(sp)
# nlocal_ eval( as.name( 'nlocal'), envir=sp.env) # used to work in S but not in R
nlocal <- get( 'nlocal', envir=sp.env)
nlocal.env <- if( is.numeric( nlocal)) sys.frame( nlocal) else as.environment( nlocal)
# on.exit stuff changed 7/2/2005; looks like old version was for Splus
on.exit( {
# eval( sys.on.exit()[[nlocal]], envir=nlocal.env) # zapped
# Get rid of temporaries
remove( list=names( params) %that.are.in%
(lsall( env=nlocal.env) %except% names( savers)), envir=nlocal.env)
# Restore things hidden by params
for( i in names( savers))
assign( i, savers[[ i]], envir=nlocal.env)
# eval( old.on.exit, envir=nlocal.env) # so old code will execute on return to 'nlocal' # zapped
})
eval( expression( on.exit())[[1]], envir=nlocal.env)
params <- formals( sys.function( sp))
params <- params[ names(params)!='nlocal']
savers <- names( params)
if( length( params)) {
names( savers) <- savers
savers <- sapply( savers, exists, envir=nlocal.env, inherits=FALSE)
savers <- names( savers)[ savers]
if( length( savers)) {
names( savers) <- savers
savers <- lapply( savers, function( x) mget( x, envir=nlocal.env)[[1]])
}
# Parameters and temporary working variables:
for( i in names( params)) {
if( eval( call( 'missing', i), envir=sp.env)) {
if( is.symbol( params[[ i]]) && !nzchar( as.character( params[[ i]])) &&
exists( i, envir=nlocal.env, inherits=FALSE))
remove( list=i, envir=nlocal.env)
else
assign( i, params[[i]], envir=nlocal.env) }
#delayedAssign( i, params[[i]], eval.env=nlocal.env, assign.env=nlocal.env) }
else # CHANGED from: bugs here? doesn't force... should do so or use delayedAssign?
assign( i, sp.env[[i]], envir=nlocal.env)
#assign( i, eval( call( 'get', i), envir=sp.env), envir=nlocal.env)
#delayedAssign( i, call( 'eval', i, envir=sp.env), assign.env=nlocal.env)
} # else NORMAL case
} # parameter loop
# Embed "expr" in an artificial loop, so that calls to 'break' at top-level will quit the function. This feature
# is only for S-compatibility. Preferred syntax in R is return( local.return( ...)) which works inside any depth of
# loops
expr <- substitute( repeat{ assign( 'answer', expr, envir=env); break },
list( expr=substitute( expr), env=sys.frame(sys.nframe())))
# The business end!
on.exit.code <- quote( NULL)
eval( expr, envir=nlocal.env, enclos=sys.frame( sys.nframe()))
# New bug fix, 7/2/2005
eval( on.exit.code, envir=nlocal.env, enclos=sys.frame( sys.nframe()))
if( exists( 'override.answer', envir=sys.frame( sys.nframe()), inherits=FALSE)) # set by a call to "local.return"
answer <- override.answer
if( exists( 'answer', envir=sys.frame( sys.nframe()), inherits=FALSE))
answer # else return NULL. Will only happen if user has a "return" call
# without "local.return"-- bad practice.
}
"most.recent" <-
function( lvec) {
stopifnot( is.logical( lvec))
nmax <- length( lvec)
ivec <- index( lvec)
rep( c( 0, ivec), diff( c( 1, ivec, nmax+1)))
}
"move" <-
function( x='.', from='.', to='.', what, overwrite.by.default=FALSE, copy=FALSE) {
if( !missing( what)) {
to <- substitute( from)
from <- substitute( x) }
else {
what <- as.character( substitute( x))
from <- substitute( from)
to <- substitute( to) }
if( (to %is.a% 'call') && (to[[1]]==quote( `$`))) { # maintained package
to <- eval( to, parent.frame())
} else { # normal
if( !is.character( to))
to <- deparse( to)
to <- find.path( char.rel.path=to)
}
if( (from %is.a% 'call') && (from[[1]]==quote( `$`))) { # maintained package
from <- eval( from, parent.frame())
} else { # normal
if( !is.character( from))
from <- deparse( from)
from <- find.path( char.rel.path=from)
}
from <- prepare.for.move( from)
to <- prepare.for.move( to)
if( identical( from$env, to$env) || from$path==to$path)
stop( '"from" and "to" point to the same place!')
found <- !is.na( match( what, from$obj))
if( !all( found))
warning( 'Can\'t find ' %&% paste( what[!found], collapse=','))
what <- what[ found]
if( !length( what)) {
cat( 'Nothing to move!')
return( invisible( character(0))) }
overwrite <- is.na( match( what, to$obj)) | overwrite.by.default
names( overwrite) <- what
for( i in what[!overwrite]) {
all.over <- FALSE
repeat{
cat( 'Overwrite ', i, ' [Y(es)/N(o)/A(ll)]? ')
answer <- upper.case( substring( readline(), 1,1))
overwrite[ i] <- NA
if( answer=='Y')
overwrite[ i] <- TRUE
else if( answer=='N')
overwrite[ i] <- FALSE
else if( answer=='A') {
overwrite[ index( i==what):length( overwrite)] <- TRUE
all.over <- TRUE }
if( !is.na( overwrite[i]))
break }
if( all.over)
break }
what <- what[ overwrite]
if( !length( what)) {
cat( 'Nothing to move!')
return( invisible( character(0))) }
# Changed 14/3/2004 to cope with mrefs
to.mcache <- attr( to$env, 'mcache')
from.mcache <- attr( from$env, 'mcache') # replaces info from to$env
whatrefs <- what %such.that% (. %in% names( from.mcache))
mtidy( what=whatrefs, from$env)
for( i in what %except% whatrefs) {
obj <- from$env[[ i]]
assign( i, obj, envir=to$env)
update.loaded.pkg( names( attr( to$env, 'path')), i, obj) # live pkgs: 6/7/2006
move.backup.file( i, old.dir=from$path, new.dir=to$path)
}
if( length( whatrefs)) {
mkdir( file.path( to$path, 'mlazy')) # otherwise file.rename below won't work
# mcache not applicable to loaded packages, phew
new.to.mcache <- mupdate.mcache( whatrefs, to.mcache, from$env)
from.obj.files <- file.path( from$path, 'mlazy',
'obj' %&% from.mcache[ whatrefs] %&% '.rda')
to.obj.files <- file.path( to$path, 'mlazy',
'obj' %&% new.to.mcache[ whatrefs] %&% '.rda')
suppressWarnings( file.remove( to.obj.files))
renamed <- logical( length( from.obj.files))
for( i in seq_along( from.obj.files))
renamed[i] <- file.rename( from.obj.files[i], to.obj.files[i])
if( any( !renamed))
file.copy( from.obj.files[ !renamed], to.obj.files[ !renamed] )
attr( to$env, 'mcache') <- new.to.mcache
setup.mcache( to$env, refs=whatrefs) # change nfile & env
}
move.fix.list()
maybe.save.after.move( to)
if( !copy) {
remove( list=what, envir=from$env)
if( length( maintained.packages) &&
!is.na( mp <- index( sapply( maintained.packages, identical, from$env))[1]))
rm.pkg( names( maintained.packages)[ mp], list=what, save.=FALSE)
if( length( whatrefs)) {
suppressWarnings( file.remove( from.obj.files))
attr( from$env, 'mcache') <- from.mcache %without.name% whatrefs
}
maybe.save.after.move( from)
}
invisible( what)
}
"move.backup.file" <-
function( name, old.dir, new.dir, copy=FALSE) {
if( !nchar( old.file <- get.bkfile( name, old.dir, create=FALSE)))
return()
new.index <- create.bkind.if.needed( new.dir)
new.file <- get.bkfile( name, new.dir, create=TRUE)
file.copy( from=old.file, to=new.file, overwrite=TRUE)
unlink( old.file)
if( !copy) {
old.index <- create.bkind.if.needed( old.dir) # sure to exist
old.index.contents <- read.bkind( old.dir)
which <- match( name, old.index.contents$object.names)
cat( paste( old.index.contents$files[ -which], old.index.contents$object.names[ -which], sep='='), sep='\n',
file=old.index)
}
}
"move.fix.list" <-
function( nlocal=sys.parent()) mlocal({
fixing <- match( fix.list$name, what, 0) > 0
if( any( fixing)) { # must all be moving to the same place
stt <- search.task.trees()
path.list <- sapply( stt, function( x) attr( pos.to.env( x), 'path'))
if( !is.na( to.match <- match( attr( to$env, 'path'), path.list)[1])) {
fix.list$where[ fixing] <<- names( stt)[ to.match]
fix.list$where.type[ fixing] <<- 'task'
} else {
if( !is.null( attr( to$env, 'name')) && (attr( to$env, 'name') %in% names( maintained.packages))) {
fix.list$where[ fixing] <<- paste( attr( to$env, 'task.tree'), collapse='/')
fix.list$where.type[ fixing] <<- 'package'
} else {
cat( 'Warning: the following have moved out of memory and further fixes will not be committed: ',
paste( fix.list$name[ fixing], collapse=','), '\n')
fix.list <<- fix.list[ !fixing,]
}
}
}
})
"move.to.mcache" <-
function( what, envir, save.now) { # used to have a getfrom arg
mcache <- attr( envir, 'mcache')
if( is.null( mcache))
mcache <- numeric(0)
if( !length( what))
return( mcache)
what <- (what %SUCH.THAT% exists( ., envir=envir)) %SUCH.THAT% !bindingIsActive( ., env=envir)
# what <- what %SUCH.THAT% exists( ., envir=getfrom, inherits=TRUE)
ow <- options( warn=-1)
on.exit( options( ow))
attr( envir, 'mcache') <- mcache <- mupdate.mcache( what, mcache, envir)
path <- attr( envir, 'path')
if( getOption( 'mlazy.subdir', TRUE)) {
dir.create( file.path( path, 'mlazy'), showWarnings=FALSE)
objpath <- file.path( 'mlazy', 'obj')
} else
objpath <- 'obj'
for( i in what) {
# Anything moved to the cache must be saved
this.file <- file.path( path, objpath %&% mcache[ i] %&% '.rda')
xsave( list=i, file=this.file, envir=envir) # used to have envir=getfrom ???
fx <- get.mcache.reffun( i, envir)
environment( fx)[[ i]] <- envir[[ i]]
remove( list=i, envir=envir)
suppressWarnings( makeActiveBinding( i, fx, envir))
}
mupdate.mcache.index.if.opt( mcache, file.path( path, objpath))
return( mcache)
}
"mp.synch" <-
function( pkg){
nspos <- try( asNamespace( pkg), silent=TRUE)
if( nspos %is.not.a% 'try-error') {
# use identical to check whether *really* changed
if( exports.have.changed)
users <- getNamespaceUsers( pkg)
}
pkpos <- match( 'package:' %&% pkg, search(), 0)
if( pkpos>0) {
}
}
"mtidy" <-
function( ..., what, envir=.GlobalEnv) {
if( missing( what))
what <- sapply( match.call( expand.dots=FALSE)$..., deparse)
if( !length( what))
return()
envir <- as.environment( envir)
mcache <- attr( envir, 'mcache')
if( !missing( what)) {
what <- what %such.that% ( . %in% lsall( envir))
mlazy( what=what, envir=envir) # %except% names( mcache), envir=envir) # caused trouble with direct assign
} else
what <- names( mcache) %such.that% ( . %in% lsall( envir))
if( !length( what))
return( invisible( what))
path <- attr( envir, 'path')
if( is.null( path))
stop( 'environment has no path attribute')
save.mchanged( what, envir)
# Replace cachees by new active bindings
remove( list=what, envir=envir)
setup.mcache( refs=what, envir=envir)
invisible( what)
}
"multinsert" <-
function( orig, at, ins, sorted.at=TRUE){
if( !length( at))
return( orig)
if( !is.list( ins))
ins <- if( length( at)==1) list( ins) else as.list( ins) # assumes each ins elt is length-1
if( length( ins) < length( at))
ins <- rep( ins, length( at) / length( ins))
if( !sorted.at) {
o <- order( at)
at <- at[ o]
ins <- ins[ o]
}
inslen <- sapply( ins, length)
# NB replace call in next line: in case at[1]==0
new <- orig[ rep( seq_along( orig), c( 1, 1+inslen)[ 1+match( seq_along( orig),
replace( at, at==0, 1), nomatch=0)])]
new[ rep( at, inslen) + 1:sum( inslen)] <- unlist( ins)
new
}
"multirep" <-
function( orig, at, repl, sorted.at=TRUE){
if( !length( at))
return( orig)
if( !sorted.at) {
o <- order( at)
at <- at[ o]
repl <- repl[ o]
}
replen <- sapply( repl, length)
new <- orig[ rep( seq_along( orig), c( 1, replen)[ 1+match(
seq_along( orig), at, nomatch=0)])]
new[ rep( at, replen) + 1:sum( replen) - rep( 1:length(at), replen)] <- unlist( repl)
new
}
"mupdate.mcache" <-
function( what, mcache, envir) {
had.num <- what %such.that% (. %in% names( mcache))
need.num <- what %except% had.num
if( !length( need.num))
return( mcache)
mci <- attr( mcache, 'info')
if( !length( mcache))
new.mcache <- seq( along=need.num)
else {
new.mcache <- (1 %upto% (max( c( 0, abs( mcache)), na.rm=TRUE) + length( need.num))
) %except% abs( mcache)
new.mcache <- new.mcache[ 1:length( need.num)]
}
names( new.mcache) <- need.num
new.mci <- lapply( need.num, get.info.for.mcache, envir=envir, name=TRUE)
mcache <- c( mcache, new.mcache)
attr( mcache, 'info') <- c( mci, new.mci)
mcache
}
"mupdate.mcache.index.if.opt" <-
function(
mcache=attr( env, 'mcache'),
objpath=file.path( attr( env, 'path'), 'mlazy', 'obj'),
mlazy.index=getOption( 'mlazy.index', FALSE),
env=.GlobalEnv)
if( !is.null( mcache) && mlazy.index)
cat( names( mcache) %&% '\t' %&% abs( mcache), sep='\n', file= objpath %&% '.ind')
"mvb.eval.parent" <-
function( expr, n=1){
p <- mvb.parent.frame( n+1)
eval( expr, p)
}
"mvb.file.copy" <-
function( file1, file2, overwrite=TRUE) {
# file.copy used to stuff up 'mtime' so I wrote a special version. Presumably no longer needed...
# ... and my version (using system calls) was very slow
if( getRversion() >= '3.3.3') { # bug in R's file.copy here; Sys.setFileTime only does one at a time
ok <- file.copy( from=file1, to=file2, overwrite=overwrite,
recursive=FALSE, copy.mode=TRUE, copy.date=FALSE)
for( iok in which( ok)) {
Sys.setFileTime( file2[iok], file.info( file1[iok], extra_cols=FALSE)$mtime)
}
return( ok)
} else if( getRversion() >= '3.4.0') { # nope still not bloody fixed in 3.4.4
return( file.copy( from=file1, to=file2, overwrite=overwrite,
recursive=FALSE, copy.mode=TRUE, copy.date=TRUE))
}
if( .Platform$OS.type=='windows') {
syscopy <- Sys.getenv( 'COMSPEC') %&% ' /c copy /y'
file1 <- '"' %&% gsub( '/', '\\\\', file1) %&% '"'
file2 <- '"' %&% gsub( '/', '\\\\', file2) %&% '"'
copy.same.mtime <- function( f1, f2)
system( paste( syscopy, f1, f2), show.output.on.console=FALSE)
} else {
syscopy <- 'cp'
# Escape spaces and backslashes... and probably all sorts of other crap NFN
subbo <- function( f) {
f <- gsub( '\\', '\001', f, fixed=TRUE)
f <- gsub( ' ', '\\ ', f, fixed=TRUE)
f <- gsub( '\001', '\\\\', f, fixed=TRUE)
}
copy.same.mtime <- function( f1, f2) {
result <- system( paste( syscopy, subbo( f1), subbo( f2)))
if( result==0) {
f1.mtime <- format( file.info( f1)$mtime, '%Y%m%d%H%M.%S')
system( paste( 'touch -m -t ', f1.mtime, subbo( f2)))
}
result
}
}
ok <- rep( FALSE, length( file1))
for( i in seq_along( file1))
if( overwrite || !file.exists( file2[i]))
ok[ i] <- copy.same.mtime( file1[i], file2[i])
return( ok)
}
"mvb.formalize.package.hook" <-
function( default.list) {
default.list$exclude.funs <- character( 0)
default.list
}
"mvb.match.call" <-
function (definition = sys.function( mvb.sys.parent()),
call = sys.call(mvb.sys.parent()),
expand.dots = TRUE,
envir= mvb.parent.frame( 2)) {
# This has to be tricky to get it to work in 'debug'
# eg f <- function( ...) g(...), g <- function( alpha=1) match.call(), f(1)
# It's not clear to me that ... is consistently handled when call is non-default
# ... because it still depends on the calling context
# envir arg added in base-R at some point <= R 3.3
callo <- quote( baseenv()$match.call())
callo[[2]] <- definition
callo[[3]] <- baseenv()$call( 'quote', call)
callo$envir <- envir
callo$expand.dots <- expand.dots
eval( callo, mvb.parent.frame(2))
}
"mvb.nargs" <-
function()
length( sys.calls()[[ mvb.sys.parent()]])-1
"mvb.parent.frame" <-
function (n = 1)
sys.frame( mvb.sys.parent( n+1)) # +1 added Oct 09
"mvb.rbind.data.frame" <-
function( ..., deparse.level=1) {
scatn( "'mvb.rbind.data.frame' is obsolete, but still being called!")
allargs <- list( ...) %SUCH.THAT% !is.null( .)
if( !length( allargs))
return( brdf()) # weird-ass 0*0 DF, as base-R doco mandates (why??!!); should not be reached by dispatch
# This for some kind of compatibility with potty base-R behaviour
is.scalar <- sapply( allargs, is.atomic) & sapply( allargs, is.vector)
allargs[ !is.scalar] <- lapply( allargs[ !is.scalar], data.frame)
ncols <- sapply( allargs[ !is.scalar], ncol)
if( any( ncols != ncols[1]))
stop( 'Differing number of columns')
# Make all scalars into single-row data frames: crazy base-R. Should not be allowed!
if( any( is.scalar)) {
warning( "risky to supply scalar argument(s) to 'rbind.data.frame'")
target <- names( allargs[ !is.scalar][[ 1]])
make.like.target <- function( x) {
xout <- rep( x[1], length( target))
xout[] <- x
names( xout) <- target
data.frame( as.list( xout))
}
allargs[ is.scalar] <- lapply( allargs[ is.scalar], make.like.target)
}
if( length( allargs)==1)
return( allargs[[1]])
rows <- sapply( allargs, nrow)
norows <- rows==0
# 0-row args get a row of NAs. Must avoid calling rbind!
allargs[ norows] <- lapply( allargs[ norows], function( x) {
x <- data.frame( x) # since matrices don't like next line...
x[1,] <- x[1,] # ... which adds a row of NAs, even for cols of DF that are matrices
x
})
# brdf = base::rbind.data.frame, modded to handle classed matrices
rbindo <- do.call( brdf, c( allargs, list( deparse.level=deparse.level)))
if( any( norows)) # should work anyway but...
rbindo <- rbindo[ -cumsum( rows + norows)[norows],,drop=FALSE]
rbindo
}
"mvb.sys.call" <-
function( which=0) {
if( which>0)
sys.call( which) # dotInternal( sys.call( which))
else {
which <- try( mvb.sys.parent( 1-which), silent=TRUE)
if( which %is.a% 'try-error')
stop( 'not that many enclosing functions')
else if( which==0)
NULL # that's what R 1.8.1 does
else
sys.call( which) # dotInternal( sys.call( which))
}
}
"mvb.sys.function" <-
function( n) {
if( missing( n))
n <- mvb.sys.parent()
sys.function( n)
}
"mvb.sys.nframe" <-
function() mvb.sys.parent(1)
"mvb.sys.parent" <-
function(n=1) {
p <- sys.nframe()
frames <- lapply( sys.frames(), list) # this wrapper seems to be necessary to get it to work. R "feature"
parents <- sys.parents()
for( gen in 0 %upto% n)
p <- parents[ which( sapply( frames, identical, frames[[p]]) )[ 1] ] # parent of FIRST pointer to this env in frame list
p
}
"mvbutils.dollar.assign.data.frame" <-
function (x, name, value) {
cl <- oldClass(x)
class(x) <- NULL
nrows <- .row_names_info(x, 2L)
if (!is.null(value)) {
N <- NROW(value)
if (N > nrows) {
if( nrows>0) {
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
} else { # create "empty" version of value
if( length( dv <- dim( value)) > 1L) {
emptyval <- structure( as.vector( value)[0L], dim=c( 0L, dv[-1L]))
if( !is.null( dn <- dimnames( value))) {
newdn <- c( list( character()), dn[-1L])
names( newdn) <- NULL # because I say so
dimnames( emptyval) <- newdn
} # if dimnames
attributes( emptyval) <- c( attributes( emptyval), # dim and maybe dimnames
attributes( value) %without.name% c( 'dim', 'dimnames'))
value <- emptyval
} else {
value <- value[0]
} # ?empty vector, or empty array?
} # if need empty
} else if (N < nrows) {
if (N > 0L && (nrows%%N == 0L) && length(dim(value)) <= 1L)
value <- rep(value, length.out = nrows)
else
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
}
if (is.atomic(value) && !is.null(names(value)))
names(value) <- NULL
} # if something to replace with
x[[name]] <- value
class(x) <- cl
return(x)
}
"mvbutils.subassign.data.frame" <-
function (x, i, j, value) {
if (!all(names(sys.call()) %in% c("", "value")))
warning("named arguments are discouraged")
cl <- oldClass(x)
class(x) <- NULL
nrows <- .row_names_info(x, 2L)
if (is.atomic(value) && !is.null(names(value)))
names(value) <- NULL
if (nargs() < 4L) {
nc <- length(x)
if (!is.null(value)) {
N <- NROW(value)
if (N > nrows) {
if( nrows>0) {
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
} else { # create "empty" version of value
if( length( dv <- dim( value)) > 1L) {
emptyval <- structure( as.vector( value)[0L], dim=c( 0L, dv[-1L]))
if( !is.null( dn <- dimnames( value))) {
newdn <- c( list( character()), dn[-1L])
names( newdn) <- NULL # because I say so
dimnames( emptyval) <- newdn
} # if dimnames
attributes( emptyval) <- c( attributes( emptyval), # dim and maybe dimnames
attributes( value) %without.name% c( 'dim', 'dimnames'))
value <- emptyval
} else {
value <- value[0]
} # ?empty vector, or empty array?
} # if need empty
} else if (N < nrows) {
if (N > 0L && (nrows%%N == 0L) && length(dim(value)) <= 1L)
value <- rep(value, length.out = nrows)
else
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
}
}
x[[i]] <- value
if (length(x) > nc) {
nc <- length(x)
if (names(x)[nc] == "")
names(x)[nc] <- paste0("V", nc)
names(x) <- make.unique(names(x))
}
class(x) <- cl
return(x)
}
if (missing(i) || missing(j))
stop("only valid calls are x[[j]] <- value or x[[i,j]] <- value")
rows <- attr(x, "row.names")
nvars <- length(x)
if (n <- is.character(i)) {
ii <- match(i, rows)
n <- sum(new.rows <- is.na(ii))
if (n > 0L) {
ii[new.rows] <- seq.int(from = nrows + 1L, length.out = n)
new.rows <- i[new.rows]
}
i <- ii
}
if (all(i >= 0L) && (nn <- max(i)) > nrows) {
if (n == 0L) {
nrr <- (nrows + 1L):nn
if (inherits(value, "data.frame") && (dim(value)[1L]) >= length(nrr)) {
new.rows <- attr(value, "row.names")[seq_len(nrr)]
repl <- duplicated(new.rows) | match(new.rows, rows, 0L)
if (any(repl))
new.rows[repl] <- nrr[repl]
} else {
new.rows <- nrr
}
}
x <- xpdrows.data.frame(x, rows, new.rows)
rows <- attr(x, "row.names")
nrows <- length(rows)
}
iseq <- seq_len(nrows)[i]
if (anyNA(iseq))
stop("non-existent rows not allowed")
if (is.character(j)) {
if ("" %in% j)
stop("column name \"\" cannot match any column")
jseq <- match(j, names(x))
if (anyNA(jseq))
stop(gettextf("replacing element in non-existent column: %s",
j[is.na(jseq)]), domain = NA)
} else if (is.logical(j) || min(j) < 0L)
jseq <- seq_along(x)[j]
else {
jseq <- j
if (max(jseq) > nvars)
stop(gettextf("replacing element in non-existent column: %s",
jseq[jseq > nvars]), domain = NA)
}
if (length(iseq) > 1L || length(jseq) > 1L)
stop("only a single element should be replaced")
x[[jseq]][[iseq]] <- value
class(x) <- cl
x
}
"my.all.equal" <-
function (x, y, ...) {
# This *really* shouldn't be needed--- but is :/
# R has, delightfully, changed the behaviour of all.equal() over the years
# I am in a polite frame of mind today (late 2018) so will refrain from further comment
# the ... is so you can tell R to just effin do it, for example
stupid <- all.equal(x, y, ...)
if (!is.logical(stupid))
stupid <- FALSE
return( stupid)
}
"my.fixup.package.URLs" <-
function (pkg, force = FALSE)
{
top <- paste("file:///", chartr("\\", "/", R.home()), sep = "")
fixedfile <- file.path(pkg, "fixedHTMLlinks")
if (file.exists(fixedfile)) {
oldtop <- readLines(fixedfile)
if (!force && (length(oldtop) == 1) && top == oldtop)
return(TRUE)
olddoc <- paste(oldtop, "/doc", sep = "")
oldbase <- paste(oldtop, "/library/base", sep = "")
oldutils <- paste(oldtop, "/library/utils", sep = "")
oldgraphics <- paste(oldtop, "/library/graphics", sep = "")
oldstats <- paste(oldtop, "/library/stats", sep = "")
olddata <- paste(oldtop, "/library/datasets", sep = "")
oldgrD <- paste(oldtop, "/library/grDevices", sep = "")
oldmeth <- paste(oldtop, "/library/methods", sep = "")
}
else {
olddoc <- "../../../doc"
oldbase <- "../../base"
oldutils <- "../../utils"
oldgraphics <- "../../graphics"
oldgrDevices <- "../../grDevices"
oldstats <- "../../stats"
olddata <- "../../datasets"
oldgrD <- "../../grDevices"
oldmeth <- "../../methods"
}
if (!file.create(fixedfile))
return(FALSE)
cat(top, "\n", sep = "", file = fixedfile)
htmldir <- file.path(pkg, "html")
if (!file.exists(htmldir))
return(FALSE)
files <- list.files(htmldir, pattern = "\\.html$", full.names = TRUE)
doc <- paste(top, "/doc", sep = "")
base <- paste(top, "/library/base", sep = "")
utils <- paste(top, "/library/utils", sep = "")
graphics <- paste(top, "/library/graphics", sep = "")
stats <- paste(top, "/library/stats", sep = "")
datasets <- paste(top, "/library/datasets", sep = "")
grD <- paste(top, "/library/grDevices", sep = "")
meth <- paste(top, "/library/methods", sep = "")
# altered by MVB 3/2009, to avoid changing unmodified files
for (f in files) {
page <- readLines(f)
old.page <- page # MVB
page <- gsub(olddoc, doc, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(oldbase, base, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(oldutils, utils, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(oldgraphics, graphics, page, fixed = TRUE,
useBytes = TRUE)
page <- gsub(oldstats, stats, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(olddata, datasets, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(oldgrD, grD, page, fixed = TRUE, useBytes = TRUE)
page <- gsub(oldmeth, meth, page, fixed = TRUE, useBytes = TRUE)
if( identical( page, old.page))
next
out <- try(file(f, open = "w"), silent = TRUE)
if (inherits(out, "try-error")) {
warning(gettextf("cannot update '%s'", f), domain = NA)
next
}
writeLines(page, out)
close(out)
}
return(TRUE)
}
"my.index" <-
function( var, ...) {
# pg <- .Primitive( '[[') # doesn't cope with pairlists
# pg <- function( x, i) .Primitive( '[[')( as.list( x), i) # screws up e.g. on factors
if( getRversion() >= '2.12') {
cc <- unlist( list( ...))
if( length( cc))
return( (baseenv()$'[[')( var, cc))
else
return( var)
}
pg <- function( x, i) .Primitive( '[[')( if( is.pairlist( x)) as.list( x) else x, i)
vv <- as.name( 'var')
for( i in c(...))
vv <- call( 'pg', vv, i)
eval( vv)
}
"my.index.assign" <-
function (var, ..., value) {
if( getRversion() >= '2.12') {
cc <- unlist( list( ...))
if( length( cc))
return( (baseenv()$'[[<-')( var, cc, value))
else
return( value)
}
i <- c(...)
if (length(i) < 2)
return(.Primitive("[[<-")(var, i, value))
pa <- .Primitive("[[<-")
pg <- .Primitive("[[")
vario <- as.name("var")
for (ii in i[-length(i)]) vario <- call("pg", vario, ii)
callio <- substitute(value, env = parent.frame())
for (ii in rev(i)) {
callio <- call("pa", vario, ii, callio)
if (length(vario) > 1)
vario <- vario[[2]]
}
return(eval(callio))
}
"my.index.exists" <-
function( i, var) {
for( ii in 1 %upto% length( i))
if( missing( var) || !is.recursive( var) || i[ ii] > length( var))
return( FALSE)
else
var <- as.list( var)[[ i[ ii] ]]
return( TRUE) }
"named" <-
function (x) {
if( !length( x))
return( x)
names(x) <- as.character(x)
x
}
"named.in.doc" <-
function( doc) {
if( is.null( doc) || !is.character( doc))
return( character( 0))
doc <- gsub( '\t', ' ', doc)
doc <- c( doc, ' ') # guarantees blank
blank <- seq( along=doc) %except% grep( '[^ ]', doc)
namelines <- doc[ 1 %upto% (min(blank)-1)] # 2: to ignore first line
namelines <- sub( '^ +', '', namelines) # leading spaces
namelines <- gsub( ' +[^ ]+', '', namelines) # keep first word only
namelines <- gsub( ' *$', '', namelines) # trailing spaces
namelines
}
"NEG" <-
function( f) {
if( is.null( f))
return( f) # useful for
if( is.primitive( f)) {
fargs <- formals( args( f)) # primitives don't have formals
argo <- lapply( names( fargs), as.name)
gbod <- list( as.name( '-'), as.call( c( list( substitute( f)), argo)))
g <- function() 0
body( g) <- as.call( gbod)
formals( g) <- fargs
environment( g) <- .GlobalEnv
} else {
# f is normal function
g <- f
body( g) <- substitute( {
mc <- match.call()
mc[[1]] <- f
-eval( mc, parent.frame())
}, list( f=f))
formals( g) <- formals( f)
environment( g) <- environment( f)
}
return( g)
}
"no.lazyLoad.attach.hook" <-
function( pkgname, pkglib) {
# Identical to no.lazyLoad.hook, but for search-path version
# Hook to force immediate loading, and to avoid trouble with lazyLoad being out-of-synch later
# Don't force loading of mlazies
ns <- as.environment( 'package:' %&% pkgname)
for( obj in lsall( ns)) {
get.promise <- call( 'substitute', as.name( obj))
c1 <- eval( get.promise, ns)
if( (c1 %is.a% 'call') && (c1[[1]]==as.name( 'lazyLoadDBfetch'))) {
assign( obj, ns[[ obj]], envir=ns) # force and overwrite promise
}
}
}
"no.lazyLoad.hook" <-
function( pkgname, pkglib) {
# Hook to force immediate loading, and to avoid trouble with lazyLoad being out-of-synch later
# Don't force loading of mlazies
ns <- asNamespace( pkgname)
for( obj in lsall( ns)) {
get.promise <- call( 'substitute', as.name( obj))
c1 <- eval( get.promise, ns)
if( (c1 %is.a% 'call') && (c1[[1]]==as.name( 'lazyLoadDBfetch'))) {
# Can force just via ns[[ obj]], but it still leaves the promise lying around...
# ... paranoia wins
# ns[[ obj]] # force
assign( obj, ns[[ obj]], envir=ns) # force and overwrite promise
}
}
}
"noice" <-
function( cc, ...) { # Args of cc on separate lines
cc <- as.list( cc)
zub <- unname( do.on( 2 %upto% length( cc), {
thing <- deparse( as.call( c( list( quote( X)), cc[ .])), ...)
if( length( thing) > 1) {
thing <- thing[1] %&% '...)'
}
sub( ')$', ',', sub( 'X(', '', thing, fixed=TRUE))
}))
zub[ length( zub)] <- sub( ',$', ')', zub[ length( zub)])
zub <- c( deparse( cc[[ 1]]) %&% '(', ' ' %&% zub)
as.cat( zub)
}
"not.for.packaging" <-
function( env){
nfp <- cq( tasks, .Traceback, .packageName, last.warning, .Random.seed, .SavedPlots)
if( !is.null( pkgname <- attr( env, 'name')))
nfp <- c( nfp, pkgname %&% '.package.doc')
if( exists( 'exclude.from.package', mode='character', env))
nfp <- c( nfp, env$exclude.from.package, 'exclude.from.package')
nfp
}
"nscat" <-
function( fmt, ..., sep='\n', file='') {
s <- sprintf( fmt, ...)
s[1] <- '\n' %&% s[1]
s <- paste( s, collapse='\n')
cat( s, file=file)
}
"nscatn" <-
function( fmt, ..., sep='\n', file='') cat( '', sprintf( fmt, ...), sep=sep, file=file)
"old.$[[<-.data.frame" <-
function (x, i, j, value) {
if (!all(names(sys.call()) %in% c("", "value")))
warning("named arguments are discouraged")
cl <- oldClass(x)
class(x) <- NULL
nrows <- .row_names_info(x, 2L)
if (is.atomic(value) && !is.null(names(value)))
names(value) <- NULL
if (nargs() < 4L) {
nc <- length(x)
if (!is.null(value)) {
N <- NROW(value)
if (N > nrows) {
if( nrows>0) {
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
} else { # create "empty" version of value
if( length( dv <- dim( value)) > 1L) {
emptyval <- structure( as.vector( value)[0L], dim=c( 0L, dv[-1L]))
if( !is.null( dn <- dimnames( value))) {
newdn <- c( list( character()), dn[-1L])
names( newdn) <- NULL # because I say so
dimnames( emptyval) <- newdn
} # if dimnames
attributes( emptyval) <- c( attributes( emptyval), # dim and maybe dimnames
attributes( value) %without.name% c( 'dim', 'dimnames'))
value <- emptyval
} else {
value <- value[0]
} # ?empty vector, or empty array?
} # if need empty
} else if (N < nrows) {
if (N > 0L && (nrows%%N == 0L) && length(dim(value)) <= 1L)
value <- rep(value, length.out = nrows)
else
stop(sprintf(ngettext(N, "replacement has %d row, data has %d",
"replacement has %d rows, data has %d"), N, nrows), domain = NA)
}
}
x[[i]] <- value
if (length(x) > nc) {
nc <- length(x)
if (names(x)[nc] == "")
names(x)[nc] <- paste0("V", nc)
names(x) <- make.unique(names(x))
}
class(x) <- cl
return(x)
}
if (missing(i) || missing(j))
stop("only valid calls are x[[j]] <- value or x[[i,j]] <- value")
rows <- attr(x, "row.names")
nvars <- length(x)
if (n <- is.character(i)) {
ii <- match(i, rows)
n <- sum(new.rows <- is.na(ii))
if (n > 0L) {
ii[new.rows] <- seq.int(from = nrows + 1L, length.out = n)
new.rows <- i[new.rows]
}
i <- ii
}
if (all(i >= 0L) && (nn <- max(i)) > nrows) {
if (n == 0L) {
nrr <- (nrows + 1L):nn
if (inherits(value, "data.frame") && (dim(value)[1L]) >= length(nrr)) {
new.rows <- attr(value, "row.names")[seq_len(nrr)]
repl <- duplicated(new.rows) | match(new.rows, rows, 0L)
if (any(repl))
new.rows[repl] <- nrr[repl]
} else {
new.rows <- nrr
}
}
x <- xpdrows.data.frame(x, rows, new.rows)
rows <- attr(x, "row.names")
nrows <- length(rows)
}
iseq <- seq_len(nrows)[i]
if (anyNA(iseq))
stop("non-existent rows not allowed")
if (is.character(j)) {
if ("" %in% j)
stop("column name \"\" cannot match any column")
jseq <- match(j, names(x))
if (anyNA(jseq))
stop(gettextf("replacing element in non-existent column: %s",
j[is.na(jseq)]), domain = NA)
} else if (is.logical(j) || min(j) < 0L)
jseq <- seq_along(x)[j]
else {
jseq <- j
if (max(jseq) > nvars)
stop(gettextf("replacing element in non-existent column: %s",
jseq[jseq > nvars]), domain = NA)
}
if (length(iseq) > 1L || length(jseq) > 1L)
stop("only a single element should be replaced")
x[[jseq]][[iseq]] <- value
class(x) <- cl
x
}
"old.methodize.USAGE" <-
function( nlocal=sys.parent()) mlocal({
# Post-process to set "\method" pedantry in USAGE
# Check for aliases that don't appear in USAGE-- if these appear to be methods of S3 generics, then
# ... tag the USAGE calls with \method
USAGE.start <- grep( '^\\\\usage\\{', Rd)[1]
if( !is.na( USAGE.start)) { # Not all docos have USAGE or ARGUMENTS, e.g. package doco
# All on one line? If so, split
if( grepl( '}', Rd[ USAGE.start], fixed=TRUE)) {
bits <- sub( ' *\\} *$', '', sub( '^\\\\usage\\{ *', '', Rd[ USAGE.start]))
Rd <- multirep( Rd, USAGE.start, list( c( '\\usage{', bits, '}')))
} else if( grepl( '[{] *[^ ]', Rd[ USAGE.start])) {
Rd <- multirep( Rd, USAGE.start, list( c( '\\usage{', substring( Rd[ USAGE.start], nchar( '.usage{')+1))))
}
USAGE.end <- match( '}', Rd[ -(1:USAGE.start)], NA)+USAGE.start
ulines <- (USAGE.start+1) %upto% (USAGE.end-1)
if( FALSE) { # Old code
aliases <- unique( c( overall.name, sub( '\\\\alias\\{ *', '', sub( ' *\\}.*', '',
grep( '\\alias{', Rd, fixed=TRUE, value=TRUE)))))
parzo <- uparzo <- parse( text=gsub( '\\%', '%', Rd[ ulines], fixed=TRUE), keep.source=TRUE)
if( length( parzo)) {
is.a.call <- sapply( parzo, is.call)
is.complass <- is.a.call # complex assignments, e.g. dim(y) <- ...
is.complass[ is.a.call] <- do.on( parzo[ is.a.call],
identical( .[[1]], as.name( '<-')) && is.call( .[[2]]))
which.calls <- which( is.a.call)
srcref <- do.on( which.calls,
unclass( attr( parzo[.], 'srcref')[[1]][ 3:4]))
comments <- substring( Rd[ ulines][ srcref[1,]], srcref[2,]+1)
rx <- regexpr("^ *# *S3 +method +for +(?:class +)?(?<class>(?:(\\w|[.])+|\"[^\"]+\"|'[^']+'))",
comments, perl = TRUE)
is.S3.meth <- rx>0
if( any( is.S3.meth)) {
cs <- attr( rx, 'capture.start')[ is.S3.meth, 'class']
ce <- cs + attr( rx, 'capture.length')[ is.S3.meth, 'class'] - 1
S3.class <- substring( comments[ is.S3.meth], cs, ce)
# CRANia checks no longer like funny-named functions in normal quotes; need backticks
S3.class <- gsub( '^["\']', '`', S3.class)
S3.class <- gsub( '["\']$', '`', S3.class)
# S3.class <- gsub( '\\{', '{', S3.class, fixed=TRUE) # fixes earlier mistake; Lcurly shouldn't be escaped
meth.calls <- which.calls[ which( is.S3.meth)]
for( i in which( is.complass) %that.are.in% meth.calls) {
parzo[[ c( i, 2, 1)]] <- as.name( '@@method@@' %&% as.character( parzo[[ c( i, 2, 1)]]))
}
for( i in which( !is.complass) %that.are.in% meth.calls) {
parzo[[ c( i, 1)]] <- as.name( '@@method@@' %&% as.character( parzo[[ c( i, 1)]]))
}
deparzo <- do.on( parzo, paste( deparse( ., width.cutoff=500), collapse=' '))
deparzo <- gsub( '%', '\\%', deparzo, fixed=TRUE)
deparzo[ which.calls] <- deparzo[ which.calls] %&% comments
deparzo[ meth.calls] <- sprintf( sub( '`@@method@@([^`]+)`', '\\\\method{\\1}{%s}', deparzo[ meth.calls]),
S3.class)
Rd <- massrep( Rd, list( ulines), list( deparzo))
} # if any S3 meths
} # if length parzo
} # END OLD CODE
# New code tested in 'glungo', Dec 2018...
Rcode <- Rd[ ulines]
Rcode <- ' ' %&% Rcode %&% ' ' # so gap ops are legit
Rcode <- c( '{', Rcode, '}')
pp <- try( parse( text=Rcode))
# Parse-error *shouldn't* happen, since code should have been parsed/disinfected
# back in make.Rd2(). But... Also, contentless text (eg all comments) requires no action!
if( (pp %is.a% 'try-error') || (length( pp[[1]])==1)) {
return( local.return())
}
src <- attr( pp[[1]], 'srcref')[-1] # drop with the {}
# Add a spurious final line
src <- c( src, list( rep( src[[ length( src)]][ 3:4] + c( 0, 1), 2)))
pp <- as.expression( as.list( pp[[1]])[-1])
# Gaps between R expressions
for( ipp in seq_along( pp)) {
gappi <- c( src[[ ipp]][3:4]+c(0,1), src[[ipp+1]][1:2]-c(0,1))
at_gap_start <- substring( Rcode[ gappi[ 1]], gappi[ 2])
rx <- regexpr("^ *# *S3 +method +for +(?:class +)?(?<class>(?:(\\w|[.])+|\"[^\"]+\"|'[^']+'))",
at_gap_start, perl = TRUE)
if( rx>0) { # METHOD AHOY! modify preceding function call
cs <- attr( rx, 'capture.start')[ 1, 'class']
ce <- cs + attr( rx, 'capture.length')[ 1, 'class'] - 1
S3.class <- substring( at_gap_start[ 1], cs, ce)
# CRANia checks no longer like funny-named functions in normal quotes; need backticks
S3.class <- gsub( '^["\']', '`', S3.class)
S3.class <- gsub( '["\']$', '`', S3.class)
# S3.class <- gsub( '\\{', '{', S3.class, fixed=TRUE) # fixes earlier mistake; Lcurly shouldn't be escaped
# Now identify the method--- might be an assignment or subset
metho <- as.character( pp[[ c( ipp, 1)]])
is_assign <- metho=='<-'
if( is_assign) {
metho <- as.character( pp[[ c( ipp, 1, 2, 1)]])
}
if( metho %in% c( '[', '[[', '$')) {
# Require the actual call and the S3 message to be all on one line ..!
# subset/assign methods should after all be simple
if( src[[ ipp]][ 1] == src[[ ipp]][ 3]){
warning( "Subset/replace method in USAGE needs to be all on one line. Sorry.'")
# ... but I don't really want to cause a crash, so just do nothing...
# ie "more than my job's worth mate"
} else {
# then we need to replace the actual usage-line(s)--- which should be short--- by fake version
# First, concat the args
args <- paste( deparse( pp[[ c( ipp, 2)]]), collapse=' ')
args <- sub( '\\]+', '', sub( '(\\[+)|\\$)', ',', args))
args <- sprintf( '(%s)', args)
if( is_assign) {
args <- args %&% ' <- ' %&% as.character( pp[[ c( ipp, 3)]])
}
Rcode[ gappi[1]] <- ' ' %&% metho %&% args %&% substring( Rcode[ gappi[ 1]], gappi[2])
}
}
Rcode[ src[[ ipp]][ 1]] <- sprintf( ' \\method{%s}{%s}', metho, S3.class) %&% sub( '^[^(]*[(]', '(', Rcode[ src[[ ipp]][ 1]])
} # if method
} # for expressions
# Remember to strip wrapping {}
Rcode <- Rcode[ -c( 1, length( Rcode))]
# ... and extra starting/trailing spaces
Rcode <- substring( Rcode, 2, nchar( Rcode)-1)
# Reinsert backslashes...
# strings <- gsub( rep.percent, '\\%', strings, fixed=TRUE)
# strings <- gsub( rep.brace, '\\{', strings, fixed=TRUE)
# strings <- gsub( rep.backbrace, '\\}', strings, fixed=TRUE)
# strings <- gsub( rep.backslash, '\\\\', strings, fixed=TRUE) # ?is this correct #backslashes?
#
Rd[ ulines] <- Rcode
} # if USAGE
})
"old.onLoad.stuff" <-
function ( nlocal=sys.parent()) mlocal({
hack.help <- function ( ...) {
# help <- get("base.help", pos = "mvb.session.info")
mc <- as.list(match.call(expand.dots = TRUE))
mc[[1]] <- quote( as.environment( 'mvb.session.info')$base.help)
# Set 'mvb_help_type', just in case it's needed
mvb_help_type <- mc$help_type
if( is.null( mvb_help_type))
mvb_help_type <- getOption( 'mvb_help_type', getOption( 'help_type', "text"))
if (!is.null(mc$topic) && !is.call(mc$topic) && is.null(mc$type) &&
is.null(mc$lib.loc) && is.null(mc$try.all.packages)) {
h1 <- try(eval(as.call(mc), sys.frame( sys.parent())), silent = TRUE)
if (((h1 %is.not.a% "try-error") && length(unclass(h1)) >
0) || ((h1 <- dochelp( as.character( mc$topic), help_type=mvb_help_type)) %is.a%
c( "pagertemp", "browsertemp")))
return(h1)
}
eval(as.call(mc), sys.frame( sys.parent()))
}
formals( hack.help) <- formals( help)
# assign.to.base.opt( 'help', hack.help)
hack.query <- function ( e1, e2) {
# `?` <- get("base.?", pos = "mvb.session.info")
mc <- as.list(match.call())
mc[[1]] <- quote( as.environment( 'mvb.session.info')$'base.?')
if( is.null( mc$e2)) {
# Set 'mvb_help_type', just in case it's needed
mvb_help_type <- mc$help_type
if( is.null( mvb_help_type))
mvb_help_type <- getOption( 'mvb_help_type', getOption( 'help_type', "text"))
h1 <- try(eval(as.call(mc), parent.frame()), silent = TRUE)
if( (h1 %is.not.a% "try-error") && (length(unclass(h1)) > 0))
return( h1)
h1 <- dochelp( as.character( mc$e1), help_type=mvb_help_type)
if( h1 %is.a% c( "pagertemp", "browsertemp"))
return(h1)
# If that failed too, just call it again & permit the crash...
}
eval(as.call(mc), parent.frame())
}
if( FALSE && (getRversion() >= '2.14') && ('print.function' %in% my.reps))
assign.to.base( 'print.function', pfn)
# source.print( TRUE)
})
"old_help2flatdoc_bits" <-
function () {
if( FALSE) { # old code
# cat( length( text), 'lines of help read; class=', class( text), '\n')
otext <- text
text <- c( text, '')
text <- gsub( '[' %&% sQuote( '') %&% ']', "'", text)
text <- gsub( '[' %&% dQuote( '') %&% ']', '"', text)
# Remove bolding of section headings; could have told Rd2txt not to do it...
# ... but it makes them easy to find
is.heading <- regexpr( '^_\b', text) > 0 & regexpr( ':$', text) > 0
text <- gsub( '_\b', '', text)
text[ is.heading] <- upper.case( substring( text[ is.heading], 1, nchar( text[ is.heading])-1))
# Trim leading spaces, but only as far as the indent in DESCRIPTION
is.descrip <- index( text=='DESCRIPTION')[1]
is.normal.line <- grep( '^ *[^ ]', text)
descrip.text.1 <- min( is.normal.line %such.that% (. > is.descrip))
def.indent <- sub( '[^ ].*', '', text[ descrip.text.1])
text <- gsub( '^' %&% def.indent, '', text)
# old brutal version: text <- gsub( '^ +', '', text)
# Zap xtuple spaces *inside* headings
text[ is.heading] <- gsub( '([^ ]+) +', '\\1 ', text[ is.heading])
# Infer subsec level
text[ is.heading] <- sub( secindent, '', text[ is.heading], fixed=TRUE)
text[ is.heading] <- gsub( persubsecindent, '.', text[ is.heading], fixed=TRUE)
expando <- rep( seq( along=text), 1+is.heading)
text <- text[ expando]
is.heading <- is.heading[ expando]
zappo <- 1+index( diff( is.heading)==1)
is.heading[ zappo] <- FALSE
text[ zappo] <- ''
nc <- nchar( text)
nc.next <- c( nc[-1], 0)
nc.prev <- c( 0, clip( nc))
is.heading <- is.heading & nc>0
myhead <- c( '', text[ is.heading])[ 1+cumsum( is.heading)]
is.argdef <- myhead=='ARGUMENTS' & nc>0 & nc.prev==0 &
regexpr( '^( *[[:alpha:]]+,)* *[[:alpha:]]+ *: ', text)>0
text[ is.argdef] <- ' ' %&% text[ is.argdef]
if( any( is.argdef)) {
# Nonblank lines right after an argdef, ie before next blank line, should be joined to previous
is.argdef.contline <- !is.argdef &
(most.recent( is.argdef) > most.recent( nc==0))
text[ is.argdef.contline] <- sub( '^ +', ' ', text[ is.argdef.contline])
}
start.cont <- (myhead %not.in% cq( USAGE, EXAMPLES)) & nc.prev==0 & nc>0 & nc.next>0
mid.cont <- (myhead %not.in% cq( USAGE, EXAMPLES)) & nc>0 & nc.prev>0
end.cont <- (myhead %not.in% cq( USAGE, EXAMPLES)) & nc.prev >0 & nc>0 & nc.next==0
if( any( start.cont | mid.cont)) {
splitto <- split( text[ start.cont | mid.cont], cumsum( start.cont)[ start.cont | mid.cont])
text[ start.cont] <- sapply( splitto, paste, collapse=' ')
}
# All lists left-justified, not colon-justified:
text <- sub( '^ +([A-Za-z0-9_.]+:)', ' \\1', text)
}
}
"option.or.default" <-
function (opt.name, default=NULL) {
value <- getOption(opt.name)
if (!is.null(value))
value
else default
}
"organize.web.display" <-
function( resequence=TRUE, merge01=FALSE, plotmath=FALSE, nlocal=sys.parent()) mlocal({
# Now we have to figure out what level in the hierarchy each fn. belongs at.
# Simple-minded approach: anything NOT called by any other function is top-
# level; anything called only by top-levels is second-level; etc.
level <- rep(0, n); names( level) <- funs
current.level <- 1
if( n>1)
while( any( level==0)) {
tops <- rep( 1, sum( level==0)) %**% funmat[level==0, level==0] == 0
if( !any( tops)) # we have to sort out functions that call each other
tops <- least.mutual.dependency( funmat, funs, level)
level[ (1:n)[ level==0] [tops] ] <- current.level # dimnames( funmat)[[1]]
current.level <- current.level+1 }
else
level[] <- 1
# Super. Now we need to organize things on each level, placing slaves below
# their masters. This OUGHT to be a 'forwards-and-backwards' algorithm,
# because the appropriate placement of masters may depend on which slaves
# they call. EG if you have masters A, B, C, calling slaves (a,c), (b), (c)
# respectively, then ACB is better than ABC, to avoid crossings.
# Bugger that for now! I am going to fix each layer in concrete, and let the
# underlings sort themselves out.
x <- numeric( n)
n.masters <- sum( level==1)
# Now sift out 'level 0 functions'; that is, top-level functions that don't
# call any others. No logical reason for this, but may improve clarity.
if( !merge01) {
level[ level==1 & ((funmat %*% rep(1,n))==0)] <- 0
if( !sum( level==1)) # then we have 'taken the top biscuit'!
level[level==0] <- 1
}
for( current.level in min(level):max(level)) {
if( resequence) {
if( current.level>1) {
# Position of slave 's' is based on mean position of s's callers
slave.of <- funmat[ funs[level<current.level], funs[level==current.level],
drop=FALSE]
pos.order <- (x[ level<current.level] %*% slave.of) /
(rep( 1, sum( level<current.level)) %*% slave.of)
pos.order <- jitter( c( 0, 1, pos.order))[ -(1:2)] }
else if( current.level==1) {
# Rough ordering algorithm for the top layer. The aim is to put heavy
# callers in the middle, light ones at either end.
pos.order <- rank( jitter( c( -2, -1, funmat[ level==1,] %*% rep( 1, n)))[-(1:2)])
pos.order[ pos.order %% 2==0] <-
2*length( pos.order)-pos.order[ pos.order %% 2==0] }
else # level 0 order is arbitrary
pos.order <- 1:sum( level==0)
pos.order <- order( pos.order)
} else # if not resequence
pos.order <- 1:sum(level==current.level)
# Offset x-positions in intermediate levels, to reduce line overlap
# max offset = +/- 0.5 char
# Added 12/2011
level.shift <- if( current.level %in% c( 0, 1, max( level))) 0 else
(current.level-1) / (max( level)-1) - 0.5
# Space out function names ppnl to # of letters
if( plotmath) {
fn <- lapply( funs[ level==current.level], function( x) parse( text=x)[[1]])
nch <- sapply( fn, strwidth)
charlim <- strwidth( paste( rep( 'x', charlim), collapse='')) }
else
nch <- nchar( funs[ level==current.level])
if( exists( 'minstrl', frame=sys.nframe()))
nch <- pmax( nch, minstrl)
nch <- cumsum( nch[ pos.order])
x[ level==current.level][pos.order] <-
(c(0, clip( nch)) + nch + level.shift)/ (2*nch[length(nch)])
layers <- nch[length(nch)] %/% charlim
if( layers)
layers <- rep( 0.1*seq( from=-layers, to=layers, by=2),
sum( level==current.level) / (1+layers) + 1)[
1:sum(level==current.level)]
level[level==current.level][pos.order] <-
level[level==current.level][pos.order] + layers
}
level <- 1+max(round(level))-level
})
"osource.mvb" <-
function( con, envir=parent.frame(), max.n.expr=Inf,
echo=getOption( 'verbose', FALSE), prompt.echo=getOption( 'prompt'),
evaluate=TRUE, debug.script=FALSE) {
############################
# Obsolete version I haven't had the guts to cull
if( !exists( 'source.list', 'mvb.session.info'))
source.list <- list()
else
source.list <- get( 'source.list', 'mvb.session.info')
if( is.character( con))
con <- file( con)
source.list[[ length( source.list)+1]] <- con
put.in.session( source.list=source.list)
if( !isOpen( con)) {
open( con, 'r') # if you want fancy options on e.g. blocking, you need to pre-open 'con'
on.exit( try( close( con)))
}
on.exit( { put.in.session( source.list=clip( source.list)) },
add=TRUE)
orig.line <- 0
ow <- options( warn=-1)
on.exit( options( ow), add=TRUE)
expr.count <- 1
while( expr.count <= max.n.expr) {
# Loop until EOF or a non-blank line
repeat{
check.EOF <- readLines( con, n=1, ok=TRUE)
if( !length( check.EOF) || nchar( check.EOF))
break
}
if( !length( check.EOF))
break
pushBack( check.EOF, con)
# cat( 'Con =', seek( con)); print( con)
# cat( 'Inc=', isIncomplete( con), '\n')
tryo <- try( list( parse( file=con, n=1)), silent=TRUE)
if( tryo %is.a% 'try-error') {
# print( readLines( con))
if( echo)
cat( "parse error; not echoing expression\n")
errline <- as.numeric( rev( strsplit( geterrmessage(), ' ')[[1]])[1])
if( !is.na( errline))
stop( "parse error in line " %&% errline, call.=FALSE)
else
stop( geterrmessage(), call.=FALSE)
}
if( echo) {
dp <- unlist( lapply( tryo[[1]], deparse), use.names=FALSE)
dp[ 1] <- prompt.echo %&% dp[1]
dp[ 2 %upto% length( dp)] <- getOption( 'continue') %&% dp[ 2 %upto% length( dp)]
cat( '', dp, sep='\n')
}
# Experimental code to only evaluate if it seems "useful"-- probably not a good idea
# do.eval <- !is.na( evaluate) && evaluate
# if( is.na( evaluate)) {
# do.eval <- is.call( tryo[[1]][[1]]) && (tryo[[1]][[1]][[1]]=='structure') &&
# is.call( lt <- tryo[[1]][[1]][[ length( tryo[[1]][[1]]) ]] ) &&
# is.name( lt[[1]]) && (as.character(lt[[1]]) %in% cq( readLines.mvb, flatdoc))
# }
# if( do.eval)
if( evaluate) {
last <- {if( identical( unname( debug.script), TRUE)) eval.scriptlet else eval}(
tryo[[ 1]], env=envir)
} else
last <- tryo[[1]][[1]] # get through the 'expression'
if( echo)
try( print( last))
expr.count <- expr.count + 1
}
last
}
"parse_and_maybe_methodize_USAGE" <-
function( Rcode, methodize=NA) {
# Called directly from make.Rd2
# Can be called with methodize=FALSE simply to check parsing--- eg for EXAMPLES
# Previously (mvbutils <- 2.8.210) there was methodize.USAGE which was called
# post hoc on a dot-Rd--- but when revising that to deal with longer lines,
# I hit problems because USAGE already had
# backslash before percent, brace, etc at that stage
orig_Rcode <- Rcode
Rcode <- ' ' %&% Rcode %&% ' ' # so gap ops are legit
Rcode <- c( '{', Rcode, '}')
pp <- try( parse( text=Rcode, keep.source=TRUE), silent=TRUE)
if( (pp %is.a% 'try-error')) {
return( pp)
}
# Content-free text (eg all comments) requires no action
if( (length( pp[[1]])==1) || !methodize) {
return( orig_Rcode)
}
src <- attr( pp[[1]], 'srcref')[-1] # drop with the {}
# Add a spurious final line
src <- c( src, list( rep( src[[ length( src)]][ 3:4] + c( 0, 1), 2)))
pp <- as.expression( as.list( pp[[1]])[-1])
# print( pp)
# print( src)
# Gaps between R expressions
for( ipp in seq_along( pp)) {
gappi <- c( src[[ ipp]][3:4]+c(0,1), src[[ipp+1]][1:2]-c(0,1))
at_gap_start <- substring( Rcode[ gappi[ 1]], gappi[ 2])
rx <- regexpr("^ *# *S3 +method +for +(?:class +)?(?<class>(?:(\\w|[.])+|\"[^\"]+\"|'[^']+'))",
at_gap_start, perl = TRUE)
if( rx>0) { # METHOD AHOY! modify preceding function call
cs <- attr( rx, 'capture.start')[ 1, 'class']
ce <- cs + attr( rx, 'capture.length')[ 1, 'class'] - 1
S3.class <- substring( at_gap_start[ 1], cs, ce)
# CRANia checks no longer like funny-named functions in normal quotes; need backticks
S3.class <- gsub( '^["\']', '`', S3.class)
S3.class <- gsub( '["\']$', '`', S3.class)
# S3.class <- gsub( '\\{', '{', S3.class, fixed=TRUE) # fixes earlier mistake; Lcurly shouldn't be escaped
# Now identify the method--- might be an assignment or subset
metho <- as.character( pp[[ c( ipp, 1)]])
is_assign <- metho=='<-'
if( is_assign) {
metho <- as.character( pp[[ c( ipp, 1, 2, 1)]])
}
if( metho %in% c( '[', '[[', '$')) {
# Require the actual call and the S3 message to be all on one line ..!
# subset/assign methods should after all be simple
if( src[[ ipp]][ 1] == src[[ ipp]][ 3]){
warning( "Subset/replace method in USAGE needs to be all on one line. Sorry.'")
# ... but I don't really want to cause a crash, so just do nothing...
# ie "more than my job's worth mate"
} else {
# then we need to replace the actual usage-line(s)--- which should be short--- by fake version
# First, concat the args
args <- paste( deparse( pp[[ c( ipp, 2)]]), collapse=' ')
args <- sub( '\\]+', '', sub( '(\\[+)|\\$)', ',', args))
args <- sprintf( '(%s)', args)
if( is_assign) {
args <- args %&% ' <- ' %&% as.character( pp[[ c( ipp, 3)]])
}
# Put a nice version of the call
Rcode[ gappi[1]] <- ' ' %&% metho %&% args %&% substring( Rcode[ gappi[ 1]], gappi[2])
}
}
Rcode[ src[[ ipp]][ 1]] <- sprintf( ' "method{%s}{%s}"', metho, S3.class) %&%
sub( '^[^(]*[(]', '(', Rcode[ src[[ ipp]][ 1]])
} # if method
} # for expressions
# Remember to strip wrapping {}
Rcode <- Rcode[ -c( 1, length( Rcode))]
# ... and extra starting/trailing spaces
Rcode <- substring( Rcode, 2, nchar( Rcode)-1)
return( Rcode)
}
"patch.install" <-
function(...){
# Synonym for patch.installed
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- as.name( 'patch.installed')
eval( mc, parent.frame())
}
"patch.installed" <-
function( pkg, character.only=FALSE, force.all.docs=FALSE, help.patch=TRUE, DLLs.only=FALSE,
update.installed.cache=getOption( 'mvb.update.installed.cache', TRUE),
pre.inst=!DLLs.only, dir.above.source='+', R.target.version=getRversion(), autoversion=getOption( 'mvb.autoversion', TRUE)){
########################
set.pkg.and.dir() # dir. sourcedir ewhere pkg (as character)
rpath <- dir.
spath <- sourcedir
if( is.null( rpath))
stop( "Can't find path of raw package '" %&% pkg %&% "'")
is.Rd2 <- R.target.version >= '2.10'
find.pkg <- index( search()=='package:' %&% pkg)[1]
ipath <- if( !is.na( find.pkg))
attr( as.environment( find.pkg), 'path')
else if( pkg %in% loadedNamespaces())
asNamespace( pkg)$.__NAMESPACE__.$path
else
dirname( system.file( '.', package=pkg)) # returns '.' if pkg not installed
if( is.null( ipath) || (ipath=='.'))
stop( "Can't find path of installed package '" %&% pkg %&% "'")
ipath <- ipath[1] # if multiple installations, then fix only topmost
dynamic.help <- is.Rd2 && file.exists( file.path( ipath, 'help', 'paths.rds'))
if( pre.inst) {
pre.install( pkg, character.only=TRUE, force.all.docs=force.all.docs,
R.target.version=R.target.version, dir.above.source=dir.above.source,
autoversion=autoversion)
# If specific docs are forced (via force.all.docs as character), need fixup.help below to notice
force.all.docs <- is.character( force.all.docs) || force.all.docs
}
# DLLs: if new(er)/better, copy to installed place; re-load if in memory
fixup.DLLs( pkg %in% loadedNamespaces(), ipath, rpath, spath, pkg, use.newest=TRUE)
if( DLLs.only)
return( invisible( NULL))
# files to copy
update.installed.dir( spath, ipath, 'demo')
update.installed.dir( spath, ipath, 'exec')
update.installed.dir( spath, ipath, 'data')
if( is.dir( file.path( spath, 'inst'))) {
update.installed.dir( spath, ipath, 'inst', '.', FALSE) # don't zap dirs in installed pkg but not in inst
}
# R functions
if( !file.exists( from <- file.path( spath, 'R', 'funs.rda')))
stop( "No 'funs.rda' file available for quick reinstall")
if( file.exists( nsfile <- file.path( spath, 'NAMESPACE'))) {
file.copy( nsfile, file.path( ipath, 'NAMESPACE'), TRUE)
} else
suppressWarnings( unlink( file.path( ipath, 'NAMESPACE'))) # changed to non-NAMESPACE package!
# Force direct use of NAMESPACE, if any
suppressWarnings( unlink( file.path( ipath, 'Meta', 'nsInfo.rds')))
is.rda <- file.exists( to <- file.path( ipath, 'R', 'all.rda'))
is.rdb <- !is.rda && file.exists( file.path( ipath, 'R', pkg %&% '.rdb'))
# is.rdb==TRUE if lazy-loading
lazy.loading <- getRversion() >= '2.14'
if( !lazy.loading) {
lazy.loading <- tools$.read_description( file.path( ipath, 'DESCRIPTION'))[ 'LazyLoad']
lazy.loading <- is.na( lazy.loading) | (toupper( lazy.loading) %in% c( 'Y', 'YES'))
}
if( lazy.loading)
is.rdb <- TRUE # from R 2.14 on, lazy.loading is always TRUE
must.unload <- FALSE
nsreg <- NULL
if( packageHasNamespace( pkg, dirname( ipath))) {
loader.file <- 'nspackloader.R'
must.unload <- pkg %not.in% loadedNamespaces()
if( !must.unload) {
ns <- asNamespace( pkg)
} else {
ns <- try( loadNamespace( pkg, partial=TRUE))
if( ns %is.a% 'try-error')
stop( "Package isn't loadable; must be sorted out before 'patch.install' will work")
unloadio <- function() {
try( unloadNamespace( ns), silent=TRUE) # prints Error cos of unregistered ns cos of partial load in first place
try( suppressWarnings( rm( list=pkg, envir=nsreg)), silent=TRUE) # actually done
}
on.exit( if( must.unload) unloadio(), add=TRUE)
# Next bit needed otherwise 'identity' below fails to find the namespace, warns, and then replaces it with .GlobalEnv ... :/
nsreg <- get.nsreg()
assign( pkg, ns, envir=nsreg)
}
} else {
ns <- .GlobalEnv
loader.file <- 'packloader.R'
} # loader files may not be used
eapply( ns, identity) # force lazy-loads--- avoid out-of-date lazyload promises later evalling wrong
if( !lazy.loading) { # Raw source
src <- readLines( file.path( spath, 'R', pkg %&% '.R'))
src <- c( ".packageName <- '" %&% pkg %&% "'", src)
cat( src, file=file.path( ipath, 'R', pkg), sep='\n')
} else
file.copy( file.path( R.home(), "share", "R", loader.file), file.path( ipath, 'R', pkg),
overwrite=TRUE)
# For some reason, R2.10 makes a pkg.rdb even if not lazy-loading
if( is.rda | is.rdb) {
e <- new.env()
load( from, envir=e)
f <- find.funs( e) # should be all of them
for( i.f in f) {
g <- e[[i.f]]
environment( g) <- ns
e[[ i.f]] <- g
}
if( is.rda) # Saved image
save( list=lsall( e), envir=e, file=to)
else { # Lazy load
# NB all in-package promises are forced at load-time for maintained packages, so should be no risk
# of loading the wrong bit of the file.
# Should apply to importees, too, thanks to hack of importIntoEnv
tools$makeLazyLoadDB( e, file.path( ipath, 'R', pkg), compress=TRUE)
LLDBflush( file.path( ipath, 'R', pkg %&% '.rdb'))
}
rm( e)
}
if( must.unload) {
unloadio()
must.unload <- FALSE # so it's not repeated on exit
}
# Non-functions
if( file.exists( from.nonfuns <- file.path( spath, 'R', 'sysdata.rda'))) {
# As of ~R2.9, extra data *must* be lazy-loaded
to.nonfuns <- file.path( ipath, 'R', 'sysdata')
e <- new.env()
load( from.nonfuns, envir=e)
tools$makeLazyLoadDB( e, to.nonfuns, compress=TRUE)
LLDBflush( to.nonfuns %&% '.rdb')
rm( e)
# if( file.exists( to.nonfuns %&% '.rdb')) {
# ...code above
# } else
# file.copy( from.nonfuns, to.nonfuns %&% '.rda', TRUE)
}
#fixup.package.info()-- luckily done by:
#tools:::.vinstall_package_descriptions_as_RDS( sub( '/[^/]+$', '', ipath), pkg)
owidth <- options( width=72)
on.exit( options( owidth))
tools$.install_package_description( spath, ipath)
if( file.exists( file.path( ipath, 'NAMESPACE'))) {
tools$.install_package_namespace_info( ipath, ipath)
# Re-register S3 methods
nsInfo <- readRDS( file.path( ipath, 'Meta', 'nsInfo.rds'))
evalq( S3methods <- matrix( '', 0, 3), ns$.__NAMESPACE__.) # purge
evalq( rm( list=ls( all.names=TRUE)), ns$.__S3MethodsTable__.) # purge
registerS3methods( nsInfo$S3methods, pkg, ns)
}
rindex <- file.path( spath, 'INDEX')
iindex <- file.path( ipath, 'INDEX')
if( !identical( md5sum( rindex), md5sum( iindex))) # OK with non-existent files
mvb.file.copy( rindex, iindex)
if( file.exists( vigind <- file.path( spath, 'R', 'meta.vignette.rds')))
file.copy( vigind, file.path( ipath, 'Meta', 'vignette.rds'), overwrite=TRUE)
# more.fixup.vignettes
if( help.patch)
fixup.help() # doesn't yet link properly into search system
if( pkg %in% loadedNamespaces())
fixup.exports( pkg)
if( update.installed.cache)
installed.packages( noCache=TRUE) # reset info
invisible( NULL)
}
"pfn" <-
function( x, useSource=TRUE, ...){
# Obsolete??
if( is.null( sr <- attr( x, 'srcref')) && !is.null( osrc <- attr( x, 'source'))) {
last.line <- max( which( nzchar( osrc)))
last.char <- nchar( osrc[ last.line])
attr( x, 'srcref') <- srcref( srcfilecopy( 'dummy', osrc),
c( 1, 1, last.line, last.char))
}
# AntiCRANKiness FFS; oooh doesn't like mvbutils:::bpf; hates print.function( x, useSource, ...))
eval( asNamespace( 'mvbutils')$body.print.function)
}
"plot.cdtree" <-
function( x, ...) {
foodweb( x, ...)
invisible( x)
}
"plot.foodweb" <-
function( x, textcolor, boxcolor, xblank, border, textargs=list(), use.centres=TRUE, color.lines=TRUE,
poly.args=list(), expand.xbox=1.05, expand.ybox=expand.xbox*1.2, plotmath=FALSE, cex=par( 'cex'),
...) {
for( ipar in cq( boxcolor, xblank, border, textcolor))
if( do.call( 'missing', list( ipar)))
assign( ipar, formals( foodweb)[[ ipar]])
# Weird buggy R bollox with changing the font sizes--- the 'ps' param gets decremented by 1 *every* time it's reset!!!
# FFS... have had to work round this in foodweb itself
oldwarn <- options( warn=-1)$warn
oldpar <- par( no.readonly=TRUE) %without.name% 'ps' # %such.that% grepl( 'cex', names( .)) # , new=FALSE)
on.exit( par( oldpar))
if( names( dev.cur())=='RGUI-BUG-windows') { # par( 'ps') SNAFU
oldpar$ps <- par( 'ps') + 1L
on.exit( scatn( '%i %i', par( ps=5)$ps, par( 'ps')), add=T) # oldpar$ps+2L), add=TRUE)
}
options( warn=oldwarn)
do.call( 'par', list( mar=c(1,2,1,2), ...))
web <- x # called 'x' in arglist only to match generic 'plot'
level <- web$level; funmat <- web$funmat; x <- web$x; funs <- names(level)
n <- length( level)
# if( names(dev.cur()[1])=='graphsheet') {
# gs <- guiGetCurrMetaDoc( 'GraphSheet')
# colortab <- guiGetPropertyValue( 'GraphSheet', Name=gs, 'ColorTable')
# colortab <- unlist( unpaste( colortab, '|'), use=FALSE)
# boxcolor <- background <- length( colortab)
## Can't get background color directly as a number. Make it the negative of the first colour!
# background.color <- 255 - as.numeric( unlist( unpaste( colortab[1], ','), FALSE))
# colortab[ background] <- paste( background.color, collapse=',') # '255,255,255'
# colortab <- paste( colortab, collapse='|')
# guiModify( 'GraphSheet', Name=gs, ColorTable=colortab)
# }
plot( 0:1, c(min(level)-0.5, max( level)+0.5), axes=FALSE, type='n',
xlab='', ylab='', main='')
from <- rep( 1:n, n)[ funmat>0]
to <- rep( 1:n, rep(n,n))[ funmat>0]
same <- round(level[from])== round(level[to])
if( any( same)) {
segments( (x[from[same]]+x[to[same]])/2, level[from[same]]+0.5,
x[ to[same]], level[ to[same]], col=if( color.lines) level[from[same]] else 1 )
arrows( x[from[same]], level[from[same]], (x[from[same]]+x[to[same]])/2,
level[from[same]]+0.5, #size=par('cin'), open=TRUE, works in Splus
col=if( color.lines) level[from[same]] else 1)
from <- from[!same]; to <- to[!same] }
# Now just the different-level calls (the vast majority). Used to have arrows
# here too, but can make for too much clutter!
if( identical( version$language, 'R')) {
if( plotmath)
funs <- lapply( funs, function( x) parse( text=x)[[1]])
sw <- sapply( funs, strwidth); sh <- sapply( funs, strheight) # works for plotmath expressions as well as text
} else
sw <- sh <- 0
if( length( from)) {
if( use.centres)
segments( x[from], level[from], x[to], level[to], col=if( color.lines) level[from] else 1 )
else
segments( x[from], level[from]-sh[from]/2, x[to], level[to]+sh[to]/2, col=if( color.lines) level[from] else 1)
}
# arrows( x[from], level[from], (x[to]+x[from])/2,
# (level[from]+level[to])/2, size=par('cin'), open=TRUE)
# Empty boxes for text. Doesn't work in Splus 4.0.
# charscale <- par('1em')
# if( is.null( charscale))
charscale <- par( 'cxy')
if( is.null( xblank))
xblank <- 1
if( identical( version$language, 'R'))
do.call( 'rect', c( list( x-expand.xbox*sw/2, level-expand.ybox*sh/2,
x+expand.xbox*sw/2, level+expand.ybox*sh/2, border=border, col=boxcolor), poly.args))
else
do.call( 'polygon', c( list( rep( x, rep( 5, n))+xblank*charscale[1]*rep( nchar( funs), rep( 5, n))*c(-1,-1,1,1,NA),
rep( level, rep( 5, n))+0.5*charscale[2]*c(-1,0.5,0.5,-1,NA), col=boxcolor), poly.args))
retlist <- returnList( x, level, funs)
for( i in seq( along=x))
text( x[i], level[i], funs[[i]], col=textcolor, cex=cex)
# do.call( 'text', c( unname( retlist), list( col=textcolor), textargs))
mc <- as.list( match.call( expand.dots=TRUE))
print( mc)
ac <- formals( sys.function())
not.named <- names( ac) %except% c( names( mc), '...')
for( i in not.named)
mc[[ i]] <- get( i)
mode( mc) <- 'call'
attr( retlist, 'call') <- mc
invisible( retlist)
}
"pos" <-
function(substrs, mainstrs, any.case = FALSE, names.for.output) {
ls <- length(substrs)
lm <- length(mainstrs)
.pos <- function(substr, mainstr)
{
ns <- nchar(substr)
nm <- nchar(mainstr)
if(ns > nm)
return(0)
mainstr <- substring(mainstr, 1:(nm - ns + 1), ns:nm)
t <- (1:length(mainstr))[mainstr == substr]
if(length(t) == 0)
0
else t
}
if(any.case) {
substrs <- upper.case(substrs)
mainstrs <- upper.case(mainstrs)
}
if((ls == 1) && (lm == 1))
return(matrix(.pos(substrs, mainstrs), 1))
if((ls %% lm) * (lm %% ls))
warning( "Length of longer not a multiple of length of shorter")
if(ls < lm) {
if(missing(names.for.output))
names.for.output <- names(mainstrs)
substrs <- rep(substrs, (lm %/% ls) + 1)
}
else if(ls > lm) {
if(missing(names.for.output))
names.for.output <- names(substrs)
mainstrs <- rep(mainstrs, (ls %/% lm) + 1)
}
else if(missing(names.for.output))
names.for.output <- names(mainstrs)
ls <- max(ls, lm)
j <- vector("list", ls)
for(i in (1:ls))
j[[i]] <- .pos(substrs[i], mainstrs[i])
max.n.pos <- max(sapply(j, length))
if(max.n.pos == 1)
jj <- matrix(unlist(j), 1)
else {
jj <- sapply(j, function(x, w)
c(x, rep(0, w - length(x))), w = max.n.pos)
}
dimnames(jj) <- list(character(0), names.for.output)
t(jj)
}
"pre.install" <-
structure( function( pkg, character.only=FALSE, force.all.docs=FALSE,
dir.above.source='+', autoversion=getOption( 'mvb.autoversion', TRUE),
R.target.version=getRversion(), ...) {
#########
set.pkg.and.dir( FALSE) # set 'dir.', 'sourcedir', and 'ewhere', and ensure 'pkg' is character
# Herewith a fudge to avoid unnecessary file-copies of mlazy objects later on
# ... move all existing inst/mlazy/obj**.rda files into a tempdir
mlazy.temp.dir <- NULL
if( is.dir( mlazy.inst.dir <- file.path( sourcedir, 'inst', 'mlazy'))) {
# Some fairly paranoid programming here
tdctr <- 0
while( file.exists( mlazy.temp.dir <- file.path( dir., 'temp-inst-mlazy' %&% tdctr)))
tdctr <- tdctr + 1
mkdir( mlazy.temp.dir)
mlazy.OK <- FALSE # reset later if all goes well
on.exit({
if( !mlazy.OK) {
suppressWarnings( mkdir( mlazy.inst.dir))
mlazy.inst.files <- dir( mlazy.temp.dir, pattern='^obj[0-9]+.rda$')
for( fi in mlazy.inst.files)
file.rename( file.path( mlazy.temp.dir, fi),
file.path( mlazy.inst.dir, fi)) # won't overwrite newer versions
}
unlink( mlazy.temp.dir, TRUE)
}) # on.exit
old.mlazy.files <- dir( mlazy.inst.dir, pattern='^obj[0-9]+.rda$')
for( fi in old.mlazy.files)
file.rename( file.path( mlazy.inst.dir, fi), file.path( mlazy.temp.dir, fi))
}
unlink( file.path( sourcedir), recursive=TRUE)
if( !all( mkdir( file.path( sourcedir, cq( R, man, inst)))))
stop( "couldn't make essential directories")
# Precedence now given to an internal text object 'mypack.DESCRIPTION'
if( !is.null( description <- ewhere[[ pkg %&% '.DESCRIPTION']])) {
cat( description, sep='\n', file=file.path( dir., 'DESCRIPTION'))
}
if( file.exists( description.file <- file.path( dir., 'DESCRIPTION'))) {
# Can't do in one step as gsub strips names
description <- read.dcf( description.file)[1,]
description[] <- gsub( '\n', ' ', description)
} else {
description <- c( Package=pkg, Title='What the package does',
Version='1.0.0', Author='R.A. Fisher', Description='More about what it does',
Maintainer='Who to complain to <yourfault@somewhere.net>',
License='???') # adapted from 'package.skeleton'
cat( sprintf( '%s: %s', names( description), description),
file=file.path( dir., 'DESCRIPTION'), sep='\n')
}
# Autoversion: package must already be installed, and have at least 3 parts to version number
if( autoversion) {
should.inc.version <- TRUE
ood.version <- ewhere[[ pkg %&% '.VERSION']]
if( is.null( ood.version)) {
ood.version <- try( package_version( ood.version, strict=TRUE))
if( (ood.version %is.a% 'try-error') || (length( ood.version) != 1)) {
warning( sprintf( "Illegal package version in '%s.VERSION': %s", pkg, ewhere[[ pkg %&% '.VERSION']]))
ood.version <- NULL
}
}
if( is.null( ood.version)) {
# Choose newer of installed and DESCRIPTION...
# ... but these may not be all possible installed versions
# ... eg for later versions of R than is now running
inst.version <- max_pkg_ver( pkg, .libPaths())
desc.version <- try( package_version( description[ 'Version']))
if( inst.version %is.a% 'try-error') {
inst.version <- desc.version
} else if( desc.version %is.a% 'try-error') {
desc.version <- inst.version
}
if( inst.version %is.a% 'try-error') {
warning( "Can't deduce version: setting to 1.0.0")
ood.version <- numeric_version( '1.0.0')
should.inc.version <- FALSE
} else {
ood.version <- if( inst.version > desc.version) inst.version else desc.version
}
}
# Update the description
ood.version <- as.character( ood.version)
if( should.inc.version) {
ok.bit <- sub( '([.-])[0-9]+$', '\\1', ood.version)
last.bit <- as.numeric( substring( ood.version, nchar( ok.bit)+1))
last.bit <- last.bit + 1
new.version.str <- ok.bit %&% last.bit
} else {
new.version.str <- ood.version
}
description[ 'Version'] <- new.version.str
assign( pkg %&% '.VERSION', new.version.str, envir=ewhere)
Save.pos( ewhere)
}
description <- description %without.name% c( 'Built', 'LazyLoad', 'SaveImage')
# description[ 'SaveImage'] <- 'yes'
# description[ cq( LazyLoad, LazyData)] <- 'no'
changes.file <- file.path( dir., 'changes.txt')
changes.exists <- exists( 'changes.txt', mode='character', ewhere, inherits=FALSE)
has.changelog <- changes.exists || file.exists( changes.file)
if( has.changelog) {
# description[ 'ChangeLog'] <- 'inst/changes.txt' # removed for R 3.0 CRANal checks
if( changes.exists)
cat( ewhere$changes.txt, file=file.path( sourcedir, 'inst', 'changes.txt'),
sep='\n')
else
mvb.file.copy( changes.file, file.path( sourcedir, 'inst', 'changes.txt'), TRUE)
}
# Sometimes makefiles live in the main dir, instead of / as well as in src:
if( length( makes.in.top <- dir( dir., pattern='^Makefile')))
mvb.file.copy( file.path( dir., makes.in.top), file.path( sourcedir, makes.in.top))
fixup.DLLs( TRUE, NULL, dir., sourcedir, pkg)
excludo <- ewhere[[ pkg %&% '.file.exclude.regexes']]
if( !length( excludo))
unexcluded <- identity
else
unexcluded <- function( strs) {
o <- do.call( 'rbind', lapply( excludo, grepl, x=strs))
strs[ !apply( o, 2, any)]
}
get.nondirs <- function( x, recursive=TRUE) {
if( is.dir( cdir <- file.path( dir., x))) {
f <- unexcluded( file.path( x, list.files( cdir, all.files=TRUE, full.names=FALSE, recursive=recursive)))
return( f)
} else
return( character( 0))
}
copies <- lapply( named( cq( inst, src, data, demo, vignettes, exec, tests)), get.nondirs, recursive=TRUE)
# Allow non-functions to be documented via aliasses in func doco
allfuns <- find.funs( ewhere)
allthings <- lsall( ewhere)
alldoc <- find.documented( ewhere, doctype='Rd', only.real.objects=FALSE)
nonfuncs.docoed.in.funcs <- alldoc %except% allfuns
# Documented non-functions and ine
extra.docs <- (allthings %that.match% '\\.doc$') %SUCH.THAT% exists( ., ewhere,
mode='character')
named.in.extra.docs <- unlist( lapply( extra.docs,
function( x) named.in.doc( ewhere[[x]])))
# avoid mvbutils-utils
named.in.extra.docs <- unique( c( named.in.extra.docs, nonfuncs.docoed.in.funcs)
) %that.are.in% allthings
# Namespace
use.existing.NAMESPACE <- FALSE
if( NAMESPACE.exists <- file.exists( file.path( dir., 'NAMESPACE'))) {
nscontents <- readLines( file.path( dir., 'NAMESPACE'))
use.existing.NAMESPACE <- any( regexpr( '^ *export(Pattern)? *\\(', nscontents) > 0)
}
has.namespace <- NAMESPACE.exists || exists( '.onLoad', ewhere, inherits=FALSE) ||
!is.na( description[ 'Imports']) || (R.target.version >= '2.14')
# Next line is default namespace stuff-- may not use
forced.exports <- if( exists( 'forced!exports', ewhere, mode='character',
inherits=FALSE))
ewhere$'forced!exports'
else
character( 0)
nsinfo <- make.NAMESPACE( ewhere, description=description,
more.exports=c( named.in.extra.docs, forced.exports))
# *** HOOK CALLED HERE ***
default.list <- c( copies, dll.paths, returnList(
extra.filecontents=list(),
env=ewhere,
extra.docs,
description,
has.namespace,
use.existing.NAMESPACE,
nsinfo,
exclude.funs= c( 'pre.install.hook.' %&% pkg, '.First.task'),
exclude.data= c( extra.docs, pkg %&% '.DESCRIPTION', pkg %&% '.UNSTABLE',
cq( 'forced!exports',
.required, .Depends, tasks, .Traceback, .packageName, last.warning,
.Random.seed, .SavedPlots, .Last.value)),
task.path=pkg,
dont.check.visibility=getOption( 'mvb_dont_check_visibility', TRUE))
)
if( is.function( fphook <- ewhere[[ 'pre.install.hook.' %&% pkg]]))
default.list <- fphook( default.list, ...)
extract.named( default.list %without.name% cq( task.path, env))
cat( paste( names( description), description, sep=': '),
file = file.path( sourcedir, 'DESCRIPTION'), sep = '\n')
# Straight file copies:
for( cdir in names( copies))
if( length( cfiles <- default.list[[cdir]])) {
mkdir( file.path( sourcedir, cdir))
csourcedirs <- unique( dirname( cfiles)) %except% cq( ., ..)
mkdir( file.path( sourcedir, csourcedirs))
mvb.file.copy( file.path( dir., cfiles), file.path( sourcedir, cfiles), TRUE)
}
# Sep 2016
# 'extra.filecontents' should be a list of character vectors; names should include paths eg "inst/src/utils.pas" as ONE name; elements are file contents.
# Hook can create each element via readLines() or "manually"
write_the_bloody_Lines <- function( text, filename) { # create dir if necessary
if( !dir.exists( dirname( filename))) {
mkdir( dirname( filename))
}
writeLines( text, filename)
}
FOR( names( extra.filecontents),
write_the_bloody_Lines( extra.filecontents[[.]], file.path( sourcedir, .)))
# Demo index
if( is.dir( demo.dir <- file.path( sourcedir, 'demo')) &&
!file.exists( file.path( demo.dir, '00Index'))) {
# make one!
demos <- dir( demo.dir, pattern='\\.(r|R)$')
first.comment <- function( f) {
txt <- readLines( file.path( demo.dir, f))
hash <- grep( '^#', txt, value=TRUE)[1]
if( !is.na( hash))
stuff <- sub( '# +', '', hash)
else
stuff <- 'Demo of ' %&% sub( '\\.(r|R)$', '', basename( f))
return( stuff)
}
demo.lines <- sapply( demos, first.comment)
cat( paste( sub( '\\.(r|R)$', '', demos), demo.lines, sep='\t'),
file=file.path( demo.dir, '00Index'), sep='\n')
}
fixup.vignettes()
# Zap inst if empty, otherwise R 2.10 complains...
if( !length( dir( file.path( sourcedir, 'inst'), all.files=TRUE) %except% c( '.', '..')))
unlink( file.path( sourcedir, 'inst'), recursive=TRUE)
# DLLs
if( length( dll.paths)) {
slibpath <- file.path( sourcedir, 'inst', 'libs')
if( getRversion() > '2.12')
slibpath <- file.path( slibpath, .Platform$r_arch)
mkdir( slibpath)
mvb.file.copy( dll.paths, file.path( slibpath, names( dll.paths)))
}
# Augment functions to include all that are named in each others aliasses
funs <- find.funs( ewhere) %except% exclude.funs
# Search env for functions: son of ewhere so on-the-fly changes can go there
ewhereson <- new.env( parent=ewhere)
# mlazy objects, and code to auto-load them (involves hacking .onLoad or .First.lib
mlazies <- mcachees( ewhere) %except% c( '.Random.seed', exclude.data)
if( length( mlazies)) {
mkdir( file.path( sourcedir, 'inst', 'mlazy'))
objfiles <- 'obj' %&% attr( ewhere, 'mcache')[ mlazies] %&% '.rda'
md5new <- sapply( file.path( dir., 'mlazy', objfiles), md5sum)
if( !is.null( mlazy.temp.dir)) {
md5old <- sapply( file.path( mlazy.temp.dir, objfiles), md5sum)
# fsnew <- file.info( file.path( dir., 'mlazy', objfiles))
# fsold <- file.info( file.path( sourcedir, 'inst', 'mlazy', objfiles)) # some may not exist
# different.file <- (fsnew$size != fsold$size) | (fsnew$mtime != fsold$mtime)
different.file <- md5old != md5new
different.file[ is.na( different.file)] <- TRUE
} else
different.file <- rep( TRUE, length( objfiles))
if( any( different.file))
mvb.file.copy( file.path( dir., 'mlazy', objfiles[ different.file]),
file.path( sourcedir, 'inst', 'mlazy', objfiles[ different.file]))
for( fi in objfiles[ !different.file])
file.rename( file.path( mlazy.temp.dir, fi), file.path( sourcedir, 'inst', 'mlazy', fi))
mlazy.OK <- TRUE # files sorted out
if( has.namespace) {
wot.env <- 'environment( sys.function())'
wot.fun <- '.onLoad'
} else {
wot.env <- 'as.environment( "package:" %&% pkgname))'
wot.fun <- '.First.lib'
}
plb <- substitute( nsenv <- wot.env, list( wot.env=parse( text=wot.env)[[1]]))
for( i in mlazies)
plb <- c( plb, substitute( delayedAssign( x=i, {
load( file.path( libname, pkgname, 'mlazy', objfile), nsenv)
nsenv[[ i]]
}, assign.env=nsenv, eval.env=environment()),
returnList( i, objfile='obj' %&% attr( ewhere, 'mcache')[i] %&% '.rda')))
# Ensure these data are unlocked, so that they can be loaded.
# ...use 'dont.lockBindings' mechanism but ensure package is indept of mvbutils
dlb <- dont.lockBindings
sho <- setHook.once
environment( dlb) <- environment( sho) <- .GlobalEnv
plb <- c( plb, substitute( {
dont.lockBindings <- dlb
setHook.once <- sho}, returnList( dlb, sho)))
plb <- c( plb, substitute( dont.lockBindings( mlazies, pkgname),
list( mlazies=mlazies)))
loader <- get( wot.fun, ewhere)
if( is.null( loader))
loader <- function( libname, pkgname) NULL
# Now have to prepend plb to body of loader
# ...not easy
thing <- quote( {a})
for( i in seq_along( plb))
thing[[ i+1]] <- plb[[i]]
body( loader) <- call( '{', thing, body( loader))
assign( wot.fun, loader, envir=ewhereson)
mlazy.OK <- TRUE
}
# Source code:
# hide.vars and ifun are for workaround to silly CRAN check below
hide.vars <- vector( 'list', length( funs))
ifun <- 1
ff <- function( x) {
cat( '\n"', x, '" <-\n', sep='', file=rfile, append=TRUE)
fx <- get( x, ewhereson, inherits=TRUE) # ewhere[[ x]] is broken
if( is.function( fx)) {
attributes( fx) <- attributes( fx) %without.name% 'doc'
write.sourceable.function( fx, rfile, append=TRUE, doc.special=FALSE)
hide.vars[[ ifun]] <<- c( all.names( body( fx), unique=TRUE),
unlist( lapply( formals( fx), all.names, unique=TRUE), use.names=FALSE))
ifun <<- ifun+1
} else
print( fx)
}
suppressWarnings(
file.path( sourcedir, 'R',
dir( file.path( sourcedir, 'R'), all.files=TRUE))) # clean out oldies
rfile <- file.path( sourcedir, 'R', pkg %&% '.R')
# cat( '.packagename <- "', pkg, '"\n', sep='', file=rfile)
cat( '# This is package', pkg, '\n', file=rfile)
sapply( funs, ff)
if( is.logical( dont.check.visibility) && isT( dont.check.visibility[1])) {
# Workaround silly CRAN check
# No point in hiding imports or existing functions
dont.hide.vars <- c( funs, lsall( baseenv()))
for( imp in nsinfo$import)
dont.hide.vars <- c( dont.hide.vars, getNamespaceExports( asNamespace( imp)))
dont.hide.vars <- unique( dont.hide.vars)
hide.vars <- unique( unlist( hide.vars, use.names=FALSE)) %except% dont.hide.vars
# NB Feb 2013: Checking code is in codetools:::checkUsageEnterGlobal...
# ... hidden vars are specified in tools:::.check_code_usage_in_package by calling globalVariables()
} else if( is.character( dont.check.visibility))
hide.vars <- dont.check.visibility
else
hide.vars <- character( 0)
if( length( hide.vars)) {
# .Traceback gets excluded during pre.install because it exists in baseenv()...
# ... but it may not exist during RCMD CHECK, so add the bloody thing!
# In any case, need some var on first line for first comma to latch onto
cat( "# MVB's workaround for futile CRAN 'no visible blah' check:",
sprintf( 'globalVariables( package="%s",', pkg),
' names=c( ".Traceback"',
file=rfile, sep='\n', append=TRUE)
cat( sprintf( ' ,"%s"', hide.vars), '))', '', file=rfile, sep='\n', append=TRUE)
}
# Non-functions:
extra.data <- allthings %except% c( allfuns, exclude.data, mlazies)
if( length( extra.data))
save( list=extra.data, file=file.path( sourcedir, 'R', 'sysdata.rda'), envir=ewhere,
compress=TRUE)
# Save file ready for patch.installed
epar <- new.env()
epar$globalVariables <- function( ...) 0 # not sure if this is required, but avoid side-effects from 'source'...
e <- new.env( parent=epar) # will hold stuff to save for patch.installed
# ... did have 'parent=ewhere' but parent( ewhere)==EmptyEnv for maintained package so..?
eval( substitute( source( rfile, local=TRUE, keep.source=TRUE)), envir=e)
for( ff in find.funs( e))
environment( e[[ff]]) <- .GlobalEnv
e$.packageName <- pkg # ready for quick install
save( list=lsall( e), file=file.path( sourcedir, 'R', 'funs.rda'), envir=e,
compress=TRUE)
rm( e)
# Try to tell RCMD not to build "funs.rda" into package... doesn't seem to work
if( file.exists( RBI <- file.path( dir., '.Rbuildignore')))
mvb.file.copy( RBI, file.path( sourcedir, '.Rbuildignore'))
cat( c( '[.]/R/funs[.]rda', ''), file=file.path( sourcedir, '.Rbuildignore'), append=TRUE, sep='\n')
# Obsolete: Object list, used by maintain.packages-- funny name to avoid clashing
# cat( '\n`original!object!list` <-', deparse( c( funs, extra.data)), '', sep='\n',
# file=rfile, append=TRUE)
# Documentation:
# Code is set to only update files if they've changed. However, they're *all* deleted anyway
# ...by the unlink( recruvsive=TRUE) above
doc2Rd.info.file <- file.path( dir., 'doc2Rd.info.rda')
if( is.character( force.all.docs)) {
forcible.redoc <- force.all.docs
force.all.docs <- FALSE
} else {
forcible.redoc <- character()
}
if( !force.all.docs && file.exists( doc2Rd.info.file)) {
load( doc2Rd.info.file) # creates doc2Rd.info
if( length( forcible.redoc)) {
doc2Rd.info <- doc2Rd.info %without.name% forcible.redoc
force.all.docs <- FALSE
}
} else {
doc2Rd.info <- list()
}
# Check for handwritten Rd files-- must live in a sourcedir called Rd
Rd.files.to.keep <- character(0)
if( is.dir( Rd.dir <- file.path( dir., 'Rd'))) {
existing.Rd.files <- dir( Rd.dir, pattern='\\.Rd$', all.files=TRUE)
Rd.files.to.keep <- existing.Rd.files
Rd.already <- character( 0)
mvb.file.copy( file.path( Rd.dir, existing.Rd.files),
file.path( sourcedir, 'man', existing.Rd.files), TRUE)
for( i in existing.Rd.files) {
rl <- readLines( file.path( Rd.dir, i))
docced <- rl %that.match% c( '^\\name\\{', '^\\alias\\{')
Rd.already <- c( Rd.already, sub( '.*\\{([^}])\\}.*', '\\1', rl))
}
} else
Rd.already <- character(0)
# The point here is to avoid calling the Rdconv function if the requisite output already exists
# Rdconv will basically be doc2Rd but can vary slightly depending on how get.updated.Rd is called
get.updated.Rd <- function( docname, new.docco, Rdconv, ...) {
if( !identical( new.docco, doc2Rd.info[[ docname]]$docattr)) {
scatn( "Generating Rd for '%s'", docname)
Rd <- try( Rdconv( ...))
doc2Rd.info[[ i]] <<- if( Rd %is.not.a% 'try-error')
list( docattr=new.docco, Rd=Rd)
else
NULL
} else # no change
Rd <- doc2Rd.info[[ docname]]$Rd
Rd
}
provisionally.add.man.file <- function( docname, text, fname) {
new.md5 <- doc2Rd.info[[ docname]]$md5
already <- file.path( sourcedir, 'man', fname)
if( !force.all.docs && !is.null( new.md5) && !is.na( new.md5) &&
file.exists( already)) {
do.write <- md5sum( already) != new.md5
} else
do.write <- TRUE
if( do.write) {
cat( text, file=already, sep='\n')
doc2Rd.info[[ docname]]$md5 <<- md5sum( already)
}
Rd.files.to.keep <<- c( Rd.files.to.keep, fname)
}
Rd.version <- if( R.target.version < '2.10') "1" else "2"
docfuns <- (funs %except% Rd.already) %that.are.in%
find.documented( ewhere, doctype='own')
for( i in docfuns) {
geti <- ewhere[[i]]
Rd <- get.updated.Rd( i, attr( geti, 'doc'), doc2Rd, geti, Rd.version=Rd.version,
def.valids=alldoc)
if( Rd %is.not.a% 'try-error') {
fname <- sub( '\\}', '', sub( '\\\\name\\{', '', Rd[1])) %&% '.Rd'
fname <- legal.filename( fname)
if( length( grep( '^\\.', fname)))
fname <- '01' %&% fname
provisionally.add.man.file( i, Rd, fname)
}
}
if( !has.namespace) {
Rdconv.internals <- function()
doc2Rd( make.internal.doc( undoc.funs, pkg, pkenv=ewhere), Rd.version=Rd.version)
undoc.funs <- funs %except% c( find.documented( ewhere, doctype='any'),
cq( .First.lib, .Last.lib, .onLoad, .onAttach))
if( length( undoc.funs)) {
raw.undocco <- unlist( lapply( cq( mlazy, cd),
function( x) clip( deparse( args( get( x))))))
Rd.undoc <- get.updated.Rd( pkg %&% '-internal', raw.undocco, Rdconv.internals)
provisionally.add.man.file( pkg %&% '-internal', Rd.undoc, pkg %&% '-internal.Rd')
}
}
# Could possibly check for clash with Rd.already, but will assume user's brain is working
for( i in extra.docs) {
geti <- ewhere[[ i]]
Rd.extra <- get.updated.Rd( i, geti, doc2Rd, geti, Rd.version=Rd.version, def.valids=alldoc)
# For package doc, put 00 first to get indexing right...
# ...and change . into -
docname <- if( length( grep( '\\.package\\.doc$', i)))
'00' %&% sub( '\\.', '-', sub( '\\.doc$', '', i))
else
sub( '\\.doc$', '', i)
provisionally.add.man.file( i, Rd.extra, docname %&% '.Rd')
# cat( file=file.path( sourcedir, 'man', docname %&% '.Rd'), Rd.extra, sep='\n')
}
suppressWarnings( file.remove( file.path( sourcedir, 'man',
dir( file.path( sourcedir, 'man'), all.files=TRUE) %except% Rd.files.to.keep)))
save( doc2Rd.info, file=doc2Rd.info.file)
if( has.namespace) {
if( use.existing.NAMESPACE)
mvb.file.copy( file.path( dir., 'NAMESPACE'), file.path( sourcedir, 'NAMESPACE'), TRUE)
else
write.NAMESPACE( nsinfo, file.path( sourcedir, 'NAMESPACE'))
}
# Index last, so it looks up-to-date for RCMD BUILD
index.file <- file.path( sourcedir, 'INDEX')
Rdindex( file.path( sourcedir, 'man'), index.file)
# Put the ***-package file first, if it exists
index.stuff <- scan( index.file, what='', sep='\n', quiet=TRUE)
if( !is.na( i <- grep( '^' %&% pkg %&% '\\-package', index.stuff)[1]))
cat( index.stuff[ c( i, (1:length( index.stuff)) %except% i)], sep='\n',
file=index.file)
invisible( NULL)
}
, vignette.stub = structure(c("%\\VignetteIndexEntry{User manual}", "\\documentclass{article}", "\\begin{document}", "\\end{document}"), class = "docattr")
)
"pre.install.hook.mvbutils" <-
function( default.list) {
# Just for demo purposes really; its only role is to include itself in the package!
default.list$exclude.funs <- default.list$exclude.funs %except% 'pre.install.hook.mvbutils'
default.list
}
"prepare.for.move" <-
function( path) {
if( is.environment( path)) { # maintained.packages$packagename
saving <- NA # used to have TRUE, which forced auto-save; bit bossy
env <- path
path <- attr( env, 'path')
} else {
found.me <- function( x) (!is.null( spath <- attr( as.env( x), 'path')) && spath==path)
env <- index( sapply( 1:length( search()), found.me))[1]
if( found <- !is.na( env))
env <- as.environment( env)
else if( length( maintained.packages)) {
env <- index( sapply( maintained.packages, found.me))[1]
if( found <- !is.na( env))
env <- maintained.packages[[ env]]
}
if( !found) {
env <- new.env()
attr( env, 'path') <- path
load.refdb( file=file.path( path, '.RData'), envir=env)
saving <- TRUE
} else
saving <- if( path != .Path[ length( .Path)]) NA else FALSE # don't explicitly save globalenv
}
obj <- lsall( envir=env)
list( env=env, saving=saving, obj=obj, path=path)
}
"print" <-
function( x, ...)
UseMethod( 'print')
"print.(" <-
function( x, ...) {
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.{" <-
function( x, ...) {
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.<-" <-
function( x, ...) {
# This seemed to work, but makes me nervous...
# x <- substitute( x)
# base:::print.default( eval.parent( x), ...)
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.browsertemp" <-
function( x, ...){
########
# Display the file, *and delete it!!!*
browseURL( 'file://' %&% x, getOption( 'browser'))
unlink( x)
invisible( NULL)
}
"print.call" <-
function( x, ...) {
# This seemed to work, but makes me nervous...
# x <- substitute( x)
# base:::print.default( eval.parent( x), ...)
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.cat" <-
function( x, ...) { cat( x, sep='\n'); invisible( x) }
"print.cdtree" <-
function( x, ...) {
levs <- round( x$level)
max.lev <- max( levs)
indents <- sapply( split( names( levs), levs), function( nn) max( nchar( nn)))
indents <- cumsum( c( 0, rev( indents[-1])+1))
indents <- sapply( indents, function( x) paste( rep( ' ', x), collapse=''))
indents <- rev( indents)[ levs] %&% names( levs)
cat( indents, sep='\n')
invisible( x)
}
"print.default" <-
function( x, ...) {
# Access S3 methods known to base::print but not mvbutils::print
# cat( "Class of x:", class( x), '', sep='\n')
# base::print( x, ...) # leads to recursion if default selected, as do other tricks
l <- c( list( quote( print), x), list( ...)) # eval all args
eval( as.call( l), baseenv()) # ensure that only ORIGINAL S3 method table is searched
invisible( x)
}
"print.docattr" <-
function (x, ...)
cat("# FLAT-FORMAT DOCUMENTATION\n")
"print.for" <-
function( x, ...) {
# This seemed to work, but makes me nervous...
# x <- substitute( x)
# base:::print.default( eval.parent( x), ...)
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.function" <-
function(x, useSource=TRUE, ...) {
if( is.null( sr <- attr( x, 'srcref')) && !is.null( osrc <- attr( x, 'source'))) {
# Concoct artificial srcref
last.line <- max( which( nzchar( osrc)))
last.char <- nchar( osrc[ last.line])
attr( x, 'srcref') <- srcref( srcfilecopy( 'dummy', osrc),
c( 1, 1, last.line, last.char))
}
# Patch to avoid explicit useless printing of x@source in newer R
if( exists( 'getRversion', mode='function') && getRversion() > '3.2') {
attr( x, 'source') <- NULL
}
# Call base method
eval( body.print.function) # unmentionable( print.function( x, useSource, ...)) # sigh...
}
"print.if" <-
function( x, ...) {
# This seemed to work, but makes me nervous...
# x <- substitute( x)
# base:::print.default( eval.parent( x), ...)
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"print.name" <-
function( x, ...)
cat( as.character( x), '\n')
"print.nullprint" <-
function( x, ...)
NULL
"print.pagertemp" <-
function( x, ...) {
file.show( x, title="mvbutils-style informal help on '" %&% names( x) %&% "'", delete.file=TRUE)
put.in.session( just.created.window=TRUE)
invisible( x)
}
"print.specialprint" <-
function( x, ...){
# scatn( "G'day!")
printo <- attr( x, 'print')
if( printo %is.not.an% 'expression') {
scatn( "No 'print' attribute found-- using default")
NextMethod()
} else {
mc <- match.call( expand.dots=TRUE)
thrub <- new.env()
# scatn( 'Filling...')
for( i in names( mc)[-1])
thrub[[ i]] <- get( i) # force
# scatn( 'Ready to eval...')
eval( printo, thrub)
# scatn( 'Done!')
}
invisible( x) # so won't call print again
}
"print.thing.with.source" <-
function( x, ...) {
cat( '# SOURCED FROM THIS:', attr( x, 'source'), sep='\n', ...)
invisible( x)
}
"print.while" <-
function( x, ...) {
# This seemed to work, but makes me nervous...
# x <- substitute( x)
# base:::print.default( eval.parent( x), ...)
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( baseenv()$print.default)
eval.parent( mc)
}
"promote.2.to.1" <-
function () {
full.path <- attr(pos.to.env(2), "path")
detach(2)
load.mvb( filename = file.path( full.path, '.RData'), name=names( full.path), pos=1, path=full.path)
env <- .GlobalEnv
attr(env, "path") <- full.path
}
"put.in.session" <-
function (...)
{
orig.mc <- mc <- as.list(match.call())[-1]
if (length(mc)) {
if (is.null(names(mc)))
which <- 1:length(mc)
else which <- names(mc) == ""
for (i in index(which)) if (is.symbol(orig.mc[[i]]))
names(mc)[i] <- as.character(orig.mc[[i]])
mc <- lapply(mc, eval, envir = parent.frame())
for (i in 1:length(mc)) assign(names(mc)[i], mc[[i]],
pos = "mvb.session.info")
}
invisible(NULL)
}
"rbdf" <-
function( ..., deparse.level=1) {
mc <- match.call()
mc[[1]] <- rbind.data.frame # should find mvbutils version...
# ... so don't need to upset the CRANIAcs with quote( mvbutils:::rbind.data.frame)
eval( mc, parent.frame())
}
"rbind" <-
function (..., deparse.level = 1)
eval( body.rbind)
"rbind.data.frame" <-
function( ..., deparse.level=1) {
allargs <- list( ...) %SUCH.THAT% !is.null( .)
if( !length( allargs))
return( brdf()) # weird-ass 0*0 DF, as base-R doco mandates (why??!!); should not be reached by dispatch
# This for some kind of compatibility with potty base-R behaviour
is.scalar <- sapply( allargs, is.atomic) & sapply( allargs, is.vector)
allargs[ !is.scalar] <- lapply( allargs[ !is.scalar], data.frame)
ncols <- sapply( allargs[ !is.scalar], ncol)
if( any( ncols != ncols[1]))
stop( 'Differing number of columns')
# Make all scalars into single-row data frames: crazy base-R. Should not be allowed!
if( any( is.scalar)) {
warning( "risky to supply scalar argument(s) to 'rbind.data.frame'")
target <- names( allargs[ !is.scalar][[ 1]])
make.like.target <- function( x) {
xout <- rep( x[1], length( target))
xout[] <- x
names( xout) <- target
data.frame( as.list( xout), check.names=FALSE)
}
allargs[ is.scalar] <- lapply( allargs[ is.scalar], make.like.target)
}
if( length( allargs)==1)
return( allargs[[1]])
rows <- sapply( allargs, nrow)
norows <- rows==0
# 0-row args get a row of NAs. Must avoid calling rbind!
allargs[ norows] <- lapply( allargs[ norows], function( x) {
x <- data.frame( x, check.names=FALSE) # since matrices don't like next line...
x[1,] <- x[1,] # ... which adds a row of NAs, even for cols of DF that are matrices
x
})
# brdf = base::rbind.data.frame, modded to handle classed matrices
rbindo <- do.call( brdf, c( allargs, list( deparse.level=deparse.level)))
if( any( norows)) # should work anyway but...
rbindo <- rbindo[ -cumsum( rows + norows)[norows],,drop=FALSE]
rbindo
}
"rcmdgeneric.pkg2" <-
function(
pkg,
outdir,
indir,
cmd='ECHO',
postfix='',
flags=character( 0),
...) {
#########################
cd <- getwd()
old.rlibs <- Sys.getenv( 'R_LIBS') # must at least set R_LIBS...
tf <- tempfile()
on.exit({
setwd( cd)
Sys.setenv( R_LIBS=old.rlibs)
unlink( tf)
})
setwd( outdir) # dirname( subdir)) # pre-7/2013, was (dir.)
Sys.setenv( R_LIBS=paste( .libPaths(), collapse=';'))
comm <- paste( c( 'RCMD', cmd, paste( flags, collapse=' '), indir %&% postfix), collapse=' ')
has.tee <- nzchar( Sys.which( 'tee'))
if( has.tee) {
comm <- comm %&% '| tee ' %&% tf
} else {
warno <- "'tee' not available-- return value (error status) will be NA"
if( .Platform$OS.type=='windows') {
warno <- warno %&% "; install 'coreutils' from Gnuwin32 and check '?build.pkg'"
}
warning( warno)
}
stuff <- shell( comm, intern=!has.tee, invisible=has.tee, ...)
if( has.tee) {
tc <- readLines( tf)
} else {
tc <- stuff
stuff <- NA
}
attributes( stuff) <- returnList( pkg, outdir, output=tc)
return( stuff)
}
"Rd2txt_easy" <-
function( p1, options=FALSE) { # p1 from parse_Rd()
rdo <- Rd2txt_options( width=10000,
itemBullet= '* ',
sectionIndent= 80, sectionExtra= 2,
minIndent= -24, extraIndent=0, # ignore list nesting
enumFormat= function( n) sprintf( '%d. ', n),
showURLs=TRUE,
code_quote=TRUE,
underline=TRUE)
on.exit( Rd2txt_options( rdo))
if( options) {
return( Rd2txt_options()) # the new lot
}
t1 <- tempfile()
on.exit( { unlink( t1); Rd2txt_options( rdo)})
Rd2txt( p1, t1)
readLines( t1)
}
"read.bkind" <-
function( where=1) {
dir <- get.path.from.where( where)
files <- object.names <- character( 0) # in case can't find
index.file <- file.path( dir, '.Backup.mvb/index')
if( file.exists( index.file)) {
ow <- options( warn=-1)
files <- readLines( index.file)
options( ow)
files <- files[ substr( files, 1, 2)=='BU']
}
if( length(files)) {
object.names <- strsplit( files, '=', fixed=TRUE)
files <- sapply( object.names, '[', 1)
object.names <- lapply( object.names, '[', -1)
object.names <- sapply( object.names, paste, collapse='=') # e.g. for something called 'per=verse'
}
returnList( files, object.names)
}
"readLines.mvb" <-
function( con = stdin(), n = -1, ok = TRUE, EOF=as.character( NA), line.count=FALSE) {
if( con %is.a% 'character')
con <- file( con)
if( !isOpen( con, 'r')) {
open( con, open='r')
on.exit( close( con))
}
n[ n < 0] <- Inf
answer <- character( 0)
lines.read <- 0
while( lines.read < n) {
new.answer <- readLines( con=con, n=1, ok=TRUE)
if( length( new.answer))
lines.read <- lines.read + 1
if( !length( new.answer) || match( new.answer, EOF, 0))
break
answer <- c( answer, new.answer)
}
if( line.count) {
attr( answer, 'line.count') <- lines.read
try(
if( !is.null( sli <- attr( con, 'source.list.num'))) {
if( !is.null( olc <- attr( con, 'line.count'))) {
mvbsi <- as.environment( 'mvb.session.info')
sl <- mvbsi$source.list
attr( sl[[ sli]], 'line.count') <- olc + lines.read
assign( 'source.list', sl, envir=mvbsi)
}
}
) # end try
}
return( answer)
}
"readr" <-
function( x, ...) {
mc <- match.call( expand.dots=TRUE)
mc$fixing <- FALSE
mc$new <- FALSE
mc[[1]] <- quote( fixr)
eval( mc, parent.frame())
}
"reduce.empty.links" <-
function( nlocal=sys.parent()) mlocal({
# Rather pointless since empty links are harmless
# Shouldn't be any occurrences of \link{} except to avoid Rd bugs...
# ... because \link{} itself would appear as something different!
# I *think* that...
# ... if character after \link{} is not special, we can delete the \link{}
# ... do it sequentially, deleting last one in each line in turn
# Note that \code is always a risky thing, so "c" is treated as special here
mtlinx <- seq_along( Rd)
repeat{
mtlinx <- mtlinx[ grep( '\\\\link\\{\\}([^c{\\\\%]|$|\\\\\\})', Rd[ mtlinx])]
if( !length( mtlinx))
break
Rd[ mtlinx] <- sub( '\\\\link\\{\\}([^c{\\\\%]|$|\\\\\\})', '\\1', Rd[ mtlinx])
}
})
"remove.from.package" <-
function( ...) { # identical to rm.pkg
mc <- match.call( expand.dots=TRUE)
mc[[1]] <- quote( rm.pkg)
eval( mc, sys.parent())
}
"returnList" <-
function( ...) {
# Returns its arguments; unnamed arguments are named using deparse & substitute
# Does what the deprecated version of 'return' used to do before R 1.8
orig.mc <- mc <- as.list( match.call())[ -1]
if( length( mc)) {
if( length( mc)==1)
mc <- eval( mc[[1]], envir=parent.frame())
else { # multiple arguments, so return as named list
if( is.null( names( mc)))
which <- 1:length( mc)
else
which <- names( mc)==''
for( i in index( which))
if( is.symbol( orig.mc[[ i]]))
names( mc)[ i] <- as.character( orig.mc[[ i]] )
mc <- lapply( mc, eval, envir=parent.frame())
}
}
mc
}
"rm.pkg" <-
function( pkg, ..., list=NULL, save.=NA) {
if( is.null( list))
list <- sapply( match.call( expand.dots=FALSE)$..., as.character)
if( is.null( list)) # nothing to do-- can happen in patch.package
return()
if( is.environment( pkg)) {
pkenv <- pkg
pkg <- attr( pkenv, 'name')
} else {
pkenv <- maintained.packages[[ pkg]]
}
suppressWarnings( rm( list=list, envir=pkenv)) # that bit was easy
maybe.save.after.move( list( env=pkenv, path=attr( pkenv, 'path'), saving=save.))
attacho <- index( search()=='package:' %&% pkg)[1]
if( !is.na( attacho))
suppressWarnings( rm( list=list, envir=pos.to.env( attacho)))
lns <- loadedNamespaces()
if( pkg %in% lns) {
nspkg <- asNamespace( pkg)
suppressWarnings( rm( list=list, envir=nspkg))
exlist <- list %that.are.in% lsall( nspkg$.__NAMESPACE__.$exports)
if( length( exlist)) {
# Import envs are locked, so can't remove
# Could possibly hack round that with 'hack.lockEnvironment' but hard & ?dangerous?
# Can't use active binding instead of existing binding either
# Best is to use delayedAssign to try to fetch the object from baseenv
gnu <- getNamespaceUsers( pkg)
impenvs <- lapply( named( gnu), function( x) parent.env( asNamespace( x)))
impls <- lapply( impenvs, ls)
impacks <- rep( gnu, sapply( impls, length))
impls <- unlist( impls, use.names=FALSE)
for( x in exlist %that.are.in% impls) {
for( impenv in impenvs[ impacks[ impls==x]]) {
if( bl <- balloonIsTethered( x, impenv)) # should be locked
untetherBalloon( x, impenv)
do.call( 'delayedAssign', list( x=x, value=substitute( get( x, baseenv()), list( x=x)),
eval.env=baseenv(), assign.env=impenv))
if( bl)
tetherBalloon( x, impenv)
} # for ihas in has
} # for x in exlist...
} # if length exlist
# meths <- pmatch( names( .knownS3Generics) %&% '.', list, dup=TRUE)
# For now, just zap methods known to base
suppressWarnings( rm( list=list, envir=baseenv()$.__S3MethodsTable__.))
}
}
"safe.rbind" <-
function( df1, df2) {
# As of 2013:
.Deprecated( 'rbind', package='mvbutils', msg='Better to look after column classes manually')
# In R, can hit problems when vars take all-NA or "numeric" values in one df, but character values in the other
if( is.null( df1))
return( df2)
if( is.null( df2))
return( df1)
fac1 <- sapply( df1, is.factor)
fac2 <- sapply( df2, is.factor)
if( any( fac2 & !fac1))
df1[ fac2 & !fac1] <- lapply( df1[ fac2 & !fac1], factor)
if( any( fac1 & !fac2))
df2[ fac1 & !fac2] <- lapply( df2[ fac1 & !fac2], factor)
rbind( df1, df2)
}
"Save" <-
function() {
Save.pos( 1)
try( savehistory())
}
"save.mchanged" <-
function( objs, envir) {
path <- attr( envir, 'path')
mcache <- omcache <- attr( envir, 'mcache')
mcache <- mcache %such.that% (names(.) %in% lsall( envir))
# Check to avoid "objNA.rda"; but this fun is called only
# ...by mtidy & save.refdb, which should check anyhow
objs <- objs %such.that% (. %in% lsall( envir))
changed.objs <- objs %such.that% (mcache[.]<0)
if( any( is.na( mcache[ changed.objs])))
warning( "mcache is corrupted somehow-- use 'demlazy' and 'mlazy' again for these objects: " %&%
paste( changed.objs %such.that% is.na( mcache[ .]), collapse=', '))
if( length( changed.objs) || length( mcache)<length(omcache)) {
if( getOption( 'mlazy.subdir', TRUE)) {
dir.create( file.path( path, 'mlazy'), showWarnings=FALSE)
objpath <- file.path( 'mlazy', 'obj') }
else
objpath <- 'obj'
# e <- new.env() # looks as if 'e' is unnecessary-- acbins get saved as normal objects
for( i in changed.objs)
xsave( list=i, file=file.path( path, objpath %&% -mcache[ i] %&% '.rda'), envir=envir)
mcache[ changed.objs] <- -mcache[ changed.objs]
mupdate.mcache.index.if.opt( mcache, objpath)
}
attr( envir, 'mcache') <- mcache
}
"Save.pos" <-
function (pos, path, ascii = FALSE) {
set.pos.and.path()
# on.exit(save.pos(pos)) # in R2.0, can't safely default to this
if ("mvb.session.info" %!in% search()) {
warning("Can't find session info")
return(invisible(NULL))
}
if( ('package:debug' %in% search()) && exists( 'tracees', 'package:debug')
&& length( pos.tracees <- check.for.tracees( pos))) {
retracees <- pos.tracees %that.are.in% names( tracees)
restoro <- sapply( named( retracees), get, envir=pos)
temp.unmtraced <- tracees[ retracees]
on.exit( {
for( fname in retracees)
lapply( retrace.envs[[ fname]], assign, x=fname, value=restoro[[ fname]])
tp <- asNamespace( 'debug')$tracees # debug:::tracees annoys RCMD CHECK...
tp[ retracees] <- temp.unmtraced
assign( 'tracees', tp, 'package:debug') # does namespace version as well!
})
# Now untrace them, and store the environment(s) containing (un)traced functions...
# ... this may not be 'pos' if there is namespacing
retrace.envs <- lapply( named( retracees), mtrace, fname=NULL, tracing=FALSE,
from=pos, return.envs=TRUE) # fname=NULL forces char.fname
# Now functions that are in a debugged state, but that debug has forgotten...
lapply( pos.tracees %except% retracees, mtrace, fname=NULL, tracing=FALSE,
from=pos, return.envs=FALSE) # fname=NULL forces char.fname
}
save.refdb( file=file.path( path, '.RData'), pos)
if( !is.null( getOption( 'backup.fix', NULL)))
create.backups( pos)
return(invisible(NULL))
}
"save.refdb" <-
function( file, envir, ...) {
envir <- as.env( envir)
if( missing( file)) {
path <- attr( envir, 'path')
if( !is.dir( path))
mkdir( path)
file <- file.path( path, '.RData')
} else
path <- dirname( file)
mcache <- attr( envir, 'mcache')
mcache <- mcache %such.that% (names( .) %in% lsall( envir))
attr( envir, 'mcache') <- mcache
if( is.null( mcache))
mcache <- numeric(0)
# Housekeep dead files
mpath <- attr( envir, 'path')
if( getOption( 'mlazy.subdir', TRUE))
mpath <- file.path( mpath, 'mlazy')
if( is.dir( mpath)) {
objfiles <- list.files( mpath, '^obj(NA|[0-9]+)\\.rda$')
file.remove( file.path( mpath, objfiles %except% ('obj' %&% abs( mcache) %&% '.rda')))
}
# Save into temporary file and keep old one, in case of stuff-up
# Changed Sept 07 so safety-check works even without mcached objects
new.file <- file
while( file.exists( new.file))
new.file <- file.path( dirname( new.file), 'n' %&% basename( new.file))
# Check for ..mypackage accidentally stored here...
badness <- lsall( envir) %that.match% '^[.][.][^.]'
badness <- badness %SUCH.THAT% is.environment( envir[[.]])
badness <- badness %SUCH.THAT% (all( cq( path, name, task.tree) %in%
names( attributes( envir[[.]]))))
if( length( badness))
warning( "Not saving '" %&% paste( badness, collapse="', '") %&% "' which didn't ought to be here...")
if( length( mcache)) {
cache.name <- get.mcache.store.name( envir) %&% '0' # guaranteed not to exist & to be findable
e <- new.env( parent=envir)
assign( cache.name, abs( mcache), e) # avoid assigning into envir
# was.there etc check if any changes have been made. If not, leave original file...
# strictly unchanged datewise.
ans <- xsave( list = c( cache.name, lsall( envir=envir) %except% c( names( mcache), badness,
dont.save())), file=new.file, envir=e, ...)
rm( e) # ?not necessary?
save.mchanged( names( mcache), envir)
} else
ans <- xsave( list=lsall( envir=envir) %except% c( badness, dont.save()), file=new.file,
envir=envir, ...)
if( new.file != file) {
checksums <- md5sum( c( file, new.file))
if( checksums[1]==checksums[2])
file.remove( new.file)
else {
file.remove( file)
file.rename( from=new.file, to=file)
}
}
ans
}
"scatn" <-
function( fmt, ..., sep='\n', file='') cat( sprintf( fmt, ...), sep=sep, file=file)
"search.for.regexpr" <-
function( pattern, where=1, lines=FALSE, doc=FALSE, code.only=FALSE, ...) {
if( doc %is.a% 'character') {
stopifnot( length( doc) == 1)
docmatch <- doc
doc <- TRUE
} else if( doc) {
docmatch <- "\\.doc$"
}
## Function definitions
get.source <- if( doc) {
function( f)
as.character( if( is.function( f)) { # as.list() next to catch NULL
do.call( 'paste', as.list( attributes( f) %SUCH.THAT% is.character( .)))
#attr( f, 'doc')
} else if( is.character( f))
f
else
character())
} else {
function( f) {
if( !code.only && !is.null( source <- attr( f, 'source')))
source
else {
attributes( f) <- list()
deparse( f)
}
}
} # if doc
found <- function( f, pattern, where) {
f <- get.source( get( f, envir=where))
any( grepl( pattern, f, ...))
}
search.one <- function( where) {
ff <- find.funs( where)
if( doc)
ff <- c( ff, (lsall( where) %except% ff) %that.match% docmatch)
if( length( ff)) {
successful <- sapply( ff, found, pattern=pattern, where=as.environment( where))
ff <- ff[ successful]
}
ff
}
## actual code here ####
if( is.environment( where))
where <- list( where)
answer <- lapply( where, search.one)
if( is.numeric( where) || is.character( where))
names( answer) <- search()[ where]
has.some <- sapply( answer, length)>0
if( lines) {
for( e in index( has.some))
answer[[ e]] <- lapply( named( answer[[ e]]),
function( x) grep( pattern, get.source( get( x, envir=where[[e]])), value=TRUE, ...))
}
answer[ has.some]
}
"search.task.trees" <-
function(){
tasks <- lapply( seq( along=search()), function( x) names( attr( pos.to.env( x), 'path')[1]))
taski <- index( sapply( tasks, is.character))
tasks <- unlist( tasks)
task.trees <- sapply( 1:length( tasks), function( x) paste( tasks[length( tasks):x], collapse='/'))
names( taski) <- task.trees
taski
}
"set.finalizer" <-
function( handle, finalizer.name, PACKAGE=NULL) {
# Should make this flexi enuf for .Call as well as .C
# Avoid creation unless we can finalize
# Check for existence of finalizer FIRST
if( is.character( finalizer.name)) {
finalizer.name <- getNativeSymbolInfo( finalizer.name, PACKAGE=PACKAGE)
} else {
oc <- oldClass( finalizer.name)
stopifnot( any( (oc == 'CRoutine') | (oc == 'RegisteredNativeSymbol')))
}
# NOW trigger creation, thanks to lazy eval
handle <- as.integer( handle)
if( all( handle==0)) # all() in case 64 bit, when handle is length 2
return( list( handle=handle, trigger=emptyenv()))
e <- new.env( parent=.GlobalEnv)
e$handle <- handle # not really needed
finalize.me <- function( x) .C( finalizer, handle)
e1 <- new.env( parent=baseenv()) # so .C is found
e1$finalizer <- finalizer.name
e1$handle <- handle
environment( finalize.me) <- e1
reg.finalizer( e, finalize.me, onexit=TRUE)
return( list( handle=handle, trigger=e))
}
"set.path.attr" <-
function (env, the.path, task.name = character(0))
{
if (length(task.name))
names(the.path) <- task.name
attr(env, "path") <- the.path
}
"set.pkg.and.dir" <-
function( need.outdir=FALSE, force.outdir=need.outdir, nlocal=sys.parent(), where, loaded.as.task) mlocal({
# Create dir. sourcedir ewhere outdir; maybe modify pkg
if( is.character( character.only)) {
pkg <- character.only
} else if( !character.only) {
pkg <- as.character(substitute( pkg))
# Allow eg ..mypack, technically a mistake
if( (substring( pkg, 1, 2)=='..') & (substring( pkg, 3) %in% names( maintained.packages))) {
pkg <- substring( pkg, 3)
}
} else if( is.environment( pkg)) { # can happen with eg build.pkg( ..mypack)
pkg <- names( attr( pkg, 'path')) # and if this is null, eg if not actually a maintained package, then it will barf later
}
loaded.as.task <- regexpr( '/' %&% pkg %&% '$', names( search.task.trees()) %&% '$',
fixed=TRUE)>0
where <- index( loaded.as.task)[1]
if( !is.na( where))
ewhere <- as.environment( where)
else {
ewhere <- maintained.packages[[ pkg]]
if( is.null( ewhere)) {
# Might be a path...
if( dir.exists( pkg)) {
ewhere <- structure( 0, path=pkg)
pkg <- basename( pkg)
} else {
stop( "Can't find raw package '" %&% pkg %&% "'")
}
}
}
dir. <- file.path.as.absolute( attr( ewhere, 'path'))
sourcedir <- file.path( dir., pkg %&% getOption( 'mvbutils.sourcepkgdir.postfix', ''))
if( need.outdir) {
extract.named( get.last.R.mandatory.rebuild.version()) # Rrebver, last.R.major
outdir <- dir(dir., include.dirs=TRUE,
pattern = "^[Rr][ _-]?[0-9]+", full.names=TRUE) %such.that% is.dir( .)
if( length( outdir)) {
# Find most up-to-date, but not in R's future...
udver <- numeric_version( sub( '^[^0-9]+', '', sub( '([0-9])[^0-9]+$', '\\1',
basename( outdir))))
not.in.future <- udver <= last.R.major
outdir <- outdir[ not.in.future]
udver <- udver[ not.in.future]
wmax <- match( max( udver), udver) # no 'which.max'
udver <- udver[ wmax]
outdir <- outdir[ wmax]
# ... or too far in R's past!
if( !length( udver) || (udver < Rrebver)) {
# Trigger new folder, for last R major
outdir <- NULL
}
}
if( !length( outdir) && eval( force.outdir)) { # eval() because of non-lazy-eval in mlocal()
outdir <- file.path( dir., 'R' %&% as.character( last.R.major))
mkdir( outdir)
}
} else { # not required
outdir <- NULL
}
})
"set.pos.and.path" <-
function (nlocal = sys.parent()) mlocal({
pos <- as.environment( pos)
if (missing(path)) {
path <- attr( pos, "path")
if (is.null(path))
{
cat("No obvious place to save it. What is the filename (single forward slashes only please)? ")
path <- readline()
}
}
path
})
"set.presave.hook.mvb" <-
function( hook, set=TRUE){
if( set)
presave.hooks <<- c( presave.hooks, list( hook))
else {
which <- lapply( presave.hooks, hook, identical)
presave.hooks <<- presave.hooks[ !which]
}
NULL
}
"set.rcmd.vars" <-
function( ...) {
######## NYI NYI NYI #########
# Supposed to let users set env vars specifically for R-related system calls, so that
# eg system( 'R CMD whatever') will just work.
# NYI!
return()
?sep
vars <- unlist( list( ...))
sysvars <- Sys.getenv()
already <- names( vars) %that.are.in% names( sysvars)
new <- names( vars) %except% names( sysvars)
old.sysvars <- sysvars[ already]
names( sysvars) <- sep %&% names( sysvars) %&% sep
m <- gregexpr( paste( names( sysvars), collapse='|'), names( vars))
for( ivar in seq_along( vars)) {
if( m[[ ivar]][1] > 0) {
starts <- m[[ ivar]]
ends <- starts + + attr( m[[ ivar]], 'match.length') - 1
bits <- substring( vars[ ivar], starts, ends)
valbits <- sysvars[ bits]
vars[ ivar] <- rawToChar( massrep( charToRaw( vars[ ivar]),
atlist = mapply( ':', starts, ends),
replist = lapply( valbits, charToRaw)))
}
}
on.exit( {
Sys.unsetenv( new)
do.call( 'Sys.setenv', old.sysvars)
})
do.call( 'Sys.setenv', vars)
}
"set.test" <-
function (a, b)
{
r <- range(a - b)
if (all(r == c(-1, 0)))
-1
else if (all(r == c(0, 1)))
1
else 0
}
"setHook.once" <-
function( pkg, hook.type, f, action=c( 'append', 'prepend', 'replace')){
# the WEIRD thing here is that if I use cq instead of c in the args, R can't find it...
identical.to.f <- function( x) {
y <- x
attr( y, '.Environment') <- NULL
identical( y, f) }
mangle <- packageEvent( pkg, hook.type)
hooks <- getHook( mangle)
if( !any( sapply( hooks, identical.to.f))) {
action <- match.arg( action)
setHook( mangle, f, action)
}
}
"setup.dontruns" <-
function( Rd) {
# Post-process to set /dontrun examples
if( !length( ex <- grep( '^[\\]examples[{]', Rd)))
return( Rd)
# If example on first line, give it its own line
if( !grepl( '^[\\]examples[{] *$', Rd[ ex])) {
Rd <- multirep( Rd, ex, list( c( '\\examples{', substring( Rd[ ex], nchar( '\\examples{')+1))))
}
end.ex <- (grep( '^[}]', Rd) %such.that% (.>ex)) [1] # braces must be escaped in ex so this is fine
min <- function( ...) suppressWarnings( base::min( ...)) # annoying R "improvement"
repeat{ # once unless error; twice at most
dontrun <- grep( "^ *## +(DON'T|NOT) +RUN *(:)? *$", Rd, ignore.case=TRUE) %such.that%
(. %in.range% c( ex, end.ex))
if( length( dontrun)) {
end.dontrun <- grep( "^## +END( +| *\\( *)(DON'T|NOT) +RUN\\b", Rd, ignore.case=TRUE)
if( (length( end.dontrun) != length( dontrun)) || !all( diff( c( t(
matrix( c( dontrun, end.dontrun), ncol=2)))) > 0)) {
# Don't allow fatal error
oww <- getOption( 'warn')
if( oww==2)
options( warn=1)
warning( "Unmatched DON'T RUN will be made as big as possible, " %&%
"in doc with header:\n%s" %&% Rd[1] )
options( warn=oww)
# Add a dontrun immediately after unmatched ones
unmatched <- rep( FALSE, length( dontrun))
for( i in seq_along( dontrun)) {
mind <- min( end.dontrun %such.that% (. > dontrun[ i]))
unmatched[ i] <- mind >= min( dontrun[ -(1:i)])
}
unmatched <- index( unmatched)
dontrun <- c( dontrun, end.ex)
Rd <- multinsert( Rd, dontrun[ unmatched+1]-1, "## END DON'T RUN")
next
} else { # ie dontrun & end.dontrun are consistent
Rd[ dontrun] <- '\\dontrun{'
Rd[ end.dontrun] <- '}'
}
}
break
}
return( Rd)
}
"setup.mcache" <-
function( envir, fpath=attr( envir, 'path'), refs) {
envir <- as.environment( envir)
mcache <- attr( envir, 'mcache') # usually NULL & overwritten by next bit
if( missing( refs)) {
cache.name <- get.mcache.store.name( envir)
if( !exists( cache.name, envir=envir, inherits=FALSE))
return() # nothing to do; pre-mcache DB
mcache <- get( cache.name, envir)
refs <- names( mcache)
remove( list=cache.name, envir=envir)
}
if( !length( refs)) # post-mcache nothing to do
return()
objpath <- 'obj'
if( getOption( 'mlazy.subdir', TRUE)) {
# Back-compatibility tedious here; move files if in wrong place
files.to.move <- (objpath %&% mcache[ refs] %&% '.rda') %such.that% (
file.exists( file.path( fpath, .)) & !file.exists( file.path( fpath, 'mlazy', .)))
# Normally, next if won't happen
if( length( files.to.move)) {
dir.create( file.path( fpath, 'mlazy'), showWarnings=FALSE) # harmless fail if exists
file.rename( file.path( fpath, files.to.move), file.path( fpath, 'mlazy', files.to.move))
}
objpath <- file.path( 'mlazy', 'obj')
}
# Create promises to load
remove( list=refs %such.that% (. %in% lsall( envir=envir)), envir=envir) # only needed with 'move'
for( i in refs) {
objfile <- file.path( fpath, objpath %&% mcache[ i] %&% '.rda')
if( !file.exists( objfile)) {
warning( 'Can\'t find file "' %&% objfile %&% '"; deleting object "' %&% i %&% '"')
mcache <- mcache %without.name% i
} else {
fx <- get.mcache.reffun( i, envir)
efx <- environment( fx)
# For efficiency (?), do this via promise, rather than directly coding 'if(!loaded)' in fx
subbo <- substitute( { load( file, e); e[[i]]}, list( e=efx, file=objfile, i=i))
do.call( 'delayedAssign', list( x=i, value=subbo, eval.env=efx, assign.env=efx))
suppressWarnings( makeActiveBinding( i, fx, envir))
}
}
attr( envir, 'mcache') <- mcache
}
"sleuth" <-
function( pattern, ...) {
ss <- named( search())
if( 'mvb.session.info' %in% ss) {
mp <- as.environment( 'mvb.session.info')$maintained.packages
ss <- ss %except% ( 'package:' %&% names( mp))
ss <- c( as.list( ss), mp)
}
ss <- FOR( ss, { obj <- lsall( pos=.); grep( pattern=pattern, obj, ..., value=TRUE)} )
return( ss[ lengths( ss) > 0])
}
"source.mvb" <-
function( con, envir=parent.frame(), max.n.expr=Inf,
echo=getOption( 'verbose'), print.eval=echo,
prompt.echo=getOption( 'prompt'), continue.echo=getOption( 'continue')) {
#####################
mvbsi <- as.environment( 'mvb.session.info')
if( is.null( source.list <- mvbsi$source.list))
source.list <- list()
if( is.character( con))
con <- file( con)
else if( con==stdin())
stop( 'source.mvb cannot read from stdin()')
attr( con, 'line.count') <- 0
source.list[[ length( source.list)+1]] <- con
mvbsi$source.list <- source.list
if( !isOpen( con)) {
open( con, 'r') # if you want fancy options on e.g. blocking, you need to pre-open 'con'
on.exit( try( close( con)))
}
on.exit( { put.in.session( source.list=clip( source.list)) },
add=TRUE)
all.lines <- readLines(con)
pushBack( all.lines, con)
ow <- options( warn=-1)
on.exit( options( ow), add=TRUE)
lines.read <- 0
total.lines <- -1
expr.count <- 1
while( expr.count <= max.n.expr) {
# Because srcfilecopy objects are environments, can't just change the lines each time---
# ... need a new one each time
sf <- srcfilecopy( 'dummyfile', all.lines[ (lines.read +1) %upto% length( all.lines)])
old.lines.read <- lines.read
thrub <- try( parse( con, n=1, srcfile=sf, keep.source=TRUE), silent=TRUE)
if( !length( thrub))
break # done
if( thrub%is.a% 'try-error') {
# old-style
errline <- as.numeric( rev( strsplit( geterrmessage(), ' ')[[1]])[1])
if( is.na( errline)) # try new-style
errline <- as.numeric( sub( '.*dummyfile:([0-9]+):.*', '\\1', geterrmessage()))
errmsg <- if( !is.na( errline))
sprintf( "line %i", errline+lines.read)
else
sprintf( 'after line %i: %s', lines.read, geterrmessage())
stop( sprintf( 'parsing %s in %s', errmsg, summary( con)$description), call.=FALSE)
}
if( echo) {
stuff <- deparse( thrub)
stuff[1] <- prompt.echo %&% stuff[1]
stuff[-1] <- continue.echo %&% stuff[-1]
cat( stuff, sep='\n')
}
tryo <- try( list( eval( thrub, envir=envir)), silent=TRUE)
if( tryo %is.a% 'try-error') {
# Try to deduce line--- I don't think this ever works in the eval() phase
errline <- as.numeric( rev( strsplit( geterrmessage(), ' ')[[1]])[1])
errmsg <- if( !is.na( errline))
sprintf( "at line %i", errline+lines.read)
else
sprintf( 'after line %i, in %s: %s', lines.read, paste( capture.output( print( thrub[[1]])), collapse=''),
sub( '[^:]*: *', '', geterrmessage()))
stop( sprintf( 'in %s, %s', summary( con)$description, errmsg), call.=FALSE)
}
lines.just.read <- unclass( attr( thrub, 'srcref')[[1]])[3]
sl <- mvbsi$source.list
lines.read <- attr( sl[[ length( sl)]], 'line.count')
lines.read <- lines.read + lines.just.read
attr( sl[[ length( sl)]], 'line.count') <- lines.read
assign( 'source.list', sl, mvbsi)
last <- tryo[[1]]
if( print.eval)
print( tryo[[1]])
expr.count <- expr.count + 1
}
last
}
"source.print" <-
function( on=TRUE){
# Obsolete ??
if( on) {
body( pfn) <- do.call( 'substitute', list( body( pfn),
list( unmentionable=as.name( '.' %&% 'Internal'))))
assign.to.base( 'print.function', pfn)
} else if( is.function( bpfn <- as.environment( 'mvb.session.info')$base.print.function)) {
assign.to.base( 'print.function', bpfn)
}
invisible( NULL)
}
"spkg" <-
function( pkg) {
character.only <- FALSE
dir.above.source <- '+'
set.pkg.and.dir( FALSE)
return( sourcedir)
}
"strip.missing" <-
function( obs) {
sp <- sys.frame( mvb.sys.parent())
for( i in obs) {
get.i <- mget( i, sp)[[1]]
if( try( mode( get.i), silent=TRUE) %is.a% 'try-error')
obs <- obs %except% i
}
obs
}
"subco" <-
function( line, auto.link=!is.null( valid.links), valid.links=NULL){
# This is the most recent version that had comments. I don't know why they were stripped
# don't quite trust just using this version, and don't have an easy way to check the diff
# PERL syntax in regexes
line <- ' ' %&% line %&% ' '
chsubs <- raw(0)
fullsubs <- character(0)
rawl <- function( i, n.clip=0) rawToChar( rl[clip( i, n.clip)])
# This must come before code & auto-link tests
pkg1.frags <- gregexpr( "\\b[Pp]ackage '[a-zA-Z.][a-zA-Z.0-9]*'", line)[[1]]
pkg2.frags <- gregexpr( "[Tt]he '[a-zA-Z.][a-zA-Z.0-9]*' package\\b", line)[[1]]
pkg.frags <- c( pkg1.frags, pkg2.frags)
o <- order( pkg.frags)
o <- o[ pkg.frags[o]>0]
pkg.frags <- pkg.frags[o]
if( any( pkg.frags>0)) { # then they all will be
pkg.len <- c( attr( pkg1.frags, 'match.length'), attr( pkg2.frags, 'match.length'))[o]
pkg.seq <- mapply( seq, from=pkg.frags, length=pkg.len, SIMPLIFY=FALSE)
rl <- charToRaw( line)
pkg.sub <- sapply( pkg.seq, rawl)
pkg.sub <- sub( "'([^']+)'", "\\\\pkg\\{\\1\\}", pkg.sub)
rl[ pkg.frags] <- charToRaw( '\003')
chsubs <- c( chsubs, rep( '\003', length( pkg.sub)))
fullsubs <- c( fullsubs, pkg.sub)
line <- rawToChar( rl[ -unlist( lapply( pkg.seq, '[', -1))])
}
if( (link.qv.frags <- gregexpr( "[( -]'[a-zA-Z.][a-zA-Z.0-9]*' +\\(qv\\)", line)[[1]])[1] > 0) {
link.qv.frags[] <- link.qv.frags + 1
link.qv.len <- attr( link.qv.frags, 'match.length') - 1
link.qv.seq <- mapply( seq, from=link.qv.frags+1, length=link.qv.len-1, SIMPLIFY=FALSE)
rl <- charToRaw( line)
link.qv.sub <- sapply( link.qv.seq, rawl) # start AFTER sQuote
link.qv.sub <- sub( "([^']+)'.*", "\\\\code\\{\\\\link\\{\\1\\}\\}", link.qv.sub)
rl[ link.qv.frags] <- charToRaw( '\001')
chsubs <- c( chsubs, rep( '\001', length( link.qv.sub)))
fullsubs <- c( fullsubs, link.qv.sub)
line <- rawToChar( rl[ -unlist( link.qv.seq)])
}
if( (link.see.frags <- gregexpr( "\\b[Ss]ee '[a-zA-Z.][a-zA-Z.0-9]*'", line)[[1]])[1] > 0) {
link.see.len <- attr( link.see.frags, 'match.length')
link.see.seq <- mapply( seq, from=link.see.frags, length=link.see.len, SIMPLIFY=FALSE)
rl <- charToRaw( line)
link.see.sub <- sapply( link.see.seq, rawl)
link.see.sub <- sub( "'([^']+)'", "\\\\code\\{\\\\link\\{\\1\\}\\}", link.see.sub)
rl[ link.see.frags] <- charToRaw( '\002')
chsubs <- c( chsubs, rep( '\002', length( link.see.sub)))
fullsubs <- c( fullsubs, link.see.sub)
line <- rawToChar( rl[ -unlist( lapply( link.see.seq, '[', -1))])
}
if( auto.link && ((
link.auto.frags <- gregexpr( "[( -]'([a-zA-Z.][a-zA-Z0-9._]*)'", line)[[1]])[1] > 0)) {
link.auto.frags[] <- link.auto.frags
link.auto.len <- attr( link.auto.frags, 'match.length')
link.auto.seq <- mapply( seq, from=link.auto.frags+2, length=link.auto.len-2, SIMPLIFY=FALSE)
rl <- charToRaw( line)
link.auto.sub <- sapply( link.auto.seq, rawl, n.clip=1) # between quotes
if( !is.null( valid.links)) {
ok <- link.auto.sub %in% valid.links
link.auto.sub <- link.auto.sub[ok]
link.auto.frags <- link.auto.frags[ok]
link.auto.seq <- link.auto.seq[ok]
}
if( length( link.auto.sub)) {
rl[ link.auto.frags+1] <- charToRaw( '\007')
chsubs <- c( chsubs, rep( '\007', length( link.auto.sub)))
fullsubs <- c( fullsubs, '\\code{\\link{' %&% link.auto.sub %&% '}}')
line <- rawToChar( rl[ -unlist( link.auto.seq)])
}
}
if( (code.frags <- gregexpr( "([ (])'([^']+)'", line)[[1]])[1] > 0) {
code.len <- attr( code.frags, 'match.length')
code.seq <- mapply( seq, from=code.frags+2, length=code.len-2, SIMPLIFY=FALSE)
rl <- charToRaw( line)
code.sub <- sapply( code.seq, rawl)
code.sub <- substring( code.sub, 1, nchar( code.sub)-1)
# Some characters need to be escaped:
# code.sub <- gsub( '{', '\\{', gsub( '%', '\\%', code.sub, fixed=TRUE), fixed=TRUE)
code.sub <- '\\code{' %&% code.sub %&% '}'
rl[ code.frags+1] <- charToRaw( '\006')
# Backslash and braces in \code will be treated differently...
code.sub <- gsub( '\016', '\017', code.sub, fixed=TRUE)
code.sub <- gsub( '\020', '\022', code.sub, fixed=TRUE)
code.sub <- gsub( '\021', '\023', code.sub, fixed=TRUE)
chsubs <- c( chsubs, rep( '\006', length( code.sub)))
fullsubs <- c( fullsubs, code.sub)
line <- rawToChar( rl[ -unlist( code.seq)])
}
emph.frags <- gregexpr( '[ (]_[^"_]+_', line)[[1]]
if( emph.frags[1]>0) {
emph.len <- attr( emph.frags, 'match.length')
emph.seq <- mapply( seq, from=emph.frags+2, length=emph.len-2, SIMPLIFY=FALSE)
rl <- charToRaw( line)
emph.sub <- sapply( emph.seq, rawl)
emph.sub <- '\\emph{' %&% substring( emph.sub, 1, nchar( emph.sub)-1) %&% '}'
rl[ emph.frags+1] <- charToRaw( '\004')
chsubs <- c( chsubs, rep( '\004', length( emph.sub)))
fullsubs <- c( fullsubs, emph.sub)
line <- rawToChar( rl[ -unlist( emph.seq)])
}
bold.frags <- gregexpr( '[ (]\\*[^"*]+\\*', line)[[1]]
if( bold.frags[1]>0) {
bold.len <- attr( bold.frags, 'match.length')
bold.seq <- mapply( seq, from=bold.frags+2, length=bold.len-2, SIMPLIFY=FALSE)
rl <- charToRaw( line)
bold.sub <- sapply( bold.seq, rawl)
bold.sub <- '\\bold{' %&% substring( bold.sub, 1, nchar( bold.sub)-1) %&% '}'
rl[ bold.frags+1] <- charToRaw( '\005')
chsubs <- c( chsubs, rep( '\005', length( bold.sub)))
fullsubs <- c( fullsubs, bold.sub)
line <- rawToChar( rl[ -unlist( bold.seq)])
}
url.frags <- gregexpr( "<[a-z]+://[0-9a-zA-Z%$_.+!*'()/-]+>", line)[[1]]
if( url.frags[1]>0) {
url.len <- attr( url.frags, 'match.length')
url.seq <- mapply( seq, from=url.frags+1, length=url.len-1, SIMPLIFY=FALSE)
rl <- charToRaw( line)
url.sub <- sapply( url.seq, rawl)
url.sub <- '\\url{' %&% substring( url.sub, 1, nchar( url.sub)-1) %&% '}'
rl[ url.frags] <- charToRaw( '\010')
chsubs <- c( chsubs, rep( '\010', length( url.sub)))
fullsubs <- c( fullsubs, url.sub)
line <- rawToChar( rl[ -unlist( url.seq)])
}
email.frags <- gregexpr( '<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]+>', line)[[1]]
if( email.frags[1]>0) {
email.len <- attr( email.frags, 'match.length')
email.seq <- mapply( seq, from=email.frags+1, length=email.len-1, SIMPLIFY=FALSE)
rl <- charToRaw( line)
email.sub <- sapply( email.seq, rawl)
email.sub <- '\\email{' %&% substring( email.sub, 1, nchar( email.sub)-1) %&% '}'
rl[ email.frags] <- charToRaw( '\013')
chsubs <- c( chsubs, rep( '\013', length( email.sub)))
fullsubs <- c( fullsubs, email.sub)
line <- rawToChar( rl[ -unlist( email.seq)])
}
# Escape other special characters - {}\ already done
# line <- gsub( '([#\\_${}])', '\\\\\\1', line)
if( numeric_version( Rd.version) < '2')
line <- gsub( '([#_$])', '\\\\\\1', line)
# R
line <- gsub( "( |\\()R([ .,;:'])", "\\1\\R{}\\2", line)
# Ellipsis: not within dquotes
# 2013: not converting ... any more, because it was INCREDIBLY slow. Unbelievable actually.
if( FALSE) {
# Seems to be an R bug that can't cope with nested backref numbers. Nesting per se works fine.
# old.line <- line
repeat {
break # check!
findots <- regexpr( "^([^\"]*(\"[^\"]*\")*)*[.]{3}", line)
if( findots<0)
break
ml <- attr( findots, 'match.length')
line <- substring( line, 1, ml-3) %&% "\\dots{}" %&% substring( line, ml+1)
#line <- gsub("^([^\"]*(\"[^\"]*\")*)*[.]{3}", "\\1\\\\dots{}", old.line)
#if (all(line == old.line))
#break
# old.line <- line
}
# Very old code that presumably did some unwanted conversions
# line <- gsub( '...', '\\dots{}', line, fixed=TRUE)
} # if FALSE: dots
# Multiple tabs & spaces go down to 1 space, except keep a double space at the start
line <- gsub( '(.)[ \t]+', '\\1 ', line)
# Put things back
for( isub in seq_along( chsubs))
line <- sub( chsubs[ isub], fullsubs[ isub], line, fixed=TRUE)
substring( line, 2, nchar( line)-1) # remove first and last spaces
}
"task.home" <-
function(fname) {
if(!missing(fname)) {
if(fname == "" || substr( fname, 1, 1) %in% c( '/', '\\') || pos(":", fname)[1])
return(fname)
else
return( file.path( .Path[ length( .Path)], fname))
} else
return( as.vector( .Path[ length( .Path)]))
}
"to.regexpr" <-
function (x)
{
x <- strsplit(x, "")
repfun <- function(xx) {
m <- match(xx, c("&", ".", "%", "\\", "[", "]", "(",
")", "^", "{", "}", "+", "|", "$", "?", "*"), 0)
xx[m > 0] <- "\\" %&% xx[m > 0]
paste(xx, collapse = "")
}
sapply(x, repfun)
}
"unmaintain.package" <-
function( pkg, character.only=FALSE){
if( !character.only)
pkg <- as.character( substitute( pkg))
maintained.packages <<- maintained.packages %without.name% pkg
rm( list='..' %&% pkg, envir=as.environment( 'mvb.session.info'))
# Anything being fixr-ed?
editees <- (do.on( fix.list$where, tail( strsplit( ., '/', fixed=TRUE)[[1]], 1))==pkg) &
fix.list$where.type=='package'
fix.list$where.type[ editees] <<- 'task'
}
"unmaintain.packages" <-
function( ..., character.only=FALSE, autosave=NA){
if( character.only)
packs <- list(...)[[1]]
else {
mc <- as.list( match.call( expand.dots=FALSE)$...)
packs <- sapply( mc, as.character)
}
if( is.na( autosave) || save)
for( i in packs %that.are.in% names( maintained.packages))
if( !is.na( autosave) || yes.no( "Save maintained package '" %&% i %&% "'? "))
Save.pos( maintained.packages[[ i]])
maintained.packages <<- maintained.packages %without.name% packs
# Clear load hooks
for( i in packs) {
setHook( packageEvent( i, 'onLoad'), NULL, 'replace')
setHook( packageEvent( i, 'attach'), NULL, 'replace')
}
dont.lock.envs <<- dont.lock.envs %without.name% 'imports:' %&% packs
dont.lock.envnames <<- dont.lock.envnames %except% 'package:' %&% packs
return( names( maintained.packages))
}
"unpackage" <-
function( spath, force=FALSE) {
if( getRversion() < '2.10')
stop( "help2flatdoc only works with R 2.10 & up")
oppo <- options( useFancyQuotes=FALSE, keep.source=TRUE)
on.exit( options( oppo))
# DESCRIPTION.in used to be legal; not sure it is now but let's be nice
if( !is.dir( spath) || is.na(
desc <- grep( '^DESCRIPTION([.]in)?$', dir( spath), perl=TRUE, value=TRUE)[1]))
stop( dQuote( spath) %&% " doesn't seem to be a source package")
x <- tools$.read_description( file.path( spath, desc))[ 'Package']
descro <- readLines( file.path( spath, desc))
if( !force && is.dir( x) && length( dir( x, all.files=TRUE) %except% c( '.', '..'))>2) {
force <- yes.no( 'Directory "' %&% x %&%
'" already exists and has stuff in it, which will be deleted if you proceed. OK? ')
} else if( !force && file.exists( x) && !is.dir( x)) {
cat( '"x" already exists, as a file\n')
force <- FALSE
} else
force <- TRUE
if( force) {
tpath <- file.path( getwd(), x)
mkdir( tpath)
unlink( file.path( tpath, dir( tpath) %except% c( '.', '..')), recursive=TRUE)
} else
stop( "Not overwriting")
# one file goes straight to task: DESCRIPTION, Makefile.*
# some files disappear: CONTENTS, INDEX, MD5, NAMESPACE (
# other files go to "inst" (this will include CITATION)
# some dirs disappear: chtml, html, latex, meta, R-ex
# some dirs get used (R, help, data)
# some dirs go straight to task (src) (??)
# all other dirs (incl. libs, demos) go to "inst"
# Recursive file- or directory-copy
filecop <- function( fname, ...) {
# fname: either a single dir or a bunch of non-dirs
if( !any( file.exists( file.path( spath, fname))))
return()
tpath... <- do.call( 'file.path', c( list( tpath), unlist( list( ...))))
mkdir( tpath...)
if( is.dir( file.path( spath, fname[1]))) {
mkdir( file.path( tpath..., fname))
mcf <- mcd <- as.list( match.call( expand.dots=TRUE))
fd <- dir( file.path( spath, fname), all.files=TRUE) %except% c( '.', '..')
# Copy all *files* at once...
fd.dirs <- fd[ is.dir( file.path( spath, fname, fd))]
mcf$fname <- file.path( fname, fd %except% fd.dirs)
eval( as.call( mcf), sys.parent())
# ... and subdirs one at a time...
for( this.dir in fd.dirs) {
mcd$fname <- file.path( fname, this.dir)
eval( as.call( mcd), sys.parent())
}
} else
file.copy( file.path( spath, fname),
file.path( tpath..., fname))
}
# not filecop( 'DESCRIPTION') in case DESCRIPTION.in
# was: mvb.file.copy( file.path( spath, desc), file.path( tpath, 'DESCRIPTION'))
# now insert text object later
nondirs <- dir( spath, all.files=TRUE) %such.that% !is.dir( file.path( spath, .))
nondirs <- nondirs %except% c( desc, cq( CONTENTS, INDEX, MD5, NAMESPACE))
filecop( nondirs, '.')
filecop( 'src')
filecop( 'demo')
filecop( 'tests')
filecop( 'exec')
filecop( 'inst')
filecop( 'vignettes')
instdirs <- (dir( spath, all.files=TRUE) %such.that% is.dir( .))
instdirs <- instdirs %except%
cq( ., .., src, chtml, html, latex, meta, 'R-ex', R, help, data, libs)
filecop( instdirs, 'inst')
filecop( 'libs', file.path( 'inst', 'libs'))
# Deal wih R code, data, and help
# R code: changed 11/2017 to deal better with labyrinthine srcref arcana
e <- new.env( parent=.GlobalEnv)
e[[ x %&% '.DESCRIPTION']] <- as.cat( descro)
# sapply( dir( file.path( spath, 'R'), pattern='[.][RrSsq]$', full.names=TRUE), source, local=e)
srcfiles <- dir(file.path(spath, "R"), pattern = "[.][RrSsq]$", full.names = TRUE)
FOR( srcfiles, source( ., keep.source=TRUE, local = e))
# Set srcrefs to
tf <- tempfile()
on.exit( unlink( tf), add=TRUE)
for( stuff in lsall( e)) {
thing <- e[[stuff]]
if( is.function( thing)) {
temp_thing <- thing
attributes( temp_thing) <- attributes( thing)[ 'srcref']
write.sourceable.function( temp_thing, tf, append=FALSE, print.name=FALSE)
lines <- readLines( tf)
last.line <- max( index( nzchar( lines)))
last.char <- nchar( lines[ last.line])
if( length( attributes( thing))>1) { # write out all inclu attrs, but srcref will only point to the "core" function
write.sourceable.function( thing, tf, append=FALSE, print.name=FALSE, doc.special=TRUE)
lines <- readLines( tf)
}
sc <- as.integer( c( 1, regexpr( 'function', lines[1]), last.line, last.char, 1, last.char, 1, last.line))
attr( sc, 'srcfile') <- srcfilecopy( 'dummyfile', lines)
oldClass( sc) <- 'srcref'
attr( thing, 'srcref') <- sc
e[[stuff]] <- thing
}
}
if( file.exists( file.path( spath, 'NAMESPACE')) && is.null( e$.onLoad))
e$.onLoad <- function( libname, pkgname){} # so pre.install will NAMESPACE
funs <- find.funs(e)
do.on( funs, environment( e[[.]]) <- .GlobalEnv) # OK unless weird stuff has been done (poss legit, but deffo weird)
droppo <- lsall( e) %except% funs
droppo <- droppo %SUCH.THAT% (e[[.]] %is.an% 'environment')
if( length( droppo)) {
cat( "Warning: dropping some environments:", droppo, sep='\n')
rm( list=droppo, envir=e)
}
# Unexported data:
if( file.exists( sysdat <- file.path( spath, 'R', 'sysdata.rda')))
load( sysdat, envir=e)
# Next: exported data
if( is.dir( datdir <- file.path( spath, 'data'))) {
exdata <- dir( datdir, pattern='[.](R|r|rda|Rdata|txt|TXT|tab|csv|CSV)$')
lapply( sub( '[.][^.]+$', exdata), data, package=x, lib.loc=dirname( spath), verbose=FALSE, envir=e)
}
# Help:
Rd.files <- dir( file.path( spath, 'man'), pattern='Rd$', full.names=TRUE)
for( rdf in Rd.files) {
p1 <- parse_Rd( rdf)
rdt <- tools$RdTags( p1)
name <- unlist( p1[ rdt=='\\name'])
aliases <- unlist( p1[ rdt=='\\alias'])
namal <- unique( c( name, aliases))
helpo <- help2flatdoc( fun.name=name, pkg=x, aliases=aliases, text=Rd2txt_easy( p1))
class( helpo) <- 'docattr'
# What fun to associate this with? Try 'name' first, otherwise
matcho <- match( name, funs, 0)
if( !matcho) {
matcho <- min( match( namal, funs, 0))
}
if( matcho) {
# Make sure the doco is included in srcref. src@srcfile$lines contains *all*, but src itself
# ... only points to a part of it
attr( e[[ funs[ matcho]]], 'doc') <- helpo
write.sourceable.function( e[[ funs[ matcho]]], tf, append=FALSE, print.name=FALSE, doc.special=TRUE)
lines <- readLines( tf)
attr( attr( e[[ funs[ matcho]]], 'srcref'), 'srcfile')$lines <- lines
attr( e[[ funs[ matcho]]], 'srcref')[ 2] <- regexpr( 'function', lines[1])
} else {
e[[ name %&% '.doc']] <- helpo
}
}
# And save...
save( list=lsall( e), file=file.path( tpath, '.RData'), envir=e)
# Update tasks...
if( is.null( tasks <- .GlobalEnv$tasks))
tasks <- character( 0)
tasks <- c( tasks, structure( './' %&% x, names=x))
top.workspace <- .GlobalEnv # CRANally retentive check coming up...
assign( 'tasks', tasks, top.workspace)
cat( sprintf(
'"tasks" vector has been augmented with "%1$s"-- remember to Save()...\n' %&%
'...otherwise R won\'t be able to find task pkg for "%1$s" next time\n', x))
return( invisible( NULL))
}
"update.installed.dir" <-
function( opath, ipath, source, installed=source, delete.obsolete=TRUE, excludo=character( 0)) {
#################
if( is.dir( file.path( opath, source))) {
mkdir( file.path( ipath, installed))
# Avoid a/./b
fp <- function( ...) normalizePath( file.path( ...), winslash='/', mustWork=FALSE)
if( !length( excludo))
unexcluded <- identity
else
unexcluded <- function( strs) {
o <- do.call( 'rbind', lapply( excludo, grepl, x=strs))
strs[ !apply( o, 2, any)]
}
source.dirs <- unexcluded( list.dirs( fp( opath, source)))
inst.dirs <- list.dirs( fp( ipath, installed))
nipath <- fp( ipath, installed)
nopath <- fp( opath, source)
ibasename <- function( fpath) substring( fpath, nchar( nipath) + 2)
sbasename <- function( fpath) substring( fpath, nchar( nopath) + 2)
if( delete.obsolete) {
is.xs <- ibasename( inst.dirs) %not.in% sbasename( source.dirs)
unlink( inst.dirs[ is.xs])
inst.dirs <- inst.dirs[ !is.xs]
}
is.new.dir <- sbasename( source.dirs) %not.in% ibasename( inst.dirs)
mkdir( fp( ipath, sbasename( source.dirs[ is.new.dir])))
# Used to use dir() here, but list.files doesn't include folders; better
sources <- unexcluded( list.files( fp( opath, source), full.names=TRUE, recursive=TRUE))
installeds <- list.files( fp( ipath, installed), full.names=TRUE, recursive=TRUE)
if( delete.obsolete) {
is.xs <- ibasename( installeds) %not.in% sbasename( sources)
unlink( installeds[ is.xs])
installeds <- installeds[ !is.xs]
}
if( length( sources)) {
# Really should check whether files have turned into dirs or vice versa...
old.md5 <- md5sum( installeds)
names( old.md5) <- ibasename( names( old.md5))
new.md5 <- md5sum( sources)
names( new.md5) <- sbasename( names( new.md5))
new.files <- sbasename( sources) %except% ibasename( installeds)
changed.files <- names( new.md5) %that.are.in% names( old.md5)
changed.files <- changed.files[ new.md5[ changed.files] != old.md5[ changed.files]]
to.copy <- c( new.files, changed.files)
if( length( to.copy)) # keep file times
mvb.file.copy( fp( opath, source, to.copy), fp( ipath, installed, to.copy),
overwrite=TRUE)
} # if anything potentially to copy
} else if( delete.obsolete)
unlink( file.path( ipath, installed), recursive=TRUE)
}
"update.loaded.pkg" <-
function( pkg, name, ff, disatt= ff %is.a% 'function') {
ffatt <- attributes( ff)
if( disatt) {
if( ff %is.a% 'function') {
keepo <- names( ffatt) %except% cq( doc, export.me)
if( !getOption( 'keep.source.pkgs', TRUE))
keepo <- keepo %except% 'source'
attributes( ff) <- ffatt[ keepo]
} # else attributes( ff) <- list() # too brutal? what about 'source' attr for call-types etc?
} # if disatt
if( !is.na( j <- index( search()=='package:' %&% pkg)[1])
&& (pkg %not.in% loadedNamespaces()))
assign( name, ff, j) # shouldn't be locked
# Put into namespace & importers thereof
if( pkg %in% loadedNamespaces()) {
nspkg <- asNamespace( pkg)
if( is.function( ff)) {
# respect existing environment, in case of weird stuff like my soap hacks
if( exists( name, envir=nspkg, mode='function', inherits=FALSE))
environment( ff) <- environment( nspkg[[ name]])
else
environment( ff) <- nspkg # don't muck about
}
if( name %in% lsall( nspkg$.__NAMESPACE__.$exports)
|| any( names( ffatt) %in% cq( doc, export.me))
|| exists( name %&% '.doc', envir=nspkg, mode='character', inherits=FALSE) ) {
if( match( 'package:' %&% pkg, search(), 0)) # still with source
try( force.assign( name, ff, as.environment( 'package:' %&% pkg)))
# Check importers that are loaded:
gnu <- getNamespaceUsers( pkg) %that.are.in% loadedNamespaces()
for( j in lapply( gnu, function( x) parent.env( asNamespace( x))))
if( exists( name, j, inherits=FALSE))
force.assign( name, ff, j)
}
# If a doc object or function, be sure to export the thing(s) being docced
exclude.me <- character(0)
if( length( grep( '\\.doc$', name)) && is.character( ff)
&& exists( sub( '\\.doc$', '', name), envir=nspkg, inherits=FALSE))
doc.to.check <- ff
else if( is.function( ff) && ('doc' %in% names( ffatt))) {
doc.to.check <- ffatt$doc
exclude.me <- name # have already arranged my own export
} else
doc.to.check <- NULL
for( doccee in named.in.doc( doc.to.check) %except% exclude.me) {
if( exists( doccee, envir=nspkg, inherits=FALSE)) {
if( match( 'package:' %&% pkg, search(), 0)) # ?on search path?
force.assign( doccee, get( doccee, envir=nspkg), as.environment( 'package:' %&% pkg))
nspkg$.__NAMESPACE__.$exports[[ doccee]] <- doccee
for( j in lapply( getNamespaceUsers( pkg), function( x) parent.env( asNamespace( x))))
if( !environmentIsLocked( j) || exists( name, j, inherits=FALSE))
force.assign( name, ff, j)
} # if docced object exists yet
} # loop over docced objects
force.assign( name, ff, nspkg)
if( ('package:' %&% pkg) %in% search())
force.assign( name, ff, as.environment( 'package:' %&% pkg))
is.S3method<- !is.na( pmatch( names( .knownS3Generics) %&% '.', name))
if( any( is.S3method))
force.assign( name, ff, asNamespace( .knownS3Generics[ is.S3method])$.__S3MethodsTable__.)
} # if namespaced
}
"update.maintained.package" <-
function( pkg, nlocal = sys.parent()) mlocal({
if( !is.null( mp <- maintained.packages[[ pkg]])) {
rm( list=lsall( mp), envir=mp)
load.refdb( envir=mp) # filename is deduced
try( pre.install( pkg, character.only=TRUE))
try( patch.installed( pkg, character.only=TRUE))
}
})
"upper.case" <-
function (s)
{
a <- attributes(s)
if (exists("casefold", mode = "function"))
s <- casefold(s, upper = TRUE)
else {
s <- strsplit(s, "")
lets <- LETTERS
names(lets) <- letters
transfer <- function(x) {
change <- x %in% letters
x[change] <- lets[x[change]]
paste(x, collapse = "")
}
s <- sapply(s, transfer)
}
do.call("structure", c(list(.Data = s), a))
}
"warn.and.subset" <-
function( x, cond,
mess.head=deparse( substitute( x), width.cutoff=20, control=NULL, nlines=1),
mess.cond=deparse( substitute( cond), width.cutoff=40, control=NULL, nlines=1),
row.info=rownames( x), sub=TRUE) {
mum <- mvb.sys.parent()
mum <- if( mum==0)
.GlobalEnv
else
sys.frames()[[ mum]]
force( mess.cond)
if( sub)
cond <- substitute( cond)
cond <- eval( cond, x, enclos=mum)
cond[ is.na( cond)] <- FALSE
if( !all( cond)) {
warning( mess.head %&% ': dropping cases that fail ' %&% mess.cond %&% ':', call.=FALSE)
outo <- paste( row.info[ !cond], collapse='; ')
cat( file=stderr(), strwrap( outo, indent=2), '\n')
}
x[ cond,,drop=FALSE]
}
"what.is.open" <-
function ()
{
if (!exists(".Open", "mvb.session.info"))
character(0)
else get(".Open", "mvb.session.info")
}
"write.mvb.tasks" <-
function( tasks=env$tasks, env=.GlobalEnv, dir=attr( env, 'path'))
cat( '\ntasks <- ', deparse( as.call( c( as.name( 'c'), tasks))),
file=file.path( dir, 'tasks.R'), append=TRUE)
"write.NAMESPACE" <-
function( ns, file){
sink( file)
on.exit( sink())
if( !is.null( ns$useDynLib))
cat( 'useDynLib\n')
if( length( ns$export)) {
cat( 'export( ')
# I used to have dQuote here but it just leads to trouble AAAAARGH
cat( paste( '"' %&% ns$export %&% '"', collapse=",\n"))
cat( ')\n')
}
if( length( ns$import))
scatn( 'import( %s)', ns$import)
if( length( ns$importFrom))
scatn( 'importFrom( %s, %s)', ns$importFrom[,1], ns$importFrom[,2])
if( length( ns$S3))
scatn( sprintf( 'S3method( "%s", "%s")', ns$S3[,1], ns$S3[,2]))
cat( '\n')
}
"write.sourceable.function" <-
function( x, con, append=FALSE, print.name=FALSE, doc.special=TRUE, xn=NULL) {
############################
if( is.character( con))
con <- file( con)
if( need.to.close <- !isOpen( con))
open( con, open=ifelse( append, 'a', 'w'))
if( !identical( con, stdout())) {
sink( con)
on.exit( sink())
}
on.exit( if( need.to.close) try( close( con)), add=TRUE)
if( print.name && is.null( xn)) {
xn <- x
if( !is.character( x)) {
if( is.name( substitute( x)))
xn <- deparse( substitute( x))
else
stop( "Can't figure out what name to print")
}
cat( '"', xn, '" <- ', sep='')
}
if( is.character( x))
x <- get( x)
natts <- names( attributes( x)) %except% cq( source, bug.position, srcref)
if( is.function( x) && length( natts)) {
# Prepare to have other attributes
cat( 'structure( ')
atts <- attributes( x)[ natts]
attributes( x)[ natts] <- NULL
}
if( is.function( x)) {
environment( x) <- .GlobalEnv # avoid <environment: x> after definition
if( is.null( sr <- attr( x, 'srcref')) && !is.null( osr <- attr( x, 'source')) && (getRversion() >= '2.14'))
print( as.cat( osr))
else
print( x)
} else {
x <- as.cat( attr( x, 'source'))
print(x)
}
if( is.function( x) && length( natts)) {
# Treat class "docattr" attributes specially. Non-character doc's (references) are OK.
freeforms <- if( doc.special)
natts[ sapply( atts, 'inherits', 'docattr') ]
else
character( 0)
for( iatt in natts %except% freeforms)
cat( ',', iatt, '=',
paste( deparse.names.parsably( atts[[ iatt]]), collapse=' '), '\n')
if( length( freeforms)) { # bizarre syntax of next line is to avoid misleading a syntax-highlighting editor
if( any( freeforms=='doc'))
freeforms <- c( freeforms %except% 'doc', 'doc') # move doc to last
eof.markers <- '<<end of ' %&% freeforms %&% '>>'
names( eof.markers) <- freeforms
for( iatt in freeforms)
while( any( atts[[ iatt]] == eof.markers[ iatt]))
eof.markers[ iatt] <- paste( eof.markers[ iatt], '<', iatt, '>', sep='')
# eof.markers[ length( eof.markers)] <- '' # default for doc; help syntax highlighters
cat( ',', paste( freeforms %&% '=flatdoc( EOF="' %&% eof.markers %&% '")',
collapse=',\n'), ')\n', sep='')
for( iatt in freeforms)
cat( atts[[iatt]], eof.markers[ iatt], sep='\n') } # last one will be end of doc
else
cat( ')')
cat( '\n')
}
cat("\n")
}
"xsave" <-
function( list, file, envir, ...){
# Jul 2011: user-controlled compression options
compress <- getOption( 'mvbutils.compress', TRUE)
compression_level <- getOption( 'mvbutils.compression_level', NULL)
if( is.null( compression_level))
save( list=list, file=file, envir=envir, compress=compress, ...)
else
save( list=list, file=file, envir=envir, compress=compress,
compression_level=compression_level, ...)
}
"yes.no" <-
function (prompt, default)
repeat {
cat(prompt)
answer <- upper.case(readline())
if (answer == "" && !missing(default))
answer <- default
if (!is.na(answer <- pmatch(answer, c("YES", "NO"))))
return(answer == 1)
}
# MVB's workaround for futile CRAN 'no visible blah' check:
globalVariables( package="mvbutils",
names=c( ".Traceback"
,"a"
,"b"
,"x"
,"y"
,"e"
,"value"
,"i"
,"from"
,"to"
,"condition"
,"patt"
,"what"
,"fun"
,"."
,"ind"
,"mum"
,"cond"
,"sub.cond"
,"sub.x"
,"rx"
,"new.names"
,"wd"
,"a.bloody.ttach"
,"nsenv"
,"mvboptions"
,"tools"
,"utils"
,"body.rbind"
,"body.print.function"
,"brdf"
,"base"
,"newarray"
,"atts"
,"BODY"
,"ATTACH"
,"untetherBalloon"
,"tetherBalloon"
,"balloonIsTethered"
,"LLDBflush"
,"unmentionable"
,"bottom"
,"lazyLoadDBflush"
,"get.nsreg"
,"getNamespaceRegistry"
,"maintained.packages"
,"originals.mp"
,"dont.lock.envs"
,"presave.hooks"
,"mvb.base.S3.generics"
,"fix.list"
,"dont.lock.envnames"
,"REGS3M"
,"S3MT"
,"pkgname"
,"f"
,"blah"
,"val"
,".Path"
,"my.reps"
,"my.reps.opts"
,"assign.to.base.opt"
,"..."
,"ok"
,"pn"
,"partial.namespaces"
,"package"
,"tasks"
,"ROOT"
,"mvbutils"
,"histfile"
,".First.top.search"
,"poz"
,"hack.save.image"
,"mc"
,"base.save.image"
,"form"
,"R.rebuild.versions"
,"s"
,"e2"
,"mvb_help_type"
,"help_type"
,"h1"
,"e1"
,"res"
,"env"
,"pkg"
,"char.x"
,"filename"
,"glob"
,"reassign"
,"tethered"
,"obj"
,"override.env"
,"w"
,"penv"
,"in.imports"
,"get.S3.methods.tables"
,"where.gen"
,"wherestr"
,"has.meth"
,"meth"
,"xi"
,"this"
,"where.xi"
,"where"
,"system.xi"
,"envs.xi"
,"ienv"
,"name"
,"do"
,"autoedit.callback"
,"orig.pkg"
,"character.only"
,"thing"
,"result"
,"outdir"
,"sourcedir"
,"flags"
,"temp.inst.lib"
,"preclean"
,"multiarch"
,"fsep"
,"file.sep"
,"fname"
,"flist"
,"everything"
,"can.match"
,"fw"
,"orig.funs"
,"funs"
,"out"
,"vec"
,"these"
,"recursive"
,"need.to.promote.on.failure"
,"orig.path"
,"ii"
,".Random.seed"
,"last.warning"
,".Saved.plots"
,"execute.Last"
,".Last.task"
,"can.go.up"
,"orig.cd.path"
,"fixing.in.pkg"
,"where.type"
,"case"
,"OS"
,"from.text"
,"old.path"
,"new.path"
,"task.name"
,"otasks"
,"task.dir"
,"found"
,"taskname"
,"attach.new"
,"epos"
,"ns"
,"etemp"
,"extroids"
,"repfl"
,"execute.First"
,".First.task"
,"answer"
,"pattern"
,"show.task.name"
,"o"
,"nodes"
,"node.list"
,"parents"
,"is.task"
,"attached.tasks"
,"orig.env"
,"this.name"
,"m"
,"this.file"
,"checko"
,"so.far"
,"what.to.do"
,"deeper"
,"new.nodes"
,"sr"
,"prefix"
,"other.prefix"
,"j"
,"opened"
,"abbr.char"
,"regexp"
,"indices"
,"own.name"
,"n"
,"pre.X"
,"d"
,"funmat"
,"parent"
,"level"
,"task.info"
,"this.task.name"
,"full.name"
,"egood"
,"topfun"
,"to.do"
,"fchanges"
,"done"
,"ebad"
,"changed"
,"more"
,"listable"
,"getSlots"
,".Data"
,"xx"
,"nmp"
,"instances"
,"MP"
,"installed"
,"tarball"
,"binary"
,"mat"
,"pv"
,"tarballs"
,"binaries"
,"keep"
,"icare"
,"care"
,"build.flags"
,"check.flags"
,"CRAN"
,"dcf"
,"dir."
,"biarch_field"
,"con"
,"description"
,"icns"
,"senv"
,"blurb"
,"fob"
,"cand"
,"object.names"
,"index.file"
,"dll.name"
,"this.dll.info"
,"dll.env"
,"routs"
,"n.routs.by.callmech"
,"irout.class"
,"rout.class.prefix"
,"irout"
,"this.un"
,"zipdirs"
,"izipdir"
,"tarver"
,"zippos"
,"zipver"
,"maxver"
,"cs"
,"sl"
,"infeasible.R.line"
,"backup.fix"
,"bdd"
,"ow"
,"previous.backups"
,"char.type"
,"line.breaks"
,"next.break"
,"session.start.time"
,"envir"
,"mcache"
,"temp"
,"fp"
,"keepo"
,"prev.times"
,"old.sessions"
,"is.this.session"
,"copy.lengths"
,"nondit"
,"ff"
,"fbody"
,"cc"
,"fungo"
,"bod"
,"l"
,"expr"
,"simplify"
,"forig"
,"regexo"
,"perl"
,"fixed"
,"useBytes"
,"Rd.version"
,"is.Rd2"
,"notcom"
,"cbstart"
,"cbend"
,"cblines"
,"warnings.on"
,"first.blank"
,"seclines"
,"sectitles"
,"secti"
,"short.secti"
,"rss"
,"xref"
,"xref2"
,"lptr"
,"nlines"
,"Rd"
,"EOF"
,"verbatim"
,"string"
,"maxchar"
,"new.nesting"
,"nesting"
,"string2"
,"strip.spaces.at.start"
,"uncomment"
,"skip.blanks"
,"do.subs"
,"auto.link"
,"def.valids"
,"block"
,"new.line"
,"blank.stop"
,"bs17"
,"pref.block"
,"Rd2.Rlike"
,"width"
,"methodize"
,"insert.para.breaks"
,"itemize"
,"items"
,"n.items"
,"list.block"
,"item"
,"sub.item.names"
,"seealso.block"
,"keyword.block"
,"nice.title"
,"section.title"
,"sectionize"
,"field.name"
,"niced.up.title"
,"overall.name"
,"is.package"
,"is.data"
,"next.field"
,"preflines"
,"one.liners"
,"docType"
,"author"
,"olsplit"
,"check.legality"
,"check.file"
,"p1"
,"current.topic"
,"topic"
,"doc"
,"ext"
,"t1"
,"fff"
,"has.doc"
,"drd"
,"tf1"
,"doco"
,"fun.or.text"
,"tf"
,"tf2"
,"sx"
,"assign."
,"namespace."
,".packageName"
,".SavedPlots"
,"OS.type"
,"is.a.name"
,"stringsAsFactors"
,"namio"
,"enclos"
,"any.case"
,"short"
,"long"
,"fs"
,"size"
,"lengo"
,"reado"
,"fullw"
,"acw"
,"nl"
,"fields"
,"col.names"
,"libr.sodding.ary"
,"methas"
,"fi"
,"colClasses"
,"na.strings"
,"tz"
,"new.file.times"
,"modified"
,"file.time"
,"set.srcfilecopy"
,"sc"
,"last.line"
,"last.char"
,"old.warn"
,"mod"
,"stuffed"
,"the.class"
,"dataclass"
,"should.be.func"
,"source.code"
,"mt"
,"code"
,"fftext"
,"mods.in.packages"
,"autosave"
,"mods.in.tasks"
,"is.traced"
,"tracees"
,"mtrace"
,"stt"
,"where.tasks"
,"not.here"
,"use"
,"task.trees"
,"where.packs"
,"mods.in.attached"
,"where.att"
,"fpa"
,"new"
,"num.load.from"
,"mpls"
,"fixing"
,"load.from"
,"name.load.from"
,"type.load.from"
,"trace.was.on"
,"searchfun.Rd"
,"xo"
,"searchfun.casual"
,"searchfun.own"
,"keepo1"
,"Rds"
,"ins"
,"keepo2"
,"keepo3"
,"findo"
,"oallall"
,"oall"
,"ofuns"
,"odoc"
,"searchfun.docobj.Rd"
,"doctype"
,"obs"
,"only.real.objects"
,"pos2"
,"exclude.mcache"
,"warn"
,"listo"
,"out.str"
,"out.size"
,"delve"
,"attro"
,"char.rel.path"
,"rel.path"
,"search.list"
,"get.tasks.if.present"
,"env.or.pos"
,"wp"
,"igo"
,"go"
,"ctasks"
,"old.wd"
,"actual.ctask"
,"return.all"
,"generics"
,"master.of"
,"n.master"
,"setup"
,"drop.generics"
,"color"
,"textcolor"
,"prune"
,"prunio"
,"highlight"
,"descendents"
,"old.descendents"
,"ancestors"
,"old.ancestors"
,"current.level"
,"tops"
,"oenv"
,"path"
,"fdates"
,"files"
,"mtime"
,"prog"
,"proged"
,"install"
,"new.doc"
,"exact.same"
,"partial"
,"version.suffix"
,"ofnames"
,"versions"
,"new.version"
,"fsuffix"
,"failed.to.edit"
,"task"
,"src"
,"force.srcref"
,"cmd"
,"OK"
,"is.new"
,"try.load.from"
,"callo"
,"wait"
,"suffix"
,"dlls1"
,"rpath"
,"libs"
,"dlls2"
,"r_arch"
,"dlls3"
,"dlls"
,"dll.paths"
,"spath"
,"ipath"
,"ipath.libs"
,"idlls"
,"inst.dll.paths"
,"use.raw"
,"both"
,"time.raw"
,"time.inst"
,"md5.raw"
,"md5.inst"
,"use.newest"
,"newer.inst"
,"not.installed.yet"
,"try.dyn.load"
,"try.dyn.unload"
,"try.library.dynam.load"
,"try.library.dynam.unload"
,"ldlist"
,"loadeds"
,"via.dyn.loads"
,"via.library.dynams"
,"in.memory"
,"inxs.dlls"
,"src.files"
,"src.dlls"
,"things.to.export"
,"exports"
,"expenv"
,".__NAMESPACE__."
,"unexportees"
,"new.exportee"
,"visible"
,"loaded.users"
,"lu"
,"vis"
,"things.to.make.vis"
,"things.to.zap"
,"assenv"
,"can.reset"
,"manpath"
,"Rd.files"
,"new.Rd.info"
,"uaf"
,"alias.files"
,"Rd.info.file"
,"force.all.docs"
,"old.Rd.info"
,"zipped"
,"new.files"
,"changed.files"
,"gone.files"
,"dynamic.help"
,"bf"
,"commands"
,"debug_fixup_help"
,"intern"
,"fzap"
,"dealias.files"
,"files.to.update"
,"fnew"
,"full.fnew"
,"enco"
,".get_package_metadata"
,"testo"
,".install_package_Rd_objects"
,"Rdlist"
,"fetchRdDB"
,"aliases"
,".Rd_get_metadata"
,".install_package_Rd_indices"
,".writePkgIndices"
,"text.fnew"
,"html.fnew"
,"Rd.fnew"
,"prepare_Rd"
,"i.html"
,"ifnew"
,"filio"
,"sections"
,"namas"
,"not.namas"
,"this.alias"
,"own.vig.dir"
,"own.vigs"
,"vig.info"
,"ewhere"
,"need.rudi"
,"vig.R.files"
,"ivig"
,"ivig.rnw"
,"stubbo"
,"empty.list"
,"vig.index"
,".writeVignetteHtmlIndex"
,"sweave.vig.dir"
,"old.pdfs"
,"doctext"
,"oldpar"
,"charlim"
,"lwd"
,"skip.computations"
,"rprune"
,"plotmath"
,"plotting"
,"opar"
,"dev.cur"
,"border"
,"boxcolor"
,"xblank"
,"color.lines"
,"bl"
,"f1"
,"c1"
,"first.parent"
,"dll.path"
,"libname"
,"subarch"
,"this.ext"
,"dynlib.ext"
,"idll"
,"ignore_error"
,"bu"
,"nonblanks"
,"zap.name"
,"zap.name.function"
,"unlength"
,"bkdir"
,"create"
,"file.nums"
,"catstop"
,"line.end"
,"last.R.major"
,"R.rebuild.vers"
,"fx"
,"qwhati"
,"mci"
,"whati"
,"lsnc"
,"cache.name"
,"had.numbers"
,"derefs"
,"file.numbers"
,"new.file.numbers"
,"pfw"
,"path.list"
,"apfun"
,"ap"
,"cache"
,"envo"
,"lscache"
,"refs"
,"promises"
,"prom.func"
,"fnum.func"
,"nfile"
,"packname"
,"pack"
,"meths"
,"prefixes"
,"imeth"
,"spl"
,"packgens"
,"le"
,"subbo"
,"impnames"
,"expnames"
,"impenv"
,"default"
,"is.mp.ns"
,"type"
,"lib.loc"
,"libpath"
,"al"
,"hfilename"
,"fun.name"
,"repager"
,"delete.file"
,"ufq"
,"blanko"
,"consec"
,"iheadings"
,"headings"
,"heading_indents"
,"uhi"
,"first_typical"
,"def_indent"
,"noli_me_tangere"
,"specials"
,"special_ranges"
,"special"
,"USAGE"
,"EXAMPLES"
,"tr"
,"minind"
,"alias_lmethods"
,"alias_lines1"
,"alias_funs"
,"subat"
,"alias_methods"
,"alias_lines2"
,"alias_ops"
,"dotch"
,"itemBullet"
,"gaps"
,"prev_iheading"
,"indent"
,"idot"
,"ich1"
,"subness"
,"start_of_code"
,"identical.to.f"
,"mangle"
,"hook.type"
,"hooks"
,"action"
,"prepend"
,"lvector"
,"lib"
,"readonly"
,"option.name"
,"pe.path"
,"pe"
,"path1"
,"path2"
,"edit.scratchdir"
,"check"
,"n.per.session"
,"n.sessions"
,"lo"
,"hi"
,"args.to.integrate"
,"isdir"
,"makeLazyLoadDB"
,"loaderFile"
,"pkgpath"
,"chname"
,"ldyn"
,"rezzo"
,"patho"
,"l1"
,"dl"
,"whicho"
,"old.group"
,"newbies"
,"nn"
,"not.keep"
,"length.limit"
,"filenames"
,"ld"
,"rr"
,"gnsym"
,"task.tree"
,"tryo"
,"mvb.session.info"
,"editees"
,"splitto"
,"ll"
,"fpath"
,"subex"
,"add"
,"oldex"
,"orig.mc"
,"override.answer"
,"funcs"
,"mcs"
,"mcfiles"
,"mcsize"
,"obsize"
,"packs"
,"already"
,"snames"
,"owner"
,"ipkg"
,"autopatch"
,"ipack"
,"instpath"
,"instdate"
,"moddate"
,"arguments"
,"ax"
,"xfuns"
,"pkenv"
,"embedCR"
,"import"
,"has.NAMESPACE"
,"lp"
,"new.imps.here"
,"owndoc"
,"force.exports"
,"possible.methods"
,"ffe"
,"export"
,"more.exports"
,"group.generics"
,"prims"
,"S3.generics"
,"gen"
,"pseudo.ns"
,"arg1"
,"genarg1"
,"metharg1"
,"is.meth"
,"methdoc"
,"methdoclen"
,"docobj"
,"USAGE.line"
,"ARGUMENTS.line"
,"classes"
,"S3"
,"dir.name"
,"pe2"
,"rdata.path"
,"badatt"
,"strings"
,"pp"
,"search.string"
,"sq"
,"dq"
,"bq"
,"hash"
,"eol"
,"brace"
,"backbrace"
,"backslash"
,"percent"
,"rep.brace"
,"rep.backbrace"
,"rep.backslash"
,"rep.percent"
,"end.specials"
,"state"
,"istr"
,"rch"
,"states"
,"matcho"
,"next.state"
,"escape.braces"
,"usage"
,"icol"
,"cols"
,"all.objects"
,"mm"
,"tabu"
,"atlist"
,"orig"
,"repextend"
,"r"
,"la"
,"rl"
,"replist"
,"sorted.at"
,"max.ver"
,"libroot"
,"ver"
,"potlibs"
,"to.from"
,"saving"
,"thing.for.message"
,"lbreaks"
,"breaks"
,"digits"
,"mid.lab"
,"labs"
,"pre.lab"
,"post.lab"
,"xc"
,"all.levels"
,"by.breaks"
,"xlabs"
,"gap1"
,"outcome"
,"dirlist"
,"next.dir"
,"save.now"
,"sp"
,"sp.env"
,"nlocal"
,"nlocal.env"
,"params"
,"savers"
,"on.exit.code"
,"lvec"
,"nmax"
,"ivec"
,"overwrite"
,"overwrite.by.default"
,"all.over"
,"to.mcache"
,"from.mcache"
,"whatrefs"
,"new.to.mcache"
,"from.obj.files"
,"to.obj.files"
,"renamed"
,"copy"
,"mp"
,"old.file"
,"old.dir"
,"new.index"
,"new.dir"
,"new.file"
,"old.index"
,"old.index.contents"
,"to.match"
,"objpath"
,"nspos"
,"exports.have.changed"
,"users"
,"pkpos"
,"at"
,"inslen"
,"repl"
,"replen"
,"had.num"
,"need.num"
,"new.mcache"
,"new.mci"
,"mlazy.index"
,"p"
,"file1"
,"file2"
,"iok"
,"syscopy"
,"copy.same.mtime"
,"f2"
,"f1.mtime"
,"default.list"
,"exclude.funs"
,"definition"
,"expand.dots"
,"allargs"
,"is.scalar"
,"ncols"
,"target"
,"make.like.target"
,"xout"
,"rows"
,"norows"
,"rbindo"
,"deparse.level"
,"frames"
,"cl"
,"nrows"
,"N"
,"dv"
,"emptyval"
,"dn"
,"newdn"
,"nc"
,"nvars"
,"new.rows"
,"nrr"
,"iseq"
,"jseq"
,"stupid"
,"top"
,"fixedfile"
,"oldtop"
,"olddoc"
,"oldbase"
,"oldutils"
,"oldgraphics"
,"oldstats"
,"olddata"
,"oldgrD"
,"oldmeth"
,"oldgrDevices"
,"htmldir"
,"graphics"
,"stats"
,"datasets"
,"grD"
,"old.page"
,"pg"
,"vv"
,"pa"
,"vario"
,"callio"
,"blank"
,"namelines"
,"fargs"
,"argo"
,"gbod"
,"g"
,"get.promise"
,"zub"
,"X"
,"nfp"
,"exclude.from.package"
,"fmt"
,"sep"
,"USAGE.start"
,"bits"
,"USAGE.end"
,"ulines"
,"parzo"
,"uparzo"
,"is.a.call"
,"is.complass"
,"which.calls"
,"comments"
,"is.S3.meth"
,"ce"
,"S3.class"
,"meth.calls"
,"deparzo"
,"Rcode"
,"ipp"
,"gappi"
,"at_gap_start"
,"metho"
,"is_assign"
,"hack.help"
,"base.help"
,"try.all.packages"
,"hack.query"
,"otext"
,"is.heading"
,"is.descrip"
,"is.normal.line"
,"descrip.text.1"
,"def.indent"
,"secindent"
,"persubsecindent"
,"expando"
,"zappo"
,"nc.next"
,"nc.prev"
,"myhead"
,"is.argdef"
,"is.argdef.contline"
,"start.cont"
,"mid.cont"
,"end.cont"
,"opt.name"
,"n.masters"
,"merge01"
,"resequence"
,"slave.of"
,"pos.order"
,"level.shift"
,"fn"
,"nch"
,"minstrl"
,"layers"
,"source.list"
,"orig.line"
,"expr.count"
,"max.n.expr"
,"check.EOF"
,"echo"
,"errline"
,"dp"
,"prompt.echo"
,"evaluate"
,"last"
,"debug.script"
,"orig_Rcode"
,"R.target.version"
,"find.pkg"
,"pre.inst"
,"dir.above.source"
,"autoversion"
,"DLLs.only"
,"nsfile"
,"is.rda"
,"is.rdb"
,"lazy.loading"
,".read_description"
,"must.unload"
,"nsreg"
,"loader.file"
,"unloadio"
,"i.f"
,"from.nonfuns"
,"to.nonfuns"
,"owidth"
,".install_package_description"
,".install_package_namespace_info"
,"nsInfo"
,"S3methods"
,"rindex"
,"iindex"
,"vigind"
,"help.patch"
,"update.installed.cache"
,"osrc"
,"ipar"
,"oldwarn"
,"ps"
,"web"
,"same"
,"language"
,"sw"
,"sh"
,"use.centres"
,"charscale"
,"expand.xbox"
,"expand.ybox"
,"poly.args"
,"retlist"
,"cex"
,"ac"
,"not.named"
,"substrs"
,"mainstrs"
,".pos"
,"nm"
,"mainstr"
,"names.for.output"
,"max.n.pos"
,"jj"
,"mlazy.temp.dir"
,"mlazy.inst.dir"
,"tdctr"
,"mlazy.OK"
,"mlazy.inst.files"
,"old.mlazy.files"
,"R"
,"man"
,"inst"
,"description.file"
,"should.inc.version"
,"ood.version"
,"inst.version"
,"desc.version"
,"ok.bit"
,"last.bit"
,"new.version.str"
,"changes.file"
,"changes.exists"
,"has.changelog"
,"changes.txt"
,"makes.in.top"
,"excludo"
,"unexcluded"
,"strs"
,"get.nondirs"
,"cdir"
,"copies"
,"vignettes"
,"exec"
,"tests"
,"allfuns"
,"allthings"
,"alldoc"
,"nonfuncs.docoed.in.funcs"
,"extra.docs"
,"named.in.extra.docs"
,"use.existing.NAMESPACE"
,"NAMESPACE.exists"
,"nscontents"
,"has.namespace"
,"forced.exports"
,"nsinfo"
,".required"
,".Depends"
,"fphook"
,"task.path"
,"cfiles"
,"csourcedirs"
,".."
,"write_the_bloody_Lines"
,"extra.filecontents"
,"demo.dir"
,"demos"
,"first.comment"
,"txt"
,"stuff"
,"demo.lines"
,"slibpath"
,"ewhereson"
,"mlazies"
,"exclude.data"
,"objfiles"
,"md5new"
,"md5old"
,"different.file"
,"wot.env"
,"wot.fun"
,"plb"
,"objfile"
,"dlb"
,"sho"
,"loader"
,"hide.vars"
,"ifun"
,"rfile"
,"dont.check.visibility"
,"dont.hide.vars"
,"imp"
,"extra.data"
,"epar"
,"RBI"
,"doc2Rd.info.file"
,"forcible.redoc"
,"doc2Rd.info"
,"Rd.files.to.keep"
,"Rd.dir"
,"existing.Rd.files"
,"Rd.already"
,"docced"
,"get.updated.Rd"
,"new.docco"
,"docname"
,"docattr"
,"Rdconv"
,"provisionally.add.man.file"
,"new.md5"
,"md5"
,"do.write"
,"docfuns"
,"geti"
,"Rdconv.internals"
,"undoc.funs"
,".First.lib"
,".Last.lib"
,".onAttach"
,"raw.undocco"
,"Rd.undoc"
,"Rd.extra"
,"index.stuff"
,"found.me"
,"levs"
,"max.lev"
,"indents"
,"printo"
,"thrub"
,"old.rlibs"
,"comm"
,"indir"
,"postfix"
,"has.tee"
,"warno"
,"tc"
,"rdo"
,"lines.read"
,"new.answer"
,"line.count"
,"sli"
,"olc"
,"mvbsi"
,"mtlinx"
,"save."
,"attacho"
,"lns"
,"nspkg"
,"exlist"
,"gnu"
,"impenvs"
,"impls"
,"impacks"
,"df1"
,"df2"
,"fac1"
,"fac2"
,"omcache"
,"objs"
,"changed.objs"
,"pos.tracees"
,"check.for.tracees"
,"retracees"
,"restoro"
,"temp.unmtraced"
,"retrace.envs"
,"tp"
,"mpath"
,"badness"
,"ans"
,"checksums"
,"docmatch"
,"get.source"
,"code.only"
,"search.one"
,"successful"
,"has.some"
,"taski"
,"finalizer.name"
,"PACKAGE"
,"oc"
,"handle"
,"finalize.me"
,"finalizer"
,"the.path"
,"loaded.as.task"
,"need.outdir"
,"udver"
,"not.in.future"
,"wmax"
,"Rrebver"
,"force.outdir"
,"set"
,"hook"
,"vars"
,"sysvars"
,"old.sysvars"
,"ivar"
,"starts"
,"ends"
,"valbits"
,"ex"
,"end.ex"
,"dontrun"
,"end.dontrun"
,"oww"
,"unmatched"
,"mind"
,"files.to.move"
,"efx"
,"ss"
,"all.lines"
,"total.lines"
,"sf"
,"old.lines.read"
,"errmsg"
,"continue.echo"
,"lines.just.read"
,"print.eval"
,"on"
,"bpfn"
,"base.print.function"
,"get.i"
,"chsubs"
,"fullsubs"
,"rawl"
,"n.clip"
,"pkg1.frags"
,"pkg2.frags"
,"pkg.frags"
,"pkg.len"
,"pkg.seq"
,"pkg.sub"
,"link.qv.frags"
,"link.qv.len"
,"link.qv.seq"
,"link.qv.sub"
,"link.see.frags"
,"link.see.len"
,"link.see.seq"
,"link.see.sub"
,"link.auto.frags"
,"link.auto.len"
,"link.auto.seq"
,"link.auto.sub"
,"valid.links"
,"code.frags"
,"code.len"
,"code.seq"
,"code.sub"
,"emph.frags"
,"emph.len"
,"emph.seq"
,"emph.sub"
,"bold.frags"
,"bold.len"
,"bold.seq"
,"bold.sub"
,"url.frags"
,"url.len"
,"url.seq"
,"url.sub"
,"email.frags"
,"email.len"
,"email.seq"
,"email.sub"
,"findots"
,"ml"
,"isub"
,"repfun"
,"oppo"
,"desc"
,"descro"
,"tpath"
,"filecop"
,"tpath..."
,"mcf"
,"mcd"
,"fd"
,"fd.dirs"
,"this.dir"
,"nondirs"
,"CONTENTS"
,"INDEX"
,"MD5"
,"NAMESPACE"
,"instdirs"
,"chtml"
,"html"
,"latex"
,"meta"
,"srcfiles"
,"temp_thing"
,"droppo"
,"sysdat"
,"datdir"
,"exdata"
,"rdf"
,"rdt"
,"RdTags"
,"namal"
,"helpo"
,"top.workspace"
,"opath"
,"source.dirs"
,"inst.dirs"
,"nipath"
,"nopath"
,"ibasename"
,"sbasename"
,"delete.obsolete"
,"is.xs"
,"is.new.dir"
,"sources"
,"installeds"
,"old.md5"
,"to.copy"
,"ffatt"
,"disatt"
,"export.me"
,"exclude.me"
,"doc.to.check"
,"doccee"
,"is.S3method"
,"lets"
,"transfer"
,"change"
,"mess.cond"
,"mess.head"
,"outo"
,"row.info"
,"useDynLib"
,"importFrom"
,"need.to.close"
,"xn"
,"natts"
,"bug.position"
,"osr"
,"freeforms"
,"doc.special"
,"iatt"
,"eof.markers"
,"compress"
,"compression_level"
))
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.