Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/moul/progress
🏗 progress, steps, completion patterns for golang
https://github.com/moul/progress
golang progress
Last synced: about 6 hours ago
JSON representation
🏗 progress, steps, completion patterns for golang
- Host: GitHub
- URL: https://github.com/moul/progress
- Owner: moul
- License: other
- Created: 2020-12-22T16:24:07.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-09-06T22:41:45.000Z (27 days ago)
- Last Synced: 2024-09-07T02:19:22.001Z (26 days ago)
- Topics: golang, progress
- Language: Go
- Homepage: https://manfred.life/golang
- Size: 134 KB
- Stars: 12
- Watchers: 4
- Forks: 4
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE-APACHE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: SECURITY.md
- Support: .github/SUPPORT.md
- Authors: AUTHORS
Awesome Lists containing this project
README
# progress
:smile: progress
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/moul.io/progress)
[![License](https://img.shields.io/badge/license-Apache--2.0%20%2F%20MIT-%2397ca00.svg)](https://github.com/moul/progress/blob/master/COPYRIGHT)
[![GitHub release](https://img.shields.io/github/release/moul/progress.svg)](https://github.com/moul/progress/releases)
[![Made by Manfred Touron](https://img.shields.io/badge/made%20by-Manfred%20Touron-blue.svg?style=flat)](https://manfred.life/)[![Go](https://github.com/moul/progress/workflows/Go/badge.svg)](https://github.com/moul/progress/actions?query=workflow%3AGo)
[![PR](https://github.com/moul/progress/workflows/PR/badge.svg)](https://github.com/moul/progress/actions?query=workflow%3APR)
[![GolangCI](https://golangci.com/badges/github.com/moul/progress.svg)](https://golangci.com/r/github.com/moul/progress)
[![codecov](https://codecov.io/gh/moul/progress/branch/master/graph/badge.svg)](https://codecov.io/gh/moul/progress)
[![Go Report Card](https://goreportcard.com/badge/moul.io/progress)](https://goreportcard.com/report/moul.io/progress)
[![CodeFactor](https://www.codefactor.io/repository/github/moul/progress/badge)](https://www.codefactor.io/repository/github/moul/progress)[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/moul/progress)
## Usage
[embedmd]:# (.tmp/godoc.txt txt /TYPES/ $)
```txt
TYPEStype Progress struct {
Steps []*Step `json:"steps,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`// Has unexported fields.
}
Progress is the top-level object of the 'progress' library.func New() *Progress
New creates and returns a new Progress.func (p *Progress) AddStep(id string) *Step
AddStep creates and returns a new Step with the provided 'id'. A non-empty,
unique 'id' is required, else it will panic.func (p *Progress) Get(id string) *Step
Get retrieves a Step by its 'id'. A non-empty 'id' is required, else it will
panic. If 'id' does not match an existing step, nil is returned.func (p *Progress) MarshalJSON() ([]byte, error)
MarshalJSON is a custom JSON marshaler that automatically computes and
append the current snapshot.func (p *Progress) Percent() float64
Percent returns the current completion percentage, it's a faster alternative
to Progress.Snapshot().Percent.func (p *Progress) SafeAddStep(id string) (*Step, error)
SafeAddStep is equivalent to AddStep with but returns error instead of
panicking.func (p *Progress) Snapshot() Snapshot
Snapshot computes and returns the current stats of the Progress.func (p *Progress) Subscribe(subscriber chan *Step)
Subscribe register a provided chan as a target called each time a step is
changed.type Snapshot struct {
State State `json:"state,omitempty"`
Doing string `json:"doing,omitempty"`
NotStarted int `json:"not_started,omitempty"`
InProgress int `json:"in_progress,omitempty"`
Completed int `json:"completed,omitempty"`
Total int `json:"total,omitempty"`
Percent float64 `json:"percent,omitempty"`
TotalDuration time.Duration `json:"total_duration,omitempty"`
StepDuration time.Duration `json:"step_duration,omitempty"`
CompletionEstimate time.Duration `json:"completion_estimate,omitempty"`
DoneAt *time.Time `json:"done_at,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
}
Snapshot represents info and stats about a progress at a given time.type State string
const (
StateNotStarted State = "not started"
StateInProgress State = "in progress"
StateDone State = "done"
)
type Step struct {
ID string `json:"id,omitempty"`
Description string `json:"description,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
DoneAt *time.Time `json:"done_at,omitempty"`
State State `json:"state,omitempty"`
Data interface{} `json:"data,omitempty"`// Has unexported fields.
}
Step represents a progress step. It always have an 'id' and can be
customized using helpers.func (s *Step) Done()
Done marks a step as done. If the step was already done, it panics.func (s *Step) Duration() time.Duration
Duration computes the step duration.func (s *Step) MarshalJSON() ([]byte, error)
MarshalJSON is a custom JSON marshaler that automatically computes and
append some runtime metadata.func (s *Step) SetAsCurrent()
SetAsCurrent stops all in-progress steps and start this one.func (s *Step) SetData(data interface{}) *Step
SetData sets a custom step data. It returns itself (*Step) for chaining.func (s *Step) SetDescription(desc string) *Step
SetDescription sets a custom step description. It returns itself (*Step) for
chaining.func (s *Step) Start()
Start marks a step as started. If a step was already InProgress or Done, it
panics.```
## Example
[embedmd]:# (example_test.go /import\ / $)
```go
import (
"fmt"
"time""moul.io/progress"
"moul.io/u"
)func Example() {
// initialize a new progress.Progress
prog := progress.New()
prog.AddStep("init").SetDescription("initialize")
prog.AddStep("step1").SetDescription("step 1")
prog.AddStep("step2").SetData([]string{"hello", "world"}).SetDescription("step 2")
prog.AddStep("step3")
prog.AddStep("finish")// automatically mark the last step as done when the function quit
defer prog.Get("finish").Done()// mark init as Done
prog.Get("init").Done()// mark step1 as started
prog.Get("step1").SetData(42).Start()// then, mark it as done + attach custom data
prog.Get("step1").SetData(1337).Done()// mark step2 as started
prog.Get("step2").Start()fmt.Println(u.PrettyJSON(prog))
// outputs something like this:
// {
// "steps": [
// {
// "id": "init",
// "description": "initialize",
// "started_at": "2020-12-22T20:26:05.717427484+01:00",
// "done_at": "2020-12-22T20:26:05.717427484+01:00",
// "state": "done"
// },
// {
// "id": "step1",
// "description": "step 1",
// "started_at": "2020-12-22T20:26:05.71742797+01:00",
// "done_at": "2020-12-22T20:26:05.717428258+01:00",
// "state": "done",
// "data": 1337,
// "duration": 286
// },
// {
// "id": "step2",
// "description": "step 2",
// "started_at": "2020-12-22T20:26:05.71742865+01:00",
// "state": "in progress",
// "data": [
// "hello",
// "world"
// ],
// "duration": 496251
// },
// {
// "id": "step3"
// },
// {
// "id": "finish"
// }
// ],
// "created_at": "2020-12-22T20:26:05.717423018+01:00",
// "snapshot": {
// "state": "in progress",
// "doing": "step 2",
// "not_started": 2,
// "in_progress": 1,
// "completed": 2,
// "total": 5,
// "percent": 50,
// "total_duration": 25935,
// "started_at": "2020-12-22T20:26:05.717427484+01:00"
// }
//}
}func ExampleProgressSubscribe() {
prog := progress.New()
done := make(chan bool)
ch := make(chan *progress.Step, 0)
prog.Subscribe(ch)
go func() {
idx := 0
for step := range ch {
if step == nil {
break
}
fmt.Println(idx, step.ID, step.State)
idx++
}
done <- true
}()
time.Sleep(10 * time.Millisecond)
prog.AddStep("step1").SetDescription("hello")
prog.AddStep("step2")
prog.Get("step1").Start()
prog.Get("step2").Done()
prog.AddStep("step3")
prog.Get("step3").Start()
prog.Get("step1").Done()
prog.Get("step3").Done()
// fmt.Println(u.PrettyJSON(prog))
<-done
close(ch)// Output:
// 0 step1 not started
// 1 step1 not started
// 2 step2 not started
// 3 step1 in progress
// 4 step2 done
// 5 step3 not started
// 6 step3 in progress
// 7 step1 done
// 8 step3 done
}
```## Install
### Using go
```sh
go get moul.io/progress
```## Contribute
![Contribute <3](https://raw.githubusercontent.com/moul/moul/master/contribute.gif)
I really welcome contributions.
Your input is the most precious material.
I'm well aware of that and I thank you in advance.
Everyone is encouraged to look at what they can do on their own scale;
no effort is too small.Everything on contribution is sum up here: [CONTRIBUTING.md](./CONTRIBUTING.md)
### Contributors ✨
[![All Contributors](https://img.shields.io/badge/all_contributors-2-orange.svg)](#contributors)
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Manfred Touron
🚧 📖 ⚠️ 💻
moul-bot
🚧
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors)
specification. Contributions of any kind welcome!### Stargazers over time
[![Stargazers over time](https://starchart.cc/moul/progress.svg)](https://starchart.cc/moul/progress)
## License
© 2020 [Manfred Touron](https://manfred.life)
Licensed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
([`LICENSE-APACHE`](LICENSE-APACHE)) or the [MIT license](https://opensource.org/licenses/MIT)
([`LICENSE-MIT`](LICENSE-MIT)), at your option.
See the [`COPYRIGHT`](COPYRIGHT) file for more details.`SPDX-License-Identifier: (Apache-2.0 OR MIT)`