Skip to content

Instantly share code, notes, and snippets.

@mllg
Created March 11, 2013 15:27
Show Gist options
  • Save mllg/5135021 to your computer and use it in GitHub Desktop.
Save mllg/5135021 to your computer and use it in GitHub Desktop.
#!/usr/bin/env Rscript
### Toggle debug blocks on and off in a fashion of a pre-processor
# usage: toggle_debug [uri] [on|off]
#
# Argument uri can be a single file or directory.
# In case of a directory, the script processes all ".[rR]$" files inside and
# only writes changes if processing is successful for all files found.
#
# Debug blocks start with the comment "BDEBUG" and end with "EDEBUG"
# Toggled off code is preceded with "#DEBUG# ".
#
# Note that this script does not work nice with tabs.
# If any tabs are found, they are converted to option [tab.width] spaces.
# Setting your editor to spaces is highly recommended.
### Options
# FIXME: maybe allow more options like comment.str
tab.width = as.integer(2)
tabs2spaces = function(x) {
gsub("\t", collapse(rep(" ", tab.width), ""), x)
}
getIndentInfo = function(x) {
indent = tabs2spaces(sub("^([[:blank:]]*).*", "\\1", x))
list(string = indent, count = nchar(indent))
}
addComment = function(x, indent, comment.str = "#DEBUG# ") {
paste0(indent$string, comment.str, x)
}
rmComment = function(x, comment.str = "#DEBUG# ") {
sub(paste0("^[[:space:]]*", comment.str, "(.*)"), "\\1", x)
}
is.commented = function(x, comment.str = "#DEBUG# ") {
grepl(comment.str, x, fixed = TRUE)
}
toggle_debug = function(fn, action = "on", dry = FALSE) {
src = readLines(fn)
fname = basename(fn)
in.debug = FALSE
last.block = 0L
for (ln in seq_along(src)) {
line = src[ln]
if (grepl("^[[:blank:]]*#+[[:blank:]]*[BE]DEBUG[[:space:]]*$", line)) {
if (grepl("BDEBUG", line, fixed = TRUE)) {
if (in.debug)
stopf("Error in '%s' (%i): Tried to open new debug block before closing previous block starting in line %i",
fname, ln, last.block)
in.debug = TRUE
last.block = ln
indent = getIndentInfo(line)
} else {
if (!in.debug)
stopf("Error in '%s' (%i): Tried to close debug block before opening it",
fname, ln, last.block)
in.debug = FALSE
}
} else if (in.debug) {
if (action == "on") {
if (is.commented(line))
stopf("Parts of file '%s' are already commented out, e.g. line %i", fname, ln)
src[ln] = addComment(line, indent)
} else {
if (!is.commented(line))
stopf("Parts of file '%s' are not commented out, e.g. line %i", fname, ln)
src[ln] = rmComment(line)
}
}
}
if (in.debug)
stopf("Error in '%s': EOF reached, debug block starting in line %i not closed",
fname, last.block)
if (last.block > 0L && !dry)
writeLines(src, con = fn)
invisible(list(src = src, touched = last.block > 0L))
}
library(BBmisc)
argv = commandArgs(trailingOnly = TRUE)
if (length(argv) != 2L || !(argv[2L] %in% c("on", "off")))
stop("Usage: toggle_debug [uri] [on|off]")
uri = argv[1L]
action = argv[2L]
if (! file.exists(uri))
stopf("Could not open '%s'", uri)
if (file_test("-d", uri)) {
files = list.files(uri, pattern = "\\.R$", ignore.case = TRUE, full.names = TRUE)
src = lapply(files, toggle_debug, action = action, dry = TRUE)
ind = extractSubList(src, "touched")
res = mapply(writeLines,
text = extractSubList(src[ind], "src", simplify = FALSE),
con = files[ind])
} else {
toggle_debug(uri, action)
}
invisible(0L)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment