Skip to content

Commit

Permalink
Merge pull request #337 from Brookke/issue-261-custom-writer-for-prog…
Browse files Browse the repository at this point in the history
…ress-spinners
  • Loading branch information
MarvinJWendt committed Apr 20, 2022
2 parents 11fc7cd + 4ee46ab commit e95b01c
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 80 deletions.
63 changes: 32 additions & 31 deletions docs/docs/printer/progressbar.md
@@ -1,6 +1,6 @@
# ProgressbarPrinter

<!--
<!--
Replace all of the following strings with the current printer.
progressbar Progressbar ProgressbarPrinter DefaultProgressbar
-->
Expand All @@ -9,7 +9,6 @@ Replace all of the following strings with the current printer.

<p align="center"><a href="https://github.com/pterm/pterm/blob/master/_examples/progressbar/main.go" target="_blank">(Show source of demo)</a></p>


## Usage

### Basic usage
Expand All @@ -23,12 +22,12 @@ progressbar.Increment()

### Functions

|Function|Description|
|--------|-----------|
|[Add(count int)](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.Add)|Add `count` to current value.|
|[GetElapsedTime()](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.GetElapsedTime)|GetElapsedTime returns the elapsed time, since the ProgressbarPrinter was started.|
|[Increment()](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.Increment)|Increment current value by one.|
|[UpdateTitle(title string)](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.UpdateTitle)|Update the progressbar's title.|
| Function | Description |
| ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| [Add(count int)](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.Add) | Add `count` to current value. |
| [GetElapsedTime()](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.GetElapsedTime) | GetElapsedTime returns the elapsed time, since the ProgressbarPrinter was started. |
| [Increment()](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.Increment) | Increment current value by one. |
| [UpdateTitle(title string)](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.UpdateTitle) | Update the progressbar's title. |

### Options

Expand All @@ -41,38 +40,40 @@ progressbar.Increment()
> [!TIP]
> Click the options and types to show the documentation on _pkg.go.dev_
|Option|Type|
|------|----|
|[BarCharacter](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarCharacter)|string|
|[BarStyle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarStyle)|[*Style](https://pkg.go.dev/github.com/pterm/pterm#Style)|
|[Current](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithCurrent)|int|
|[ElapsedTimeRoundingFactor](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithElapsedTimeRoundingFactor)|time.Duration|
|[LastCharacter](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithLastCharacter)|string|
|[RemoveWhenDone](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithRemoveWhenDone)|...bool|
|[ShowCount](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowCount)|...bool|
|[ShowElapsedTime](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowElapsedTime)|...bool|
|[ShowPercentage](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowPercentage)|...bool|
|[ShowTitle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowTitle)|...bool|
|[Title](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTitle)|string|
|[TitleStyle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTitleStyle)|[*Style](https://pkg.go.dev/github.com/pterm/pterm#Style)|
|[Total](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTotal)|int|
|[BarFiller](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarFiller)|string|
|[MaxWidth](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithMaxWidth)|int|
| Option | Type |
| ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| [BarCharacter](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarCharacter) | string |
| [BarStyle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarStyle) | [\*Style](https://pkg.go.dev/github.com/pterm/pterm#Style) |
| [Current](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithCurrent) | int |
| [ElapsedTimeRoundingFactor](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithElapsedTimeRoundingFactor) | time.Duration |
| [LastCharacter](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithLastCharacter) | string |
| [RemoveWhenDone](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithRemoveWhenDone) | ...bool |
| [ShowCount](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowCount) | ...bool |
| [ShowElapsedTime](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowElapsedTime) | ...bool |
| [ShowPercentage](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowPercentage) | ...bool |
| [ShowTitle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithShowTitle) | ...bool |
| [Title](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTitle) | string |
| [TitleStyle](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTitleStyle) | [\*Style](https://pkg.go.dev/github.com/pterm/pterm#Style) |
| [Total](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithTotal) | int |
| [BarFiller](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithBarFiller) | string |
| [MaxWidth](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithMaxWidth) | int |
| [Writer](https://pkg.go.dev/github.com/pterm/pterm#ProgressbarPrinter.WithWriter) | io.Writer |

### Output functions

> This printer implements the interface [`LivePrinter`](https://github.com/pterm/pterm/blob/master/interface_live_printer.go)
|Function|Description|
|------|---------|
|Start()|Returns itself and possible errors|
|Stop()|Returns itself and possible errors|
|GenericStart()|Returns the started LivePrinter and possible errors|
|GenericStop()|Returns the stopped LivePrinter and possible errors|
| Function | Description |
| -------------- | --------------------------------------------------- |
| Start() | Returns itself and possible errors |
| Stop() | Returns itself and possible errors |
| GenericStart() | Returns the started LivePrinter and possible errors |
| GenericStop() | Returns the stopped LivePrinter and possible errors |

> [!NOTE]
> The generic start and stop methods are only used to implement the printer into the interface.
> Use the normal `Start()` and `Stop()` methods if possible.
## Related

- [Override default printers](docs/customizing/override-default-printer.md)
54 changes: 27 additions & 27 deletions docs/docs/printer/spinner.md
@@ -1,6 +1,6 @@
# SpinnerPrinter

<!--
<!--
Replace all of the following strings with the current printer.
spinner Spinner SpinnerPrinter DefaultSpinner
-->
Expand All @@ -9,7 +9,6 @@ Replace all of the following strings with the current printer.

<p align="center"><a href="https://github.com/pterm/pterm/blob/master/_examples/spinner/main.go" target="_blank">(Show source of demo)</a></p>


## Usage

### Basic usage
Expand All @@ -20,12 +19,12 @@ pterm.DefaultSpinner.Start()

### Functions

|Function|Description|
|--------|-----------|
|[Fail(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.Fail)|Fail displays the fail printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message.|
|[Success(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.Success)|Success displays the success printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message.|
|[UpdateText(text string)](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.UpdateText)|UpdateText updates the message of the active SpinnerPrinter. Can be used live.|
|[Warning(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#TemplatePrinter.UpdateText)|Warning displays the warning printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message.|
| Function | Description |
| ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| [Fail(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.Fail) | Fail displays the fail printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message. |
| [Success(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.Success) | Success displays the success printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message. |
| [UpdateText(text string)](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.UpdateText) | UpdateText updates the message of the active SpinnerPrinter. Can be used live. |
| [Warning(message ...interface{})](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.UpdateText) | Warning displays the warning printer. If no message is given, the text of the SpinnerPrinter will be reused as the default message. |

### Options

Expand All @@ -38,33 +37,34 @@ pterm.DefaultSpinner.Start()
> [!TIP]
> Click the options and types to show the documentation on _pkg.go.dev_
|Option|Type|
|------|----|
|[Delay](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithDelay)|time.Duration|
|[MessageStyle](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithMessageStyle)|[*Style](https://pkg.go.dev/github.com/pterm/pterm#Style)|
|[RemoveWhenDone](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithRemoveWhenDone)|...bool|
|[Sequence](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithSequence)|...string|
|[Style](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithStyle)|[*Style](https://pkg.go.dev/github.com/pterm/pterm#Style)|
|[Text](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithText)|string|
|[ShowTimer](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithShowTimer)|...bool|
|[TimerRoundingFactor](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithTimerRoundingFactor)|time.Duration|
|[TimerStyle](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithTimerStyle)|[*Style](https://pkg.go.dev/github.com/pterm/pterm#Style)|

| Option | Type |
| ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| [Delay](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithDelay) | time.Duration |
| [MessageStyle](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithMessageStyle) | [\*Style](https://pkg.go.dev/github.com/pterm/pterm#Style) |
| [RemoveWhenDone](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithRemoveWhenDone) | ...bool |
| [Sequence](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithSequence) | ...string |
| [Style](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithStyle) | [\*Style](https://pkg.go.dev/github.com/pterm/pterm#Style) |
| [Text](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithText) | string |
| [ShowTimer](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithShowTimer) | ...bool |
| [TimerRoundingFactor](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithTimerRoundingFactor) | time.Duration |
| [TimerStyle](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithTimerStyle) | [\*Style](https://pkg.go.dev/github.com/pterm/pterm#Style) |
| [Writer](https://pkg.go.dev/github.com/pterm/pterm#SpinnerPrinter.WithWriter) | io.Writer |

### Output functions

> This printer implements the interface [`LivePrinter`](https://github.com/pterm/pterm/blob/master/interface_live_printer.go)
|Function|Description|
|------|---------|
|Start()|Returns itself and possible errors|
|Stop()|Returns itself and possible errors|
|GenericStart()|Returns the started LivePrinter and possible errors|
|GenericStop()|Returns the stopped LivePrinter and possible errors|
| Function | Description |
| -------------- | --------------------------------------------------- |
| Start() | Returns itself and possible errors |
| Stop() | Returns itself and possible errors |
| GenericStart() | Returns the started LivePrinter and possible errors |
| GenericStop() | Returns the stopped LivePrinter and possible errors |

> [!NOTE]
> The generic start and stop methods are only used to implement the printer into the interface.
> Use the normal `Start()` and `Stop()` methods if possible.
## Related
- [Override default printers](docs/customizing/override-default-printer.md)

- [Override default printers](docs/customizing/override-default-printer.md)
6 changes: 3 additions & 3 deletions print.go
Expand Up @@ -106,15 +106,15 @@ func Fprint(writer io.Writer, a ...interface{}) {
var printed bool

for _, bar := range ActiveProgressBarPrinters {
if bar.IsActive {
if bar.IsActive && bar.Writer == writer {
ret += sClearLine()
ret += Sprinto(a...)
printed = true
}
}

for _, spinner := range activeSpinnerPrinters {
if spinner.IsActive {
if spinner.IsActive && spinner.Writer == writer {
ret += sClearLine()
ret += Sprinto(a...)
printed = true
Expand All @@ -124,7 +124,7 @@ func Fprint(writer io.Writer, a ...interface{}) {
if !printed {
ret = color.Sprint(Sprint(a...))
}

if writer != nil {
color.Fprint(writer, Sprint(ret))
} else {
Expand Down
19 changes: 14 additions & 5 deletions progressbar_printer.go
@@ -1,6 +1,7 @@
package pterm

import (
"io"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -55,6 +56,8 @@ type ProgressbarPrinter struct {
IsActive bool

startedAt time.Time

Writer io.Writer
}

// WithTitle sets the name of the ProgressbarPrinter.
Expand Down Expand Up @@ -149,6 +152,12 @@ func (p ProgressbarPrinter) WithBarFiller(char string) *ProgressbarPrinter {
return &p
}

// WithWriter sets the custom Writer.
func (p ProgressbarPrinter) WithWriter(writer io.Writer) *ProgressbarPrinter {
p.Writer = writer
return &p
}

// Increment current value by one.
func (p *ProgressbarPrinter) Increment() *ProgressbarPrinter {
p.Add(1)
Expand Down Expand Up @@ -227,7 +236,7 @@ func (p *ProgressbarPrinter) updateProgress() *ProgressbarPrinter {
}

if !RawOutput {
Printo(before + bar + after)
Fprinto(p.Writer, before+bar+after)
}
return p
}
Expand All @@ -250,7 +259,7 @@ func (p *ProgressbarPrinter) Add(count int) *ProgressbarPrinter {
// Start the ProgressbarPrinter.
func (p ProgressbarPrinter) Start() (*ProgressbarPrinter, error) {
if RawOutput && p.ShowTitle {
Println(p.Title)
Fprintln(p.Writer, p.Title)
}
p.IsActive = true
ActiveProgressBarPrinters = append(ActiveProgressBarPrinters, &p)
Expand All @@ -268,10 +277,10 @@ func (p *ProgressbarPrinter) Stop() (*ProgressbarPrinter, error) {
}
p.IsActive = false
if p.RemoveWhenDone {
fClearLine(nil)
Fprinto(nil)
fClearLine(p.Writer)
Fprinto(p.Writer)
} else {
Fprintln(nil)
Fprintln(p.Writer)
}
return p, nil
}
Expand Down
42 changes: 42 additions & 0 deletions progressbar_printer_test.go
@@ -1,6 +1,8 @@
package pterm_test

import (
"io"
"os"
"testing"
"time"

Expand Down Expand Up @@ -209,3 +211,43 @@ func TestProgressbarPrinter_UpdateTitle(t *testing.T) {

testza.AssertEqual(t, "test2", p2.Title)
}

func TestProgressbarPrinter_WithWriter(t *testing.T) {
p := pterm.ProgressbarPrinter{}
s := os.Stderr
p2 := p.WithWriter(s)

testza.AssertEqual(t, s, p2.Writer)
testza.AssertZero(t, p.Writer)
}

func TestProgressbarPrinter_OutputToWriters(t *testing.T) {
testCases := map[string]struct {
action func(*pterm.ProgressbarPrinter)
expectOutputToContain string
}{
"ExpectUpdatedTitleToBeWrittenToStderr": {
action: func(pb *pterm.ProgressbarPrinter) {
pb.UpdateTitle("Updated text")
},
expectOutputToContain: "Updated text",
},
}

for testTitle, testCase := range testCases {
t.Run(testTitle, func(t *testing.T) {
stderr, err := testza.CaptureStderr(func(w io.Writer) error {
pb, err := pterm.DefaultProgressbar.WithTitle("Hello world").WithWriter(os.Stderr).Start()
time.Sleep(time.Second) // Required otherwise the goroutine doesn't run and the text isnt outputted
testza.AssertNoError(t, err)
testCase.action(pb)
time.Sleep(time.Second) // Required otherwise the goroutine doesn't run and the text isnt updated
return nil
})

testza.AssertNoError(t, err)
testza.AssertContains(t, stderr, "Hello world")
testza.AssertContains(t, stderr, testCase.expectOutputToContain)
})
}
}

0 comments on commit e95b01c

Please sign in to comment.