mirror of
https://github.com/Maks1mS/bubbles.git
synced 2024-12-24 14:44:38 +03:00
111 lines
2.4 KiB
Go
111 lines
2.4 KiB
Go
package progress
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/lucasb-eyer/go-colorful"
|
|
"github.com/muesli/reflow/ansi"
|
|
"github.com/muesli/termenv"
|
|
)
|
|
|
|
var color func(string) termenv.Color = termenv.ColorProfile().Color
|
|
|
|
// Option is used to set options in NewModel. For example:
|
|
//
|
|
// progress := NewModel(
|
|
// WithRamp("#ff0000", "#0000ff"),
|
|
// )
|
|
type Option func(*Model)
|
|
|
|
// WithDefaultRamp sets a gradient fill with default colors.
|
|
func WithDefaultRamp() Option {
|
|
return WithRamp("#00dbde", "#fc00ff")
|
|
}
|
|
|
|
// WithRamp sets a gradient fill blending between two colors.
|
|
func WithRamp(colorA, colorB string) Option {
|
|
a, _ := colorful.Hex(colorA)
|
|
b, _ := colorful.Hex(colorB)
|
|
return func(m *Model) {
|
|
m.useRamp = true
|
|
m.colorA = a
|
|
m.colorB = b
|
|
}
|
|
}
|
|
|
|
type Model struct {
|
|
// Left side color of progress bar. By default, it's #00dbde
|
|
colorA colorful.Color
|
|
|
|
// Left side color of progress bar. By default, it's #fc00ff
|
|
colorB colorful.Color
|
|
|
|
// Total width of the progress bar, including percentage, if set.
|
|
Width int
|
|
|
|
// Rune for "filled" sections of the progress bar.
|
|
Full rune
|
|
|
|
// Rune for "empty" sections of progress bar.
|
|
Empty rune
|
|
|
|
// if true, gradient will be setted from start to end of filled part. Instead, it'll work
|
|
// on all proggress bar length
|
|
FullGradientMode bool
|
|
|
|
ShowPercent bool
|
|
PercentFormat string
|
|
|
|
useRamp bool
|
|
}
|
|
|
|
// NewModel returns a model with default values.
|
|
func NewModel(opts ...Option) *Model {
|
|
m := &Model{
|
|
Width: 40,
|
|
Full: '█',
|
|
Empty: '░',
|
|
ShowPercent: true,
|
|
PercentFormat: " %3.0f%%",
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(m)
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
func (m Model) View(percent float64) string {
|
|
if m.ShowPercent {
|
|
s := fmt.Sprintf(m.PercentFormat, percent*100)
|
|
w := ansi.PrintableRuneWidth(s)
|
|
return m.bar(percent, w) + s
|
|
}
|
|
return m.bar(percent, 0)
|
|
}
|
|
|
|
func (m Model) bar(percent float64, textWidth int) string {
|
|
w := m.Width - textWidth
|
|
|
|
ramp := make([]string, int(float64(w)*percent))
|
|
for i := 0; i < len(ramp); i++ {
|
|
gradientPart := float64(w)
|
|
if m.FullGradientMode {
|
|
gradientPart = float64(len(ramp))
|
|
}
|
|
percent := float64(i) / gradientPart
|
|
c := m.colorA.BlendLuv(m.colorB, percent)
|
|
ramp[i] = c.Hex()
|
|
}
|
|
|
|
var fullCells string
|
|
for i := 0; i < len(ramp); i++ {
|
|
fullCells += termenv.String(string(m.Full)).Foreground(color(ramp[i])).String()
|
|
}
|
|
|
|
fullCells += strings.Repeat(string(m.Empty), w-len(ramp))
|
|
return fullCells
|
|
}
|