pulse

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 7 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.
  • 🏷️ Timeline Annotations: Pin events, deploys, and alerts onto the sliding timeline with custom glyphs and vertical guidelines.
  • 📦 Live Legend Box: Bordered legend overlay displaying swatches, names, and real-time values.
  • ⚖️ Bidirectional & RX/TX Traffic: Grafana-style zero baseline rulings, inverted mirror series, auto-symmetric centering, and adaptive byte rate formatters.
  • 🫧 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

⚖️ Bidirectional & RX/TX Traffic

Monitor inverted network streams, disk I/O, or profit/loss with a central zero baseline ruling (├), smooth bidirectional area fill, and auto-symmetric scaling:

chart := pulse.New(80, 15,
	pulse.WithRange(0, 100*MB),
	pulse.WithSymmetric(true),
	pulse.WithZeroBaseline(true),
	pulse.WithSeriesInverted("tx", true),
	pulse.WithLabelFormatter(scale.BytesRateFormatter(true)),
)

Pulse Bidirectional RX/TX Traffic

📚 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
Zero-Crossing & RX/TX Grafana-style bidirectional charts, zero baseline rulings, and series inversion
Timeline Events Pin deployments, alerts, and markers (▼, 🚀, ⚡) with guidelines and sliding cards
Bubble Tea Integration Embedding in Bubble Tea models, telemetry ticks, and interactive hotkeys

🎮 Interactive Demos

Try the included examples directly from your terminal:

# Grafana-style live network traffic (RX / TX) with zero baseline & mode toggles
go run ./examples/rxtxdemo

# 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

View Source
var DefaultEventColor color.Color = lipgloss.Color("#7dcfff")

DefaultEventColor is the default foreground color for timeline event pins and guidelines (#7dcfff).

View Source
var DefaultTintColor color.Color = lipgloss.Color("#1f2335")

DefaultTintColor is the default background tint used when TintedFill is active and no custom tint color or style background is specified. Defaults to Tokyo Night slate (#1f2335).

Functions

This section is empty.

Types

type BrailleRenderer added in v0.3.0

type BrailleRenderer struct{}

BrailleRenderer renders 2x4 dot Braille patterns.

func (BrailleRenderer) Render added in v0.3.0

func (BrailleRenderer) Render(c Chart, ctx RenderContext) string

Render implements Renderer for BrailleRenderer.

type Chart added in v0.4.0

type Chart interface {
	Width() int
	Height() int
	Min() float64
	Max() float64
	Fill() bool
	TintedFill() bool
	SolidFill() bool
	TintColor() color.Color
	Grid() bool
	Smooth() bool
	LineWidth() int
	AxisStyle() lipgloss.Style
	LineStyle() lipgloss.Style
	SeriesStyle(name string) lipgloss.Style
	SeriesNames() []string
	SeriesData(name string) []float64
	VisibleEvents() []VisibleEvent
	ZeroBaseline() bool
	Symmetric() bool
	NegativeStyle() lipgloss.Style
	SeriesNegativeStyle(name string) lipgloss.Style
	SeriesInverted(name string) bool
}

Chart provides the read-only contract for inspecting chart dimensions, data, and styles.

type Event added in v0.4.1

type Event struct {
	ID     string         // Optional identifier for programmatic lookup or removal
	Label  string         // Human-readable description (e.g. "Deploy v1.4.2")
	Glyph  string         // Marker glyph (e.g. "▼", "🚀", "▲", "◆", "!", "⚠️"). Defaults to "▼".
	Style  lipgloss.Style // Style for the marker glyph and vertical guideline
	NoLine bool           // If true, omits the vertical guideline across the chart
}

Event represents a discrete timeline annotation or event marker.

type LinesRenderer added in v0.3.0

type LinesRenderer struct{}

LinesRenderer renders smooth box-drawing lines with optional area fill.

func (LinesRenderer) Render added in v0.3.0

func (LinesRenderer) Render(c Chart, ctx RenderContext) string

Render implements Renderer for LinesRenderer.

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) AddEvent added in v0.4.1

func (m *Model) AddEvent(ev Event)

AddEvent records an event at the current newest point on the timeline. As new points are pushed, the event moves left across the window.

func (*Model) AddEventAt added in v0.4.1

func (m *Model) AddEventAt(offset int, ev Event)

AddEventAt records an event at a historical offset (0 = newest point, 10 = 10 points ago).

func (*Model) AxisStyle added in v0.3.0

func (m *Model) AxisStyle() lipgloss.Style

AxisStyle returns the axis lipgloss style.

func (*Model) ClearEvents added in v0.4.1

func (m *Model) ClearEvents()

ClearEvents removes all timeline events from the chart.

func (*Model) EventsBox added in v0.4.1

func (m *Model) EventsBox() string

EventsBox returns a boxed card listing all currently visible timeline events. Returns an empty string if there are no visible events.

func (*Model) Fill added in v0.3.0

func (m *Model) Fill() bool

Fill returns whether area fill is enabled.

func (*Model) Grid added in v0.3.0

func (m *Model) Grid() bool

Grid returns whether grid lines are enabled.

func (*Model) Height added in v0.3.0

func (m *Model) Height() int

Height returns the chart plot height in terminal cells.

func (*Model) Inverted added in v0.5.0

func (m *Model) Inverted() bool

Inverted returns whether value inversion is enabled for the default series.

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) LineStyle added in v0.3.0

func (m *Model) LineStyle() lipgloss.Style

LineStyle returns the default line lipgloss style.

func (*Model) LineWidth

func (m *Model) LineWidth() int

LineWidth returns the current line width.

func (*Model) Max added in v0.3.0

func (m *Model) Max() float64

Max returns the chart maximum Y value.

func (*Model) Min added in v0.3.0

func (m *Model) Min() float64

Min returns the chart minimum Y value.

func (*Model) Mode

func (m *Model) Mode() RenderMode

Mode returns the current rendering mode derived from the active renderer.

func (*Model) NegativeStyle added in v0.5.0

func (m *Model) NegativeStyle() lipgloss.Style

NegativeStyle returns the negative line style for the default series, or default line style.

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) Renderer added in v0.3.0

func (m *Model) Renderer() Renderer

Renderer returns the current chart renderer.

func (*Model) SeriesData added in v0.3.0

func (m *Model) SeriesData(name string) []float64

SeriesData returns a copy of data points for a series.

func (*Model) SeriesInverted added in v0.5.0

func (m *Model) SeriesInverted(name string) bool

SeriesInverted returns whether value inversion is enabled for a named series.

func (*Model) SeriesNames added in v0.3.0

func (m *Model) SeriesNames() []string

SeriesNames returns registered series names in order.

func (*Model) SeriesNegativeStyle added in v0.5.0

func (m *Model) SeriesNegativeStyle(name string) lipgloss.Style

SeriesNegativeStyle returns the negative style for a named series.

func (*Model) SeriesStyle added in v0.4.0

func (m *Model) SeriesStyle(name string) lipgloss.Style

SeriesStyle returns the style for a named series, or default line style.

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) SetInverted added in v0.5.0

func (m *Model) SetInverted(inverted bool)

SetInverted enables or disables value inversion for the default series.

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). ModeCustom cannot be set: install the renderer with SetRenderer instead.

func (*Model) SetNegativeStyle added in v0.5.0

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

SetNegativeStyle dynamically sets the negative line style for the default series.

func (*Model) SetRange added in v0.3.0

func (m *Model) SetRange(min, max float64)

SetRange dynamically sets the Y-axis range.

func (*Model) SetRenderer added in v0.3.0

func (m *Model) SetRenderer(r Renderer)

SetRenderer dynamically updates the chart renderer and synchronizes Mode(). A nil renderer falls back to LinesRenderer.

func (*Model) SetSeriesInverted added in v0.5.0

func (m *Model) SetSeriesInverted(name string, inverted bool)

SetSeriesInverted enables or disables value inversion for a named series.

func (*Model) SetSeriesNegativeStyle added in v0.5.0

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

SetSeriesNegativeStyle dynamically sets the negative style for a named series.

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) SetSolidFill added in v0.4.0

func (m *Model) SetSolidFill(on bool)

SetSolidFill enables or disables solid background fill dynamically.

func (*Model) SetSymmetric added in v0.5.0

func (m *Model) SetSymmetric(on bool)

SetSymmetric enables or disables symmetric Y range normalization around zero ([-max, +max]).

func (*Model) SetTicks

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

SetTicks dynamically sets explicit tick values for the Y axis. Ticks are copied, sorted ascending, and deduplicated.

func (*Model) SetTintColor added in v0.4.0

func (m *Model) SetTintColor(c color.Color)

SetTintColor dynamically updates the chart background tint color.

func (*Model) SetTintedFill added in v0.4.0

func (m *Model) SetTintedFill(on bool)

SetTintedFill enables or disables tinted background fill dynamically.

func (*Model) SetZeroBaseline added in v0.5.0

func (m *Model) SetZeroBaseline(on bool)

SetZeroBaseline enables or disables explicit zero baseline rendering.

func (*Model) Smooth added in v0.3.0

func (m *Model) Smooth() bool

Smooth returns whether line smoothing is enabled.

func (*Model) SolidFill added in v0.4.0

func (m *Model) SolidFill() bool

SolidFill returns whether solid background fill is enabled.

func (*Model) String added in v0.3.0

func (m *Model) String() string

String implements fmt.Stringer, returning the rendered chart View().

func (*Model) Symmetric added in v0.5.0

func (m *Model) Symmetric() bool

Symmetric returns whether symmetric Y range normalization is enabled.

func (*Model) TintColor added in v0.4.0

func (m *Model) TintColor() color.Color

TintColor returns the custom background tint color, or nil if using default.

func (*Model) TintedFill added in v0.4.0

func (m *Model) TintedFill() bool

TintedFill returns whether tinted area fill is enabled.

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.

func (*Model) VisibleEvents added in v0.4.1

func (m *Model) VisibleEvents() []VisibleEvent

VisibleEvents returns all timeline events currently visible within the chart window.

func (*Model) Width added in v0.3.0

func (m *Model) Width() int

Width returns the chart plot width in terminal cells.

func (*Model) ZeroBaseline added in v0.5.0

func (m *Model) ZeroBaseline() bool

ZeroBaseline returns whether explicit zero baseline rendering is enabled.

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 WithEvent added in v0.4.1

func WithEvent(offset int, ev Event) Option

WithEvent registers an initial timeline event marker at a historical offset (0 = newest point).

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 WithInverted added in v0.5.0

func WithInverted(inverted bool) Option

WithInverted configures the default series to invert its values when plotted (v -> -v).

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 WithMode

func WithMode(mode RenderMode) Option

WithMode sets rendering mode (ModeLines or ModeBraille).

func WithNegativeStyle added in v0.5.0

func WithNegativeStyle(s lipgloss.Style) Option

WithNegativeStyle sets the style for negative values (< 0) of the default series.

func WithRange

func WithRange(min, max float64) Option

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

func WithRenderer added in v0.3.0

func WithRenderer(r Renderer) Option

WithRenderer sets a custom chart renderer.

func WithSeriesInverted added in v0.5.0

func WithSeriesInverted(name string, inverted bool) Option

WithSeriesInverted configures a named series to invert its values when plotted (v -> -v).

func WithSeriesNegativeStyle added in v0.5.0

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

WithSeriesNegativeStyle sets the style for negative values (< 0) of a named series.

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 WithSolidFill added in v0.4.0

func WithSolidFill(on bool) Option

WithSolidFill enables or disables solid background fill (spaces with background color) instead of stippled glyphs (░).

func WithSymmetric added in v0.5.0

func WithSymmetric(on bool) Option

WithSymmetric normalizes the Y range to be symmetric around zero ([-max, +max]), ensuring the zero baseline remains anchored directly in the center of the chart.

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).

func WithTintColor added in v0.4.0

func WithTintColor(c color.Color) Option

WithTintColor sets a custom background tint color for tinted fill mode. If nil, DefaultTintColor (#1f2335) is used.

func WithTintedFill added in v0.4.0

func WithTintedFill(on bool) Option

WithTintedFill enables or disables tinted background fill under the line, seamlessly bridging the gap between box-drawing characters and area fill.

func WithZeroBaseline added in v0.5.0

func WithZeroBaseline(on bool) Option

WithZeroBaseline enables or disables explicit zero baseline rendering (├ on Y-axis and baseline ruling at Y=0).

type RenderContext added in v0.3.0

type RenderContext struct {
	LabelWidth     int
	LabelStyle     lipgloss.Style
	RowLabel       map[int]string
	HGrid          []bool
	VGrid          []bool
	Names          []string
	Styles         []lipgloss.Style
	NegativeStyles []lipgloss.Style
	HasNegStyles   []bool
	SeriesData     [][]float64
	GridStyle      lipgloss.Style
	ZeroRow        int
}

RenderContext contains prepared axis, tick, label, and style metadata passed to a Renderer.

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
	// ModeCustom represents a custom user-supplied Renderer.
	ModeCustom
)

type Renderer added in v0.3.0

type Renderer interface {
	Render(c Chart, ctx RenderContext) string
}

Renderer defines how chart series data and axes are rendered into a string. Custom renderers only need the Chart contract: build one with New and Push in tests, no mocks required.

type VisibleEvent added in v0.4.1

type VisibleEvent struct {
	Col   int   // Column index in current plot area (0 to Width()-1)
	Age   int   // How many time steps ago this event occurred
	Event Event // The event metadata
}

VisibleEvent pairs an Event with its current visible column in the chart window.

Directories

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

Jump to

Keyboard shortcuts

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