First of all: I think ProgressMeter.jl is great and thanks for putting so much effort into it. Looking through the open and closed issues at least several of them are about adding new features or options of how the information is displayed, e.g. #286 #255 #244 and so I want to propose modular elements of the progress printed that can easily be extended to achieve customization. This is raised from my side because in SpeedyWeather/SpeedyWeather.jl#989 I've been trying to print additional information as part of the progress of a simulation while it's running. I was only able to do this by committing type piracy on ProgressMeter.showspeed so I'm proposing a more general extensible interface that hopefully also means for you as developer less work because people can do more easily their own extensions.
Define current progress elements as <: AbstractProgressElement
To achieve extensibility, I propose to use multiple dispatch of custom types <: ProgressMeter.AbstractProgressElement and to reimplement the currently printed elements as those too, something like
abstract type AbstractProgressElement end # the abstract type to subtype for custom elements
function print_element end # the function to extend for each new type, expected to return a string
So the "desc" keyword argument is just a string that's returned
mutable struct DescriptionElement <: AbstractProgressElement
description::String
end
# always pass on the progress as second argument
print_element(E::DescriptionElement, progress::AbstractProgress) = E.description
but if one wanted to style that string you could adapt print_element or add fields to DescriptionElement. The percentage element would be
struct PercentageElement <: AbstractProgressElement end
print_element(::PercentageElement, progress::AbstractProgress) = # calculate the X% string here from `progress`
and similar the BarElement which would probably have as fields barlen, barglyphs etc. And similar for TimeElement or SpeedElement. Then every progress::AbstractProgress would get a field called elements::NamedTuple, e.g.
mutable struct Progress{E} <: AbstractProgress
...
elements::E
...
end
which determines the order in which the elements are concatenated, and allows one to flexibly reuse existing elements or define new ones, e.g.
p = ProgressMeter.Progress(n, elements = (desc = DescriptionElement("Going fast:"), perc = PercentageElement(), bar = BarElement(glyphs = "abcde"))
Why is this extensible?
As a user of this package I can now do
using ProgressMeter
mutable struct MyElement <: ProgressMeter.AbstractProgressElement
some_information::T
end
function ProgressMeter.print_element(E::MyElement, progress::ProgressMeter.AbstractProgress)
# return any information from MyElement or the progress as string
end
So at any time I can update my_element = MyElement(...) (or let it just be a pointer to some object that's changing during progress) and the progress meter would automatically pull in that information and print as I like -- without committing type piracy because only I have defined MyElement.
Please let me know what you think but I think this could be a win-win, i.e. in the long term less work for you because many feature requests can be implemented by the users autonomously plus freedom of styles beyond just custom barglyphs etc.
First of all: I think ProgressMeter.jl is great and thanks for putting so much effort into it. Looking through the open and closed issues at least several of them are about adding new features or options of how the information is displayed, e.g. #286 #255 #244 and so I want to propose modular elements of the progress printed that can easily be extended to achieve customization. This is raised from my side because in SpeedyWeather/SpeedyWeather.jl#989 I've been trying to print additional information as part of the progress of a simulation while it's running. I was only able to do this by committing type piracy on
ProgressMeter.showspeedso I'm proposing a more general extensible interface that hopefully also means for you as developer less work because people can do more easily their own extensions.Define current progress elements as
<: AbstractProgressElementTo achieve extensibility, I propose to use multiple dispatch of custom types
<: ProgressMeter.AbstractProgressElementand to reimplement the currently printed elements as those too, something likeSo the "desc" keyword argument is just a string that's returned
but if one wanted to style that string you could adapt
print_elementor add fields toDescriptionElement. The percentage element would beand similar the
BarElementwhich would probably have as fieldsbarlen,barglyphsetc. And similar forTimeElementorSpeedElement. Then everyprogress::AbstractProgresswould get a field calledelements::NamedTuple, e.g.which determines the order in which the elements are concatenated, and allows one to flexibly reuse existing elements or define new ones, e.g.
Why is this extensible?
As a user of this package I can now do
So at any time I can update
my_element = MyElement(...)(or let it just be a pointer to some object that's changing during progress) and the progress meter would automatically pull in that information and print as I like -- without committing type piracy because only I have definedMyElement.Please let me know what you think but I think this could be a win-win, i.e. in the long term less work for you because many feature requests can be implemented by the users autonomously plus freedom of styles beyond just custom barglyphs etc.