TermMosaic v1.0.0

v1.0.0 is the first release that makes a stability promise: the public API freezes here and Semantic Versioning applies in earnest — with one documented exception: widgets/widgettest is excluded from that promise, because it must evolve with the framework. Read the limitations before you rely on anything here.

Widgets widgets/basic

Paragraph

Wrapped, styled prose that reflows to the width it is given.

Wrapped, styled prose that reflows to the width it is given.

Package widgets/basic. API reference: pkg.go.dev/widgets/basic.

Paragraph renders wrapped, aligned, styled text over as many lines as fit.

It shows the TOP of its content: there is no scrolling here, because scrolling a block of text is Pager’s job and a Paragraph that scrolled by itself would be a second scroll model. The paragraph that does not fit is the one that gets dropped content, which is ADR 0007’s “information budget” case stated for text: show what fits, clip the rest, never blank.

Rendered output

Paragraph rendered by cmd/capture through widgettest.Capture: colour at 3 widths (40, 80, 120 columns), and the exact plain-text cell grid at the widest of them.

MinSize() is not in the manifest for this widget, so this page does not claim a minimum. If you need one, call it.

40 columns × 10 rows

A capture is one settled frame after N
frames have been rendered.              
It cannot show a keypress, a selection  
moving, a cell flickering or a pager    
scrolling. Every widget page therefore  
links a runnable program: the capture is
a still, and the program is the widget. 
                                        
                                        
                                        

80 columns × 9 rows

A capture is one settled frame after N frames have been rendered.               
It cannot show a keypress, a selection moving, a cell flickering or a pager     
scrolling. Every widget page therefore links a runnable program: the capture is 
a still, and the program is the widget.                                         
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                

120 columns × 7 rows

A capture is one settled frame after N frames have been rendered.                                                       
It cannot show a keypress, a selection moving, a cell flickering or a pager scrolling. Every widget page therefore links
a runnable program: the capture is a still, and the program is the widget.                                              
                                                                                                                        
                                                                                                                        
                                                                                                                        
                                                                                                                        

Plain text — the exact cell grid, trimmed per line. This is the honest form: Braille and block-element glyphs can take a different advance width in a web font than a terminal gives them, which breaks the alignment they depend on.

# Paragraph — Wrapped, styled prose that reflows to the width it is given.
# package: widgets/basic
# constructor: basic.NewParagraph(r buffer.Rect, spans []buffer.Span) *basic.Paragraph
# 120 columns x 7 rows, rendered through widgettest.Capture

A capture is one settled frame after N frames have been rendered.
It cannot show a keypress, a selection moving, a cell flickering or a pager scrolling. Every widget page therefore links
a runnable program: the capture is a still, and the program is the widget.




What you are looking at. This is the cell grid the renderer produced, in a web page. It is not a screenshot of a terminal, and it cannot show interaction, resize or animation — a capture is one settled frame after N frames of settling. Braille and Block Elements can take a different advance width in your browser's font than in a terminal, so if a gauge or a sparkline above looks wrong, the plain-text form below it is the exact output and the colour one is the decoration. The colour frames are at 40, 80, 120 columns; the plain-text frame is at 120. More on this.

Package context

Package basic provides the two text widgets: Text, which writes styled spans on one line, and Paragraph, which wraps them.

Both follow the same two rules, which are the rules every widget in the catalog follows:

  • The available space is Bounds(), never buf.Size(). The buffer is the screen; the rect is the widget’s space (ADR 0007 §1 rule 1).
  • Nothing derived from the size is built in Draw. Wrap and Truncate both allocate, so Paragraph caches its Wrapped and Text caches its truncation against the rect they were computed for, and recompute only when Bounds() differs (ADR 0007 §3, ADR 0008 §4).

Constructing it

basic.NewParagraph(r buffer.Rect, spans []buffer.Span) *basic.Paragraph

Same shape as Text: spans in, wrapping out. The wrapping is buffer.Wrap’s work, not the widget’s, and it allocates — which is why it happens on the first Draw after a width change rather than every frame.

  • Spans — []buffer.Span — the styled content, wrapped to the width it is given.
  • Align — geometry.Align — applied per line.
  • Ascii — bool — force ASCII wrapping rules.

When not to use it

Do not use it for text the user must scroll. A Paragraph shows the top of its content and stops; it has no scroll position and no key contract, so a paragraph longer than its rect silently loses the rest. Scrolling a body of text is Pager, deliberately.

Do not use it for a single line. Text is the smaller widget and does not pay for the wrap cache. Paragraph on a one-line string works but buys nothing.

Do not use it to lay out a form or anything with per-element state. It wraps prose, not widgets. A field label next to an input is two widgets in a solved rect, which is a layout problem — see Composing with Block and Split.

Do not expect it to keep its wrapped cache across a resize for free. A width change re-wraps, and Wrap allocates. That is correct and it is once per width change, but it does mean a drag-resize re-wraps on every step.

Instead: Pager to scroll it, Text for one line, composition for anything with state.