I’ve been working a lot recently on organising the code I wrote for my master’s thesis into an R package to hopefully get it published on CRAN. Since the calculations involved are rather intensive, I chose to implement them in C++ and Fortran, and used the OpenMP API to parallelise them. After many grueling hours of debugging segfaults, the package finally seemed to be coming together, but there was still one aspect I couldn’t quite get right: tracking progress.
You could argue that this is somewhat of a superfluous functionality, but I disagree: when you have a blocking function that does a long computation, not providing some indicator of how far along it has come is just a bad user experience. Personnaly, I also like for progress bars to be aesthetically appealing, although I will admit this is primarily driven by vanity.
When it comes to producing beautiful output in the R world, it’s undeniable that the tidyverse
suite (primarily maintained by Posit, of RStudio fame) rules the roost. Say what you will about the opinionated nature of many its packages, which can often feel a bit too frameworky to me as well, it’s hard to compete with ggplot
or devtools
when it comes to eye candy. The same goes for their cli
package, which provides tools for building some truly stunning outputs in the terminal.
The good news is that cli
does provide a C API, which could be made available in Fortran through some straightforward wrappers. Unfortunately for my use-case, however, the package is not thread safe, and there does not appear to be an easy way to make it so. As far as I can tell, the only package which provides a parallel-friendly progress bar in R is RcppProgress
, but this only provides ASCII-based progress bars out of the box.
Unwilling to abandon my aesthetic aspirations, I tried to find another way of reproducing cli
’s output. Luckily, RcppProgress
allows users to easily define their own progress bars following the tutorial here. After looking at the cli
progress bar’s underlying C code here and checking out this great ANSI reference on GitHub, this is what I came up with:
|
|
And here is what it looks like:
Not too shabby if you ask me!