Nothing
#' @title Create a progress bar with estimated time.
#'
#' @description
#' Create a progress bar function that displays the estimated time till
#' completion and optional messages. Call the returned functions \code{set} or
#' \code{inc} during a loop to change the display.
#' Note that you are not allowed to decrease the value of the bar.
#' If you call these function without setting any of the arguments
#' the bar is simply redrawn with the current value.
#' For errorhandling use \code{error} and have a look at the example below.
#'
#' You can globally change the behavior of all bars by setting the option
#' \code{options(BBmisc.ProgressBar.style)} either to \dQuote{text} (the default)
#' or \dQuote{off}, which display no bars at all.
#'
#' You can globally change the width of all bars by setting the option
#' \code{options(BBmisc.ProgressBar.width)}. By default this is \code{getOption("width")}.
#'
#' You can globally set the stream where the output of the bar is directed by setting the option
#' \code{options(BBmisc.ProgressBar.stream)} either to \dQuote{stderr} (the default)
#' or \dQuote{stdout}. Note that using the latter will result in the bar being shown in
#' reports generated by Sweave or knitr, what you probably do not want.
#'
#' @param min [\code{numeric(1)}]\cr
#' Minimum value, default is 0.
#' @param max [\code{numeric(1)}]\cr
#' Maximum value, default is 100.
#' @param label [\code{character(1)}]\cr
#' Label shown in front of the progress bar.
#' Note that if you later set \code{msg} in the progress bar function,
#' the message will be left-padded to the length of this label, therefore
#' it should be at least as long as the longest message you want to display.
#' Default is \dQuote{}.
#' @param char [\code{character(1)}]\cr
#' A single character used to display progress in the bar.
#' Default is \sQuote{+}.
#' @param style [\code{character(1)}]\cr
#' Style of the progress bar. Default is set via options (see details).
#' @param width [\code{integer(1)}]\cr
#' Width of the progress bar. Default is set via options (see details).
#' @param stream [\code{character(1)}]\cr
#' Stream to use. Default is set via options (see details).
#' @return [\code{\link{ProgressBar}}]. A list with following functions:
#' \item{set [function(value, msg = label)]}{Set the bar to a value and possibly display a message instead of the label.}
#' \item{inc [function(value, msg = label)]}{Increase the bar and possibly display a message instead of the label.}
#' \item{kill [function(clear = FALSE)]}{Kill the bar so it cannot be used anymore. Cursor is moved to new line. You can also erase its display.}
#' \item{error [function(e)]}{Useful in \code{tryCatch} to properly display error messages below the bar. See the example.}
#' @export
#' @aliases ProgressBar
#' @examples
#' bar = makeProgressBar(max = 5, label = "test-bar")
#' for (i in 0:5) {
#' bar$set(i)
#' Sys.sleep(0.2)
#' }
#' bar = makeProgressBar(max = 5, label = "test-bar")
#' for (i in 1:5) {
#' bar$inc(1)
#' Sys.sleep(0.2)
#' }
#' # display errors properly (in next line)
#' \dontrun{
#' f = function(i) if (i>2) stop("foo")
#' bar = makeProgressBar(max = 5, label = "test-bar")
#' for (i in 1:5) {
#' tryCatch ({
#' f(i)
#' bar$set(i)
#' }, error = bar$error)
#' }
#' }
makeProgressBar = function(min = 0, max = 100, label = "", char = "+",
style = getOption("BBmisc.ProgressBar.style", "text"),
width = getOption("BBmisc.ProgressBar.width", getOption("width")),
stream = getOption("BBmisc.ProgressBar.stream", "stderr")) {
assertNumber(min)
assertNumber(max)
assertString(label)
assertChoice(style, c("text", "off"))
assertInt(width, lower = 30L)
assertChoice(stream, c("stderr", "stdout"))
if (style == "off")
return(structure(list(
set = function(value, msg = label) invisible(NULL),
inc = function(inc, msg = label) invisible(NULL),
kill = function(clear = FALSE) invisible(NULL),
error = function(e) stop(e)
), class = "ProgressBar"))
mycat = if (stream == "stdout")
function(...) cat(...)
else
function(...) cat(..., file = stderr())
## label |................................| xxx% (hh:mm:ss)
label.width = nchar(label)
bar.width = width - label.width - 21L
bar = rep(" ", bar.width)
start.time = as.integer(Sys.time())
delta = max - min
kill.line = "\r"
killed = FALSE
cur.value = min
draw = function(value, inc, msg) {
if (!missing(value) && !missing(inc))
stop("You must not set value and inc!")
else if (!missing(value))
assertNumber(value, lower = max(min, cur.value), upper = max)
else if (!missing(inc)) {
assertNumber(inc, lower = 0, upper = max - cur.value)
value = cur.value + inc
} else {
value = cur.value
}
if (!killed) {
# special case for min == max, weird "empty" bar, but might happen...
if (value == max)
rate = 1
else
rate = (value - min) / delta
bin = round(rate * bar.width)
bar[seq(bin)] <<- char
delta.time = as.integer(Sys.time()) - start.time
if (value == min)
rest.time = 0
else
rest.time = (max - value) * (delta.time / (value - min))
rest.time = splitTime(rest.time, "hours")
# as a precaution, so we can _always_ print in the progress bar cat
if (rest.time["hours"] > 99)
rest.time[] = 99
mycat(kill.line)
msg = sprintf(sprintf("%%%is", label.width), msg)
mycat(sprintf("%s |%s| %3i%% (%02i:%02i:%02i)", msg, collapse(bar, sep = ""), round(rate*100),
rest.time["hours"], rest.time["minutes"], rest.time["seconds"]))
if (value == max)
kill()
flush.console()
}
cur.value <<- value
}
clear = function(newline = TRUE) {
mycat(kill.line)
mycat(rep(" ", width))
if (newline)
mycat("\n")
}
kill = function(clear = FALSE) {
if (clear)
clear(newline = TRUE)
else
mycat("\n")
killed <<- TRUE
}
makeS3Obj("ProgressBar",
set = function(value, msg = label) draw(value = value, msg = msg),
inc = function(inc, msg = label) draw(inc = inc, msg = msg),
kill = kill,
error = function(e) {
kill(clear = FALSE)
stop(e)
}
)
}
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.