上面的函数对于不完整的行还是没法处理啊
想了想,与其写函数的人折腾得死去活来,不如让用户自觉遵守规范,不把注释写在行末算了
我最终决定不管那些写在行末的注释,并添加了几个参数,让用户可以控制是否保留注释(keep.comment)、是否保留空行(keep.blank.line)、注释首尾的标记,并保证这两个标记与原始代码没有冲突:
tidy.source <- function(source = "clipboard", keep.comment = TRUE,
keep.blank.line = FALSE, begin.comment, end.comment, ...) {
tidy.block = function(block.text) {
exprs = parse(text = block.text)
n = length(exprs)
res = character(n)
for (i in 1:n) {
dep = paste(deparse(exprs[i]), collapse = "\n")
res[i] = substring(dep, 12, nchar(dep) - 1)
}
return(res)
}
text.lines = readLines(source, warn = FALSE)
if (keep.comment) {
identifier = function() paste(sample(LETTERS), collapse = "")
if (missing(begin.comment))
begin.comment = identifier()
if (missing(end.comment))
end.comment = identifier()
text.lines = gsub("^[[:space:]]+|[[:space:]]+$", "",
text.lines)
while (length(grep(sprintf("%s|%s", begin.comment, end.comment),
text.lines))) {
begin.comment = identifier()
end.comment = identifier()
}
head.comment = substring(text.lines, 1, 1) == "#"
if (any(head.comment)) {
text.lines[head.comment] = gsub("\"", "\'", text.lines[head.comment])
text.lines[head.comment] = sprintf("%s=\"%s%s\"",
begin.comment, text.lines[head.comment], end.comment)
}
blank.line = text.lines == ""
if (any(blank.line) & keep.blank.line)
text.lines[blank.line] = sprintf("%s=\"%s\"", begin.comment,
end.comment)
text.tidy = tidy.block(text.lines)
text.tidy = gsub(sprintf("%s = \"|%s\"", begin.comment,
end.comment), "", text.tidy)
}
else {
text.tidy = tidy.block(text.lines)
}
cat(paste(text.tidy, collapse = "\n"), "\n", ...)
invisible(text.tidy)
}
测试:
> tidy.source('http://addictedtor.free.fr/graphiques/sources/source_152.R')
circle.corr <- function(corr, col = c("black", "white"),
bg = "white", cex = 1, order = FALSE, title = "", ...) {
if (is.null(corr))
return(invisible())
if ((!is.matrix(corr)) || (round(min(corr, na.rm = TRUE),
6) < -1) || (round(max(corr, na.rm = TRUE), 6) > 1))
stop("Need a correlation matrix!")
n <- nrow(corr)
m <- ncol(corr)
if (order) {
if (!n == m) {
stop("The matrix must be squre if order is TRUE!")
}
x.eigen <- eigen(corr)$vectors[, 1:2]
e1 <- x.eigen[, 1]
e2 <- x.eigen[, 2]
alpha <- ifelse(e1 > 0, atan(e2/e1), atan(e2/e1) + pi)
corr <- corr[order(alpha), order(alpha)]
}
rname <- rownames(corr)
cname <- colnames(corr)
if (is.null(rname))
rname <- 1:n
if (is.null(cname))
cname <- 1:m
rname <- as.character(rname)
cname <- as.character(cname)
par(mar = c(0, 0, 2, 0), bg = "white")
plot.new()
plot.window(c(0, m), c(0, n), asp = 1)
xlabwidth <- max(strwidth(rname, cex = cex))
ylabwidth <- max(strwidth(cname, cex = cex))
plot.window(c(-xlabwidth + 0.5, m + 0.5), c(0, n + 1 + ylabwidth),
asp = 1, xlab = "", ylab = "")
rect(0.5, 0.5, m + 0.5, n + 0.5, col = bg)
text(rep(-xlabwidth/2, n), n:1, rname, col = "red", cex = cex)
text(1:m, rep(n + 1 + ylabwidth/2, m), cname, srt = 90, col = "red",
cex = cex)
title(title)
segments(rep(0.5, n + 1), 0.5 + 0:n, rep(m + 0.5, n + 1),
0.5 + 0:n, col = "gray")
segments(0.5 + 0:m, rep(0.5, m + 1), 0.5 + 0:m, rep(n + 0.5,
m), col = "gray")
nc <- length(col)
if (nc == 1)
bg <- rep(col, n * m)
else {
ff <- seq(-1, 1, length = nc + 1)
bg2 = rep(0, n * m)
for (i in 1:(n * m)) {
bg2[i] <- rank(c(ff[2:nc], as.vector(corr)[i]), ties.method = "random")[nc]
}
bg <- (col[nc:1])[bg2]
}
symbols(rep(1:m, each = n), rep(n:1, m), add = TRUE, inches = F,
circles = as.vector(sqrt(abs(corr))/2), bg = as.vector(bg))
}
data(mtcars)
circle.corr(cor(mtcars), order = TRUE, bg = "gray50",
col = colorRampPalette(c("blue", "white", "red"))(100))