ansi

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

Documentation

Overview

Package ansi is what an escape sequence is made of.

Escape sequences travel in both directions and carry many meanings. What their readers share is syntax: which bytes are parameters, which byte ends a sequence, what an empty field means, and where a sequence stops. This package owns only that syntax so every semantic decoder can build on the same byte-level rules.

Nothing here decides what a sequence means. A final byte of 'm' is a style to one reader and nothing at all to the other, and this package has no opinion about either.

What a sequence looks like

Three shapes, and everything else is text:

ESC [ 1 ; 31 m          a control sequence: parameters, then a final byte
ESC ] 8 ; ; url ST      a string command: a body, then a terminator
ESC ( B                 an escape with intermediates and a final byte

Index

Constants

View Source
const (
	// Escape introduces every sequence there is.
	Escape = 0x1b
	// Bell ends a string command on the terminals that never adopted the standard
	// terminator, which is most of them.
	Bell = 0x07
)
View Source
const Limit = 1 << 20

Limit is well past any real parameter and short of anything that could overflow. A number beyond it is treated as malformed.

Variables

This section is empty.

Functions

func Body

func Body(b byte) bool

Body reports whether b may appear between a control sequence's introducer and the byte that ends it: an intermediate byte, which selects a variant of the sequence, or a parameter byte, which is a digit, a separator, or the marker a private sequence opens with.

The two halves are not separately exported. Nothing outside this package has ever needed to tell them apart — what a reader asks is "is this still the body" and then "is this the end" — and a predicate nobody calls is a predicate nobody keeps true.

func Final

func Final(b byte) bool

Final reports whether b ends a control sequence and says what it was.

Types

type Kind

type Kind uint8

Kind says what a piece of a stream turned out to be.

const (
	// Plain is text carrying no sequence.
	Plain Kind = iota
	// Control is ESC [ — parameters and a final byte. Styling, cursor movement,
	// erasure and mode changes are all this shape.
	Control
	// String is a command with a body and a terminator: an operating system
	// command, a device control string, and the three like them. [Piece.Final]
	// holds the byte that introduced it, because that is what says which.
	String
	// Other is an escape with intermediates and a final byte and no parameters:
	// selecting a character set, entering keypad mode, saving the cursor.
	Other
	// Malformed is bytes that began like a sequence and cannot be one. They are a
	// piece of their own rather than text, because a reader that fell back to
	// reading them as text would print the introducer.
	Malformed
)

type Params

type Params struct {
	// Private is the marker byte a private sequence begins with — '<' for a mouse
	// report, '?' for a terminal's answer about a mode — or zero for an ordinary
	// sequence.
	Private byte
	// Groups are the semicolon-separated parameters, each of which may carry
	// colon-separated subparameters.
	//
	// A field left empty is the protocol's default, which is zero. A field that is
	// not a number, or is far larger than any parameter legitimately gets, is -1: a
	// decoder can then refuse the sequence instead of acting on a value invented
	// for it.
	Groups [][]int
}

Params is a sequence's parameter section, parsed once and read by whichever decoder the final byte selects.

There is one parser rather than one per sequence family. Two parsers over the same syntax drift: they disagree about what an empty field means, or about what to do with a field that is not a number, and the sequence that exercises the difference is the one nobody tested.

func Parse

func Parse(body string) Params

Parse reads a control sequence's parameter section — everything between the introducer and the final byte.

func (Params) At

func (ps Params) At(i int) int

At is the leading value of group i, or zero when the group is absent.

func (Params) Count

func (ps Params) Count() int

Count is how many parameter groups the sequence carried.

func (Params) Empty

func (ps Params) Empty() bool

Empty reports whether the sequence carried no parameters.

func (Params) First

func (ps Params) First() int

First is the leading parameter, or zero when there was none. Zero is the protocol's own default for a missing parameter, so a caller need not distinguish.

func (Params) Group

func (ps Params) Group(i int) []int

Group is parameter i and its subparameters, or nothing when there is no such parameter.

type Piece

type Piece struct {
	Kind Kind
	// Raw is the piece's own bytes, whole. For a sequence it includes the
	// introducer and the terminator, so that a reader passing what it does not
	// understand through to a terminal can pass it on exactly as it came.
	Raw string
	// Body is the part between the introducer and the end: the parameter section
	// of a [Control] piece, or a [String] piece's body without its terminator.
	// Empty for anything else.
	Body string
	// Final is the byte that ended a [Control] or [Other] piece and says what it
	// was, and the byte that introduced a [String] piece, for the same reason.
	Final byte
}

Piece is one part of a stream: a run of text, or one sequence.

func Next

func Next(s string) (p Piece, n int, ok bool)

Next reads the piece at the front of s.

It reports the piece and how many bytes it took. The false case is the one that matters for anything reading a stream: what is at the front of s could still become a longer sequence, nothing about it can be decided until more arrives, and no bytes were consumed. What is left over then always begins with an escape byte, which is what tells a caller at the end of its input that the remainder is half a sequence rather than text.

Text runs up to the next escape byte and no further, so a caller is handed the largest run it can treat as one thing.

Jump to

Keyboard shortcuts

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