progress/0000755000175100001440000000000013024271005012126 5ustar hornikusersprogress/inst/0000755000175100001440000000000013024205045013104 5ustar hornikusersprogress/inst/logo.png0000644000175100001440000001345712563173000014566 0ustar hornikusersPNG  IHDR%?sBIT|d pHYs![![&ttEXtSoftwarewww.inkscape.org<IDATx{_Uu?%kݬ̙o]眽s-pqqqqqqqqqqqq,0s ,ʨ?6? 8=ucZܶsڃQ\pR`ya- X;c=h#οxIa-x1 /-+e,)ulf3Mgn{5;hl>+V?k.u-6WqrM% 4ՏZNqflLw"`afZkk1R࠾v[A_ccS#F]F{>rޒltq %tޤCQBWG֦H=%yXbBư`*Vy:9b]_+Z;Z5ljh:\M\.dUv=^vjiiòM- N{Yٿg6>ٙ V? ;X4T@(K{8,L5=H>?m2Y-t oLB t7YYEM@4>ٿ }N/C~lk8oeG PCoA# vZ 6jh}+;@dXx轲KqpK^]FQw 5$ he+ljA4je$z%ְxtv`3QkT'(cVmyM`] }oN碩%'17WJtXd&LN&'Ԟ;;ii-u')@,&}jr./Eh=3#PR΍rny..n(礈rNjM5mv r1 I5A#FԞ!,i maL^^cJ&݅.՘Rm9MS!*} 8 mM{A@Πk PFY-HVws_$K%-z6aفzscŞEI;-==Y+~M' M>f@TKv *NjDo X1r2Ut۾*%ȣ߇MK4rR!FHWa-F> 3-)uRPƤss9aͤװX@oyh‚=!u ȍ4&(ޤT/PҼ{CF7iVs1&Q=Ѽ@j6%8*ڰ`bhu WdМ75JYļҗm$$w3rJN p^zo-G2 ; S;'GN^`1Rn^L@N87I)*Q[@@ 𖛶ĆT/G$糊Fz YI& ƜR*l"^Sb}}kO9UJ3SٖrDckdrK2HW㔠@i|ri/AMWo;sX~ih{y*Wdb>'ٗH[o+v[$-!O̕{z"?,,k@l&):ӾVaD7 RXz2K ˁrtkAXŵ楻܁"J{9'(#f(7y!L$BDžv 1!aBO5)DhIg=a-`iXȤѴB)*5cƩĄ>R[ppTJ[q '54 TTFҪ4?DI*2:NcWڌIӒ,EׅeOVc]ߤ܊|5رϷ/$t[<J MZs> ,,Rz&t8;I{k)8FYHμU-߻mǗ'7 bDzO({Ց<נ3&FUY+˅4kcmַ55Cؼطʚ+T?>`ϘU%#'V۰cRv'݈zDVBOkٖVz%!keh8]C<97=1rEÁ4uR)IIQ[y9脼 [Cx]%!s'ꬣQg[#89ȸ>k_r"]7W+/g]uf354J*[D($9X13=Ĵt&DS1!ar3KV/gs%!K8_~JlS%cʜ%ks 1c6f3iRٖm\bHJ<\Y a{ 1+s3HeWyYp ';+HaQLF+<'-5R%Inrrnd<})A݁X8@Vw 5R%sױ#wA_:%aihU3eՁ%8+M:ٟ)A/$}Lx$-݁hJ![qMX}lDY; `m ])v\YѹJc7aoVՊ i;0hj;^QIzڎVt@Oіb[K1t@5*QO5DfNdfVlZyz{0cʊMr%q1~0%r= -IY vfiB5kbZ,(aizeY@>3A;a7NJV99OV ЬՊM:g} E*rON~0՛sa%V,v{ЭʽHnfKgzW>F9@V- 9`bѦu>JX4@Q=e1\~0VxKe6ZbS+:Aw#w\Y ܁ c`XJﳞ"VV+6>ˀ2YKx!|'|k+cUިZ|-PXG0_3u1 ,Ji2M{ _ 5Tje4Z#ֲfZyMWdItp7ibaȀÀ=iǃ@Aj%: :V~?Z:| gYʉYv8>ȧu}zq%@Xp@v/w>&qld8jqq qCX_r NcpޟeU~?n I9<ޟ_Q8>ϋ? xRF_8G-x%3H8Q' n62*:Rfhj;^[Azڎ\@O۱ 7*v|zڎ;)ڎWҝ jJbhs%K5ਗ਼m:΁ Ȳb! ZAp:@M--[J5`ŦQ, nv2l[JiѦ+2zc}sMU> ]{ `e}Ejֹ02ߧɩCE} @ya` &̛LDR ћWg52֎cxbkr$z$|Se& ]=?8c6Hzq ,qq̵9==uqpCWqQ•9{z8(:dCWZ3:8."@C88󗃀ОaFIqids ;8*BD+{84t=vqqqqqqqqqqqq ЄwmIENDB`progress/inst/NEWS.md0000644000175100001440000000070413024205045014203 0ustar hornikusers # 1.1.2 * Do not run tests on CRAN, Solaris does not have microbenchmark # 1.1.1 * Move README.md, so that it is not parsed on CRAN * Use https URLs instead of http, whenever possible # 1.1.0 * Support for the `:spin` token which adds a simple ASCII spinner, @richfitz * Respect custom token width for calculation of the bar width, @mllg # 1.0.2 * Fix the C++ API on Windows, and on older compilers in general. # 1.0.1 First version on CRAN. progress/inst/README.metacran0000644000175100001440000001046213023752661015572 0ustar hornikusers



progress


[![Linux Build Status](https://travis-ci.org/gaborcsardi/progress.svg?branch=master)](https://travis-ci.org/gaborcsardi/progress) [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/gaborcsardi/progress?svg=true)](https://ci.appveyor.com/project/gaborcsardi/progress) [![](https://www.r-pkg.org/badges/version/progress)](https://r-pkg.org/pkg/progress) > Progress bar in your R terminal An R package to show ASCII progress bars. Heavily influenced by the https://github.com/tj/node-progress JavaScript project. ## Installation ```r devtools::install_github("gaborcsardi/progress") ``` ## Usage Use the `progress_bar` R6 class: ```r library(progress) pb <- progress_bar$new(total = 100) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ``` ``` [==========================================================-------------] 81% ``` The progress bar is displayed after the first `tick` command. This might not be desirable for long computations, because nothing is shown before the first tick. It is good practice to call `tick(0)` at the beginning of the computation or download, which shows the progress bar immediately. ```r pb <- progress_bar$new(total = 100) f <- function() { pb$tick(0) Sys.sleep(3) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } } f() ``` Custom format, with estimated time of completion: ```r pb <- progress_bar$new( format = " downloading [:bar] :percent eta: :eta", total = 100, clear = FALSE, width= 60) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ``` ``` downloading [========----------------------] 28% eta: 1s ``` With elapsed time: ```r pb <- progress_bar$new( format = " downloading [:bar] :percent in :elapsed", total = 100, clear = FALSE, width= 60) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ``` ``` downloading [==========================------] 80% in 1s ``` With custom tokens: ```r pb <- progress_bar$new( format = " downloading :what [:bar] :percent eta: :eta", clear = FALSE, total = 200, width = 60) f <- function() { for (i in 1:100) { pb$tick(tokens = list(what = "foo ")) Sys.sleep(2 / 100) } for (i in 1:100) { pb$tick(tokens = list(what = "foobar")) Sys.sleep(2 / 100) } } f() ``` ``` downloading foo [======------------------] 27% eta: 4s ``` It can show download rates for files with unknown sizes: ```r pb <- progress_bar$new( format = " downloading foobar at :rate, got :bytes in :elapsed", clear = FALSE, total = 1e7, width = 60) f <- function() { for (i in 1:100) { pb$tick(sample(1:100 * 1000, 1)) Sys.sleep(2/100) } pb$tick(1e7) invisible() } f() ``` ``` downloading foobar at 5.42 MB/s, got 15.45 MB in 3s ``` Progress bars can also digress, by supplying negative values to `tick()`: ```r pb <- progress_bar$new() f <- function() { pb$tick(50) ; Sys.sleep(1) pb$tick(-20) ; Sys.sleep(1) pb$tick(50) ; Sys.sleep(1) pb$tick(-30) ; Sys.sleep(1) pb$tick(100) } f() ``` See the manual for details and other options. ## Creating a plyr compatible progress bar It is easy to create progress bars for [plyr](https://github.com/hadley/plyr): ```r progress_progress <- function(...) { pb <- NULL list( init = function(x, ...) { pb <<- progress_bar$new(total = x, ...) }, step = function() { pb$tick() }, term = function() NULL ) } ``` You can try it with ```r plyr::l_ply( 1:100, .fun = function(...) Sys.sleep(0.01), .progress = 'progress' ) ``` ## C++ API The package also provides a C++ API, that can be used with or without Rcpp. See [the example package](inst/progresstest/src/test.cpp) that is [included](inst/progresstest) within `progress`. Here is a short excerpt that shows how it works: ```CPP #include ... RProgress::RProgress pb("Downloading [:bar] ETA: :eta"); pb.tick(0); for (int i = 0; i < 100; i++) { usleep(2.0 / 100 * 1000000); pb.tick(); } ... ``` The C++ API has almost the same functionality as the R API, except that it does not currently support custom tokens, custom streams, and callback functions. Note that the C++ and the R APIs are independent and for a single progress bar you need to use either one exclusively. ## License MIT progress/inst/logo.svg0000644000175100001440000004273412563172633014614 0ustar hornikusers image/svg+xml progress/inst/progresstest/0000755000175100001440000000000012706010040015643 5ustar hornikusersprogress/inst/progresstest/src/0000755000175100001440000000000013024206057016443 5ustar hornikusersprogress/inst/progresstest/src/RcppExports.cpp0000644000175100001440000000143212520265623021444 0ustar hornikusers// This file was generated by Rcpp::compileAttributes // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 #include using namespace Rcpp; // test_progress Rcpp::CharacterVector test_progress(Rcpp::CharacterVector formatSEXP); RcppExport SEXP progresstest_test_progress(SEXP formatSEXPSEXP) { BEGIN_RCPP Rcpp::RObject __result; Rcpp::RNGScope __rngScope; Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type formatSEXP(formatSEXPSEXP); __result = Rcpp::wrap(test_progress(formatSEXP)); return __result; END_RCPP } // test_units Rcpp::CharacterVector test_units(); RcppExport SEXP progresstest_test_units() { BEGIN_RCPP Rcpp::RObject __result; Rcpp::RNGScope __rngScope; __result = Rcpp::wrap(test_units()); return __result; END_RCPP } progress/inst/progresstest/src/test.cpp0000644000175100001440000000335312520265623020136 0ustar hornikusers #include #include #include // [[Rcpp::export]] Rcpp::CharacterVector test_progress(Rcpp::CharacterVector formatSEXP = "[:bar] :percent ") { BEGIN_RCPP const char *format = formatSEXP[0]; RProgress::RProgress pb(format); pb.tick(0); for (int i = 0; i < 100; i++) { usleep(2.0 / 100 * 1000000); pb.tick(); } Rcpp::CharacterVector result(1); result[0] = "DONE"; return result; END_RCPP } // [[Rcpp::export]] Rcpp::CharacterVector test_units() { BEGIN_RCPP Rcpp::CharacterVector result(20); result[0] = RProgress::RProgress::vague_dt(0); result[1] = RProgress::RProgress::vague_dt(1); result[2] = RProgress::RProgress::vague_dt(1.1); result[3] = RProgress::RProgress::vague_dt(51); result[4] = RProgress::RProgress::vague_dt(2 * 60); result[5] = RProgress::RProgress::vague_dt(3 * 60 * 60); result[6] = RProgress::RProgress::vague_dt(3 * 60 * 60 * 24); result[7] = RProgress::RProgress::vague_dt(31 * 60 * 60 * 24); result[8] = RProgress::RProgress::vague_dt(400 * 60 * 60 * 24); result[9] = RProgress::RProgress::vague_dt(1500 * 60 * 60 * 24); result[10] = RProgress::RProgress::pretty_bytes(0); result[11] = RProgress::RProgress::pretty_bytes(133); result[12] = RProgress::RProgress::pretty_bytes(1337); result[13] = RProgress::RProgress::pretty_bytes(13337); result[14] = RProgress::RProgress::pretty_bytes(133337); result[15] = RProgress::RProgress::pretty_bytes(1333337); result[16] = RProgress::RProgress::pretty_bytes(13333337); result[17] = RProgress::RProgress::pretty_bytes(133333337); result[18] = RProgress::RProgress::pretty_bytes(1333333337); result[19] = RProgress::RProgress::pretty_bytes(13333333337); return result; END_RCPP } progress/inst/progresstest/NAMESPACE0000644000175100001440000000025212534062437017101 0ustar hornikusers# Generated by roxygen2 (4.1.0): do not edit by hand importFrom(Rcpp,loadRcppModules) importFrom(progress,progress_bar) useDynLib(progresstest) export(my_test_progress) progress/inst/progresstest/R/0000755000175100001440000000000012534062534016062 5ustar hornikusersprogress/inst/progresstest/R/test.R0000644000175100001440000000030712534062534017164 0ustar hornikusers #' @importFrom progress progress_bar #' @importFrom Rcpp loadRcppModules #' @useDynLib progresstest #' @export my_test_progress <- function(format = "[:bar] :percent ") { test_progress(format) } progress/inst/progresstest/R/RcppExports.R0000644000175100001440000000053112520265623020474 0ustar hornikusers# This file was generated by Rcpp::compileAttributes # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 test_progress <- function(formatSEXP = "[:bar] :percent ") { .Call('progresstest_test_progress', PACKAGE = 'progresstest', formatSEXP) } test_units <- function() { .Call('progresstest_test_units', PACKAGE = 'progresstest') } progress/inst/progresstest/README.md0000644000175100001440000000051312520266407017137 0ustar hornikusers ## Example package for the C++ API of `progress` Progress bars for your C++ code in R packages. The `progress` package has a pure C++ API for managing progress bars. This is an example package that shows how to use it. The test package uses Rcpp, for simplicity, but this is not necessary, the API itself does not rely on Rcpp. progress/inst/progresstest/DESCRIPTION0000644000175100001440000000047612520265623017375 0ustar hornikusersPackage: progresstest Title: Testing Terminal Progress Bars Version: 1.0.0 Authors@R: person("Gabor", "Csardi", , "csardi.gabort@gmail.com", role = c("aut", "cre")) Description: Test progress bars from the progress package. License: MIT + file LICENSE Imports: progress, Rcpp LinkingTo: progress, Rcpp progress/inst/progresstest/LICENSE0000644000175100001440000000005212520302375016656 0ustar hornikusersYEAR: 2015 COPYRIGHT HOLDER: Gabor Csardi progress/inst/include/0000755000175100001440000000000013023753004014531 5ustar hornikusersprogress/inst/include/RProgress.h0000644000175100001440000002210413023753004016627 0ustar hornikusers/* -*- mode: c++ -*- */ #ifndef R_PROGRESS_H #define R_PROGRESS_H #include #include #ifdef Win32 # include #endif #include #include #include #include #include #include #include #include // For gettimeofday implementation on windows #ifdef Win32 // MSVC defines this in winsock2.h!? typedef struct timeval { long tv_sec; long tv_usec; } timeval; int gettimeofday(struct timeval * tp, struct timezone * tzp); #endif namespace RProgress { class RProgress { public: RProgress(std::string format = "[:bar] :percent", double total = 100, int width = Rf_GetOptionWidth() - 2, char complete_char = '=', char incomplete_char = '-', bool clear = true, double show_after = 0.2) : first(true), format(format), total(total), current(0), width(width), complete_char(complete_char), incomplete_char(incomplete_char), clear(clear), show_after(show_after), last_draw(""), start(0), toupdate(false), complete(false) { supported = is_supported(); use_stderr = default_stderr(); } ~RProgress() { } void set_format(std::string format) { this->format = format; } void set_total(double total) { this->total = total; } void set_width(int width) { this->width = width; } void set_complete_char(char complete_char) { this->complete_char = complete_char; } void set_incomplete_char(char incomplete_char) { this->incomplete_char = incomplete_char; } void set_clear(bool clear) { this->clear = clear; } void set_show_after(double show_after) { this->show_after = show_after; } void tick(double len = 1) { // Start the timer if (first) { start = time_now(); } current += len; count++; // We only update after show_after secs toupdate = toupdate || time_now() - start > show_after; if (current >= total) complete = true; // Need to render at the beginning and at the end, always if (first || toupdate || complete) this->render(); if (complete) this->terminate(); first = false; } void update(double ratio) { double goal = ratio * total; this->tick(goal - current); } private: bool first; // Is the next one the first tick? bool supported; // \r supported at all? std::string format; // Format template double total; // Total number of ticks double current; // Current number of ticks int count; // Total number of calls int width; // Width of progress bar bool use_stderr; // Whether to print to stderr char complete_char; // Character for completed ticks char incomplete_char; // Character for incomplete ticks bool clear; // Should we clear the line at the end? double show_after; // Delay to show/increase the progress bar std::string last_draw; // Last progress bar drawn double start; // Start time bool toupdate; // Are we updating? (After show_after.) bool complete; // Are we complete? void render() { if (!supported) return; std::string str = format; std::stringstream buffer; double ratio_now = ratio(); // percent buffer << std::setw(3) << ratio_now * 100 << "%"; replace_all(str, ":percent", buffer.str()); buffer.str(""); buffer.clear(); // elapsed double elapsed_secs = time_now() - start; std::string elapsed = vague_dt(elapsed_secs); replace_all(str, ":elapsed", elapsed); // eta double percent = round(ratio_now * 100); double eta_secs = percent == 100 ? 0 : elapsed_secs * (total / current - 1.0); std::string eta = std::isinf(eta_secs) ? "?s" : vague_dt(eta_secs); replace_all(str, ":eta", eta); // rate double rate_num = current / elapsed_secs; buffer << pretty_bytes(round(rate_num)) << "/s"; replace_all(str, ":rate", buffer.str()); buffer.str(""); buffer.clear(); // current buffer << round(current); replace_all(str, ":current", buffer.str()); buffer.str(""); buffer.clear(); // total buffer << round(total); replace_all(str, ":total", buffer.str()); buffer.str(""); buffer.clear(); // bytes replace_all(str, ":bytes", pretty_bytes(round(current))); // spin replace_all(str, ":spin", spin_symbol()); // bar std::string str_no_bar = str; replace_all(str_no_bar, ":bar", ""); int bar_width = width - str_no_bar.length(); if (bar_width < 0) bar_width = 0; double complete_len = round(bar_width * ratio_now); char bar[bar_width + 1]; for (int i = 0; i < complete_len; i++) { bar[i] = complete_char; } for (int i = complete_len; i < bar_width; i++) { bar[i] = incomplete_char; } bar[bar_width] = '\0'; replace_all(str, ":bar", bar); if (last_draw != str) { if (last_draw.length() > str.length()) { clear_line(use_stderr, width); } cursor_to_start(use_stderr); if (use_stderr) { REprintf(str.c_str()); } else { Rprintf(str.c_str()); } last_draw = str; } } void terminate() { if (! supported) return; if (clear) { clear_line(use_stderr, width); cursor_to_start(use_stderr); } else { if (use_stderr) { REprintf("\n"); } else { Rprintf("\n"); } } } double ratio() { double ratio = current / total; if (ratio < 0) ratio = 0; if (ratio > 1) ratio = 1; return ratio; } std::string spin_symbol() { const char symbols[4] = {'-', '\\', '|', '/'}; return std::string(1, symbols[(count - 1) % 4]); } void clear_line(bool use_stderr, int width) { char spaces[width + 2]; for (int i = 1; i <= width; i++) spaces[i] = ' '; spaces[0] = '\r'; spaces[width + 1] = '\0'; if (use_stderr) { REprintf(spaces); } else { Rprintf(spaces); } } void cursor_to_start(bool use_stderr) { if (use_stderr) { REprintf("\r"); } else { Rprintf("\r"); } } bool is_r_studio() { char *v = std::getenv("RSTUDIO"); return v != 0 && v[0] == '1' && v[1] == '\0'; } bool is_r_app() { char *v = std::getenv("R_GUI_APP_VERSION"); return v != 0; } // In R Studio we should print to stdout, because priting a \r // to stderr is buggy (reported) bool default_stderr() { return !is_r_studio(); } // If stdout is a terminal, or R Studio or macOS R.app // On windows, stdout is a terminal, apparently bool is_supported() { return isatty(1) || is_r_studio() || is_r_app(); } // gettimeofday for windows, from // https://stackoverflow.com/questions/10905892 #ifdef Win32 #define WIN32_LEAN_AND_MEAN #include #include // portable: uint64_t MSVC: __int64 int gettimeofday(struct timeval * tp, struct timezone * tzp) { // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); SYSTEMTIME system_time; FILETIME file_time; uint64_t time; GetSystemTime( &system_time ); SystemTimeToFileTime( &system_time, &file_time ); time = ((uint64_t)file_time.dwLowDateTime ) ; time += ((uint64_t)file_time.dwHighDateTime) << 32; tp->tv_sec = (long) ((time - EPOCH) / 10000000L); tp->tv_usec = (long) (system_time.wMilliseconds * 1000); return 0; } #endif static double time_now() { struct timeval now; gettimeofday(&now, /* tzp = */ 0); return now.tv_sec + now.tv_usec / 1000000.0; } static void replace_all(std::string& str, const std::string& from, const std::string& to) { if (from.empty()) return; size_t start_pos = 0; while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); } } public: static std::string vague_dt(double seconds) { double minutes = seconds / 60; double hours = minutes / 60; double days = hours / 24; double years = days / 365.25; std::stringstream buffer; buffer << std::setw(2); if (seconds < 50) { buffer << round(seconds) << "s"; } else if (minutes < 50) { buffer << round(minutes) << "m"; } else if (hours < 18) { buffer << round(hours) << "h"; } else if (days < 30) { buffer << round(days) << "d"; } else if (days < 335) { buffer << round(days/30) << "M"; } else { buffer << round(years) << "y"; } return buffer.str(); } static std::string pretty_bytes(long bytes) { if (bytes == 0) { return "0B"; } std::string units[] = { "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; int num_units = std::floor(sizeof(units) / sizeof(units[0])); double idx = std::floor(std::log(bytes) / std::log(1000.0)); if (idx >= num_units) { idx = num_units - 1; } double res = round(bytes / std::pow(1000.0, idx) * 100.0) / 100.0; std::stringstream buffer; buffer.precision(2); buffer << std::fixed << res << units[(long) idx]; return buffer.str(); } }; // class RProgress } // namespace RProgress #endif progress/tests/0000755000175100001440000000000013024204675013301 5ustar hornikusersprogress/tests/testthat.R0000644000175100001440000000015413024204675015264 0ustar hornikusers if (Sys.getenv("NOT_CRAN", "") != "") { library(testthat) library(progress) test_check("progress") } progress/tests/testthat/0000755000175100001440000000000013024271005015130 5ustar hornikusersprogress/tests/testthat/test-cpp.R0000644000175100001440000000167213023752763017036 0ustar hornikusers context("C++ API") test_that("C++ API works", { skip_on_cran() Sys.setenv("R_TESTS" = "") ## Need to "link to" the current package test_pkg_dir <- system.file("progresstest", package = "progress") f <- file(tempfile(), open = "w") sink(f) sink(f, type = "message") install.packages("Rcpp", repos = c(CRAN = "https://cran.rstudio.com"), quiet = TRUE) sink(NULL, type = "message") sink(NULL) close(f) unlink(f) ## OK, we could install it try(silent = TRUE, unloadNamespace("progresstest")) install.packages(test_pkg_dir, repos = NULL, type = "source", quiet = TRUE) ## OK, we could load it do.call("library", list("progresstest", character.only = TRUE)) f <- file(tempfile(), open = "w") sink(f) sink(f, type = "message") my_test_progress() sink(NULL, type = "message") sink(NULL) close(f) unlink(f) try(silent = TRUE, unloadNamespace("progresstest")) }) progress/tests/testthat/test-progress.R0000644000175100001440000002056013023577201020105 0ustar hornikusers context("Progress bar") test_that("Vanilla progress bar works", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20) for (i in 1:5) { pb$tick(20) } }) sout <- win_newline( "\r[===----------] 20%", "\r[=====--------] 40%", "\r[========-----] 60%", "\r[==========---] 80%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that("Update method works", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20) updates = c(20, 40, 20, 80, 100) / 100 for (i in 1:5) { pb$update(updates[i]) } }) sout <- win_newline( "\r[===----------] 20%", "\r[=====--------] 40%", "\r[===----------] 20%", "\r[==========---] 80%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that("Calling tick(0)", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20) pb$tick(0) for (i in 1:5) { pb$tick(20) } }) sout <- win_newline( "\r[-------------] 0%", "\r[===----------] 20%", "\r[=====--------] 40%", "\r[========-----] 60%", "\r[==========---] 80%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that("Digress", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20) f <- function() { pb$tick(50) pb$tick(-20) pb$tick(50) pb$tick(-30) pb$tick(100) } f() }) sout <- win_newline( "\r[======-------] 50%", "\r[====---------] 30%", "\r[==========---] 80%", "\r[======-------] 50%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that("No :bar item, :current and :total tokens", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, total = 10, clear = FALSE, format = ":current/:total") pb$tick(2) pb$tick(5) pb$tick(3) }) sout <- win_newline( "\r2/10", "\r7/10", "\r10/10\n" ) expect_equal(out, sout) }) ## This is somewhat timing dependent, but ## should work in general test_that(":eta and :elapsed tokens", { skip_on_cran() out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, total = 4, format = "[:eta :elapsed]") pb$tick(0) Sys.sleep(1) # 1 sec per tick pb$tick(1) # So 3 more ticks is 3 secs Sys.sleep(1) pb$tick(1) # 2 more is 2 secs pb$tick(2) }) sout <- win_newline( "\r[ ?s 0s]", "\r[ 3s 1s]", "\r[ 2s 2s]", "\r[ 0s 2s]", "\r ", "\r" ) expect_equal(out, sout) }) test_that("complete and incomplete chars", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, total = 5, complete = "#", incomplete = " ", clear = FALSE) for (i in 1:5) pb$tick(1) }) sout <- win_newline( "\r[### ] 20%", "\r[##### ] 40%", "\r[######## ] 60%", "\r[########## ] 80%", "\r[#############] 100%", "\n" ) expect_equal(out, sout) }) test_that("callback function", { x <- "" cb <- function() { x <<- "done" } out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, callback = cb) pb$tick(0) pb$tick(50) pb$tick(50) }) expect_equal(x, "done") x <- "" str <- file(tmp <- tempfile(), open = "w") on.exit(unlink(tmp), add = TRUE) pb <- progress_bar$new(stream = str, show_after = 0, width = 20, callback = cb) pb$tick(0) pb$tick(50) pb$tick(50) close(str) expect_equal(x, "done") }) test_that("clearing and not clearing", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, clear = TRUE) pb$tick(0) pb$tick(50) pb$tick(50) }) sout <- win_newline( "\r[-------------] 0%", "\r[======-------] 50%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, clear = FALSE) pb$tick(0) pb$tick(50) pb$tick(50) }) sout <- win_newline( "\r[-------------] 0%", "\r[======-------] 50%", "\r[=============] 100%", "\n" ) expect_equal(out, sout) }) test_that("show_after argument", { skip_on_cran() out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = .1, width = 20, clear = TRUE) pb$tick(0) pb$tick(25) pb$tick(25) Sys.sleep(.1) pb$tick(25) pb$tick(25) }) sout <- win_newline( "\r[==========---] 75%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that("custom tokens", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, format = ":what [:bar] :percent", clear = FALSE, total = 200) pb$tick(50, tokens = list(what = "foo ")) pb$tick(50, tokens = list(what = "foo ")) pb$tick(50, tokens = list(what = "foobar")) pb$tick(50, tokens = list(what = "foobar")) }) sout <- win_newline( "\rfoo [==----] 25%", "\rfoo [===---] 50%", "\rfoobar [====--] 75%", "\rfoobar [======] 100%", "\n" ) expect_equal(out, sout) }) test_that("bar adepts to width of custom tokens", { out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, format = ":what [:bar] :percent", clear = FALSE, total = 200) pb$tick(50, tokens = list(what = "text")) pb$tick(50, tokens = list(what = "long text")) pb$tick(100, tokens = list(what = "text")) }) sout <- win_newline( "\rtext [==------] 25%", "\rlong text [==-] 50%", "\rtext [========] 100%", "\n" ) expect_equal(out, sout) }) test_that("custom streams", { str <- file(tmp <- tempfile(), open = "w") on.exit(unlink(tmp), add = TRUE) pb <- progress_bar$new(stream = str, force = TRUE, show_after = 0, width = 20) pb$tick(0) pb$tick(50) pb$tick(50) close(str) out <- rawToChar(readBin(tmp, raw(0), n = file.info(tmp)$size)) sout <- win_newline( "\r[-------------] 0%", "\r[======-------] 50%", "\r[=============] 100%", "\r ", "\r" ) expect_equal(out, sout) }) test_that(":rate and :bytes tokens", { skip_on_cran() out <- get_output({ pb <- progress_bar$new(stream = stdout(), force = TRUE, show_after = 0, width = 20, total = 4 * 1024, format = "[:rate :bytes]") pb$tick(0) Sys.sleep(1) # 1 sec per 1000 bytes pb$tick(1024) # So 3000 more bytes is 3 secs Sys.sleep(1) pb$tick(1024) # 2000 more is 2 secs pb$tick(2048) }) ## Next output line might be shorter, so 'progress_bar$render' ## might to erase it first soutm <- win_newline( "^\\r\\[0 B/s 0 B\\]", "\\r?[ ]*", "\\r\\[[0-9\\.]+ k?B/s [0-9\\.]+ k?B\\]", "\\r?[ ]*", "\\r\\[[0-9\\.]+ k?B/s [0-9\\.]+ kB\\]", "\\r?[ ]*", "\\r\\[[0-9\\.]+ k?B/s [0-9\\.]+ kB\\]", "\\r[ ]*", "\\r$" ) expect_match(out, soutm) }) test_that("very quick loops, only the nothing is shown", { out <- get_output({ pb <- progress_bar$new(total = 100, stream = stdout(), force = TRUE, width = 20) for (i in 1:100) pb$tick() }) sout <- win_newline("") expect_equal(out, sout) }) progress/tests/testthat/helper.R0000644000175100001440000000141712532136702016544 0ustar hornikusers get_output <- function(..., stream = stdout()) { if (identical(stream, stdout())) { type <- "output" } else if (identical(stream, stderr())) { type <- "message" } cleanup <- function() { unlink(tmp) sink(NULL, type = type) } tmp <- tempfile() on.exit(cleanup()) sink(tmp, type = type) force(...) ## Windows has some strange readBin and sink interplay, ## so we need to remove the sink before reading the file sink(NULL, type = type) x <- readBin(tmp, raw(0), n = file.info(tmp)$size) unlink(tmp) ## No cleanup is needed any more on.exit(force(1)) rawToChar(x) } win_newline <- function(..., collapse = NULL) { x <- paste0(...) if (.Platform$OS.type == "windows") { x <- gsub("\n", "\r\n", x, fixed = TRUE) } x } progress/NAMESPACE0000644000175100001440000000030013023604344013343 0ustar hornikusers# Generated by roxygen2: do not edit by hand export(progress_bar) importFrom(R6,R6Class) importFrom(prettyunits,pretty_bytes) importFrom(prettyunits,vague_dt) importFrom(utils,flush.console) progress/R/0000755000175100001440000000000013023606334012335 5ustar hornikusersprogress/R/utils.R0000644000175100001440000000410213014402652013612 0ustar hornikusers clear_line <- function(tty, width) { str <- paste0(c("\r", rep(" ", width)), collapse = "") cat(str, file = tty) } cursor_to_start <- function(tty) { cat("\r", file = tty) } is_stdout <- function(stream) { identical(stream, stdout()) && sink.number() == 0 } is_stderr <- function(stream) { identical(stream, stderr()) } is_r_studio <- function() { Sys.getenv("RSTUDIO") == 1 } r_studio_stdout <- function(stream) { interactive() && is_r_studio() && identical(stream, stdout()) && is_stdout(stream) } is_r_app <- function() { Sys.getenv("R_GUI_APP_VERSION") != "" } r_app_stdx <- function(stream) { interactive() && is_r_app() && (is_stdout(stream) || is_stderr(stream)) } is_supported <- function(stream) { isatty(stream) || r_studio_stdout(stream) || r_app_stdx(stream) } default_stream <- function(stream) { if (! is.null(stream)) { stream } else { if (is_r_studio()) stdout() else stderr() } } assert_character_scalar <- function(x) { stopifnot(is.character(x), length(x) == 1, !is.na(x)) } assert_scalar <- function(x, finite = TRUE) { stopifnot(is.numeric(x), length(x) == 1, !is.na(x), !finite || is.finite(x)) } assert_positive_scalar <- function(x, finite = TRUE) { assert_scalar(x, finite = finite) stopifnot(x > 0) } assert_nonnegative_scalar <- function(x, finite = TRUE) { assert_scalar(x, finite = finite) stopifnot(x >= 0) } assert_ratio <- function(x) { assert_nonnegative_scalar(x) stopifnot(x <= 1) } assert_nonzero_count <- function(x, finite = TRUE) { assert_positive_scalar(x, finite = TRUE) stopifnot(as.integer(x) == x) } assert_connection <- function(x) { stopifnot(inherits(x, "connection")) } assert_single_char <- function(x) { assert_character_scalar(x) stopifnot(nchar(x) == 1) } assert_function <- function(x) { stopifnot(is.function(x)) } assert_flag <- function(x) { stopifnot(is.logical(x), length(x) == 1, !is.na(x)) } assert_named_or_empty_list <- function(x) { stopifnot(length(x) == 0 || !is.null(names(x))) } progress/R/progress.R0000644000175100001440000002751213023606334014333 0ustar hornikusers #' Progress bar in the terminal #' #' Progress bars are configurable, may include percentage, elapsed time, #' and/or the estimated completion time. They work in the command line, #' in Emacs and in R Studio. The progress package was heavily influenced by #' https://github.com/tj/node-progress #' #' @section Creating the progress bar: #' A progress bar is an R6 object, that can be created with #' \code{progress_bar$new()}. It has the following arguments: #' \describe{ #' \item{format}{The format of the progress bar. A number of #' tokens can be used here, see them below. It defaults to #' \code{"[:bar] :percent"}, which means that the progress #' bar is within brackets on the left, and the percentage #' is printed on the right.} #' \item{total}{Total number of ticks to complete. Defaults to 100.} #' \item{width}{Width of the progress bar. Default is the current #' terminal width (see \code{options()} and \code{width}) minus two.} #' \item{stream}{The output stream to put the progress bar on. #' It defaults to \code{stderr()}, except in R Studio that has #' a bug when printing on the standard error, so there we use #' \code{stdout}. If the output stream is not a terminal and #' we are not in R Studio, then no progress bar is printed.} #' \item{complete}{Completion character, defaults to \code{=}.} #' \item{incomplete}{Incomplete character, defaults to \code{-}.} #' \item{callback}{Callback function to call when the progress #' bar finishes. The progress bar object itself is passed to it #' as the single parameter.} #' \item{clear}{Whether to clear the progress bar on completion. #' Defaults to \code{TRUE}.} #' \item{show_after}{Amount of time in seconds, after which the progress #' bar is shown on the screen. For very short processes, #' it is probably not worth showing it at all. Defaults to two #' tenth of a second.} #' \item{force}{Whether to force showing the progress bar, #' even if the given (or default) stream does not seem support it.} #' } #' #' @section Using the progress bar: #' Two functions can update a progress bar. \code{progress_bar$tick()} #' increases the number of ticks by one (or another specified value). #' \code{progress_bar$update()} sets a given ratio. #' #' The progress bar is displayed after the first `tick` command. #' This might not be desirable for long computations, because #' nothing is shown before the first tick. It is good practice to #' call `tick(0)` at the beginning of the computation or download, #' which shows the progress bar immediately. #' #' @section Tokens: #' They can be used in the \code{format} argument when creating the #' progress bar. #' \describe{ #' \item{:bar}{The progress bar itself.} #' \item{:current}{Current tick number.} #' \item{:total}{Total ticks.} #' \item{:elapsed}{Elapsed time in seconds.} #' \item{:eta}{Estimated completion time in seconds.} #' \item{:percent}{Completion percentage.} #' \item{:rate}{Download rate, bytes per second. See example below.} #' \item{:bytes}{Shows :current, formatted as bytes. Useful #' for downloads or file reads if you don't know the size of the #' file in advance. See example below.} #' \item{:spin}{Shows a spinner that updates even when progress is #' advanced by zero.} #' } #' #' Custom tokens are also supported, and you need to pass their #' values to \code{progress_bar$tick()} or \code{progress_bar$update()}, #' in a named list. See example below. #' #' @importFrom R6 R6Class #' #' @export #' @examples #' #' ## We don't run the examples on CRAN, because they takes >10s #' ## altogether. Unfortunately it is hard to create a set of #' ## meaningful progress bar examples that also run quickly. #' \dontrun{ #' #' ## Basic #' pb <- progress_bar$new(total = 100) #' for (i in 1:100) { #' pb$tick() #' Sys.sleep(1 / 100) #' } #' #' ## ETA #' pb <- progress_bar$new( #' format = " downloading [:bar] :percent eta: :eta", #' total = 100, clear = FALSE, width= 60) #' for (i in 1:100) { #' pb$tick() #' Sys.sleep(1 / 100) #' } #' #' ## Elapsed time #' pb <- progress_bar$new( #' format = " downloading [:bar] :percent in :elapsed", #' total = 100, clear = FALSE, width= 60) #' for (i in 1:100) { #' pb$tick() #' Sys.sleep(1 / 100) #' } #' #' ## Spinner #' pb <- progress_bar$new( #' format = "(:spin) [:bar] :percent", #' total = 30, clear = FALSE, width = 60) #' for (i in 1:30) { #' pb$tick() #' Sys.sleep(3 / 100) #' } #' #' ## Custom tokens #' pb <- progress_bar$new( #' format = " downloading :what [:bar] :percent eta: :eta", #' clear = FALSE, total = 200, width = 60) #' f <- function() { #' for (i in 1:100) { #' pb$tick(tokens = list(what = "foo ")) #' Sys.sleep(2 / 100) #' } #' for (i in 1:100) { #' pb$tick(tokens = list(what = "foobar")) #' Sys.sleep(2 / 100) #' } #' } #' f() #' #' ## Download (or other) rates #' pb <- progress_bar$new( #' format = " downloading foobar at :rate, got :bytes in :elapsed", #' clear = FALSE, total = 1e7, width = 60) #' f <- function() { #' for (i in 1:100) { #' pb$tick(sample(1:100 * 1000, 1)) #' Sys.sleep(2/100) #' } #' pb$tick(1e7) #' invisible() #' } #' f() #' #' } #' #' @name progress_bar NULL progress_bar <- R6Class("progress_bar", public = list( initialize = function(format = "[:bar] :percent", total = 100, width = getOption("width") - 2, stream = NULL, complete = "=", incomplete = "-", callback = function(self) {}, clear = TRUE, show_after = 0.2, force = FALSE) { pb_init(self, private, format, total, width, stream, complete, incomplete, callback, clear, show_after, force) }, tick = function(len = 1, tokens = list()) { pb_tick(self, private, len, tokens) }, update = function(ratio, tokens = list()) { pb_update(self, private, ratio, tokens) } ), private = list( render = function(tokens) { pb_render(self, private, tokens) }, terminate = function() { pb_terminate(self, private) }, ratio = function() { pb_ratio(self, private) }, first = TRUE, supported = NA, format = NULL, total = NULL, current = 0, width = NULL, stream = NULL, chars = list( complete = "=", incomplete = "-" ), callback = NULL, clear = NULL, show_after = NULL, last_draw = "", start = NULL, toupdate = FALSE, complete = FALSE, spin = NULL, has_token = c(current = FALSE, total = FALSE, elapsed = FALSE, eta = FALSE, percent = FALSE, rate = FALSE, bytes = FALSE, bar = FALSE, spin = FALSE) ) ) pb_init <- function(self, private, format, total, width, stream, complete, incomplete, callback, clear, show_after, force) { stream <- default_stream(stream) assert_character_scalar(format) assert_positive_scalar(total) assert_nonzero_count(width) assert_connection(stream) assert_single_char(complete) assert_single_char(incomplete) assert_function(callback) assert_flag(clear) assert_nonnegative_scalar(show_after) private$first <- TRUE private$supported <- force || is_supported(stream) private$format <- format private$total <- total private$width <- width private$stream <- stream private$chars$complete <- complete private$chars$incomplete <- incomplete private$callback <- callback private$clear <- clear private$show_after <- as.difftime(show_after, units = "secs") private$spin <- spin_symbols() private$has_token <- pb_update_has_token(private$has_token, format) self } pb_update_has_token <- function(tokens, format) { for (n in names(tokens)) { tokens[n] <- grepl(paste0(":", n), format, fixed = TRUE) } tokens } pb_tick <- function(self, private, len, tokens) { assert_scalar(len) assert_named_or_empty_list(tokens) if (private$first) { private$first <- FALSE private$start <- Sys.time() } private$current <- private$current + len if (!private$toupdate) { if (Sys.time() - private$start >= private$show_after) { private$toupdate <- TRUE } } if (private$current >= private$total) private$complete <- TRUE if (private$toupdate) private$render(tokens) if (private$complete) { private$terminate() private$callback() } self } #' @importFrom prettyunits vague_dt pretty_bytes #' @importFrom utils flush.console pb_ratio <- function(self, private) { ratio <- (private$current / private$total) ratio <- max(ratio, 0) ratio <- min(ratio, 1) ratio } pb_render <- function(self, private, tokens) { if (! private$supported) return(invisible()) str <- private$format if (private$has_token["percent"]) { percent <- private$ratio() * 100 str <- sub(str, pattern = ":percent", replacement = paste0(format(round(percent), width = 3), "%")) } if (private$has_token["elapsed"]) { elapsed_secs <- Sys.time() - private$start elapsed <- vague_dt(elapsed_secs, format = "terse") str <- sub(str, pattern = ":elapsed", replacement = elapsed) } if (private$has_token["eta"]) { percent <- private$ratio() * 100 elapsed_secs <- Sys.time() - private$start eta_secs <- if (percent == 100) { 0 } else { elapsed_secs * (private$total / private$current - 1.0) } eta <- as.difftime(eta_secs, units = "secs") if (is.nan(eta) || eta == Inf) { eta <- " ?s" } else { eta <- vague_dt(eta, format = "terse") } str <- sub(str, pattern = ":eta", replacement = eta) } if (private$has_token["rate"]) { elapsed_secs <- Sys.time() - private$start rate <- private$current / as.double(elapsed_secs, units = "secs") if (is.nan(rate)) rate <- 0 rate <- paste0(pretty_bytes(round(rate)), "/s") str <- sub(str, pattern = ":rate", replacement = rate) } if (private$has_token["current"]) { str <- sub(str, pattern = ":current", replacement = round(private$current)) } if (private$has_token["total"]) { str <- sub(str, pattern = ":total", replacement = round(private$total)) } if (private$has_token["bytes"]) { bytes <- pretty_bytes(round(private$current)) str <- sub(str, pattern = ":bytes", replacement = bytes) } if (private$has_token["spin"]) { ## NOTE: fixed = TRUE is needed here or "\\" causes trouble with ## the replacement (I think it's interpreted as an invalid ## backreference). str <- sub(str, pattern = ":spin", replacement = private$spin(), fixed = TRUE) } for (t in names(tokens)) { str <- gsub(paste0(":", t), tokens[[t]], str, fixed = TRUE) } if (private$has_token["bar"]) { bar_width <- nchar(sub(str, pattern = ":bar", replacement = "")) bar_width <- private$width - bar_width bar_width <- max(0, bar_width) ratio <- private$ratio() complete_len <- round(bar_width * ratio) complete <- paste(rep("", complete_len + 1), collapse = private$chars$complete) incomplete <- paste(rep("", bar_width - complete_len + 1), collapse = private$chars$incomplete) str <- sub(":bar", paste0(complete, incomplete), str) } if (private$last_draw != str) { if (nchar(private$last_draw) > nchar(str)) { clear_line(private$stream, private$width) } cursor_to_start(private$stream) cat(str, file = private$stream) private$last_draw <- str } flush.console() self } pb_update <- function(self, private, ratio, tokens) { assert_ratio(ratio) goal <- floor(ratio * private$total) self$tick(goal - private$current, tokens) } pb_terminate <- function(self, private) { if (!private$supported || !private$toupdate) return(invisible()) if (private$clear) { clear_line(private$stream, private$width) cursor_to_start(private$stream) } else { cat("\n", file = private$stream) } } spin_symbols <- function() { sym <- c("-", "\\", "|", "/") i <- 0L n <- length(sym) function() { sym[[i <<- if (i >= n) 1L else i + 1L]] } } progress/MD50000644000175100001440000000240213024271005012434 0ustar hornikusers22a1bb1188d47dcba16533993a530159 *DESCRIPTION e4c81207cdbd596c9e35a231e630e872 *LICENSE 8c924c80c47fd4b443134b51ba5ffcd9 *NAMESPACE b814ea50b680ffb9db27ad4baaf7b94f *R/progress.R 35e20d402c9bd0054a782d01fc4b61dd *R/utils.R 0c9e74abc8221a0c1c9b5b5d6a6a4dae *inst/NEWS.md b8e0ee67cec086fe5622fc959d3c8e97 *inst/README.metacran 6ddb5651141969fda582967e204cd0e2 *inst/include/RProgress.h 76f1f04c00cae388f24f4ff00636c2ae *inst/logo.png 4a607a53806f2e5afe5a834bcace11eb *inst/logo.svg b5981f6a5d933fb66575a38a8a15d187 *inst/progresstest/DESCRIPTION 8488c7e8cbfc04df9ff69dd011f878da *inst/progresstest/LICENSE 1906d818824028e3d8c5a38121018524 *inst/progresstest/NAMESPACE 9d75ffa9d3665660c3cdcf39ad5065b8 *inst/progresstest/R/RcppExports.R 1db6705374372ff537ad6a1856de075a *inst/progresstest/R/test.R 7c0b75a11963c889f7f87acfd22660c4 *inst/progresstest/README.md 7d4c5db3fbe2c2b7c93be3062b280604 *inst/progresstest/src/RcppExports.cpp 8a6f1090313e7c4b076ef60cd0838175 *inst/progresstest/src/test.cpp 22fa2206d93e2b35d881c622a29a4751 *man/progress_bar.Rd 95d3bb15732f376a121c2d619708824e *tests/testthat.R 13dc299450724118ac82173b952468fd *tests/testthat/helper.R 367aa8feade5b32c0307395662836aaf *tests/testthat/test-cpp.R 62bfdd32271e3f6a629473f52d792de8 *tests/testthat/test-progress.R progress/DESCRIPTION0000644000175100001440000000151013024271005013631 0ustar hornikusersPackage: progress Title: Terminal Progress Bars Version: 1.1.2 Author: Gábor Csárdi [aut, cre], Rich FitzJohn [aut] Maintainer: Gábor Csárdi Description: Configurable Progress bars, they may include percentage, elapsed time, and/or the estimated completion time. They work in terminals, in 'Emacs' 'ESS', 'RStudio', 'Windows' 'Rgui' and the 'macOS' 'R.app'. The package also provides a 'C++' 'API', that works with or without 'Rcpp'. License: MIT + file LICENSE LazyData: true URL: https://github.com/gaborcsardi/progress#readme BugReports: https://github.com/gaborcsardi/progress/issues Imports: prettyunits, R6 Suggests: testthat RoxygenNote: 5.0.1.9000 Encoding: UTF-8 NeedsCompilation: no Packaged: 2016-12-14 09:09:03 UTC; gaborcsardi Repository: CRAN Date/Publication: 2016-12-14 17:23:33 progress/man/0000755000175100001440000000000013014402652012704 5ustar hornikusersprogress/man/progress_bar.Rd0000644000175100001440000001156613023606337015702 0ustar hornikusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/progress.R \name{progress_bar} \alias{progress_bar} \title{Progress bar in the terminal} \description{ Progress bars are configurable, may include percentage, elapsed time, and/or the estimated completion time. They work in the command line, in Emacs and in R Studio. The progress package was heavily influenced by https://github.com/tj/node-progress } \section{Creating the progress bar}{ A progress bar is an R6 object, that can be created with \code{progress_bar$new()}. It has the following arguments: \describe{ \item{format}{The format of the progress bar. A number of tokens can be used here, see them below. It defaults to \code{"[:bar] :percent"}, which means that the progress bar is within brackets on the left, and the percentage is printed on the right.} \item{total}{Total number of ticks to complete. Defaults to 100.} \item{width}{Width of the progress bar. Default is the current terminal width (see \code{options()} and \code{width}) minus two.} \item{stream}{The output stream to put the progress bar on. It defaults to \code{stderr()}, except in R Studio that has a bug when printing on the standard error, so there we use \code{stdout}. If the output stream is not a terminal and we are not in R Studio, then no progress bar is printed.} \item{complete}{Completion character, defaults to \code{=}.} \item{incomplete}{Incomplete character, defaults to \code{-}.} \item{callback}{Callback function to call when the progress bar finishes. The progress bar object itself is passed to it as the single parameter.} \item{clear}{Whether to clear the progress bar on completion. Defaults to \code{TRUE}.} \item{show_after}{Amount of time in seconds, after which the progress bar is shown on the screen. For very short processes, it is probably not worth showing it at all. Defaults to two tenth of a second.} \item{force}{Whether to force showing the progress bar, even if the given (or default) stream does not seem support it.} } } \section{Using the progress bar}{ Two functions can update a progress bar. \code{progress_bar$tick()} increases the number of ticks by one (or another specified value). \code{progress_bar$update()} sets a given ratio. The progress bar is displayed after the first `tick` command. This might not be desirable for long computations, because nothing is shown before the first tick. It is good practice to call `tick(0)` at the beginning of the computation or download, which shows the progress bar immediately. } \section{Tokens}{ They can be used in the \code{format} argument when creating the progress bar. \describe{ \item{:bar}{The progress bar itself.} \item{:current}{Current tick number.} \item{:total}{Total ticks.} \item{:elapsed}{Elapsed time in seconds.} \item{:eta}{Estimated completion time in seconds.} \item{:percent}{Completion percentage.} \item{:rate}{Download rate, bytes per second. See example below.} \item{:bytes}{Shows :current, formatted as bytes. Useful for downloads or file reads if you don't know the size of the file in advance. See example below.} \item{:spin}{Shows a spinner that updates even when progress is advanced by zero.} } Custom tokens are also supported, and you need to pass their values to \code{progress_bar$tick()} or \code{progress_bar$update()}, in a named list. See example below. } \examples{ ## We don't run the examples on CRAN, because they takes >10s ## altogether. Unfortunately it is hard to create a set of ## meaningful progress bar examples that also run quickly. \dontrun{ ## Basic pb <- progress_bar$new(total = 100) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ## ETA pb <- progress_bar$new( format = " downloading [:bar] :percent eta: :eta", total = 100, clear = FALSE, width= 60) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ## Elapsed time pb <- progress_bar$new( format = " downloading [:bar] :percent in :elapsed", total = 100, clear = FALSE, width= 60) for (i in 1:100) { pb$tick() Sys.sleep(1 / 100) } ## Spinner pb <- progress_bar$new( format = "(:spin) [:bar] :percent", total = 30, clear = FALSE, width = 60) for (i in 1:30) { pb$tick() Sys.sleep(3 / 100) } ## Custom tokens pb <- progress_bar$new( format = " downloading :what [:bar] :percent eta: :eta", clear = FALSE, total = 200, width = 60) f <- function() { for (i in 1:100) { pb$tick(tokens = list(what = "foo ")) Sys.sleep(2 / 100) } for (i in 1:100) { pb$tick(tokens = list(what = "foobar")) Sys.sleep(2 / 100) } } f() ## Download (or other) rates pb <- progress_bar$new( format = " downloading foobar at :rate, got :bytes in :elapsed", clear = FALSE, total = 1e7, width = 60) f <- function() { for (i in 1:100) { pb$tick(sample(1:100 * 1000, 1)) Sys.sleep(2/100) } pb$tick(1e7) invisible() } f() } } progress/LICENSE0000644000175100001440000000006113023604252013133 0ustar hornikusersYEAR: 2015-2016 COPYRIGHT HOLDER: Gábor Csárdi