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
- func Clusters(s string) iter.Seq2[int, string]
- func ColumnOf(s string, i int) int
- func NextCluster(s string, i int) int
- func OffsetAt(s string, col int) int
- func PrevCluster(s string, i int) int
- func Truncate(s string, width int, ellipsis string) string
- func Width(s string) int
- type Line
- type Span
- type Wrapped
Constants ¶
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 ¶
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 NextCluster ¶
NextCluster is the byte offset after the cluster at i, or len(s) at the end.
func OffsetAt ¶
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 ¶
PrevCluster is the byte offset of the cluster ending at i, or zero at the start.
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 (Line) Draw ¶
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) Truncate ¶
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) Wrap ¶
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 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 ¶
WrapAll wraps lines in order. Every line starts a row of its own, so a blank line stays a blank row.