diff --git a/decor/decorators.go b/decor/decorators.go index 54a2294..4e96b7a 100644 --- a/decor/decorators.go +++ b/decor/decorators.go @@ -9,8 +9,8 @@ const ( // DidentRight specifies identation direction. + // |foo |b | With DidentRight // | foo| b| Without DidentRight - // |foo |b | With DidentRight DidentRight = 1 << iota // DwidthSync will auto sync max width @@ -20,6 +20,8 @@ // When DidentRight bit set, the space will be added to the right, // otherwise to the left. DextraSpace + + DSyncSpace = DwidthSync | DextraSpace ) // Statistics represents statistics of the progress bar. diff --git a/decor/format.go b/decor/format.go index 97d361a..63de955 100644 --- a/decor/format.go +++ b/decor/format.go @@ -3,23 +3,24 @@ import "fmt" const ( - _ = iota - bytesInKiB = 1 << (iota * 10) - bytesInMiB - bytesInGiB - bytesInTiB + _ = iota + KiB = 1 << (iota * 10) + MiB + GiB + TiB ) const ( - bytesInKb = 1000 - bytesInMB = bytesInKb * 1000 - bytesInGB = bytesInMB * 1000 - bytesInTB = bytesInGB * 1000 + KB = 1000 + MB = KB * 1000 + GB = MB * 1000 + TB = GB * 1000 ) const ( + _ = iota // Kibibyte = 1024 b - Unit_KiB = iota + Unit_KiB // Kilobyte = 1000 b Unit_kB ) @@ -59,14 +60,14 @@ func formatKiB(i int) (result string) { switch { - case i >= bytesInTiB: - result = fmt.Sprintf("%.1fTiB", float64(i)/bytesInTiB) - case i >= bytesInGiB: - result = fmt.Sprintf("%.1fGiB", float64(i)/bytesInGiB) - case i >= bytesInMiB: - result = fmt.Sprintf("%.1fMiB", float64(i)/bytesInMiB) - case i >= bytesInKiB: - result = fmt.Sprintf("%.1fKiB", float64(i)/bytesInKiB) + case i >= TiB: + result = fmt.Sprintf("%.1fTiB", float64(i)/TiB) + case i >= GiB: + result = fmt.Sprintf("%.1fGiB", float64(i)/GiB) + case i >= MiB: + result = fmt.Sprintf("%.1fMiB", float64(i)/MiB) + case i >= KiB: + result = fmt.Sprintf("%.1fKiB", float64(i)/KiB) default: result = fmt.Sprintf("%db", i) } @@ -75,14 +76,14 @@ func formatKB(i int) (result string) { switch { - case i >= bytesInTB: - result = fmt.Sprintf("%.1fTB", float64(i)/bytesInTB) - case i >= bytesInGB: - result = fmt.Sprintf("%.1fGB", float64(i)/bytesInGB) - case i >= bytesInMB: - result = fmt.Sprintf("%.1fMB", float64(i)/bytesInMB) - case i >= bytesInKb: - result = fmt.Sprintf("%.1fkB", float64(i)/bytesInKb) + case i >= TB: + result = fmt.Sprintf("%.1fTB", float64(i)/TB) + case i >= GB: + result = fmt.Sprintf("%.1fGB", float64(i)/GB) + case i >= MB: + result = fmt.Sprintf("%.1fMB", float64(i)/MB) + case i >= KB: + result = fmt.Sprintf("%.1fkB", float64(i)/KB) default: result = fmt.Sprintf("%db", i) } diff --git a/decor/format_test.go b/decor/format_test.go new file mode 100644 index 0000000..68a8d76 --- /dev/null +++ b/decor/format_test.go @@ -0,0 +1,43 @@ +package decor_test + +import ( + "testing" + + "github.com/vbauerster/mpb/decor" +) + +func TestFormatNoUnits(t *testing.T) { + actual := decor.Format(1234567).String() + expected := "1234567" + if actual != expected { + t.Errorf("Expected %q but found %q", expected, actual) + } +} + +func TestFormatWidth(t *testing.T) { + actual := decor.Format(1234567).Width(10).String() + expected := " 1234567" + if actual != expected { + t.Errorf("Expected %q but found %q", expected, actual) + } +} + +func TestFormatToBytes(t *testing.T) { + inputs := []struct { + v int + e string + }{ + {v: 1000, e: "1000b"}, + {v: 1024, e: "1.0KiB"}, + {v: 3*decor.MiB + 140*decor.KiB, e: "3.1MiB"}, + {v: 2 * decor.GiB, e: "2.0GiB"}, + {v: 4 * decor.TiB, e: "4.0TiB"}, + } + + for _, input := range inputs { + actual := decor.Format(input.v).To(decor.Unit_KiB).String() + if actual != input.e { + t.Errorf("Expected %q but found %q", input.e, actual) + } + } +} diff --git a/decorators.go b/decorators.go deleted file mode 100644 index 4591997..0000000 --- a/decorators.go +++ /dev/null @@ -1,126 +0,0 @@ -package mpb - -import ( - "fmt" - "time" - "unicode/utf8" -) - -const ( - // DidentRight specifies identation direction. - // | foo| b| Without DidentRight - // |foo |b | With DidentRight - DidentRight = 1 << iota - - // DwidthSync will auto sync max width - DwidthSync - - // DextraSpace adds extra space, makes sence with DwidthSync only. - // When DidentRight bit set, the space will be added to the right, - // otherwise to the left. - DextraSpace -) - -// DecoratorFunc is a function that can be prepended and appended to the progress bar -type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string - -func Name(name string, minWidth int, conf byte) DecoratorFunc { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(name) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), name) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), name) - } -} - -func Counters(pairFormat string, unit Units, minWidth int, conf byte) DecoratorFunc { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - current := Format(s.Current).To(unit) - total := Format(s.Total).To(unit) - str := fmt.Sprintf(pairFormat, current, total) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - } -} - -func ETA(minWidth int, conf byte) DecoratorFunc { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprint(time.Duration(s.Eta().Seconds()) * time.Second) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - } -} - -func (b *Bar) Elapsed(minWidth int, conf byte) DecoratorFunc { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - } -} - -func Percentage(minWidth int, conf byte) DecoratorFunc { - format := "%%" - if (conf & DidentRight) != 0 { - format += "-" - } - format += "%ds" - return func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string { - str := fmt.Sprintf("%d %%", percentage(s.Total, s.Current, 100)) - if (conf & DwidthSync) != 0 { - myWidth <- utf8.RuneCountInString(str) - max := <-maxWidth - if (conf & DextraSpace) != 0 { - max++ - } - return fmt.Sprintf(fmt.Sprintf(format, max), str) - } - return fmt.Sprintf(fmt.Sprintf(format, minWidth), str) - } -} diff --git a/decorators_test.go b/decorators_test.go deleted file mode 100644 index 73da62b..0000000 --- a/decorators_test.go +++ /dev/null @@ -1,382 +0,0 @@ -package mpb_test - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "regexp" - "strings" - "testing" - "time" - - "github.com/vbauerster/mpb" -) - -func TestPrependName(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - name := "TestBar" - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependName(name, 0, 0) - for i := 0; i < 100; i++ { - bar.Incr(1) - } - - p.Stop() - - want := name + "[" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependNameDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - name := "TestBar" - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependName(name, len(name)+1, mpb.DidentRight) - for i := 0; i < 100; i++ { - bar.Incr(1) - } - - p.Stop() - - want := name + " [" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependCounters(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - reader := strings.NewReader(content) - - total := int64(len(content)) - bar := p.AddBar(total).TrimLeftSpace().TrimRightSpace(). - PrependCounters("%3s / %3s", mpb.UnitBytes, 0, 0) - preader := bar.ProxyReader(reader) - - _, err := io.Copy(ioutil.Discard, preader) - if err != nil { - t.Errorf("Error copying from reader: %+v\n", err) - } - - p.Stop() - - barOut := buf.String() - want := fmt.Sprintf("%[1]db / %[1]db[", total) - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependCountersDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - reader := strings.NewReader(content) - - total := int64(len(content)) - bar := p.AddBar(total).TrimLeftSpace().TrimRightSpace(). - PrependCounters("%3s / %3s", mpb.UnitBytes, 12, mpb.DidentRight) - preader := bar.ProxyReader(reader) - - _, err := io.Copy(ioutil.Discard, preader) - if err != nil { - t.Errorf("Error copying from reader: %+v\n", err) - } - - p.Stop() - - barOut := buf.String() - want := fmt.Sprintf("%[1]db / %[1]db [", total) - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendPercentage(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendPercentage(6, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "] 100 %" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendPercentageDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendPercentage(6, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "]100 % " - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependPercentage(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependPercentage(6, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := " 100 %[" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependPercentageDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependPercentage(6, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "100 % [" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependElapsed(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependElapsed(0, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "1s[" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependElapsedDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependElapsed(3, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "1s [" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendElapsed(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendElapsed(0, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "]1s" - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendElapsedDindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendElapsed(3, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := "]1s " - barOut := buf.String() - if !strings.Contains(barOut, want) { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependETA(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependETA(0, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := `0s?\[` - barOut := buf.String() - - matched, err := regexp.MatchString(want, barOut) - if err != nil { - t.Logf("Regex %q err: %+v\n", want, err) - t.FailNow() - } - - if !matched { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestPrependETADindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - PrependETA(3, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := `0s?\s+\[` - barOut := buf.String() - - matched, err := regexp.MatchString(want, barOut) - if err != nil { - t.Logf("Regex %q err: %+v\n", want, err) - t.FailNow() - } - - if !matched { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendETA(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendETA(0, 0) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := `\]0s?` - barOut := buf.String() - - matched, err := regexp.MatchString(want, barOut) - if err != nil { - t.Logf("Regex %q err: %+v\n", want, err) - t.FailNow() - } - - if !matched { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} - -func TestAppendETADindentRight(t *testing.T) { - var buf bytes.Buffer - p := mpb.New().SetOut(&buf) - - bar := p.AddBar(100).TrimLeftSpace().TrimRightSpace(). - AppendETA(3, mpb.DidentRight) - - for i := 0; i < 100; i++ { - time.Sleep(10 * time.Millisecond) - bar.Incr(1) - } - - p.Stop() - - want := `\]0s? ` - barOut := buf.String() - - matched, err := regexp.MatchString(want, barOut) - if err != nil { - t.Logf("Regex %q err: %+v\n", want, err) - t.FailNow() - } - - if !matched { - t.Errorf("%q not found in bar: %s\n", want, barOut) - } -} diff --git a/format.go b/format.go deleted file mode 100644 index 3693259..0000000 --- a/format.go +++ /dev/null @@ -1,63 +0,0 @@ -package mpb - -import "fmt" - -const ( - _ = iota - bytesInKiB = 1 << (iota * 10) - bytesInMiB - bytesInGiB - bytesInTiB -) - -type Units uint - -const ( - _ = iota - UnitBytes -) - -func Format(i int64) *formatter { - return &formatter{n: i} -} - -type formatter struct { - n int64 - unit Units - width int -} - -func (f *formatter) To(unit Units) *formatter { - f.unit = unit - return f -} - -func (f *formatter) Width(width int) *formatter { - f.width = width - return f -} - -func (f *formatter) String() string { - switch f.unit { - case UnitBytes: - return formatBytes(f.n) - default: - return fmt.Sprintf(fmt.Sprintf("%%%dd", f.width), f.n) - } -} - -func formatBytes(i int64) (result string) { - switch { - case i >= bytesInTiB: - result = fmt.Sprintf("%.1fTiB", float64(i)/bytesInTiB) - case i >= bytesInGiB: - result = fmt.Sprintf("%.1fGiB", float64(i)/bytesInGiB) - case i >= bytesInMiB: - result = fmt.Sprintf("%.1fMiB", float64(i)/bytesInMiB) - case i >= bytesInKiB: - result = fmt.Sprintf("%.1fKiB", float64(i)/bytesInKiB) - default: - result = fmt.Sprintf("%db", i) - } - return -} diff --git a/format_test.go b/format_test.go deleted file mode 100644 index 7529b62..0000000 --- a/format_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package mpb_test - -import ( - "testing" - - "github.com/vbauerster/mpb" -) - -const ( - _ = iota - KiB = 1 << (iota * 10) - MiB - GiB - TiB -) - -func TestFormatNoUnits(t *testing.T) { - actual := mpb.Format(1234567).String() - expected := "1234567" - if actual != expected { - t.Errorf("Expected %q but found %q", expected, actual) - } -} - -func TestFormatWidth(t *testing.T) { - actual := mpb.Format(1234567).Width(10).String() - expected := " 1234567" - if actual != expected { - t.Errorf("Expected %q but found %q", expected, actual) - } -} - -func TestFormatToBytes(t *testing.T) { - inputs := []struct { - v int64 - e string - }{ - {v: 1000, e: "1000b"}, - {v: 1024, e: "1.0KiB"}, - {v: 3*MiB + 140*KiB, e: "3.1MiB"}, - {v: 2 * GiB, e: "2.0GiB"}, - {v: 4 * TiB, e: "4.0TiB"}, - } - - for _, input := range inputs { - actual := mpb.Format(input.v).To(mpb.UnitBytes).String() - if actual != input.e { - t.Errorf("Expected %q but found %q", input.e, actual) - } - } -}