Progress
this is progress snippet using bubbletea and lipgloss and harmonica(optional)
Progress
A simple, customizable progress meter, with optional animation via Harmonica. Supports solid and gradient fills. The empty and filled runes can be set to whatever you'd like. The percentage readout is customizable and can also be omitted entirely.
Animated Progress
A simple example that shows how to render an animated progress bar. In this example we bump the progress by 25% every two seconds, animating our progress bar to its new target state.
It's also possible to render a progress bar in a more static fashion without transitions. For details on that approach see the progress-static example.
package main
import (
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const (
padding = 2
maxWidth = 80
)
var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render
func main() {
m := model{
progress: progress.New(progress.WithDefaultGradient()),
}
if _, err := tea.NewProgram(m).Run(); err != nil {
fmt.Println("Oh no!", err)
os.Exit(1)
}
}
type tickMsg time.Time
type model struct {
progress progress.Model
}
func (m model) Init() tea.Cmd {
return tickCmd()
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
return m, tea.Quit
case tea.WindowSizeMsg:
m.progress.Width = msg.Width - padding*2 - 4
if m.progress.Width > maxWidth {
m.progress.Width = maxWidth
}
return m, nil
case tickMsg:
if m.progress.Percent() == 1.0 {
return m, tea.Quit
}
// Note that you can also use progress.Model.SetPercent to set the
// percentage value explicitly, too.
cmd := m.progress.IncrPercent(0.25)
return m, tea.Batch(tickCmd(), cmd)
// FrameMsg is sent when the progress bar wants to animate itself
case progress.FrameMsg:
progressModel, cmd := m.progress.Update(msg)
m.progress = progressModel.(progress.Model)
return m, cmd
default:
return m, nil
}
}
func (m model) View() string {
pad := strings.Repeat(" ", padding)
return "\n" +
pad + m.progress.View() + "\n\n" +
pad + helpStyle("Press any key to quit")
}
func tickCmd() tea.Cmd {
return tea.Tick(time.Second*1, func(t time.Time) tea.Msg {
return tickMsg(t)
})
}Static Progress
A simple example that shows how to render a progress bar in a pure fashion. In this example we bump the progress by 25% every second, maintaining the progress state on our top level model using the progress bar model's ViewAs method only for rendering.
The signature for ViewAs is:
func (m Model) ViewAs(percent float64) stringSo it takes a float between 0 and 1, and renders the progress bar accordingly. When using the progress bar in this pure fashion and there's no need to call an Update method.
The progress bar is also able to animate itself, however. For details see the progress-animated example:
package main
import (
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/bubbles/progress"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const (
padding = 2
maxWidth = 80
)
var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render
func main() {
prog := progress.New(progress.WithScaledGradient("#FF7CCB", "#FDFF8C"))
if _, err := tea.NewProgram(model{progress: prog}).Run(); err != nil {
fmt.Println("Oh no!", err)
os.Exit(1)
}
}
type tickMsg time.Time
type model struct {
percent float64
progress progress.Model
}
func (m model) Init() tea.Cmd {
return tickCmd()
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
return m, tea.Quit
case tea.WindowSizeMsg:
m.progress.Width = msg.Width - padding*2 - 4
if m.progress.Width > maxWidth {
m.progress.Width = maxWidth
}
return m, nil
case tickMsg:
m.percent += 0.25
if m.percent > 1.0 {
m.percent = 1.0
return m, tea.Quit
}
return m, tickCmd()
default:
return m, nil
}
}
func (m model) View() string {
pad := strings.Repeat(" ", padding)
return "\n" +
pad + m.progress.ViewAs(m.percent) + "\n\n" +
pad + helpStyle("Press any key to quit")
}
func tickCmd() tea.Cmd {
return tea.Tick(time.Second, func(t time.Time) tea.Msg {
return tickMsg(t)
})
}How is this guide?