<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>TermMosaic</title><link>https://serkanalgur.github.io/termmosaic.github.io/</link><description>Recent content on TermMosaic</description><generator>Hugo</generator><language>en-gb</language><atom:link href="https://serkanalgur.github.io/termmosaic.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>Block</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/block/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/block/</guid><description>&lt;p&gt;A bordered, titled, padded rectangle that other widgets draw inside.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/block&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/block"&gt;pkg.go.dev/widgets/block&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Block is a bordered region with an optional title. It draws chrome only: it has no content of its own beyond the background and the border.&lt;/p&gt;&#10;&lt;p&gt;The zero Block draws no border (Border is BorderNone) with the terminal&amp;rsquo;s own colours, which is a legal and unremarkable block. It is usable as constructed.&lt;/p&gt;&#10;&lt;p&gt;A Block is a plain value in every respect that matters: it is not safe for concurrent use, because SetBounds and Draw race by design — the renderer owns Bounds between frames (ADR 0003).&lt;/p&gt;</description></item><item><title>Text</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/text/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/text/</guid><description>&lt;p&gt;A single line of styled spans, aligned within its rectangle.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/basic&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/basic"&gt;pkg.go.dev/widgets/basic&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Text renders styled spans on one line.&lt;/p&gt;&#10;&lt;p&gt;It is the smallest widget in the catalog and the one most often composed: a label in a form, a value beside it, a status line. It truncates rather than wraps, because wrapping is Paragraph&amp;rsquo;s job and a widget that both wrapped and did not would be two widgets.&lt;/p&gt;</description></item><item><title>Paragraph</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/paragraph/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/paragraph/</guid><description>&lt;p&gt;Wrapped, styled prose that reflows to the width it is given.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/basic&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/basic"&gt;pkg.go.dev/widgets/basic&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Paragraph renders wrapped, aligned, styled text over as many lines as fit.&lt;/p&gt;&#10;&lt;p&gt;It shows the TOP of its content: there is no scrolling here, because scrolling a block of text is Pager&amp;rsquo;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&amp;rsquo;s &amp;ldquo;information budget&amp;rdquo; case stated for text: show what fits, clip the rest, never blank.&lt;/p&gt;</description></item><item><title>Split</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/split/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/split/</guid><description>&lt;p&gt;A container that divides its rectangle among focusable panes.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/split&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/split"&gt;pkg.go.dev/widgets/split&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Split arranges panes along one axis.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Split" data-slug="split"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Split&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;3&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 11 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#9aa4b8"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; modules &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────────────╮&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; packages &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────╮&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt;module size &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; input &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; buffer 8.2 …&lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; layout &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; geometry 3.1 …&lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt; render &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;› headless 11.4…&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; term &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; layout 6.7 …&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; render 14.9…&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/b…&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual 5.0 …&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/b…&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/d…&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/f…&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰─────────────────────╯&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰──────────────╯&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 11 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#9aa4b8"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; modules &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────────────────────────────────────╮&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; packages &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────────────────────╮&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt;module size state &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; input &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; buffer 8.2 kB stable &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; layout &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; geometry 3.1 kB stable &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt; render &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;› headless 11.4 kB beta &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; term &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; layout 6.7 kB stable &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; render 14.9 kB beta &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/basic &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual 5.0 kB alpha &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/block &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/data &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/form &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰─────────────────────────────────────────────╯&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰──────────────────────────────╯&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 11 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#9aa4b8"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; modules &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────────────────────────────────────────────────────────────╮&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╭&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt; packages &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;────────────────────────────────────╮&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt;module size state &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; input &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; buffer 8.2 kB stable &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; layout &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700;text-decoration:underline"&gt; geometry 3.1 kB stable &lt;/span&gt;&lt;span style="font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700;text-decoration:underline"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700;text-decoration:underline"&gt;│&lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt; render &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;› headless 11.4 kB beta &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; term &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; layout 6.7 kB stable &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; render 14.9 kB beta &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/basic &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; virtual 5.0 kB alpha &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/block &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;█&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/data &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&lt;span style="color:#e8ecf4;font-weight:700"&gt; widgets/form &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;│&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰─────────────────────────────────────────────────────────────────────╯&lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt;╰──────────────────────────────────────────────╯&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Split — A container that divides its rectangle among focusable panes.&#10;# package: widgets/split&#10;# constructor: split.New(d layout.Direction, panes ...termmosaic.Widget) *split.Split&#10;# 120 columns x 11 rows, rendered through widgettest.Capture&#10;&#10;╭ modules ────────────────────────────────────────────────────────────╮ ╭ packages ────────────────────────────────────╮&#10;│ module size state │ │ input │&#10;│ buffer 8.2 kB stable │ │ layout │&#10;│ geometry 3.1 kB stable │ │&amp;gt; render █│&#10;│› headless 11.4 kB beta │ │ term █│&#10;│ layout 6.7 kB stable │ │ virtual █│&#10;│ render 14.9 kB beta │ │ widgets/basic █│&#10;│ virtual 5.0 kB alpha │ │ widgets/block █│&#10;│ │ │ widgets/data │&#10;│ │ │ widgets/form │&#10;╰─────────────────────────────────────────────────────────────────────╯ ╰──────────────────────────────────────────────╯&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>TextInput</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/textinput/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/textinput/</guid><description>&lt;p&gt;A single-line editable field with a cursor, a selection and undo.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;TextInput is a single-line editable text field: a caret, an optional selection, word motions, undo, and bracketed paste.&lt;/p&gt;&#10;&lt;p&gt;It is the reference implementation of the whole form set, because ADR 0005 §4 was written about it. Three properties are load-bearing and each is pinned by a test:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;EventPaste is ONE undoable operation. A 10,000-character paste is one step on the undo stack, so one Ctrl-Z removes the whole of it.&lt;/li&gt;&#10;&lt;li&gt;Draw allocates nothing in steady state. The visible runs are rebuilt only when the text, the caret, the styles or the rect change, which is ADR 0007 §3&amp;rsquo;s rect-keyed adaptation applied to a per-keystroke value.&lt;/li&gt;&#10;&lt;li&gt;Draw is total for every rect, including 0×0 and 1×1, and below its MinSize it clips rather than blanking.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="TextInput" data-slug="textinput"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;TextInput&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;1&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;githu&lt;/span&gt;&lt;span style="background-color:#e8ecf4;text-decoration:underline"&gt;b.com/serkanalgur/termmosaic&lt;/span&gt;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;githu&lt;/span&gt;&lt;span style="background-color:#e8ecf4;text-decoration:underline"&gt;b.com/serkanalgur/termmosaic&lt;/span&gt;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;githu&lt;/span&gt;&lt;span style="background-color:#e8ecf4;text-decoration:underline"&gt;b.com/serkanalgur/termmosaic&lt;/span&gt;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&#10;&lt;span style="text-decoration:underline"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# TextInput — A single-line editable field with a cursor, a selection and undo.&#10;# package: widgets/form&#10;# constructor: form.NewTextInput(r buffer.Rect) *form.TextInput&#10;# 120 columns x 3 rows, rendered through widgettest.Capture&#10;&#10;github.com/serkanalgur/termmosaic&#10;&#10;&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>TextArea</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/textarea/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/textarea/</guid><description>&lt;p&gt;A multi-line editable field with wrapping, selection and undo.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;TextArea is a multi-line editable text region that wraps rather than scrolls horizontally.&lt;/p&gt;&#10;&lt;p&gt;The wrapping is buffer&amp;rsquo;s, not this widget&amp;rsquo;s: the content is handed to buffer.Wrap and the resulting Wrapped is cached against the rect it was built for. Wrap allocates twice over, so calling it in Draw would add an allocation to every frame — the failure ADR 0008 §4 exists to prevent. The first Draw after a width change wraps; every Draw after that reads the cache.&lt;/p&gt;</description></item><item><title>Select</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/select/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/select/</guid><description>&lt;p&gt;A single-choice control that expands into a scrollable list.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Select is a closed list of options with one highlighted, scrollable when the options do not all fit.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Select" data-slug="select"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Select&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;1&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 9 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#e8ecf4"&gt; alpine&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; bookworm&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; cachyos&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; debian&lt;/span&gt;&#10;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;&amp;gt; endeavouros&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; fedora&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; gentoo&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; nixos&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; void&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 9 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#e8ecf4"&gt; alpine&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; bookworm&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; cachyos&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; debian&lt;/span&gt;&#10;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;&amp;gt; endeavouros&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; fedora&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; gentoo&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; nixos&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; void&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 9 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#e8ecf4"&gt; alpine&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; bookworm&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; cachyos&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; debian&lt;/span&gt;&#10;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;&amp;gt; endeavouros&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; fedora&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; gentoo&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; nixos&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8ecf4;font-weight:700"&gt; void&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Select — A single-choice control that expands into a scrollable list.&#10;# package: widgets/form&#10;# constructor: form.NewSelect(r buffer.Rect, labels []string) *form.Select&#10;# 120 columns x 9 rows, rendered through widgettest.Capture&#10;&#10; alpine&#10; bookworm&#10; cachyos&#10; debian&#10;&amp;gt; endeavouros&#10; fedora&#10; gentoo&#10; nixos&#10; void&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>Checkbox</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/checkbox/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/checkbox/</guid><description>&lt;p&gt;A tri-state box: unchecked, checked, or indeterminate.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Checkbox is a toggleable box with an optional label, in one of three states.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Checkbox" data-slug="checkbox"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Checkbox&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;1&amp;nbsp;&amp;times;&amp;nbsp;5&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 5 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#8cd98a"&gt;[x] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;widgets (22)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8c56e"&gt;[-] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;visualisation (5)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#9aa4b8"&gt;[ ] release (0)&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 5 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#8cd98a"&gt;[x] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;widgets (22)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8c56e"&gt;[-] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;visualisation (5)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#9aa4b8"&gt;[ ] release (0)&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 5 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#8cd98a"&gt;[x] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;widgets (22)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#e8c56e"&gt;[-] &lt;/span&gt;&lt;span style="color:#e8ecf4"&gt;visualisation (5)&lt;/span&gt;&#10;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style="color:#9aa4b8"&gt;[ ] release (0)&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Checkbox — A tri-state box: unchecked, checked, or indeterminate.&#10;# package: widgets/form&#10;# constructor: form.NewCheckbox(r buffer.Rect, label string) *form.Checkbox&#10;# 120 columns x 5 rows, rendered through widgettest.Capture&#10;&#10;[x] widgets (22)&#10;&#10;[-] visualisation (5)&#10;&#10;[ ] release (0)&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>Radio</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/radio/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/radio/</guid><description>&lt;p&gt;A single-choice group of labels, navigated with the arrow keys.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Radio is a one-of-N group of options: exactly one is chosen, and the choice is visible without colour.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Radio" data-slug="radio"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Radio&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;6&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 6 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#e8ecf4"&gt; ( ) horizontal&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; ( ) vertical&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;(o) both&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 6 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#e8ecf4"&gt; ( ) horizontal&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; ( ) vertical&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;(o) both&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 6 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#e8ecf4"&gt; ( ) horizontal&lt;/span&gt;&#10;&lt;span style="color:#e8ecf4"&gt; ( ) vertical&lt;/span&gt;&#10;&lt;span style="color:#9aa4b8;font-weight:700"&gt;&amp;gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;(o) both&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Radio — A single-choice group of labels, navigated with the arrow keys.&#10;# package: widgets/form&#10;# constructor: form.NewRadio(r buffer.Rect, labels []string) *form.Radio&#10;# 120 columns x 6 rows, rendered through widgettest.Capture&#10;&#10; ( ) horizontal&#10; ( ) vertical&#10;&amp;gt; (o) both&#10;&#10;&#10;&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>Backend strategy</title><link>https://serkanalgur.github.io/termmosaic.github.io/adr/0001-backend-strategy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/adr/0001-backend-strategy/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Status:&lt;/strong&gt; Accepted&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2026-10-03&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-04 — recorded the &lt;code&gt;golang.org/x/term&lt;/code&gt; version pin and the&#10;verified &lt;code&gt;CGO_ENABLED=0&lt;/code&gt; cross-compilation status, including the fact that the&#10;Windows backend is a loud stub.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-05 — bumped the pin to &lt;code&gt;x/term&lt;/code&gt; v0.29.0 / &lt;code&gt;x/sys&lt;/code&gt; v0.30.0&#10;and recorded the measured floor boundary; the pin itself is unchanged.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Decides:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/status/"&gt;STATUS.md&lt;/a&gt; — Core architecture / Backend strategy&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Supersedes:&lt;/strong&gt; the &amp;ldquo;Option A / B / C&amp;rdquo; section of the former&#10;ARCHITECTURE.md &amp;ldquo;Decision 1&amp;rdquo;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="context"&gt;Context&lt;/h2&gt;&#10;&lt;p&gt;TermMosaic needs raw-mode control, alternate screen, resize handling, and input&#10;decoding. Three shapes were on the table: wrap a library, own the terminal layer,&#10;or define narrow interfaces and adapt at the edges.&lt;/p&gt;</description></item><item><title>Toggle</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/toggle/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/toggle/</guid><description>&lt;p&gt;A two-state switch with an on and an off rendering.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Toggle is an on/off switch with an optional label.&lt;/p&gt;&#10;&lt;p&gt;It is not a Checkbox with a different marker: a toggle means &amp;ldquo;this is running right now&amp;rdquo; and a checkbox means &amp;ldquo;include this in the operation&amp;rdquo;, and users read them differently. The difference is spelled in the marker — the words &amp;ldquo;on&amp;rdquo; and &amp;ldquo;off&amp;rdquo; — because a bare &amp;ldquo;[x]&amp;rdquo; would be ambiguous between the two.&lt;/p&gt;</description></item><item><title>Cell buffer representation</title><link>https://serkanalgur.github.io/termmosaic.github.io/adr/0002-buffer-representation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/adr/0002-buffer-representation/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Status:&lt;/strong&gt; Accepted&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2026-10-03&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-04 — the byte-compare soundness condition was stated&#10;incompletely (it named padding but not contiguity), and the byte-count figure&#10;was an artifact of a single-byte-glyph benchmark scene.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-04 — risk item 1b below asked whether to make &lt;code&gt;RowBytes&lt;/code&gt;&#10;refuse non-top-level buffers structurally, and deferred the question to v1.0.&#10;&lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0006-subbuffer-cell-access/"&gt;ADR 0006&lt;/a&gt; settles it now: &lt;code&gt;RowBytes&lt;/code&gt; becomes a&#10;&lt;code&gt;*Buffer&lt;/code&gt; method that panics on a sub-buffer.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Decides:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/status/"&gt;STATUS.md&lt;/a&gt; — Core architecture / Cell buffer representation&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Depends on:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0001-backend-strategy/"&gt;ADR 0001&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Supersedes:&lt;/strong&gt; the &amp;ldquo;Option AoS / SoA&amp;rdquo; section of the former ARCHITECTURE.md&#10;&amp;ldquo;Decision 2&amp;rdquo;, &lt;strong&gt;including its stated leaning toward SoA.&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="context"&gt;Context&lt;/h2&gt;&#10;&lt;p&gt;The cell buffer is the single most performance-critical structure in the&#10;framework. Everything in the widget catalog — a 100k-row virtualized table, a&#10;live sparkline, a full-screen pager — reads and writes it every frame.&lt;/p&gt;</description></item><item><title>Install</title><link>https://serkanalgur.github.io/termmosaic.github.io/getting-started/install/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/getting-started/install/</guid><description>&lt;h1 id="install"&gt;Install&lt;/h1&gt;&#10;&lt;h2 id="requirements"&gt;Requirements&lt;/h2&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;1.23 or newer&lt;/strong&gt; — matches current stable&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;cgo&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Not used.&lt;/strong&gt; &lt;code&gt;CGO_ENABLED=0&lt;/code&gt; builds are verified in CI for &lt;code&gt;linux/amd64&lt;/code&gt;, &lt;code&gt;linux/arm64&lt;/code&gt;, &lt;code&gt;darwin/amd64&lt;/code&gt;, &lt;code&gt;darwin/arm64&lt;/code&gt;, &lt;code&gt;windows/amd64&lt;/code&gt;, &lt;code&gt;windows/arm64&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Dependencies&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;golang.org/x/sys&lt;/code&gt; and &lt;code&gt;golang.org/x/term&lt;/code&gt;. That is all of them.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Terminal library&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;None.&lt;/strong&gt; TermMosaic wraps no &lt;code&gt;tcell&lt;/code&gt;, no Bubble Tea, no Textual. It owns the terminal layer through two small interfaces — see &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0001-backend-strategy/"&gt;ADR 0001&lt;/a&gt;.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Platforms that work&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;strong&gt;Linux and macOS.&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2 id="get-it"&gt;Get it&lt;/h2&gt;&#10;&lt;p&gt;TermMosaic v1.0.0 is tagged and released, so pin the version:&lt;/p&gt;</description></item><item><title>Tabs</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/tabs/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/tabs/</guid><description>&lt;p&gt;A horizontal strip of labels, one of which is the active pane.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Tabs is a single row of tab labels with one selected, scrollable when the tabs do not all fit.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Tabs" data-slug="tabs"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Tabs&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;1&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 4 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style="color:#9aa4b8"&gt; Logs &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;[Metrics]&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Traces Config &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 4 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style="color:#9aa4b8"&gt; Logs &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;[Metrics]&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Traces Config &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 4 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style="color:#9aa4b8"&gt; Logs &lt;/span&gt;&lt;span style="color:#7fb0ff;font-weight:700"&gt;[Metrics]&lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Traces Config &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Tabs — A horizontal strip of labels, one of which is the active pane.&#10;# package: widgets/form&#10;# constructor: form.NewTabs(r buffer.Rect, labels []string) *form.Tabs&#10;# 120 columns x 4 rows, rendered through widgettest.Capture&#10;&#10; Logs [Metrics] Traces Config&#10;&#10;&#10;&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>Button</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/button/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/button/</guid><description>&lt;p&gt;A labelled, activatable control with a default and a disabled state.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;Button is a focusable label that activates on Enter, Space or a click.&lt;/p&gt;&#10;&lt;h2 id="rendered-output"&gt;Rendered output&lt;/h2&gt;&#10;&lt;figure class="capture" data-widget="Button" data-slug="button"&gt;&#10; &lt;figcaption class="capture-cap"&gt;&#10; &lt;strong&gt;Button&lt;/strong&gt; rendered by &lt;code&gt;cmd/capture&lt;/code&gt; through&#10; &lt;code&gt;widgettest.Capture&lt;/code&gt;: colour at 3 widths&#10; (40, 80, 120 columns), and the exact plain-text cell grid at&#10; the widest of them.&#10; &lt;/figcaption&gt;&#10;&#10; &#10; &lt;p class="minsize"&gt;&#10; &lt;code&gt;MinSize()&lt;/code&gt; returns &lt;strong&gt;3&amp;nbsp;&amp;times;&amp;nbsp;1&lt;/strong&gt; cells.&#10; That is the whole widget &lt;em&gt;including&lt;/em&gt; its own chrome, and it is the&#10; widget's assertion about itself — below it, &lt;code&gt;Draw&lt;/code&gt; clips rather&#10; than blanks, and what to do about that is the application's decision.&#10; &lt;/p&gt;&#10; &#10;&#10; &#10; &lt;div class="tm-widths"&gt;&#10;&lt;div class="tm-width" data-cols="40"&gt;&#10;&lt;p class="tm-cap"&gt;40 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="40"&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;[Render]&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Save &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="80"&gt;&#10;&lt;p class="tm-cap"&gt;80 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="80"&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;[Render]&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Save &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div class="tm-width" data-cols="120"&gt;&#10;&lt;p class="tm-cap"&gt;120 columns &amp;times; 3 rows&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="cells" data-cols="120"&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c"&gt; &lt;/span&gt;&#10;&lt;span style=""&gt; &lt;/span&gt;&lt;span style="color:#0e1118;background-color:#7fb0ff;font-weight:700"&gt;[Render]&lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="color:#9aa4b8;font-weight:700"&gt; Save &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&#10;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;span style="font-weight:700"&gt; &lt;/span&gt;&lt;span style="background-color:#1c212c;font-weight:700"&gt; &lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;p class="tm-plain-head"&gt;Plain text &amp;mdash; 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.&lt;/p&gt;&#10;&lt;pre class="tm-capture" data-form="text"&gt;# Button — A labelled, activatable control with a default and a disabled state.&#10;# package: widgets/form&#10;# constructor: form.NewButton(r buffer.Rect, label string) *form.Button&#10;# 120 columns x 3 rows, rendered through widgettest.Capture&#10;&#10;&#10; [Render] Save&#10;&#10;&lt;/pre&gt;&#10;&#10; &lt;div class="capture-truth"&gt;&#10; &lt;p&gt;&lt;strong&gt;What you are looking at.&lt;/strong&gt; This is the cell grid the renderer&#10; produced, in a web page. It is not a screenshot of a terminal, and it cannot show&#10; interaction, resize or animation — a capture is one settled frame after N frames of&#10; settling. Braille and Block Elements can take a different advance width in your&#10; browser's font than in a terminal, so if a gauge or a sparkline above looks wrong,&#10; the plain-text form below it is the exact output and the colour one is the decoration.&#10; The colour frames are at 40, 80, 120 columns; the plain-text&#10; frame is at 120.&#10; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/#captures-are-cell-grids-not-terminal-screenshots"&gt;More on this&lt;/a&gt;.&lt;/p&gt;&#10; &lt;/div&gt;&#10;&lt;/figure&gt;</description></item><item><title>Quickstart</title><link>https://serkanalgur.github.io/termmosaic.github.io/getting-started/quickstart/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/getting-started/quickstart/</guid><description>&lt;h1 id="quickstart"&gt;Quickstart&lt;/h1&gt;&#10;&lt;p&gt;Here is the smallest complete TermMosaic program. It opens the terminal, draws a&#10;bordered panel with a frame counter and the negotiated colour depth, survives a&#10;resize, and exits on &lt;code&gt;q&lt;/code&gt;, Escape or Ctrl-C.&lt;/p&gt;&#10;&lt;p&gt;It is also, near enough, &lt;code&gt;examples/hello&lt;/code&gt; — so if a line here does not match what&#10;you see in the repository, the repository is the source of truth:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;go run github.com/serkanalgur/termmosaic/examples/hello@v1.0.0&#10;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="the-program"&gt;The program&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;sync&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/buffer&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/input&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/layout&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/render&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/term&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/serkanalgur/termmosaic/widgets/block&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;blockW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;blockH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello:&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// Restoring the terminal is not optional on any exit path: a program that&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// leaves a terminal in raw mode has broken the user&amp;#39;s shell.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;caps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Capabilities&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewSink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;Height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;Caps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;caps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;NoColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NoColorFromEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// This program has no text input, so a cursor blinking in the last cell drawn&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// would look like a bug. It is managed-but-hidden.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCursor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cursor&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Visible&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;newPanel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rootBounds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;caps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ColourDepth&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterRawMode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnterAltScreen&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LeaveRawMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// Both the input loop and the heartbeat below may want to stop the program,&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// and closing a channel twice panics, so the close goes through sync.Once.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quitOnce&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Once&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quitOnce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// The input Source is built AFTER raw mode: the kitty keyboard query it sends&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// is answered on the input stream and is meaningless without raw mode.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;sink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;term&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewSink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;withProbe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DefaultConfig&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sink&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// The panel shows a counter that changes when a frame is drawn, so it needs a&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// heartbeat to stay alive. A real application is invalidated by whatever it is&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// displaying, and should not have this goroutine at all.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;stopBeat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewTicker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;stopBeat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvalidateAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// Keys and resizes arrive on ONE ordered channel, so a resize can never be&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// delivered between the bytes of a half-read escape sequence.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the terminal reached EOF&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Kind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EventKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;isQuitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EventResize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// ADR 0007 §5&amp;#39;s order, with nothing between the two steps:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// recompute the root&amp;#39;s rectangle, then resize the renderer.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// Renderer.Resize never draws, so the whole interval is&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// available to recompute bounds, and Resize already forces a&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="c1"&gt;// full repaint.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;W&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;H&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;rootBounds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;pacer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewPacer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;frameErr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;frameErr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pacer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;frameErr&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stopBeat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LeaveAltScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LeaveRawMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// withProbe wires the input Source&amp;#39;s enable sequences and kitty query to the same&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// sink the renderer writes frames through, so the two cannot interleave badly.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;withProbe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sink&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sink&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteProbe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sink&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sink&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cfg&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// isQuitKey reports whether ev should end the program. These are keys a person&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// reaches for, expressed in the decoder&amp;#39;s vocabulary rather than as raw bytes:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Ctrl-C arrives as Ctrl+&amp;#39;c&amp;#39; rather than as 0x03, and Escape arrives as KeyEscape&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// only after the decoder has waited out its ambiguity delay.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;isQuitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KeyEscape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rune&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;q&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rune&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;Q&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Rune&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Mod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;termmosaic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ModCtrl&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="the-widget"&gt;The widget&lt;/h2&gt;&#10;&lt;p&gt;The four-method &lt;code&gt;termmosaic.Widget&lt;/code&gt; interface is the whole contract. Here is a&#10;complete widget — a &lt;code&gt;Block&lt;/code&gt; for the chrome and a body that changes each frame.&lt;/p&gt;</description></item><item><title>Renderer mode</title><link>https://serkanalgur.github.io/termmosaic.github.io/adr/0003-renderer-mode/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/adr/0003-renderer-mode/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Status:&lt;/strong&gt; Accepted&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2026-10-03&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-04 — &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0007-responsive-screens/"&gt;ADR 0007&lt;/a&gt; considered&#10;three ways to make &lt;code&gt;Widget&lt;/code&gt; express adaptive content and &lt;strong&gt;changed none of the&#10;four methods&lt;/strong&gt;; the amendment tightens the &lt;code&gt;Bounds()&lt;/code&gt;/&lt;code&gt;Draw&lt;/code&gt; ordering contract&#10;and adds one sibling optional interface (&lt;code&gt;Minimizable&lt;/code&gt;) beside &lt;code&gt;Focusable&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Decides:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/status/"&gt;STATUS.md&lt;/a&gt; — Core architecture / Renderer mode&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Depends on:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0001-backend-strategy/"&gt;ADR 0001&lt;/a&gt;,&#10;&lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0002-buffer-representation/"&gt;ADR 0002&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Supersedes:&lt;/strong&gt; the &amp;ldquo;immediate / retained / hybrid&amp;rdquo; section of the former&#10;ARCHITECTURE.md &amp;ldquo;Decision 3&amp;rdquo;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="context"&gt;Context&lt;/h2&gt;&#10;&lt;p&gt;The framework must pick how a frame gets described:&lt;/p&gt;</description></item><item><title>KeyHint</title><link>https://serkanalgur.github.io/termmosaic.github.io/widgets/keyhint/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/widgets/keyhint/</guid><description>&lt;p&gt;A one-line bar of key names and their meanings.&lt;/p&gt;&#10;&lt;p&gt;Package &lt;code&gt;widgets/form&lt;/code&gt;. API reference: &lt;a href="https://pkg.go.dev/github.com/serkanalgur/termmosaic/widgets/form"&gt;pkg.go.dev/widgets/form&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;KeyHint renders the keys available right now: the discoverability half of the form catalog.&lt;/p&gt;&#10;&lt;p&gt;It is a widget rather than a string helper because a hint is the one piece of a form that changes whenever the state changes — a Select with no options has nothing to activate, so its hint goes away — and because it must obey the same repaint and clipping rules as everything else. Drawing it by hand at each call site is how a form ends up with three different hint styles.&lt;/p&gt;</description></item><item><title>Layout engine</title><link>https://serkanalgur.github.io/termmosaic.github.io/adr/0004-layout-engine/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/adr/0004-layout-engine/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Status:&lt;/strong&gt; Accepted&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Date:&lt;/strong&gt; 2026-10-03&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Amended:&lt;/strong&gt; 2026-10-04 — the &amp;ldquo;&lt;code&gt;Fill&lt;/code&gt; is order-sensitive&amp;rdquo; sharp edge was&#10;false for this implementation; order-insensitivity is now documented as a&#10;deliberate, tested guarantee that diverges from tmux.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Decides:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/status/"&gt;STATUS.md&lt;/a&gt; — Core architecture / Layout engine&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Depends on:&lt;/strong&gt; &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/adr/0003-renderer-mode/"&gt;ADR 0003&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Supersedes:&lt;/strong&gt; the &amp;ldquo;constraint / flexbox&amp;rdquo; section of the former&#10;ARCHITECTURE.md &amp;ldquo;Decision 4&amp;rdquo;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="context"&gt;Context&lt;/h2&gt;&#10;&lt;p&gt;Terminal layouts are small, fixed, and mostly rectangular: a header, a&#10;sidebar, a main pane, a status bar. Two models compete:&lt;/p&gt;</description></item><item><title>Your first app</title><link>https://serkanalgur.github.io/termmosaic.github.io/getting-started/your-first-app/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://serkanalgur.github.io/termmosaic.github.io/getting-started/your-first-app/</guid><description>&lt;h1 id="your-first-app"&gt;Your first app&lt;/h1&gt;&#10;&lt;p&gt;The &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/getting-started/quickstart/"&gt;quickstart&lt;/a&gt; gave you a panel and a loop. This&#10;page adds the two things a real application needs and the quickstart deliberately&#10;omits: &lt;strong&gt;a widget that takes keys&lt;/strong&gt;, and &lt;strong&gt;a layout with more than one thing in&#10;it&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;Everything here is written against v1.0.0, the first release that makes a&#10;stability promise. The &lt;a href="https://serkanalgur.github.io/termmosaic.github.io/limitations/"&gt;limitations&lt;/a&gt; page applies in full.&lt;/p&gt;&#10;&lt;h2 id="the-shape-of-a-termmosaic-program"&gt;The shape of a TermMosaic program&lt;/h2&gt;&#10;&lt;p&gt;There is no framework object, no &lt;code&gt;App.Run()&lt;/code&gt; and no message algebra. Five pieces,&#10;each owned by you:&lt;/p&gt;</description></item></channel></rss>