text

package
v0.0.1 Latest Latest
Warning

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

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

Documentation

Overview

Package text lays styled text out in terminal columns: measuring it, wrapping it, truncating it, and drawing it onto a grid.View.

Everything here counts columns rather than bytes or runes. A CJK or emoji cluster is two columns wide and is never split; a combining mark is none. Text that is measured one way and drawn another is the source of every misaligned terminal UI, so measuring and drawing live in the same place and agree by construction.

Index

Constants

View Source
const TabStop = 8

TabStop is how far apart tab stops are.

Eight, because that is where a terminal would have put them: the output being rendered was usually formatted by a program writing to a terminal, and lining its columns up means agreeing with the assumption it made.

Variables

This section is empty.

Functions

func Clusters

func Clusters(s string) iter.Seq2[int, string]

Clusters iterates the grapheme clusters of s with the byte offset each starts at.

It is what anything holding a cursor into text needs. A cursor cannot live on a rune boundary: a letter and the accent that modifies it are two runes and one thing on screen, and a cursor between them has no position a terminal could show.

func ColumnOf

func ColumnOf(s string, i int) int

ColumnOf is how many columns of s sit before the byte offset i.

func NextCluster

func NextCluster(s string, i int) int

NextCluster is the byte offset after the cluster at i, or len(s) at the end.

func OffsetAt

func OffsetAt(s string, col int) int

OffsetAt is the byte offset of the cluster boundary nearest to column col, without going past it. It is how a click, or a cursor moving between lines of different lengths, finds where it lands.

func PrevCluster

func PrevCluster(s string, i int) int

PrevCluster is the byte offset of the cluster ending at i, or zero at the start.

func Truncate

func Truncate(s string, width int, ellipsis string) string

Truncate cuts plain text to at most width columns, ending it with ellipsis when anything was cut.

func Width

func Width(s string) int

Width is how many columns s would occupy, with tabs expanded from column zero.

Types

type Line

type Line []Span

Line is one logical line of styled text — logical in that it has no width yet. Wrapping turns it into however many rows it needs.

func Of

func Of(s string, style grid.Style) Line

Of is the one-span line for a piece of plain styled text.

func (Line) Draw

func (l Line) Draw(v grid.View, x, y int) int

Draw writes the line onto v at (x, y) and returns how many columns it advanced. Tabs are expanded from the line's own start, not from the view's, so a line drawn at an indent keeps the column relationships it was written with.

func (Line) String

func (l Line) String() string

String is the line's text with the styling dropped.

func (Line) Truncate

func (l Line) Truncate(width int, ellipsis string) Line

Truncate cuts the line to at most width columns, ending it with ellipsis when anything was cut. The ellipsis takes the style of the last text that survived, so it reads as part of the sentence it is ending.

The result can fall a column short of width: a cut never splits a wide cluster.

func (Line) Width

func (l Line) Width() int

Width is how many columns the line would occupy unwrapped, with tabs expanded.

func (Line) Wrap

func (l Line) Wrap(width int) []Wrapped

Wrap breaks the line into rows of at most width columns.

Breaks are preferred at spaces, and a word longer than the width is broken between grapheme clusters instead. The run of spaces at a break is consumed: it hangs off neither the end of one row nor the start of the next. Styles survive every break.

A width of zero or less returns the line whole: a caller with no width to lay out in is better served by text it can measure than by text silently thrown away.

type Span

type Span struct {
	Text  string
	Style grid.Style
}

Span is a run of text sharing one style.

type Wrapped

type Wrapped struct {
	Line Line
	// Joined marks a row that continues the line above it rather than starting a
	// line of its own. Anything rejoining rows — copying a selection, say — needs
	// to know which line breaks were the text's and which were the width's.
	Joined bool
}

Wrapped is one physical row produced by wrapping a Line.

func WrapAll

func WrapAll(lines []Line, width int) []Wrapped

WrapAll wraps lines in order. Every line starts a row of its own, so a blank line stays a blank row.

func (Wrapped) Draw

func (w Wrapped) Draw(v grid.View, x, y int) int

Draw writes the row onto v at (x, y).

func (Wrapped) Width

func (w Wrapped) Width() int

Width is how many columns the row occupies.

Jump to

Keyboard shortcuts

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