p-ranav / indicators

Activity Indicators for Modern C++

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Passing boost::optional ProgressBar handle (from inside DynamicProgress) to function for mutation

tmcg0 opened this issue · comments

Loving this repo so far, thanks for all your hard work. Any advice would be greatly appreciated. I've got a possible enhancement, but want to make sure I'm not missing anything on how I could do this via a workaround.

In short, I'd like to have worker functions which can modify an optionally (via boost::optional) passed-in ProgressBar, which is inside a DynamicProgress in the application-level code.

Say I have a a ProgressBars that I then pass into DynamicProgress dbar, like so:

indicators::ProgressBar bar1{
      indicators::option::BarWidth{40},
      indicators::option::PrefixText{"progress bar 1"},
      indicators::option::PostfixText{"not mutated by function yet"}
};
indicators::ProgressBar bar2{
      indicators::option::BarWidth{40},
      indicators::option::PrefixText{"progress bar 2"},
      indicators::option::PostfixText{"not mutated by function yet"}
  };
indicators::DynamicProgress<indicators::ProgressBar> dbar;
dbar.push_back(bar1);
dbar.push_back(bar2);

I would then like to be able to pass the ProgressBar at dbar[0] to a function which mutates it, e.g. changes the progress or text, without having to pass the parent DynamicProgress. Being forced to pass the parent DynamicProgress is messy: it means that worker functions can't be passed individual progress bars without unnecessary code (e.g. having to first put the single progressbar in a dynamicprogress at the application level), and forces a clunky interface to the worker function because you also have to pass in the index of the bar inside the DynamicProgress.

Minimum (not) working example of what I'd like to do:

#include <indicators/progress_bar.hpp>
#include <indicators/dynamic_progress.hpp>
#include <boost/optional.hpp>

void pbar_mutation_function(boost::optional<indicators::ProgressBar*> bar=boost::none);

int main() {
    // build progressbars
    indicators::ProgressBar bar1{
        indicators::option::BarWidth{40},
        indicators::option::PrefixText{"progress bar 1"},
        indicators::option::PostfixText{"not mutated by function yet"}
    };
    indicators::ProgressBar bar2{
        indicators::option::BarWidth{40},
        indicators::option::PrefixText{"progress bar 2"},
        indicators::option::PostfixText{"not mutated by function yet"}
    };
    // insert it into a dynamic progress container
    indicators::DynamicProgress<indicators::ProgressBar> dbar;
    dbar.push_back(bar1);
    dbar.push_back(bar2);
    // pass the child progressbar "bar1" into mutation function
    pbar_mutation_function(&(dbar[0])); // this doesn't work :(
    return 0;
}

void pbar_mutation_function(boost::optional<indicators::ProgressBar*> bar){
    // update bar postfix text to notify you're in the mutation function
    if(bar){
      (*(*bar)).set_option(indicators::option::PostfixText{"inside bar mutation function"});
    }
    // in loop iterate up bar
    for(uint i=0; i<=100; i++){
      if(bar){
        (*(*bar)).set_option(indicators::option::PostfixText{"inside bar mutation function: i="+std::to_string(i)});
        (*(*bar)).tick();
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(5));
    }
    // mark bar as complete
    if(bar){
      (*(*bar)).mark_as_completed();
    }
}

Desired behavior of above example
Two progress bars are initialized on the console, but only bar1 gets iterated up.

Observed behavior
Neither bar gets modified.
image