timeline

package
v0.22.0 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package timeline provides a scrollable event-log widget for termdash.

A Timeline displays a list of timestamped Event entries and supports keyboard and mouse navigation. It implements widgetapi.Widget and can be placed directly into any termdash container — no separate manager or event-handler types are needed.

Basic usage

tl, _ := timeline.New()
tl.SetEvents([]timeline.Event{...})
container.PlaceWidget(tl)

With options

tl, _ := timeline.New(
    timeline.FollowTail(),      // pin view to newest event
    timeline.MaxEvents(500),    // cap ring buffer to prevent unbounded growth
)

Package timeline provides a scrollable event-log widget for termdash.

timeline_event_handler.go is intentionally empty. Event handling has been consolidated into timeline.go (Keyboard / Mouse methods).

Package timeline provides a scrollable event-log widget for termdash.

timeline_manager.go is intentionally empty. State management has been consolidated into timeline.go.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatMiniBar

func FormatMiniBar(count, total, width int) string

FormatMiniBar returns a short ASCII bar of the given width whose filled portion is proportional to count/total. Filled cells use "▪", empty cells use "·". Returns all "·" when total or count is zero.

func SeverityColor

func SeverityColor(s Severity) cell.Color

SeverityColor returns the foreground cell color for each severity tier.

func SeverityGlyph

func SeverityGlyph(s Severity) string

SeverityGlyph returns the single-rune prefix that identifies the severity tier.

func SeverityName

func SeverityName(s Severity) string

SeverityName returns a fixed-width (5-char) display name for the severity tier, suitable for use in aligned columns (e.g. "DEBUG", "INFO ", "CRIT ").

Types

type Event

type Event struct {
	Time        string // display string shown in the log row
	Title       string
	Description string
	// Severity controls the row color and glyph prefix.  Defaults to SeverityDebug.
	Severity Severity
	// Timestamp is used for time-range filtering and by TimeRangePicker.
	// If zero, the event is never filtered out by SetTimeFilter.
	Timestamp time.Time
}

Event is a single entry in the timeline.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures a Timeline at construction time. Pass options to New():

tl, _ := timeline.New(timeline.FollowTail(), timeline.MaxEvents(200))

func CriticalBell

func CriticalBell(enable bool) Option

CriticalBell sets whether SeverityCritical events ring the terminal bell.

The default is false so dashboards and demos can show critical events without unexpectedly triggering an audible terminal alert. Enable this when the timeline is acting as an operator-facing alarm feed.

func FollowTail

func FollowTail() Option

FollowTail pins the view to the newest event so it behaves like a live log. The user can still scroll up; any new AddEvent call re-pins the view. Equivalent to calling SetFollowTail(true) after construction.

func MaxEvents

func MaxEvents(n int) Option

MaxEvents caps the in-memory event ring buffer. When the cap is reached the oldest events are discarded on each AddEvent call. Values ≤ 0 mean unlimited (the default). A reasonable production value is 500–2000.

type Severity

type Severity int

Severity indicates the importance level of an Event.

const (
	// SeverityDebug is the lowest tier — routine diagnostic noise.
	SeverityDebug Severity = iota
	// SeverityInfo marks normal operational events.
	SeverityInfo
	// SeverityWarn flags conditions that may require attention.
	SeverityWarn
	// SeverityError indicates a failure that needs investigation.
	SeverityError
	// SeverityCritical is the highest tier. The terminal bell is sounded on
	// arrival only when CriticalBell(true) is configured on the widget.
	SeverityCritical
)

type TimeRangePicker

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

TimeRangePicker is a horizontal timeline scrubber widget.

func NewTimeRangePicker

func NewTimeRangePicker(onChange func(start, end time.Time, hasRange bool)) (*TimeRangePicker, error)

NewTimeRangePicker creates an empty TimeRangePicker.

onChange is called whenever the selection changes: first click sets the start pin, drag or second click sets the end pin, r/R/Esc resets. Pass nil if you prefer to poll Selection() instead.

picker, err := timeline.NewTimeRangePicker(func(start, end time.Time, hasRange bool) {
    if hasRange {
        tl.SetTimeFilter(start, end)
    } else {
        tl.ClearTimeFilter()
    }
})

func (*TimeRangePicker) AddPickerEvent

func (p *TimeRangePicker) AddPickerEvent(e Event)

AddPickerEvent appends one event and expands the time span if needed.

func (*TimeRangePicker) Draw

func (p *TimeRangePicker) Draw(cvs *canvas.Canvas, _ *widgetapi.Meta) error

Draw renders the seven-row scrubber.

func (*TimeRangePicker) HasRange

func (p *TimeRangePicker) HasRange() bool

HasRange reports whether a complete (start+end) range is selected.

func (*TimeRangePicker) Keyboard

Keyboard handles r/R/Escape to reset the selection.

func (*TimeRangePicker) Mouse

Mouse handles click-and-drag to set a time range.

Interaction model:

  • ButtonLeft press : starts a new drag session; pins the start at the click column (any prior selection is cleared).
  • ButtonLeft held + move right : live-updates the end pin so the selection grows in real time as the user drags.
  • ButtonRelease : finalises the selection. If the release column is more than 1 cell to the right of the press column the range is committed (start+end both set). If the mouse barely moved it is treated as a plain click that sets only the start pin, leaving the user free to drag next time.

WantMouse is MouseScopeGlobal so ButtonRelease is always delivered even when the pointer drifts outside the widget during the drag.

func (*TimeRangePicker) Options

func (p *TimeRangePicker) Options() widgetapi.Options

Options declares the widget's needs.

func (*TimeRangePicker) Selection

func (p *TimeRangePicker) Selection() (start, end time.Time, hasRange bool)

Selection returns the current selection endpoints. hasRange is false if no complete range has been set.

func (*TimeRangePicker) SetPickerEvents

func (p *TimeRangePicker) SetPickerEvents(events []Event)

SetPickerEvents replaces the event snapshot and recalculates the time span.

type Timeline

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

Timeline displays a scrollable list of timestamped events. It implements widgetapi.Widget and can be placed directly in any container.

func New

func New(opts ...Option) (*Timeline, error)

New creates a new Timeline widget. Pass functional options to configure initial behaviour:

tl, err := timeline.New(timeline.FollowTail(), timeline.MaxEvents(500))

func (*Timeline) AddEvent

func (t *Timeline) AddEvent(e Event)

AddEvent appends a single event.

If CriticalBell(true) is configured and the event has SeverityCritical, the terminal bell (\a) is sounded. If FollowTail or SetFollowTail(true) is active the scroll offset is advanced so the new event will be visible on the next Draw (exact clamping happens in Draw because only Draw knows the current canvas height). If MaxEvents was set and the buffer is full, the oldest event is discarded.

func (*Timeline) ClearTimeFilter

func (t *Timeline) ClearTimeFilter()

ClearTimeFilter removes any active time filter and shows all events.

func (*Timeline) Draw

func (t *Timeline) Draw(cvs *canvas.Canvas, _ *widgetapi.Meta) error

Draw renders the timeline onto cvs, painting one event per row.

When content overflows the canvas height a right-edge scrollbar is drawn in the last column: ░ for the track, █ for the thumb (cyan), with ▲/▼ arrows at the top and bottom. Event text is truncated one column earlier so it never overlaps the scrollbar.

Each row is prefixed with a severity glyph and coloured according to its Severity tier. The selected row is additionally bolded and its leading column is replaced with ">".

func (*Timeline) EventCount

func (t *Timeline) EventCount() int

EventCount returns the number of currently displayed events (filtered or all).

func (*Timeline) Keyboard

func (t *Timeline) Keyboard(k *terminalapi.Keyboard, _ *widgetapi.EventMeta) error

Keyboard handles arrow-key navigation.

  • ArrowDown — move selection one row down; scroll if needed.
  • ArrowUp — move selection one row up; scroll if needed.
  • Enter / ' ' — confirm selection (initialises to the top visible row if nothing is selected yet).

func (*Timeline) Mouse

Mouse handles scroll-wheel, click, and drag events.

The widget uses MouseScopeGlobal so it performs its own bounds check — events outside the canvas area are silently ignored (mirroring the linechart pattern).

  • WheelUp/WheelDown — scroll the visible window (3 lines per tick).
  • ButtonLeft press — start a drag-to-scroll gesture; also remembers the press position to distinguish a click from a drag.
  • ButtonLeft hold+drag (ButtonLeft events with movement) — scroll by dragging: moving the mouse up scrolls down, moving down scrolls up, exactly like grabbing content and pulling it.
  • ButtonLeft release (ButtonRelease with no drag movement) — select the event at the clicked row (single-click behaviour preserved).

func (*Timeline) Options

func (t *Timeline) Options() widgetapi.Options

Options returns the widget's termdash options.

func (*Timeline) SelectedEvent

func (t *Timeline) SelectedEvent() *Event

SelectedEvent returns a copy of the currently selected event, or nil.

func (*Timeline) SetEvents

func (t *Timeline) SetEvents(events []Event)

SetEvents replaces all events, resetting scroll position and selection.

func (*Timeline) SetFollowTail

func (t *Timeline) SetFollowTail(follow bool)

SetFollowTail enables or disables tail-following mode. When enabled the view is automatically pinned to the last event after every AddEvent call, giving the widget a live-log / ops-dashboard feel. Manual keyboard/mouse scroll still works — call SetFollowTail(false) to stop following.

func (*Timeline) SetTimeFilter

func (t *Timeline) SetTimeFilter(start, end time.Time)

SetTimeFilter restricts the visible rows to events whose Timestamp falls within [start, end]. Events with a zero Timestamp are always hidden when a filter is active. Call ClearTimeFilter to show all events again.

func (*Timeline) SeverityCounts

func (t *Timeline) SeverityCounts() [5]int

SeverityCounts returns per-severity counts for the currently displayed events (which may be filtered). The returned array is indexed by Severity: index 0 = SeverityDebug … index 4 = SeverityCritical.

Directories

Path Synopsis
Package main is the ops-dashboard demo for the timeline widget.
Package main is the ops-dashboard demo for the timeline widget.

Jump to

Keyboard shortcuts

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