Skip to content

Commit

Permalink
Add labels to the default progress bar and allow users to provide a c…
Browse files Browse the repository at this point in the history
…ustom progress bar (#2196)

close #1880; close #2035 ; close #2077
  • Loading branch information
yihui committed Nov 24, 2022
1 parent 5a2cb72 commit f440712
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 4 deletions.
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# CHANGES IN knitr VERSION 1.42

## NEW FEATURES

- Users can specify a custom progress bar for `knit()` now. The default is still a text progress bar created from `utils::txtProgressBar()`. To specify a custom progress bar, set `options(knitr.progress.fun = function(total, labels) {})`. This function should take arguments `total` (the total number of chunks) and `labels` (the vector of chunk labels), create a progress bar, and return a list of two methods: `list(update = function(i) {}, done = function() {})`. The `update()` method takes `i` (index of the current chunk) as the input and updates the progress bar. The `done()` method closes the progress bar. See https://yihui.org/knitr/options/#global-r-options for documentation and examples.

- The default text progress bar is still written to `stdout()` by default, but can also be written to other connections or `stderr()` now. To do so, set `options(knitr.progress.output = )` to a connection or `stderr()`.

## MAJOR CHANGES

- `knit()` no longer prints out chunk options beneath the text progress bar while knitting a document (thanks, @hadley, #1880).
Expand Down
7 changes: 4 additions & 3 deletions R/output.R
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,9 @@ process_file = function(text, output) {
labels = unlist(lapply(groups, function(g) {
if (is.list(g$params)) g[[c('params', 'label')]] else ''
}))
pb = txtProgressBar(0, n, char = '.', style = 3)
on.exit(close(pb), add = TRUE)
pb_fun = getOption('knitr.progress.fun', txt_pb)
pb = if (is.function(pb_fun)) pb_fun(n, labels)
on.exit(if (!is.null(pb)) pb$done(), add = TRUE)
}
wd = getwd()
for (i in 1:n) {
Expand All @@ -302,7 +303,7 @@ process_file = function(text, output) {
}
break # must have called knit_exit(), so exit early
}
if (progress) setTxtProgressBar(pb, i)
if (progress && !is.null(pb)) pb$update(i)
group = groups[[i]]
res[i] = withCallingHandlers(
if (tangle) process_tangle(group) else process_group(group),
Expand Down
1 change: 0 additions & 1 deletion R/parser.R
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ get_option_comment = function(engine) {

print.block = function(x, ...) {
params = x$params
cat(' chunk:', params$label, '\n')
if (opts_knit$get('verbose')) {
code = knit_code$get(params$label)
if (length(code) && !is_blank(code)) {
Expand Down
27 changes: 27 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -1085,3 +1085,30 @@ str_split = function(x, split, ...) {
y[x == ''] = list('')
y
}

# default progress bar function in knitr: create a text progress bar, and return
# methods to update/close it
txt_pb = function(total, labels) {
s = ifelse(labels == '', '', sprintf(' (%s)', labels)) # chunk labels in ()
w = nchar(s) # widths of labels
n = max(w)
# right-pad spaces for same width of all labels so a wider label of the
# progress bar in a previous step could be completely wiped (by spaces)
s = paste0(s, strrep(' ', n - w))
w2 = getOption('width')
con = getOption('knitr.progress.output', '')
pb = txtProgressBar(
0, total, 0, '.', width = max(w2 - 10 - n, 10), style = 3, file = con
)
list(
update = function(i) {
setTxtProgressBar(pb, i)
cat(s[i], file = con) # append chunk label to the progress bar
},
done = function() {
# wipe the progress bar
cat(paste0('\r', strrep(' ', max(w2, 10) + 10 + n)), file = con)
close(pb)
}
)
}

0 comments on commit f440712

Please sign in to comment.