pulse

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 5 Imported by: 0

README

Pulse

Pulse Banner

Real-time terminal line charts for Charm Lip Gloss and Bubble Tea.

CI Status Go Reference Go Report Card MIT License


Pulse Terminal Chart

Pulse brings rich, responsive time-series visualization to terminal user interfaces (TUIs). Built specifically for the Charm ecosystem (Lip Gloss and Bubble Tea), Pulse features smooth box-drawing curves, high-density Braille sub-pixel rendering, half-tone shaded area fills, and Grafana-style aligned gridlines.

✨ Features

  • ╭╯ Smooth Box-Drawing: Continuous lines rendered with rounded arcs (╭ ╮ ╯ ╰) or bold strokes (┏ ┓ ┛ ┗).
  • ⠒ Sub-Pixel Braille: High-density 2×4 dot Braille matrix interpolated via cubic Catmull-Rom splines.
  • ░ Shaded Area Fill: Half-tone shading beneath curves that cleanly absorbs grid intersections.
  • ┼ Aligned Coordinate Grid: Subtle coordinate grid aligned exactly to Y-axis ticks and width quarter-steps.
  • 📈 Multi-Series Support: Plot multiple named metrics simultaneously with dedicated styles and swatches.
  • 📦 Live Legend Box: Bordered legend overlay displaying swatches, names, and real-time values.
  • 🫧 Charm Native: Fully customizable with Lip Gloss styles and built for Bubble Tea event loops.

🚀 Quick Start

Installation
go get github.com/ingvarch/pulse
Minimal Example
package main

import (
	"fmt"
	"math"

	"github.com/ingvarch/pulse"
	"github.com/ingvarch/pulse/theme"
)

func main() {
	preset := theme.TokyoNight()
	chartW, chartH := 80, 13

	chart := pulse.New(chartW, chartH,
		pulse.WithRange(0, 100),
		pulse.WithTicks(0, 25, 50, 75, 100),
		pulse.WithLineWidth(1), // Smooth rounded corners: ╭ ╮ ╯ ╰
		pulse.WithAxisStyle(preset.Axis),
		pulse.WithLineStyle(preset.LineFor(60)),
	)

	// Stream 80 data points into the sliding window
	for i := 0; i < chartW; i++ {
		val := 50 + 38*math.Sin(float64(i)*0.16)
		chart.Push(val)
	}

	fmt.Println(chart.View())
}

Pulse Quick Start Output

🎨 Lip Gloss Styling & Themes

Pulse is designed from the ground up for Lip Gloss. You can style individual series, axes, borders, and threshold colors:

package main

import (
	"fmt"
	"charm.land/lipgloss/v2"
	"github.com/ingvarch/pulse"
	"github.com/ingvarch/pulse/theme"
)

func main() {
	preset := theme.TokyoNight()

	chart := pulse.New(80, 13,
		pulse.WithRange(0, 100),
		pulse.WithTicks(0, 25, 50, 75, 100),
		pulse.WithLineWidth(2), // Bold curves: ┏ ┓ ┛ ┗
		pulse.WithAxisStyle(preset.Axis),
		pulse.WithSeriesStyle("cluster-a", preset.LineFor(88.0)), // Red warning threshold
		pulse.WithSeriesStyle("cluster-b", lipgloss.NewStyle().Foreground(lipgloss.Color("#bb9af7"))),
	)

	// Wrap the chart in a Lip Gloss bordered container
	box := lipgloss.NewStyle().
		Border(lipgloss.RoundedBorder()).
		BorderForeground(lipgloss.Color("#3b4261")).
		Padding(1, 2).
		Render(chart.View() + "\n" + chart.LegendBox())

	fmt.Println(box)
}

Pulse Lip Gloss Styling

⠒ Braille Sub-Pixel Rendering

For ultra-dense metrics, switch to pulse.ModeBraille to enable 2×4 dot matrix sub-pixel resolution powered by cubic Catmull-Rom spline interpolation:

chart.SetMode(pulse.ModeBraille)

Pulse Braille Sub-Pixel Rendering

📚 Documentation

Detailed guides and API references are available in the docs directory:

Document Description
Getting Started Constructor options, sliding window buffers, multi-series, and runtime controls
Rendering Modes Box-drawing curves (rounded vs bold), Braille sub-pixel matrix, and area fill
Axes & Grid Adaptive NiceTicks, custom tick quarter-steps, and Grafana grid alignment
Bubble Tea Integration Embedding in Bubble Tea models, telemetry ticks, and interactive hotkeys

🎮 Interactive Demos

Try the included examples directly from your terminal:

# Live multi-series stream (CPU, MEM, NET) with hotkeys: t (thickness), m (braille), q (quit)
go run ./examples/multidemo

# Live single-signal generator with thickness & mode toggle
go run ./examples/livedemo

# Real-time hardware telemetry (CPU & RAM) from your machine
go run ./examples/cpulive

# Clean terminal screenshot generator
go run ./examples/cpudemo

🤝 Community & Contributing

We welcome issues and pull requests! Please check our community guidelines:

📄 License

Pulse is licensed under the MIT License.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Model

type Model struct {
	// contains filtered or unexported fields
}

Model is a streaming terminal line chart.

func New

func New(w, h int, opts ...Option) *Model

New creates a chart for a w x h cells plot area.

func (*Model) Last

func (m *Model) Last(name string) (float64, bool)

Last returns the most recent value of a named series.

func (*Model) Legend

func (m *Model) Legend() string

Legend returns a formatted legend for named series, or empty string if none exist.

func (*Model) LegendBox

func (m *Model) LegendBox() string

LegendBox returns a boxed legend with borders, swatches, series names, and recent values.

func (*Model) Len

func (m *Model) Len() int

Len returns the number of points in the default series within the window.

func (*Model) LenSeries

func (m *Model) LenSeries(name string) int

LenSeries returns the number of points in the named series within the window.

func (*Model) LineWidth

func (m *Model) LineWidth() int

LineWidth returns the current line width.

func (*Model) Mode

func (m *Model) Mode() RenderMode

Mode returns the current rendering mode.

func (*Model) Push

func (m *Model) Push(v float64)

Push adds a data point to the default series. Maintains a sliding window of width w.

func (*Model) PushSeries

func (m *Model) PushSeries(name string, v float64)

PushSeries adds a data point to a named series.

func (*Model) SetAxisStyle

func (m *Model) SetAxisStyle(s lipgloss.Style)

SetAxisStyle dynamically updates the axis style.

func (*Model) SetFill

func (m *Model) SetFill(on bool)

SetFill enables or disables area fill dynamically.

func (*Model) SetGrid

func (m *Model) SetGrid(on bool)

SetGrid enables or disables the grid dynamically.

func (*Model) SetLabelFormatter added in v0.2.0

func (m *Model) SetLabelFormatter(fn func(float64) string)

SetLabelFormatter dynamically updates the Y-axis label formatter.

func (*Model) SetLabelWidth added in v0.2.0

func (m *Model) SetLabelWidth(w int)

SetLabelWidth dynamically updates the Y-axis label column width.

func (*Model) SetLineStyle

func (m *Model) SetLineStyle(s lipgloss.Style)

SetLineStyle dynamically updates the line style.

func (*Model) SetLineWidth

func (m *Model) SetLineWidth(w int)

SetLineWidth sets the line width: 1 for thin, 2 for bold.

func (*Model) SetMode

func (m *Model) SetMode(mode RenderMode)

SetMode sets the rendering mode (ModeLines or ModeBraille).

func (*Model) SetSeriesStyle

func (m *Model) SetSeriesStyle(name string, s lipgloss.Style)

SetSeriesStyle dynamically sets the style for a named series.

func (*Model) SetSmooth

func (m *Model) SetSmooth(on bool)

SetSmooth enables or disables smoothing dynamically.

func (*Model) SetTicks

func (m *Model) SetTicks(ticks ...float64)

SetTicks dynamically sets explicit tick values for the Y axis.

func (*Model) ToggleRenderMode

func (m *Model) ToggleRenderMode()

ToggleRenderMode switches between ModeLines and ModeBraille.

func (*Model) View

func (m *Model) View() string

View renders the chart: Y-axis labels + axis border + plot area.

type Option

type Option func(*Model)

Option configures a Model.

func WithAxisStyle

func WithAxisStyle(s lipgloss.Style) Option

WithAxisStyle sets the axes and labels style.

func WithBraille

func WithBraille() Option

WithBraille enables braille dot matrix mode (2x4 dots).

func WithFill

func WithFill(on bool) Option

WithFill enables or disables area fill under the line.

func WithGrid

func WithGrid(on bool) Option

WithGrid enables or disables gridlines at tick positions.

func WithLabelFormatter added in v0.2.0

func WithLabelFormatter(fn func(float64) string) Option

WithLabelFormatter sets a custom formatter for Y-axis tick values.

func WithLabelWidth added in v0.2.0

func WithLabelWidth(w int) Option

WithLabelWidth sets an explicit width for Y-axis labels.

func WithLineStyle

func WithLineStyle(s lipgloss.Style) Option

WithLineStyle sets the default line style.

func WithLineWidth

func WithLineWidth(w int) Option

WithLineWidth sets line width: 1 thin, 2 bold.

func WithLines

func WithLines() Option

WithLines enables continuous line rendering mode.

func WithMode

func WithMode(mode RenderMode) Option

WithMode sets rendering mode (ModeLines or ModeBraille).

func WithRange

func WithRange(min, max float64) Option

WithRange sets the fixed Y range. For example, WithRange(0, 100) for CPU/RAM.

func WithSeriesStyle

func WithSeriesStyle(name string, s lipgloss.Style) Option

WithSeriesStyle sets the style for a named series.

func WithSmooth

func WithSmooth(on bool) Option

WithSmooth enables or disables line smoothing (rounded corners or spline).

func WithTicks

func WithTicks(ticks ...float64) Option

WithTicks sets explicit Y-axis tick values (e.g. 0, 25, 50, 75, 100 or 0, 50, 100).

type RenderMode

type RenderMode int

RenderMode defines how line curves are rendered on the chart.

const (
	// ModeLines renders smooth continuous lines (box-drawing ╭, ╮, ╯, ╰, ─, │) with Grafana-style area fill ░.
	ModeLines RenderMode = iota
	// ModeBraille renders using a 2x4 dot braille matrix (Unicode Braille Patterns).
	ModeBraille
)

Directories

Path Synopsis
cmd
gen-shots command
examples
cpudemo command
cpulive command
livedemo command
multidemo command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL