Note
The animated line graph examples may appear less fluid than the actual terminal output because of an unresolved issue in the automatic media rendering process. All line graphs render fluidly when run directly in a terminal.
Pure-Nim terminal charts: connected lines, horizontal bars, static and live OHLC candles, irregular XY and scatter plots, responsive multiplot dashboards, 2D surfaces, filled contours, and sparklines.
The package renders strings with Unicode and ANSI styling—there is no Python
runtime or external plotting backend. Importing terminal_graph has no side
effects and does not change terminal state.
terminal_graph has been tested on Linux and Windows. On Windows I tested with the Terminal app which comes with Windows, other terminals may or may not work. It should also work on macOS through its standard POSIX terminal and ANSI/VT support, but macOS has not yet been tested directly.
- Nim 2.0.0 or newer
terminal_style0.1.1 or newer- No runtime dependencies beyond
terminal_style
- TerminalGraph
Install the current version with Nimble:
nimble install terminal_style
nimble install terminal_graphOr if you prefer directly via Github:
nimble install https://github.com/titanomachy/terminal-style
nimble install https://github.com/titanomachy/terminal-graphThen import the complete core API:
import terminal_graphThe main module also re-exports terminal_style, its palette API, and a modern
dark-terminal graph palette, so colors, reusable styles, ANSI stripping, and
display-width helpers do not need a second import. Typed objects and CSV/JSON
parsing use opt-in modules to keep macros and parsers out of the core facade.
One façade import is enough to render a chart:
import terminal_graph
echo plot(
[3, 4, 9, 6, 2, 4, 5, 8],
graphWidth(40),
graphHeight(8),
graphCaption("Request latency"),
graphSeriesColors(ModernGraphSeriesColors)
)| Graph family | Main API | Highlights |
|---|---|---|
| Connected lines | plot, plotMany, AsciiGraphConfig |
Interpolation, labeled axes, formatters, legends, custom glyphs, gradients, thresholds, and NaN gaps |
| Horizontal bars | plotBars, BarGraphOptions |
Single-series, grouped, and stacked positive/negative bars around a shared zero axis |
| OHLC candles | plotCandles, CandlePlotOptions, LiveCandleGraph |
Ordered periods, fixed or automatic price ranges, streaming history, and in-progress candle updates |
| XY and scatter | plotXY, plotXYMany, plotScatter, plotScatterMany |
Explicit coordinates, fixed or automatic viewports, clipping, labels, markers, and legends |
| Static graphs | StaticGraph, initStaticGraph, render |
Bounded histories, line/fill series, statistics, automatic or fixed ranges, and deterministic dimensions |
| Sparklines | sparkline, SparklineOptions |
Shared or automatic ranges, gaps, custom ticks, and ANSI-256 palettes |
| Surfaces and contours | plotSurface, plotContour, plot2D |
Matrix or flat data, resampling, fixed ranges, palettes, scales, and plain-text output |
| Multiplot layouts | multiplot, multiplotResponsive |
ANSI/Unicode-aware grids, auto-fit columns, breakpoints, alignment, and deferred width-aware renderers |
| Live displays | LiveGraph, LiveLineGraph, LiveCandleGraph, LiveDashboard |
Bounded streaming data, frame rendering, in-place redraws, alternate-screen dashboards, and resize-safe composition |
| Terminal styling | Re-exported terminal_style API and ModernGraphPalette |
Standard, bright, ANSI-256, RGB, and hex colors; a shared graph palette; plus ANSI-aware measuring, slicing, padding, and wrapping |
Most applications should import terminal_graph. Focused imports such as
terminal_graph/sparkline_graphs are also supported. Rendering is string-based
and side-effect free; explicit dimensions and options make snapshots
deterministic.
plot renders one sample-indexed series; plotMany places several series on
the same axes. Option builders configure dimensions, labels, formatters,
colors, gradients, thresholds, and X-axis ticks.
echo plot(
[18.0, 21.0, 19.0, 26.0, 34.0, 31.0],
graphWidth(40),
graphHeight(8),
graphCaption("Request latency"),
graphSeriesColors(ModernGraphSeriesColors)
)nim r --path:src examples/line_graph.nimBar charts use a shared zero baseline, so positive and negative values remain directly comparable. Multiple series may be grouped or stacked.
var options = initBarGraphOptions()
options.caption = "Regional change"
options.unit = "%"
options.seriesLegends = @["current", "previous"]
echo plotBars(
["North", "South"],
@[@[18.0, -7.0], @[12.0, 5.0]],
options
)nim r --path:src examples/bar_graph.nimCandle represents one ordered OHLC interval. Automatic ranges use visible
lows and highs without forcing zero into the viewport; explicit ranges clip
the candle geometry. Static rendering requires every candle to fit the canvas.
var options = initCandlePlotOptions()
options.caption = "Daily OHLC"
options.unit = "USD"
echo plotCandles(
["Mon", "Tue", "Wed"],
[
candle(101, 106, 99, 104),
candle(104, 108, 102, 103),
candle(103, 109, 101, 108)
],
options
)nim r --path:src examples/candle_graph.nimXY charts use explicit numeric coordinates rather than sample indices. A series can be connected in its supplied order or rendered as independent scatter points, with fixed viewports and clipping when needed.
var options = initXYPlotOptions()
options.caption = "Latency samples"
options.xLabel = "time"
options.yLabel = "ms"
echo plotScatter([
xyPoint(-2.0, 3.0),
xyPoint(0.0, 5.0),
xyPoint(3.0, 4.0)
], options)nim r --path:src examples/xy_graph.nimStaticGraph owns bounded series data and renders a complete deterministic
frame with optional statistics. Series may use markers or filled columns.
var graph = initStaticGraph("Weekly requests", unit = "requests")
let requests = graph.addSeries("requests", style = psFill, marker = "▄")
graph.push(requests, [12.0, 18.0, 15.0, 27.0, 35.0, 31.0, 42.0])
echo graph.render(width = 64, height = 14, useColor = false)nim r --path:src examples/static_graph.nimSparklines embed compact trends in ordinary text. Options provide shared ranges, custom tick glyphs, gap handling, and ANSI-256 palettes.
echo "Latency ", sparkline([18, 21, 19, 26, 34, 31, 45]), " ms"
var shared = initSparklineOptions()
shared.setSparklineRange(0.0, 100.0)
echo "Load ", sparkline([10, 25, 40, 75, 100], shared)nim r --path:src examples/sparkline_graph.nimSurface plots pack two sampled rows into each terminal row. Contours render the same matrix as discrete filled bands; both support resampling, palettes, and fixed value ranges.
let field = @[
@[0.0, 0.5, 1.0],
@[0.5, 1.0, 0.5],
@[1.0, 0.5, 0.0]
]
var options = initSurfacePlotOptions()
options.caption = "Service heatmap"
echo plotContour(field, options)nim r --path:src examples/advanced_graphs.nimMultiplot combines already-rendered strings into ANSI- and Unicode-aware grids. Responsive render callbacks receive their assigned width before rendering, so dashboards can reflow without wrapping individual charts.
let
latency = plot([18, 24, 21, 29], graphWidth(24), graphHeight(6))
load = plot([40, 55, 48, 63], graphWidth(24), graphHeight(6))
echo multiplot([latency, load], columns = 2, horizontalGap = 4)nim r --path:src examples/multiplot_graph.nimLiveGraph, LiveLineGraph, and LiveCandleGraph retain bounded streaming
state. Their renderFrame() methods are side-effect free; startLive, draw,
and stopLive provide in-place terminal output. Always restore terminal state
in a finally block.
var options = initCandlePlotOptions()
options.caption = "Live OHLC"
var graph = initLiveCandleGraph(maxCandles = 80, options = options)
graph.push(candle(101, 106, 99, 104), "09:30")
graph.startLive()
try:
graph.updateLatest(candle(101, 108, 98, 107))
graph.draw()
finally:
graph.stopLive()The interactive examples also install a temporary Ctrl+C hook backed by an atomic stop flag. Signal handling remains an application responsibility; renderers stay side-effect free, while the live-session API owns cursor, screen, and text-attribute restoration.
Use LiveDashboard for resize-safe full-screen redraws of arbitrary frames,
including responsive multiplot output. On supported Windows consoles, live
sessions enable virtual-terminal processing and restore the original mode.
The focused streaming_candle_graph.nim
example appends completed periods and repeatedly replaces the newest forming
candle. Its renderFrame() output can also be placed beside another graph in a
LiveDashboard.
![]() streaming_candle_graph.nim · .castnim r --path:src examples/streaming_candle_graph.nimCompleted periods with a repeatedly updated in-progress candle. |
![]() live_graph.nim · .castnim r --path:src examples/live_graph.nimGenerated service metrics redrawn fluidly as a full terminal frame. |
![]() streaming_line_graph.nim · .castnim r --path:src examples/streaming_line_graph.nimTwo connected series in bounded streaming windows. |
![]() streaming_sparklines.nim · .castnim r --path:src examples/streaming_sparklines.nimA compact CPU and memory dashboard from reusable sparklines. |
![]() streaming_multiplot_graph.nim · .castnim r --path:src examples/streaming_multiplot_graph.nimTwo live graphs in a wide, resize-aware full-screen dashboard. |
|
The façade re-exports terminal_style, including standard, indexed, RGB, and
hex colors; text attributes; and ANSI-aware measuring, slicing, padding, and
wrapping. It also provides a true-color palette designed for dark terminal
backgrounds:
ModernGraphPaletteprovides named TerminalStyle color roles.ModernGraphSeriesColorsis an eight-color categorical sequence.ModernGraphGradientis a seven-stop cool-to-warm value gradient.ModernGraphHeadingStyleandModernGraphMutedStylestyle surrounding UI.
var options = initBarGraphOptions()
options.seriesColors = @ModernGraphSeriesColors
var surfaceOptions = initSurfacePlotOptions()
surfaceOptions.palette = @ModernGraphGradient
echo styled(ModernGraphHeadingStyle, "Service overview")
echo plotBars(["API", "Worker"], [42, 31], options)Each screenshot above links to its focused runnable example. For a finite tour of every graph family, run:
nim r --path:src examples/all_graphs.nimall_graphs.nim — finite tour of every graph family
Compile-check every example at once with:
nimble examplesnimble test # run all test suites
nimble examples # compile-check all examples
nimble docs # generate htmldocs/ from public API comments
./scripts/regenerate_media.sh # rebuild README images, casts, and GIFsSee CONTRIBUTING.md for development rules and docs/public-api.md for the example coverage map. The generated API documentation is published from the default branch.
The connected line renderer is a Nim port inspired by
guptarohit/asciigraph. Other API
and visualization ideas were inspired by
OFThomas/drawIt,
Luteva-ssh/nivot, and
sindresorhus/sparkly. See
THIRD_PARTY_NOTICES.md for the required notice.
terminal_graph is released under the MIT License.













