terminal_graph/static_graphs

Static terminal graph rendering for numeric data.

This module contains the shared plot data model and renders complete graph frames without changing terminal state. Most applications should import the terminal_graph façade instead of this submodule directly.

import terminal_graph

var graph = initStaticGraph("Request latency", unit = "ms")
let latency = graph.addSeries("p95")
graph.push(latency, [18.0, 20.5, 19.0, 23.0])
echo graph.render(width = 60, height = 14, useColor = false)

Types

PlotStyle = enum
  psLine,                   ## Draw one marker at the sample value.
  psFill                     ## Draw a filled column from the lower bound to the sample value.
Plotter = object
  title*: string
  unit*: string
A collection of named series that can be rendered as a terminal graph.
Series = object
  name*: string
  style*: PlotStyle
  color*: ForegroundColor
  marker*: string
Configuration for one series. Samples are managed through Plotter.
SeriesStats = object
  current*: float64
  minimum*: float64
  maximum*: float64
  average*: float64
  sampleCount*: int
Summary statistics for the retained samples in a series.
StaticGraph = Plotter
Descriptive alias for Plotter when rendering standalone frames.

Consts

DefaultMaxSamples = 1000
Default number of samples retained per series.
MinimumRenderHeight = 8
Smallest supported total render height.
MinimumRenderWidth = 24
Smallest supported render width, including the y-axis.

Procs

proc addSeries(plotter: var Plotter; name: string; style = psLine;
               color = fgCyan; marker = "•"): int {.discardable,
    ...raises: [ValueError], tags: [], forbids: [].}

Adds a series and returns the index used by push and related procs.

A marker must contain exactly one Unicode code point so every sample maps to one cell in the graph grid.

proc clear(plotter: var Plotter) {....raises: [], tags: [], forbids: [].}
Removes every sample from every series.
proc clear(plotter: var Plotter; seriesIdx: int) {....raises: [], tags: [],
    forbids: [].}
Removes every sample from one series without removing its configuration.
proc clearRange(plotter: var Plotter) {....raises: [], tags: [], forbids: [].}
Restores automatic y-axis scaling.
proc initPlotter(title: string; unit = ""; maxSamples = DefaultMaxSamples): Plotter {.
    ...raises: [ValueError], tags: [], forbids: [].}

Creates an empty plotter.

maxSamples bounds memory usage for long-running applications. When a series exceeds the limit, its oldest samples are discarded.

proc initStaticGraph(title: string; unit = ""; maxSamples = DefaultMaxSamples): StaticGraph {.
    ...raises: [ValueError], tags: [], forbids: [].}
Creates a static graph. This is the descriptive equivalent of initPlotter; both constructors return the same graph type.
proc latest(plotter: Plotter; seriesIdx: int): Option[float64] {....raises: [],
    tags: [], forbids: [].}
Returns the newest sample, or none when the series is empty.
proc maxSamples(plotter: Plotter): int {....raises: [], tags: [], forbids: [].}
Returns the maximum number of retained samples per series.
proc push(plotter: var Plotter; seriesIdx: int; value: float64) {.
    ...raises: [ValueError], tags: [], forbids: [].}
Appends one finite sample to a series.
proc push(plotter: var Plotter; seriesIdx: int; values: openArray[float64]) {.
    ...raises: [ValueError], tags: [], forbids: [].}

Appends several samples to a series in order.

All values are validated before the series is changed.

proc render(plotter: Plotter; width = 0; height = 0; useColor = true;
            showStats = true): string {....raises: [ValueError],
                                        tags: [ReadEnvEffect], forbids: [].}

Renders the current graph to a string without changing the plotter.

width and height describe the complete frame. Pass zero (the default) to use the detected terminal size. Explicit dimensions make snapshots and redirected output deterministic. Set useColor to false to omit ANSI escape sequences. When multiple series occupy the same cell, the series added last is visible.

proc sampleCount(plotter: Plotter; seriesIdx: int): int {....raises: [], tags: [],
    forbids: [].}
Returns the number of retained samples for a series.
proc samples(plotter: Plotter; seriesIdx: int): seq[float64] {....raises: [],
    tags: [], forbids: [].}
Returns a copy of the retained samples, oldest first.
proc seriesCount(plotter: Plotter): int {....raises: [], tags: [], forbids: [].}
Returns the number of configured series.
proc setMaxSamples(plotter: var Plotter; maxSamples: int) {.
    ...raises: [ValueError], tags: [], forbids: [].}
Changes the retention limit and immediately trims existing series.
proc setRange(plotter: var Plotter; minimum, maximum: float64) {.
    ...raises: [ValueError], tags: [], forbids: [].}
Uses a fixed y-axis range until clearRange is called.
proc statistics(plotter: Plotter; seriesIdx: int): Option[SeriesStats] {.
    ...raises: [], tags: [], forbids: [].}
Computes statistics for a series, or none if it has no samples.
proc valueRange(plotter: Plotter): tuple[minimum, maximum: float64] {.
    ...raises: [], tags: [], forbids: [].}

Returns the fixed range or the automatically computed range.

Empty plots use 0.0 .. 1.0. A single-valued plot is padded by one on either side so rendering never has to divide by zero.