vbauerster / mpb

multi progress bar for Go cli applications
The Unlicense
2.29k stars 123 forks source link

Implement OnAbort method #103

Closed Galzzly closed 2 years ago

Galzzly commented 2 years ago

I am making use of mpb to add decorations while performing extractions of several archive files.

I have this set up as a spinner, and on completion will update to include the time taken.

    b = p.Add(
        int64(1),
        mpb.NewBarFiller(
            mpb.SpinnerStyle([]string{"∙∙∙", "●∙∙", "∙●∙", "∙∙●", "∙∙∙"}...).PositionLeft(),
        ),
        mpb.BarFillerClearOnComplete(),
        mpb.PrependDecorators(
            decor.Name(file+":", decor.WC{W: len(file) + 2, C: decor.DidentRight}),
            decor.OnComplete(decor.Name("Extracting", decor.WCSyncSpaceR), fmt.Sprintf("Done (%s)", time.Since(start))),
        ),
    )

This works just fine when I use b.SetTotal(1, true) once extraction is completed, however, when I need to abort, I would like to be able to set an alternative message rather than fmt.Sprintf("Done (%s)", time.Since(start).

It would be useful to have a function for decor.OnAbort that follows the same methods that OnComplete does - but is only initiated when Abort is used, or to have an additional field on OnComplete for a message when Abort is used (OnComplete(decorator Decorator, completeMessage, abortMessage string) for example)

vbauerster commented 2 years ago

I've implemented OnAbort in commit 086ddfabd20d0ed7b1429e40382c1cab4d4cf008. You can check remove example as well.

vbauerster commented 2 years ago

Available in v7.2.0

mmellin commented 1 year ago

@vbauerster is there a way to either run onComplete() or onAbort()? I have an errGroup and would like the bar for each Go routine to disappear and end in done! if completed successfully, but failed! if there is an error and it I ran bar.Abort(false).

Here is some sample code:

bar := p.New(0, bs,
        mpb.PrependDecorators(
            decor.Name(green(name)),
            decor.OnComplete(
                decor.Spinner(spinnerFrames, decor.WCSyncSpace), green("done!"),
            ),
            decor.OnAbort(decor.Spinner(spinnerFrames, decor.WCSyncSpace), red("failed!")),
        ),
        mpb.AppendDecorators(
            decor.OnComplete(
                decor.Percentage(), "",
            ),
            // decor.OnAbort(decor.Percentage(), red("X failed")), // ??
        ),
        mpb.BarFillerClearOnComplete(),
    )

The behavior here seems to print out 2 spinners and both messages, one for completed and one for Abort. I cannot figure out how to do one or the other.

Desired output is like this:

Host 10.87.107.8:      ⢿ [===========================================================>--] 96 %
Host 10.87.107.7: failed!
Host 10.87.107.5: done!
vbauerster commented 1 year ago

I think you need to compose like OnAbort(OnComplete). Following is patch applied to this example, which works the way you asked:

diff --git a/_examples/remove/main.go b/_examples/remove/main.go
index e9894ed..cbf1fbc 100644
--- a/_examples/remove/main.go
+++ b/_examples/remove/main.go
@@ -22,7 +22,6 @@ func main() {
        name := fmt.Sprintf("Bar#%d:", i)
        bar := p.AddBar(int64(total),
            mpb.BarID(i),
-           mpb.BarOptional(mpb.BarRemoveOnComplete(), i == 0),
            mpb.PrependDecorators(
                decor.Name(name),
            ),
@@ -33,8 +32,7 @@ func main() {
                decor.Any(func(s decor.Statistics) string {
                    return fmt.Sprintf("aborted: %v", s.Aborted)
                }, decor.WCSyncSpaceR),
-               decor.OnComplete(decor.NewPercentage("%d", decor.WCSyncSpace), "done"),
-               decor.OnAbort(decor.NewPercentage("%d", decor.WCSyncSpace), "ohno"),
+               decor.OnAbort(decor.OnComplete(decor.NewPercentage("%d", decor.WCSyncSpace), "done"), "ohno"),
            ),
        )
        go func() {