v0.5.0 31affde

README.md RawHistoryFolder

vev-vt

A Go library for reading terminal output and keeping track of what should appear on screen. It powers vev.

Feed it the bytes from a shell or command. It handles text, colors, cursor movement, scrolling and resizing. You can then read the screen, save its history, or use the ansi package to draw it in a terminal.

This library does not start processes or manage a PTY. Your application does that and passes the output to vev-vt.

Install

Requires Go 1.27 or newer.

go get github.com/bnema/vev-vt

Alpha software: APIs and saved-history formats can change between versions. The current history format does not read older VTH3 data.

Read terminal output

package main

import (
    "fmt"

    vt "github.com/bnema/vev-vt"
)

func main() {
    screen := vt.NewScreen(80, 24)
    screen.Write([]byte("Hello, \x1b[31mworld\x1b[0m!"))

    // Colors and escape sequences are processed, not included in the text.
    for x := 0; x < 13; x++ {
        fmt.Printf("%c", screen.Cell(x, 0).Rune)
    }
    fmt.Println() // Hello, world!
}

Use screen.Resize(columns, rows) when the terminal size changes. Use screen.Snapshot() when you need a copy that stays unchanged as new output arrives.

Keep scrollback

Scrollback is the text that has moved above the visible screen.

// Your application chooses these limits; vev-vt has no default budget.
config := vt.HistoryConfig{
    MaxBytes: 20_000_000, // At most 20 MB of history data.
    MaxRows:  5_000,      // Optional: also keep at most 5,000 lines.
}
screen := vt.NewScreenWithHistory(80, 24, config)

vev-vt enforces the limits your application supplies. The PTY transports bytes; it does not store scrollback. The oldest lines are removed when a supplied limit is reached. Limits apply to each screen separately and exclude the visible screen. The byte limit measures uncompressed history data, not total process memory.

History guide →: limit settings, saving/restoring history and optional compression during idle time.

A few rules

  • Serialize Write, Resize, Snapshot, reads and history mutations in one goroutine, or protect them with your own lock.
  • Rows returned by the API are copies. Changing one does not change the screen.
  • Use vt.DefaultStyle() for terminal-default colors, not vt.Style{}.
  • Callbacks run during screen.Write; keep them short.

API ownership and styles →

Packages

Package Use it for
vev-vt Parse terminal output, read the screen and manage history.
vev-vt/core Work with cells, styles and writable grids.
vev-vt/ansi Render a screen or grid as ANSI terminal output.
vev-vt/graphics Read supported terminal images and their positions.

Supported image features →

Development

go test ./...
go test ./... -race
go vet ./...

Storage benchmarks and design decisions →

source
1# vev-vt
2
3A Go library for reading terminal output and keeping track of what should appear
4on screen. It powers [vev](https://github.com/bnema/vev).
5
6Feed it the bytes from a shell or command. It handles text, colors, cursor
7movement, scrolling and resizing. You can then read the screen, save its history,
8or use the `ansi` package to draw it in a terminal.
9
10This library does **not** start processes or manage a PTY. Your application does
11that and passes the output to vev-vt.
12
13## Install
14
15Requires Go 1.27 or newer.
16
17```sh
18go get github.com/bnema/vev-vt
19```
20
21**Alpha software:** APIs and saved-history formats can change between versions.
22The current history format does not read older VTH3 data.
23
24## Read terminal output
25
26```go
27package main
28
29import (
30    "fmt"
31
32    vt "github.com/bnema/vev-vt"
33)
34
35func main() {
36    screen := vt.NewScreen(80, 24)
37    screen.Write([]byte("Hello, \x1b[31mworld\x1b[0m!"))
38
39    // Colors and escape sequences are processed, not included in the text.
40    for x := 0; x < 13; x++ {
41        fmt.Printf("%c", screen.Cell(x, 0).Rune)
42    }
43    fmt.Println() // Hello, world!
44}
45```
46
47Use `screen.Resize(columns, rows)` when the terminal size changes.
48Use `screen.Snapshot()` when you need a copy that stays unchanged as new output
49arrives.
50
51## Keep scrollback
52
53Scrollback is the text that has moved above the visible screen.
54
55```go
56// Your application chooses these limits; vev-vt has no default budget.
57config := vt.HistoryConfig{
58    MaxBytes: 20_000_000, // At most 20 MB of history data.
59    MaxRows:  5_000,      // Optional: also keep at most 5,000 lines.
60}
61screen := vt.NewScreenWithHistory(80, 24, config)
62```
63
64vev-vt enforces the limits your application supplies. The PTY transports bytes;
65it does not store scrollback. The oldest lines are removed when a supplied limit
66is reached. Limits apply to each
67screen separately and exclude the visible screen. The byte limit measures
68uncompressed history data, **not total process memory**.
69
70[History guide →](docs/history.md): limit settings, saving/restoring history and
71optional compression during idle time.
72
73## A few rules
74
75- Serialize `Write`, `Resize`, `Snapshot`, reads and history mutations in one
76  goroutine, or protect them with your own lock.
77- Rows returned by the API are copies. Changing one does not change the screen.
78- Use `vt.DefaultStyle()` for terminal-default colors, not `vt.Style{}`.
79- Callbacks run during `screen.Write`; keep them short.
80
81[API ownership and styles →](docs/ownership.md)
82
83## Packages
84
85| Package | Use it for |
86| --- | --- |
87| `vev-vt` | Parse terminal output, read the screen and manage history. |
88| `vev-vt/core` | Work with cells, styles and writable grids. |
89| `vev-vt/ansi` | Render a screen or grid as ANSI terminal output. |
90| `vev-vt/graphics` | Read supported terminal images and their positions. |
91
92[Supported image features →](docs/graphics.md)
93
94## Development
95
96```sh
97go test ./...
98go test ./... -race
99go vet ./...
100```
101
102[Storage benchmarks and design decisions →](docs/storage-optimization.md)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 13

↑↓ moveenter openesc close