Documentation
¶
Overview ¶
Package decker is a terminal slide-deck engine: a talk is a Go program, and every slide is a function that draws each frame onto a pixel canvas.
A Deck holds a Theme and a list of slides. Each Slide has a View, a function that draws one frame from a Ctx onto a Scene, and Main gives the deck its command line: present, presenter view, dev reload, a review of every build for clipped or unreadable content, snapshots, contact sheets, handouts, PDF and video. The presenter can open a deck window in Ghostty on macOS with its own terminal font size; Ghostty and kitty also support full-resolution previews.
A minimal talk loads its fonts once and draws from the frame's context:
func main() {
theme := &decker.Theme{
Background: decker.Hex("#101820"),
Text: decker.Hex("#F0F0F0"),
Display: decker.StockFont("SpaceGrotesk-Bold"),
Body: decker.StockFont("SpaceGrotesk-Medium"),
Mono: decker.StockFont("JetBrainsMono-ExtraBold"),
}
decker.Main(decker.Deck{Name: "hello", Theme: theme, Slides: []decker.Slide{{
Title: "Hello",
View: func(c decker.Ctx, sc *decker.Scene) {
decker.Text{Font: c.Theme.Display, Size: c.Size(0.15), Color: c.Theme.Text}.
Draw(sc.Px, "Hello", c.X(0.08), c.Y(0.2))
},
}}})
}
Import github.com/austinlparker/decker from a separate main package. See the hello example for a complete program with animation and build steps, the guide for slide authoring, and the CLI reference for flags and exports. This checkout requires Go 1.27.0 or later and uses Unix signals and process replacement. Video export additionally requires ffmpeg with libx264.
Pixel canvas ¶
A slide paints into Pixels, a true-color framebuffer shown with half-block characters, so each terminal cell is two pixels tall and a 240x67 terminal is a 240x134 display. Sizes are fractions of the screen (Ctx.X, Ctx.Y, Ctx.Size), so a slide looks the same at any terminal size.
Frame purity ¶
A frame depends only on its Ctx: no clocks, no math/rand. Any moment can then be replayed, snapshotted, rendered to video and checked against reference images. Use Hash01 for repeatable noise and Ctx.T, Ctx.Step and Ctx.StepT for time.
Main types ¶
- Deck, Slide: the talk with its speaker notes in Markdown, and one slide with its steps, Source citations and Transition.
- Publisher, Session, Thread, Delivery, Post, Media: posting the talk as a thread as it's given, from the post blocks in its notes: a Publisher checks posts and signs in, its Session opens a talk's posts, and the Thread posts them.
- Ctx: what changes between frames (T, Step, StepT), the slide's position (Index, Count, Section), plus layout helpers.
- Rect: a box on the canvas; layout cuts and splits rects (Rect.CutTop, Rect.Cols, Rect.Grid).
- Scale: data values mapped onto pixels, with round ticks from NiceScale, for axes a slide draws itself.
- Theme: colors, typefaces, chart series colors and an optional overlay the engine uses. Display, Body and Mono fonts are required.
- Scene, Pixels: what a View draws on (the engine makes the scene and draws the theme's overlay on it), and its pixel canvas. Scene also has a native character layer; that layer is omitted from video exports. Scene.Place hands the engine a keyed element to draw instead, which TransitionMorph can move from one slide to the next.
- Text, Font: smooth antialiased type, wrapped and fitted to a box (Text.Fit) and measured before drawing (Text.Measure).
- Rich, Span: the same type with mixed fonts, colors and decorations inside a line (ParseSpans reads a light markup).
- Block, FigletFont: FIGlet block letters scaled to fill a box (FitBlock); choose bundled faces with StockFigletFont and StockFigletFontNames, or supply fonts with LoadFigletFont and ParseFigletFont. Smooth type also accepts consumer fonts through LoadFont and ParseFont.
- GlyphEffect, BlockEffect: per-letter and per-cell animations, combined with Chain and BlockChain.
- Table, TableReveal: a grid of text fitted to a Rect at one size, built up by row or column over steps.
- Composite: a group drawn on a layer and faded, moved, scaled and clipped as one; FadeIn, FlyIn, Pop, WipeOut, Shake and the rest are its animations, built into a frame by AppearAt.
- Transition, Direction: how a slide enters (push, cover, uncover, wipe, split, fade, fade-through, dissolve, iris, zoom, pixelate, glitch, morph, none), for how long (Transition.Over) and from which side (Transition.From).
- Connector: a line, elbow or curve joining two [Rect]s, with arrowheads that sit on the edges and a Connector.Prog that draws it on.
- Issue: a problem Deck.Review finds in a build: Code lines clipped, Table rows dropped, text off the canvas or too small to read. Stock components report what they can't fit; a slide's own drawing reports through Ctx.Fits. The review command prints them.
Shapes beyond the basics (Pixels.Polygon, Pixels.Ellipse, Pixels.Polyline, Pixels.Bezier, Pixels.DashedLine) are in shapes.go. Stock components (Panel, Arrow, CycleDiagram, BulletList, PageNumber, ProgressBar, Timeline, Process, Table, and Code with its SyntaxColors, LineRange focus, CodeOverflow modes and Code.Measure) and easing helpers (Ease, CubicBezier, Spring) are in draw.go, diagram.go, table.go, code.go and anim.go. Charts (BarChart, LineChart, DonutChart, Sparkline) and the counting Stat are in chart.go; their series colors are Theme.Series. The guide covers the command line, keys and presenter view; the README starts with a runnable talk, and the authoring guide covers writing one, by hand or with an agent.
Index ¶
- Constants
- Variables
- func Arrow(p *Pixels, x0, y0, x1, y1, width float64, col RGB, prog float64)
- func BulletList(c Ctx, p *Pixels, lines []string, x, y, w, h float64, firstStep int)
- func Chip(c Ctx, p *Pixels, s string, x, y float64, fg, bg RGB, alpha float64) float64
- func ChipHeight(c Ctx) float64
- func Clamp01(p float64) float64
- func Coverage(d float64) float64
- func CubicBezier(x1, y1, x2, y2 float64) func(float64) float64
- func Ease(t, dur float64) float64
- func EaseInCubic(p float64) float64
- func EaseInOutCubic(p float64) float64
- func EaseInOutExpo(p float64) float64
- func EaseInOutQuad(p float64) float64
- func EaseInQuad(p float64) float64
- func EaseOutBack(p float64) float64
- func EaseOutBounce(p float64) float64
- func EaseOutCubic(p float64) float64
- func EaseOutElastic(p float64) float64
- func EaseOutExpo(p float64) float64
- func EaseOutQuad(p float64) float64
- func Hash01(x, y, seed int) float64
- func IllustrativeTag(c Ctx, p *Pixels, x, y float64)
- func Label(c Ctx, p *Pixels, s string, x, y float64, col RGB, align Align) (float64, float64)
- func Lerp(a, b, p float64) float64
- func LerpInt(a, b int, p float64) int
- func LineLabel(c Ctx, p *Pixels, f *Font, s string, cx, cy float64, col RGB, alpha float64)
- func Main(d Deck)
- func PageNumber(c Ctx, p *Pixels, x, y float64, align Align, col RGB) (float64, float64)
- func Panel(c Ctx, p *Pixels, x, y, w, h float64, label string, fill, edge, text RGB, ...)
- func PlaceholderBox(c Ctx, p *Pixels, x, y, w, h float64, what string)
- func Progress(t, start, dur float64) float64
- func ProgressBar(c Ctx, p *Pixels, r Rect, fill, track RGB)
- func Pulse(t, period float64) float64
- func ShineBand(t, dur, strength float64) func(float64) float64
- func Sparkline(c Ctx, p *Pixels, r Rect, values []float64, col RGB, prog float64)
- func SpeechBubble(p *Pixels, x, y, w, h, tailX, tailY float64, fill, edge RGB, alpha float64)
- func Spring(from, to, t, freq, damping float64) float64
- func StockFigletFontNames() []string
- type Align
- type ArrowHead
- type BarChart
- type Block
- type BlockCell
- type BlockEffect
- func BlockBeam(t, dur float64) BlockEffect
- func BlockChain(fxs ...BlockEffect) BlockEffect
- func BlockDecrypt(t, dur float64, noise RGB) BlockEffect
- func BlockFade(t, dur float64) BlockEffect
- func BlockGlitch(t, amount float64) BlockEffect
- func BlockRain(t float64) BlockEffect
- func BlockSlide(t float64, width int) BlockEffect
- func BlockType(t, cps float64) BlockEffect
- type BlockFX
- type Code
- type CodeLayout
- type CodeOverflow
- type Composite
- func AppearAt(c Ctx, enter, exit int, in, out func(t float64) Composite) Composite
- func Combine(fxs ...Composite) Composite
- func Dim(t, dur, level float64) Composite
- func FadeIn(t, dur float64) Composite
- func FadeOut(t, dur float64) Composite
- func FlyIn(c Ctx, t, dur float64, from Direction, dist float64) Composite
- func FlyOut(c Ctx, t, dur float64, to Direction, dist float64) Composite
- func Grow(t, dur, peak float64) Composite
- func Identity() Composite
- func Pop(t, dur float64) Composite
- func Shake(t, dur, amp float64) Composite
- func WipeIn(t, dur float64, from Direction) Composite
- func WipeOut(t, dur float64, to Direction) Composite
- func ZoomIn(t, dur, from float64) Composite
- func ZoomOut(t, dur, to float64) Composite
- type Connector
- type Ctx
- func (c Ctx) Fits(what string, r Rect, w, h float64) bool
- func (c Ctx) Frame() Rect
- func (c Ctx) PH() float64
- func (c Ctx) PW() float64
- func (c Ctx) Reached(step int) bool
- func (c Ctx) Rect(fx, fy, fw, fh float64) Rect
- func (c Ctx) Since(step int) float64
- func (c Ctx) Size(f float64) int
- func (c Ctx) SmallText(f *Font) int
- func (c Ctx) Unit(f float64) float64
- func (c Ctx) X(f float64) float64
- func (c Ctx) Y(f float64) float64
- type CycleDiagram
- type Deck
- func (d *Deck) Canvas(i int, c Ctx) *Pixels
- func (d *Deck) Check() error
- func (d *Deck) Draw(i int, c Ctx) error
- func (d *Deck) Posts(dir string) ([]Post, error)
- func (d *Deck) Render(i int, c Ctx) string
- func (d *Deck) Review() []Issue
- func (d *Deck) Section(i int) string
- func (d *Deck) Steps(i int) int
- type Delivery
- type Direction
- type DonutChart
- type FigletFont
- type Font
- type GlyphEffect
- func Chain(fxs ...GlyphEffect) GlyphEffect
- func Decode(t, dur float64, n int) GlyphEffect
- func DropIn(t, stagger float64, size int) GlyphEffect
- func FadeUp(t, dur float64, size int) GlyphEffect
- func Jitter(t, amp float64) GlyphEffect
- func RiseIn(t, stagger float64, size int) GlyphEffect
- func TypeOn(t, cps float64) GlyphEffect
- func Wave(t, amp float64) GlyphEffect
- type GlyphFX
- type Images
- type Issue
- type LineChart
- type LineRange
- type Media
- type PixelArt
- type Pixels
- func (p *Pixels) Add(x, y int, c RGB, a float64)
- func (p *Pixels) Arc(cx, cy, r, thick, a0, a1 float64, c RGB, alpha float64)
- func (p *Pixels) Art(a PixelArt, x, y, scale, alpha float64, flip bool)
- func (p *Pixels) At(x, y int) RGB
- func (p *Pixels) Bezier(x0, y0, cx0, cy0, cx1, cy1, x1, y1, width float64, c RGB, a float64, ...)
- func (p *Pixels) Blend(x, y int, c RGB, a float64)
- func (p *Pixels) Box(x0, y0, x1, y1 float64) (int, int, int, int)
- func (p *Pixels) DashedLine(xa, ya, xb, yb, width, dash, gap float64, c RGB, a float64)
- func (p *Pixels) Disc(cx, cy, r float64, c RGB, a float64)
- func (p *Pixels) Ellipse(cx, cy, rx, ry, stroke float64, c RGB, a float64)
- func (p *Pixels) Fill(c RGB)
- func (p *Pixels) Glow(cx, cy, r float64, c RGB, a float64)
- func (p *Pixels) Line(xa, ya, xb, yb, width float64, c RGB, a float64)
- func (p *Pixels) LinearGradient(x, y, w, h, radius, gx0, gy0, gx1, gy1 float64, from, to RGB, a float64)
- func (p *Pixels) Polygon(pts []float64, c RGB, a float64)
- func (p *Pixels) Polyline(pts []float64, width float64, c RGB, a float64)
- func (p *Pixels) RadialGradient(x, y, w, h, radius, gx, gy, gr float64, inner, outer RGB, a float64)
- func (p *Pixels) Rect(x, y, w, h float64, c RGB, a float64)
- func (p *Pixels) RoundRect(x, y, w, h, radius, stroke float64, c RGB, a float64)
- func (p *Pixels) Set(x, y int, c RGB)
- func (p *Pixels) VGradient(y0, y1 int, top, bottom RGB)
- type Post
- type Process
- type Publisher
- type RGB
- type Rect
- func (r Rect) Anchor(w, h, ax, ay float64) Rect
- func (r Rect) Bottom() float64
- func (r Rect) Center() (x, y float64)
- func (r Rect) Cols(gap float64, weights ...float64) []Rect
- func (r Rect) CutBottom(h float64) (bottom, rest Rect)
- func (r Rect) CutLeft(w float64) (left, rest Rect)
- func (r Rect) CutRight(w float64) (right, rest Rect)
- func (r Rect) CutTop(h float64) (top, rest Rect)
- func (r Rect) Grid(cols, rows int, gap float64) []Rect
- func (r Rect) Inset(dx, dy float64) Rect
- func (r Rect) Right() float64
- func (r Rect) Rows(gap float64, weights ...float64) []Rect
- func (r Rect) Sub(fx, fy, fw, fh float64) Rect
- type Rich
- type Route
- type Scale
- type Scene
- func (s *Scene) Cell(x, y int, ch string, st uv.Style)
- func (s *Scene) Fill(x, y, w, h int, bg color.Color)
- func (s *Scene) Overlay(x, y int, block string)
- func (s *Scene) Place(key string, r Rect, draw func(p *Pixels, r Rect))
- func (s *Scene) Put(x, y int, block string)
- func (s *Scene) PutCenter(dx, dy int, block string)
- func (s *Scene) Release()
- func (s *Scene) Render() string
- func (s *Scene) Sprite(x, y int, sp Sprite)
- func (s *Scene) Text(x, y int, text string, fg color.Color, attrs ...uint8)
- type Session
- type Severity
- type Side
- type Slide
- type Source
- type Span
- type Sprite
- type Stat
- type SyntaxColors
- type Table
- type TableReveal
- type Text
- type Theme
- type Thread
- type Timeline
- type TimelineItem
- type Transition
- type Trim
Examples ¶
Constants ¶
const DefaultLeading = 1.1
DefaultLeading is the line height, as a multiple of size, used when Leading is 0.
const MinText = 0.068
MinText is the smallest text size, as a canvas-height fraction, readable at projector resolutions.
const MorphDuration = 0.8
MorphDuration is how long TransitionMorph takes by default, in seconds: moving things need longer to read than a cut between frames.
const Settled = 1000.0
Settled is a time past every entrance animation; slides entered backwards or past a step use it to appear fully built.
const TransitionDuration = 0.45
TransitionDuration is how long a transition takes by default, in seconds; TransitionMorph takes MorphDuration.
Variables ¶
var ( // BlockShadow is Spleen 6x12 with a baked-in shaded shadow. BlockShadow = stockFig("Spleen 6x12 Shadow") // BlockSolid is Spleen 6x12, solid pixel lettering for headings. BlockSolid = stockFig("Spleen 6x12") // BlockSmall is Spleen 5x8, compact pixel lettering. BlockSmall = stockFig("Spleen 5x8") // BlockHuge is Spleen 8x16, larger pixel lettering. BlockHuge = stockFig("Spleen 8x16") // BlockFancy is Spleen 12x24, more detailed pixel lettering. BlockFancy = stockFig("Spleen 12x24") )
The default block fonts use Spleen under BSD-2-Clause; see fonts/figlet.
var ( TransitionDefault = Transition{} // DefaultTransition, but Over still sets the time TransitionNone = Transition{/* contains filtered or unexported fields */} // hard cut TransitionPush = Transition{/* contains filtered or unexported fields */} // new slide pushes the old one sideways TransitionDissolve = Transition{/* contains filtered or unexported fields */} // cells flip from old to new at random TransitionWipe = Transition{/* contains filtered or unexported fields */} // a bright edge sweeps across // TransitionMorph moves elements placed with the same key (Scene.Place) // to their new rects, and cross-fades the rest. It takes MorphDuration. TransitionMorph = Transition{/* contains filtered or unexported fields */} TransitionFade = Transition{/* contains filtered or unexported fields */} // cross-fade; characters switch half-way TransitionFadeThrough = Transition{/* contains filtered or unexported fields */} // old fades to the background, then new fades in TransitionCover = Transition{/* contains filtered or unexported fields */} // new slide slides in over the old one, which stays put TransitionUncover = Transition{/* contains filtered or unexported fields */} // old slide slides away off the new one, which stays put TransitionSplit = Transition{/* contains filtered or unexported fields */} // old slide opens like barn doors from the center TransitionIris = Transition{/* contains filtered or unexported fields */} // a circle of the new slide grows from the center TransitionZoom = Transition{/* contains filtered or unexported fields */} // old zooms in and fades out, new grows into place TransitionPixelate = Transition{/* contains filtered or unexported fields */} // old breaks into big blocks, new resolves from them TransitionGlitch = Transition{/* contains filtered or unexported fields */} // noisy slices jump sideways, split in color, and flip to new )
The transitions. A slide's Transition is one of these, optionally with Over.
var DefaultTransition = TransitionPush
DefaultTransition applies to slides that don't set Transition.
Functions ¶
func Arrow ¶
Arrow strokes a line with an arrowhead at (x1, y1), revealed up to fraction prog (0..1).
func BulletList ¶
BulletList draws lines as bullets, line i revealed at step i+firstStep, at one size that fits the box.
func ChipHeight ¶
ChipHeight is the height of a Chip; use it to lay out rows of chips.
func CubicBezier ¶
CubicBezier returns the easing of CSS's cubic-bezier(x1, y1, x2, y2): a curve from (0,0) to (1,1) through two control points, with x1 and x2 in 0..1. y may leave 0..1 to overshoot. CubicBezier(0.25, 0.1, 0.25, 1) is CSS's "ease". Build it once and keep the func: the returned function does no allocation.
func EaseInCubic ¶
EaseInCubic accelerates from rest, the mirror of EaseOutCubic: for exits.
func EaseInOutCubic ¶
EaseInOutCubic accelerates then decelerates; transitions use it.
func EaseInOutExpo ¶
EaseInOutExpo is slow at both ends with a fast middle.
func EaseInOutQuad ¶
EaseInOutQuad accelerates then decelerates, more gently than EaseInOutCubic; p is clamped to 0..1.
func EaseInQuad ¶
EaseInQuad accelerates from rest; p is clamped to 0..1.
func EaseOutBack ¶
EaseOutBack overshoots slightly before settling, for "pop" entrances.
func EaseOutBounce ¶
EaseOutBounce lands on 1 and bounces back up a few times, like a dropped ball.
func EaseOutCubic ¶
EaseOutCubic decelerates; p is clamped to 0..1.
func EaseOutElastic ¶
EaseOutElastic overshoots and rings like a spring before it settles on 1.
func EaseOutExpo ¶
EaseOutExpo decelerates sharply: most of the travel happens at the start.
func EaseOutQuad ¶
EaseOutQuad decelerates, more gently than EaseOutCubic; p is clamped to 0..1.
func Hash01 ¶
Hash01 is a deterministic pseudo-random number in [0,1) for a cell. Use it instead of math/rand so every frame replays exactly.
func IllustrativeTag ¶
IllustrativeTag labels a chart with made-up data to replace before the talk; (x, y) is its top-right corner.
func LineLabel ¶
LineLabel draws small text on a background plate centered on (cx, cy), so it reads over a line.
func Main ¶
func Main(d Deck)
Main runs a deck from the command line: live in the terminal by default, or the command given (present, list, review, handout, snapshot, sheet, pdf, video). It exits on a bad command line or a failed command; `--help` lists them all.
func PageNumber ¶
PageNumber draws the slide's position, like "12 / 40", in small body text at (x, y) and returns its size. It draws nothing when c.Count is zero, so an overlay can use it on a Ctx the engine didn't position. Meant for Theme.Overlay.
func Panel ¶
Panel draws a rounded box with a centered, auto-fitted label. A zero edge draws no outline; alpha fades the whole panel, label included.
Panel is also the pattern for components: take (c Ctx, p *Pixels, ...) in pixel coordinates, size from c.Unit and c.SmallText, take colors and fonts from c.Theme, reveal with c.Reached and c.Since, and return the size drawn if callers lay out around it. Option-heavy components are structs with a Draw method.
func PlaceholderBox ¶
PlaceholderBox is a dashed, labeled frame marking where real material still needs to go.
func ProgressBar ¶
ProgressBar fills a share of the track r equal to the slides shown so far, (c.Index+1)/c.Count, so the last slide is full. It counts slides, not build steps: Ctx doesn't carry the other slides' step counts. With c.Count zero only the track is drawn. Meant for Theme.Overlay.
func ShineBand ¶
ShineBand returns a Text.Shine func: a bright band sweeping left to right once over dur seconds from t=0.
func Sparkline ¶
Sparkline draws values as a tiny line chart with no axes inside r, scaled to fit them, in col. prog (0..1) is how much of the line to draw, left to right, so Ease(c.Since(step), 0.8) animates it; a dot marks the end of what is drawn. NaN values break the line, and a constant series is a flat line.
func SpeechBubble ¶
SpeechBubble draws a rounded bubble with a tail toward (tailX, tailY).
func Spring ¶
Spring returns the position at time t of a Harmonica spring that starts at from and is pulled toward to. freq sets speed (try 2-8); damping < 1 bounces, 1 is critically damped. The result depends only on t, which counts in whole 1/60 s steps; it stops at settling or after 10 seconds.
func StockFigletFontNames ¶
func StockFigletFontNames() []string
StockFigletFontNames returns the bundled FIGlet font names in alphabetical order, without .flf suffixes. The returned slice belongs to the caller.
Example ¶
package main
import (
"fmt"
"github.com/austinlparker/decker"
)
func main() {
for _, name := range decker.StockFigletFontNames() {
fmt.Println(name)
}
}
Output: Decker Geometric Decker Sign Decker Slab Decker Square Decker Stencil Spleen 12x24 Spleen 5x8 Spleen 6x12 Spleen 6x12 Shadow Spleen 8x16
Types ¶
type BarChart ¶
type BarChart struct {
Labels []string // one per category
Values []float64 // one series; ignored if Series is set
Series [][]float64 // grouped bars: one slice of values per series
Names []string // series names for the legend, shown for two or more series
Max float64 // the axis top; 0 picks one that rounds up from the data
Horizontal bool // bars run left to right, with labels down the left side
ShowValues bool // write each value at the end of its bar
Step int // the build step it grows in on
Stagger float64 // seconds between bars starting; 0 is 0.08, negative is none
Format func(float64) string
}
BarChart is a bar chart that grows from its baseline: bars rise (or extend, if Horizontal) one after another, then value labels appear on their ends. Set Values for one series, or Series for grouped bars; Names then label a legend.
The value axis has a few gridlines at round numbers. Negative values hang below a zero line, and NaN or infinite values leave a gap. Category labels are wrapped, then shrunk, to fit their slot.
type Block ¶
type Block struct {
Font *FigletFont
Scale float64 // pixel width of one font cell, at least 0.5; it is twice as tall
Color RGB // solid parts (█ ▀ ▄ ▌ ▐ ░ …)
To *RGB // if set, solid parts get a left-to-right gradient Color → To
Shadow RGB // everything else (box-drawing edges); zero = Color dimmed toward the canvas background
Drop RGB // if set, a drop shadow of the solid parts, offset down-right
Align Align
Gap int // blank font rows between lines
// Glow draws a soft light behind the solid parts.
Glow float64
FX BlockEffect
}
Block draws text in a block font onto the pixel canvas, scaled to the screen: each font cell becomes a Scale×(2·Scale) pixel box, so block letters are as big on stage at 682 columns as at 240. FitBlock picks a font and scale.
func (Block) Cells ¶
Cells returns the block's size in font cells for s: what BlockCell.W and BlockCell.H will be, and the width effects like BlockSlide travel.
type BlockCell ¶
type BlockCell struct {
Char int // index of the source character (across all lines)
Col, Row int // position within the whole block, in font cells
W, H int // block size in font cells
U float64 // Col / (W-1): 0 at the left edge, 1 at the right
Rune rune // the font's character for this cell
Solid bool // a filled block character, as opposed to a box-drawing edge
Line, Line0 int // which line, and the Char index where it starts
}
BlockCell describes one non-blank cell of rendered block text, for effects.
type BlockEffect ¶
BlockEffect animates the cells of a Block (Block.FX); Draw calls it for each non-blank cell. It follows GlyphEffect's contract: a pure function of t (seconds since start) and the cell, where the zero BlockFX hides the cell and BlockFX{Alpha: 1} leaves it alone. Combine with BlockChain.
func BlockBeam ¶
func BlockBeam(t, dur float64) BlockEffect
BlockBeam sweeps a bright band across once in dur seconds; layer it on settled text.
func BlockChain ¶
func BlockChain(fxs ...BlockEffect) BlockEffect
BlockChain runs effects together: offsets add, alpha multiplies, the last rune or color set wins, brightness takes the max.
func BlockDecrypt ¶
func BlockDecrypt(t, dur float64, noise RGB) BlockEffect
BlockDecrypt flickers cells through shade characters in the noise color (faint reads best), then locks them in with a bright flash, left to right over dur.
func BlockFade ¶
func BlockFade(t, dur float64) BlockEffect
BlockFade fades the whole block in over dur seconds.
func BlockGlitch ¶
func BlockGlitch(t, amount float64) BlockEffect
BlockGlitch jumps rows sideways and flickers cells; amount is 0..1.
func BlockRain ¶
func BlockRain(t float64) BlockEffect
BlockRain drops each column in from above with a bounce, staggered left to right.
func BlockSlide ¶
func BlockSlide(t float64, width int) BlockEffect
BlockSlide glides alternate rows in from opposite sides; width is the block's width in cells (Block.Cells).
func BlockType ¶
func BlockType(t, cps float64) BlockEffect
BlockType shows characters one at a time at cps characters per second.
type BlockFX ¶
type BlockFX struct {
DX, DY float64 // offset in font cells (fractions allowed)
Alpha float64 // 0 hides the cell, 1 is fully visible; Draw skips cells at 0.02 or below
Rune rune // 0 keeps the real character
Bright float64 // 0..1 pushes the color toward white
Color *RGB // replaces the color entirely
}
BlockFX is an effect's instruction for one cell of block text.
type Code ¶
type Code struct {
Source string
Lang string // a chroma language name, alias or file extension; unknown or empty draws plain text
LineNumbers bool
Title string // a filename tab above the code
// Focus has one range per step, starting at FirstStep: at step
// FirstStep+i the lines in Focus[i] are drawn at full strength and the rest
// dimmed behind a highlight bar that glides from the previous range. A step
// past the last range keeps the last; an empty range (the zero LineRange)
// returns every line to normal. Before FirstStep, or with no Focus, every
// line is normal.
Focus []LineRange
FirstStep int
// Diff reads Source as a unified diff: the first character of each line is
// its marker. "+" and "-" lines get the added and removed backgrounds and
// keep their marker in a gutter, " " marks context, and any other first
// character is part of a context line. What follows the marker is lexed as
// Lang.
Diff bool
// Size is the Mono size in pixels; 0 picks the largest that fits, but never
// below c.SmallText(Mono) unless Overflow is CodeShrink.
Size int
// Overflow is what the block does with source that doesn't fit its rect
// at the smallest readable size: clip it (the default), shrink below
// that size, or scroll to follow Focus. Code.Measure says beforehand
// whether it fits.
Overflow CodeOverflow
// Excerpt shows only these lines of Source, numbered and focused as in
// the whole source, so a long file can be shown a part at a time with
// its real line numbers. The zero LineRange shows every line.
Excerpt LineRange
}
Code draws source code on a rounded plate with syntax highlighting, and can pick out a few lines at each build step.
Code{Source: src, Lang: "go", Title: "main.go", LineNumbers: true,
Focus: []LineRange{{1, 3}, {5, 9}}, FirstStep: 1}.Draw(c, p, c.Rect(0.05, 0.2, 0.6, 0.7))
The source is lexed once per (Source, Lang) and cached. Code assumes the theme's Mono font is monospaced.
type CodeLayout ¶ added in v0.6.0
type CodeLayout struct {
Size int // the Mono size in pixels: Code.Size, or the size fitted to the rect
W, H float64 // the plate, which is never larger than the rect
// NeedW and NeedH are the plate that would show every line and column
// at Size.
NeedW, NeedH float64
// Head is the plate's height above the first line: padding, plus the
// filename tab when there is a Title.
Head float64
Lines, Shown int // lines in the source (or Excerpt); lines in view
Cols, ShownCols int // columns of the widest line, gutter included; columns drawn
}
CodeLayout is how a Code block fits a rect: the size its text is set at, the plate it draws and how much of the source shows. Code.Measure returns it without drawing, so a slide can pick a bigger rect, a smaller excerpt or a split across builds before anything is lost.
func (CodeLayout) Fits ¶ added in v0.6.0
func (l CodeLayout) Fits() bool
Fits reports whether every line and column of the source shows.
type CodeOverflow ¶ added in v0.6.0
type CodeOverflow int
CodeOverflow is what a Code block does with source that doesn't fit its rect at the smallest readable size.
const ( // CodeClip sets the code at the smallest readable size and clips what // still doesn't fit; a review reports it as "code-clipped". CodeClip CodeOverflow = iota // CodeShrink keeps shrinking until every line and column fits, below the // readable size if it must; a review reports text that small as // "text-small". CodeShrink // CodeScroll keeps the readable size and shows the lines that fit, // scrolled to keep the current Focus range in view and gliding with its // highlight, so a long file can be walked through over builds. A review // reports a focus range taller than the view, or no Focus at all, as // "code-clipped". CodeScroll )
type Composite ¶
type Composite struct {
Alpha float64 // 0 hides the element, 1 draws it as is
DX, DY float64 // offset in pixels
Scale float64 // size about the pivot; 0 means 1
// PivotX and PivotY place the point Scale grows from, as fractions of
// the bounds' width and height from their center: 0, 0 scales about the
// center and -0.5, -0.5 about the top-left corner.
PivotX, PivotY float64
Trim Trim // the part of the bounds left out, after moving and scaling
}
Composite draws a group of things as one: onto a layer of its own, then back onto the canvas faded, moved, scaled and clipped as a whole. The zero Composite is invisible (Alpha 0); start from Identity and set what you want, or take one from the element animations (FadeIn, FlyIn, ...).
A Composite is a plain value with no pointers, so building one every frame allocates nothing, and effects compose with Composite.Then. Positions are relative to the bounds given to Draw, and Trim follows the element as it moves and scales.
func AppearAt ¶
AppearAt turns "built in at step enter, out at step exit" into the Composite for this frame. in and out make the entrance and exit from the seconds since their step began (the closure sees Ctx), such as
func(t float64) Composite { return FlyIn(c, t, 0.5, DirLeft, 0.1) }
The element is hidden before enter. A nil in shows it at once, and enter < 0 has no entrance; exit < 0 never exits, and a nil out cuts it at exit. Slides entered backwards or past a step see Settled times, so the element is already in or already out.
func Dim ¶
Dim fades an element toward the background, over dur seconds, down to the opacity level (try 0.35), and holds it there. To undim it, stop calling Dim at the step it should return.
func FlyIn ¶
FlyIn slides an element in over dur seconds from dist of the screen away in direction from (DirLeft starts it left of its place; DirDefault below it), fading in over the first half. dist 1 starts it just off the screen.
func FlyOut ¶
FlyOut slides an element away over dur seconds, dist of the screen toward direction to, fading out over the second half.
func Grow ¶
Grow swells an element about its center to peak times its size (try 1.1) and back over dur seconds, to draw the eye. It is Identity outside 0..dur.
func Identity ¶
func Identity() Composite
Identity returns the Composite that changes nothing: it draws straight onto the canvas, with no layer.
func Pop ¶
Pop grows an element from nothing about its center over dur seconds, overshooting its size a little with EaseOutBack before settling.
func Shake ¶
Shake jolts an element by up to amp pixels for dur seconds, dying away, 30 times a second. Offsets are whole pixels, so the element stays sharp. It is Identity outside 0..dur.
func WipeIn ¶
WipeIn reveals an element over dur seconds from the edge in direction from across to the opposite one: DirLeft uncovers it left to right, DirDefault bottom to top. It is a clip, so nothing moves.
func WipeOut ¶
WipeOut hides an element over dur seconds into the edge in direction to, the reverse of WipeIn: DirLeft leaves the left edge showing last.
func ZoomIn ¶
ZoomIn grows an element about its center from the given scale (try 0.6) to 1 over dur seconds, fading in over the first half.
func ZoomOut ¶
ZoomOut shrinks an element about its center from 1 to the given scale (try 0.6) over dur seconds, fading out over the second half.
func (Composite) Clipped ¶
Clipped returns k showing only the part of bounds inside clip, in bounds' own coordinates (before k moves it). It sets Trim, replacing any there.
func (Composite) Draw ¶
Draw calls draw to paint the element, which lives inside bounds (in canvas pixels), and puts the result on p as k says. Like a morphing element, draw may stray up to a tenth of the canvas height outside bounds (a glow, say) and no further; what it draws beyond that is lost.
An identity k calls draw on p itself: no layer, no cost. Fading or trimming alone draws on a pooled copy of the region and mixes it back. Moving or scaling draws the element twice, onto black and onto white, to learn how much of each pixel it covers (the canvas has no alpha), then resamples that: bilinear when moving or growing, averaged over the pixels each one covers when shrinking. So draw must be pure and may run twice, and an element moved off whole pixels is slightly soft. A review sees what draw reports where k shows it, and only once.
The layers are pooled and only the region around bounds is cleared and composited, so a steady-state frame does not allocate. They are canvas sized, because draw paints in canvas coordinates.
type Connector ¶
type Connector struct {
From, To Rect
// FromSide and ToSide force the side the path leaves and arrives at. If
// the sides picked don't face each other, an elbow or a line can run
// through the rects.
FromSide, ToSide Side
Route Route
// Head marks the To end and Tail the From end.
Head, Tail ArrowHead
Width float64 // stroke width; 0 uses a width that scales with the canvas
Color RGB // zero uses the theme's Muted
Dashed bool
Label string // on a plate at the path's midpoint
// Prog is how much of the path is drawn, 0..1, by length from the From end;
// the label fades in at the end. 0 draws nothing, so a connector that is
// always there wants 1. Animate it with Ease(c.Since(step), dur).
Prog float64
}
Connector joins one Rect to another with a line, an elbow or a curve, optionally capped with arrowheads and labeled. It leaves From and arrives at To, at the middle of the sides that face each other; set FromSide or ToSide to pick a side instead. The arrowhead's tip sits exactly on the target's edge.
Connector{From: a, To: b, Route: RouteElbow, Head: HeadArrow, Prog: Ease(c.Since(1), 0.6)}.Draw(c, p)
type Ctx ¶
type Ctx struct {
W, H int // drawable area in cells
T float64 // seconds since this slide appeared
Step int // current build step, 0-based
StepT float64 // seconds since the current step began
// Index is this slide's 0-based position in the deck and Count the number
// of slides, so an overlay can draw "12 / 40" or a progress bar. Section
// is the slide's resolved Slide.Section: its own, or the nearest one
// before it, empty before the first. All three are zero in a Ctx built by
// hand and not passed through the engine (Deck.Render and Deck.Draw fill
// them in from the slide index).
Index, Count int
Section string
// Theme is the deck's theme; never nil inside View.
Theme *Theme
// contains filtered or unexported fields
}
Ctx is everything a slide needs to draw a frame. Its layout methods take fractions of the pixel canvas (W wide, 2H tall), so a slide looks the same at any size: c.X(0.5) is the center, c.Size(0.1) a font a tenth of the screen tall.
func (Ctx) Fits ¶ added in v0.6.0
Fits reports whether a w×h block fits in r, give or take half a pixel. When it doesn't and the frame is under review, it records an "overflow" error naming what, with both sizes: custom drawing reports what it can't fit the way stock components do.
Call it on the layout a slide draws, not on one it only tries: a slide that falls back to a smaller layout compares sizes itself, then checks the one it keeps.
lay := layoutWaterfall(spans, r)
if lay.W > r.W || lay.H > r.H {
lay = layoutWaterfall(spans[:8], r) // the tail, rather than clipping
}
c.Fits("waterfall", r, lay.W, lay.H)
func (Ctx) Rect ¶
Rect returns the box at (fx, fy) of size fw×fh, all fractions of the canvas like X and Y.
func (Ctx) Since ¶
Since returns seconds since step began: negative before it, Settled after it. Animate a step's element with Ease(Since(2), 0.5).
func (Ctx) Unit ¶
Unit scales a stroke, gap or radius with the canvas: f of its height. Same as Y; use it when the number isn't a position.
type CycleDiagram ¶
type CycleDiagram struct {
Labels []string
Lap float64 // seconds per loop; must be > 0
Step0 int // step at which the first station appears
Ring RGB // the ring's track; zero uses the theme's Faint
}
CycleDiagram is a ring of numbered stations with a legend, one station per step. Once the ring closes, a comet circles it and lights each station as it passes.
func (CycleDiagram) Draw ¶
func (d CycleDiagram) Draw(c Ctx, p *Pixels, top float64) (looping bool, theta float64, active int, legendX float64)
Draw renders the diagram below y=top. It returns whether the comet is circling, its angle (0 = top, clockwise), the active station (-1 if none), and the legend's x.
type Deck ¶
type Deck struct {
// Name identifies the deck on this machine: it names the presenter socket
// and the binary --dev rebuilds into, and the command line's help shows
// it as the program's name. Keep it short.
Name string
// Theme is required, and so are its Display, Body and Mono fonts.
Theme *Theme
// Slides in running order. Must not be empty.
Slides []Slide
// Notes are the speaker notes, in Markdown, for the presenter view, the
// n key and the handout. Each "## " heading starts the next slide's
// section and is that slide's Title as written, so the file reads as the
// talk's outline and a slide added or moved without its notes fails
// the deck's check rather than shifting every note after it. Text
// before the first heading is about the talk as a whole. Sections may
// stop before the last slide; the slides after have no notes. Keep
// them in a file beside the talk and embed it:
//
// //go:embed notes.md
// var notes string
//
// A fenced block whose info string is "post" is a post for a live
// thread (Publisher), left out of the notes the speaker sees:
// media=final (the default) attaches the slide's last build,
// media=builds an image of each build (builds=2-4,6 picks them),
// media=clip a looping video of it building, and media=none nothing.
// An "alt" block right after a post describes its media. Posts before
// the first section open the thread, and attach nothing.
Notes string
// Publisher posts the talk as a thread while it's given, once the
// presenter view's posting dialog (P) starts it: a slide's posts go
// out when the speaker moves on from it. Nil leaves the dialog only
// its rehearsal.
Publisher Publisher
}
Deck is a talk: its slides in running order, its theme, and a name. Pass it to Main from the talk's main function.
func (*Deck) Canvas ¶ added in v0.7.0
Canvas renders slide i's pixels as Render does, without the character layer or turning them into cells: what video and post images show, for tests (decktest.Golden). Like Render it sets c's position from i. The Pixels are the caller's.
func (*Deck) Check ¶ added in v0.7.0
Check reports what makes d unfit to run, as Main refuses it: a missing Name, Theme or theme font, no slides, or Notes whose sections don't follow the slides' titles in order.
func (*Deck) Draw ¶
Draw renders slide i into cells without encoding them: the live deck's per-frame work, for tests and benchmarks. Like Render it sets c's position from i, and a panic shows in the frame as its error. Draw also returns that panic, as an error naming the slide, the part that panicked ("View", "a placed element" or "Theme.Overlay") and the panic value, which it wraps if it is an error; it returns nil when nothing panicked.
func (*Deck) Posts ¶ added in v0.7.0
Posts are every post the deck's notes make, in order, with their media rendered into dir as the presenter view's posting dialog renders it. Clips need ffmpeg. decktest.Posts checks them before the talk.
func (*Deck) Render ¶
Render draws slide i (0-based) as a styled string of exactly c.W×c.H cells, as the snapshot command prints it. A nil c.Theme uses the deck's, and c.Index, c.Count and c.Section are set from i and the deck; a panic renders as its error.
func (*Deck) Review ¶ added in v0.6.0
Review renders every build of every slide, settled, at 240×67, 320×90 and 682×171 cells, and returns what is wrong with them, in slide, build and size order. Stock components report what they cannot fit (a Code block's hidden lines, a Table's dropped rows), text reports running off the canvas, being too small to read or running into other text, a panic is an issue rather than a crash, and a slide's own drawing reports through Ctx.Fits. Codes a slide lists in Slide.Allow are left out. The frames are the ones the deck shows: Review only listens while they are drawn.
type Delivery ¶ added in v0.7.0
type Delivery struct {
// Root and Parent are the refs of the thread's first post and of the
// post this replies to; both empty for the first.
Root, Parent string
// Key names the post: the same on every try of it, after a restart
// too, and no other post's, in this thread or another. First is when
// it was first tried. The thread file keeps both before that try goes
// out, so a Thread can derive what it sends from them, as bsky derives
// a post's record key, and find the post again on a retry.
Key string
First time.Time
// Retry is set when an earlier try of the post may have gone out: its
// answer never came, or the presenter view stopped before recording it.
Retry bool
}
Delivery is where a post goes in its thread, and which post it is.
type Direction ¶
type Direction int
Direction is a side of the screen or of an element: where an element or a transition's new slide comes from, which edge a wipe starts at, the axis a split opens along. DirUp is the top edge and DirDown the bottom.
type DonutChart ¶
type DonutChart struct {
Labels []string
Values []float64
Thickness float64 // the ring's width as a fraction of its radius, 0 is 0.32
Center string // big text in the hole
Step int // the build step it sweeps in on
}
DonutChart is a ring split into segments by value, sweeping in clockwise from 12 o'clock, with a legend beside it giving each label and its share. Negative, NaN and infinite values count as zero. Segments are drawn with round ends and a small gap, so they read as separate even when thin.
type FigletFont ¶
type FigletFont struct {
Name string // display name; file loaders use the file name without .flf
// Height is the row count the font file declares. Rendered lines trim
// blank padding rows, so use Rows for the height of drawn text.
Height int
// contains filtered or unexported fields
}
FigletFont is a parsed FIGlet (.flf) font, classic terminal-character type drawn by Block. Stock fonts' files and provenance are in fonts/figlet.
func FitBlock ¶
func FitBlock(s string, maxW, maxH float64, maxLines, gap int, fonts ...*FigletFont) (*FigletFont, []string, float64)
FitBlock picks a font and scale at which s, wrapped to at most maxLines lines with gap blank rows between them, is as big as possible in a maxW×maxH pixel box. Fonts missing a character of s are skipped. Fonts are in order of preference: a later one only wins if its letters come out 15%+ taller, and a font that fits always beats one that doesn't. Scales snap to half pixels (whole from 4 up) for nearly crisp edges, and go no smaller than 0.5: when nothing fits even then, FitBlock returns the wrap that overflows least.
func LoadFigletFont ¶
func LoadFigletFont(fsys fs.FS, path string) *FigletFont
LoadFigletFont loads a FIGlet (.flf) font from fsys, named after its file. Fonts of block (█ ▀ ▄ ░) and box-drawing (═ ║ ╗) characters draw best. It panics if the font is missing or broken. fsys may be an embed.FS or an os.DirFS. Load once, outside frame functions. For bytes and error handling, use ParseFigletFont.
Example ¶
package main
import (
"embed"
"fmt"
"github.com/austinlparker/decker"
)
//go:embed fonts/figlet/Decker*.flf
var exampleFigletFonts embed.FS
func main() {
font := decker.LoadFigletFont(exampleFigletFonts, "fonts/figlet/Decker Square.flf")
fmt.Println(font.Name, font.Has("Custom fonts!"))
}
Output: Decker Square true
func ParseFigletFont ¶
func ParseFigletFont(name string, data []byte) (*FigletFont, error)
ParseFigletFont parses a FIGlet (.flf) font from data, using name for FigletFont.Name. It returns an error for missing or malformed ASCII glyph data. Only ASCII input glyphs are loaded; selected Unicode blocks, shades and box-drawing strokes are painted by Block. ASCII-art strokes such as / and _ are not.
Example ¶
package main
import (
"embed"
"fmt"
"github.com/austinlparker/decker"
)
//go:embed fonts/figlet/Decker*.flf
var exampleFigletFonts embed.FS
func main() {
data, err := exampleFigletFonts.ReadFile("fonts/figlet/Decker Slab.flf")
if err != nil {
panic(err)
}
font, err := decker.ParseFigletFont("My heading font", data)
if err != nil {
panic(err)
}
fmt.Println(font.Name, font.Has("Hello, Go!"))
}
Output: My heading font true
func StockFigletFont ¶
func StockFigletFont(name string) *FigletFont
StockFigletFont loads a bundled FIGlet font by name, without the .flf suffix. StockFigletFontNames lists the available names. Load each font once, outside frame functions, and pass it to Block.Font or FitBlock. It panics for an unknown name. Bundled fonts retain BSD or OFL terms; see fonts/figlet.
Example ¶
package main
import (
"fmt"
"github.com/austinlparker/decker"
)
func main() {
font := decker.StockFigletFont("Decker Sign")
fmt.Println(font.Name, font.Has("Hello, Go!"))
}
Output: Decker Sign true
func (*FigletFont) DropQuotes ¶
func (f *FigletFont) DropQuotes(s string) string
DropQuotes removes quote marks the font has no glyph for, which beats falling back to a smaller font. FitBlock does this itself; call it before wrapping or measuring a string FitBlock fitted.
func (*FigletFont) Has ¶
func (f *FigletFont) Has(s string) bool
Has reports whether the font has a visible glyph for each non-space rune of s.
func (*FigletFont) Rows ¶
func (f *FigletFont) Rows() int
Rows returns the height in cells of one rendered line, measured on a sample with ascenders, descenders and capitals so it is the same for every line.
func (*FigletFont) Width ¶
func (f *FigletFont) Width(s string) int
Width returns the width in cells of s rendered on one line.
type Font ¶
type Font struct {
// Small, if set, replaces this font below SmallBelow pixels: medium weights
// get spindly at low resolution, so point it at a bolder cut.
Small *Font
SmallBelow int
// contains filtered or unexported fields
}
Font draws raster type at any pixel size, caching rasterized glyphs per size. The pixel layer is twice as tall as the terminal in cells.
func LoadFont ¶
LoadFont loads a TrueType or OpenType font from fsys. It panics if the font is missing or broken: fonts are built in, so that is a deck bug.
func StockFont ¶
StockFont loads a bundled typeface (SIL OFL; see fonts/): "SpaceGrotesk-Bold", "SpaceGrotesk-Medium" or "JetBrainsMono-ExtraBold". Load each once: a Font caches glyphs.
func (*Font) Ink ¶
Ink returns how far s's glyphs reach above (top, negative) and below (bottom, positive) the baseline at size, ignoring spaces. Both are 0 if s has no visible glyphs.
type GlyphEffect ¶
GlyphEffect animates the glyphs of a Text (Text.FX); i counts glyphs across all lines, spaces and line breaks included.
Constructors take t, the seconds since the effect starts. Effects must be pure functions of t and i (no clock, no math/rand; use Hash01) so frames replay exactly. The zero GlyphFX hides the glyph: return it before the effect reaches i, and GlyphFX{Alpha: 1} for glyphs left alone.
func Chain ¶
func Chain(fxs ...GlyphEffect) GlyphEffect
Chain runs effects together: offsets add, alphas multiply, and the last stand-in rune wins.
func Decode ¶
func Decode(t, dur float64, n int) GlyphEffect
Decode cycles letters through random characters before locking them in, left to right over dur seconds; n is the number of glyphs.
func DropIn ¶
func DropIn(t, stagger float64, size int) GlyphEffect
DropIn drops letters from above with a bounce, stagger seconds apart.
func FadeUp ¶
func FadeUp(t, dur float64, size int) GlyphEffect
FadeUp fades the block in over dur seconds while sliding up 0.4×size.
func RiseIn ¶
func RiseIn(t, stagger float64, size int) GlyphEffect
RiseIn springs letters up from below, fading in; size sets how far they travel.
func TypeOn ¶
func TypeOn(t, cps float64) GlyphEffect
TypeOn shows letters one at a time at cps characters per second.
func Wave ¶
func Wave(t, amp float64) GlyphEffect
Wave bobs letters by amp pixels in a travelling wave. It never settles.
type GlyphFX ¶
type GlyphFX struct {
DX, DY float64 // offset in pixels
Alpha float64 // 0 hides the glyph, 1 leaves it untouched
Rune rune // 0 = the real character; ignored for spaces
}
GlyphFX is an effect's instruction for one glyph of Text.
type Images ¶
type Images struct {
// contains filtered or unexported fields
}
Images is a set of raster images (PNG or JPEG), usually embedded in the binary. Each is decoded on first use, and each drawn size is cached.
func (*Images) Draw ¶
func (ims *Images) Draw(p *Pixels, name string, x, y, w, h, alpha float64) (dx, dy, dw, dh float64, ok bool)
Draw paints the image called name into the box (x, y, w, h), aspect kept, centered, at opacity alpha. Source pixels are averaged per canvas pixel and the resampled copy is cached per size. A transparent image lets the canvas show through in proportion to each pixel's own alpha. It returns the drawn rectangle, or ok=false (drawing nothing) if the image is missing.
func (*Images) DrawCover ¶
func (ims *Images) DrawCover(p *Pixels, name string, x, y, w, h, alpha float64) (dx, dy, dw, dh float64, ok bool)
DrawCover paints the image called name so it fills the box (x, y, w, h) completely: the image is scaled until both sides cover the box, keeping its aspect, and the overflow is cropped evenly from both ends. Opacity, caching and transparency work as in Draw. It returns the filled rectangle, which is the box rounded to whole pixels, or ok=false (drawing nothing) if the image is missing.
type Issue ¶ added in v0.6.0
type Issue struct {
Slide, Step int // 0-based, like Ctx.Index and Ctx.Step
Title string // the slide's title
W, H int // the frame's size in cells
Severity Severity
Code string
Rect Rect // where on the canvas, in pixels; zero for the whole frame
Msg string
}
Issue is a problem a review found in one frame: a build of a slide, settled, at one size. Code is a stable name for the kind of problem, such as "code-clipped", "text-small" or "overflow"; Msg says what and by how much, naming the element that has it.
type LineChart ¶
type LineChart struct {
Labels []string // x-axis categories
Series [][]float64 // one slice of values per line
Names []string // series names for the legend
Max float64 // the axis top; 0 fits the data
Min float64 // the axis bottom; 0 fits the data, down to zero if its smallest value is at most half its largest
Step int // the build step it draws on at
Points bool // mark every value with a dot
Format func(float64) string
}
LineChart draws one or more series as lines over shared category labels. The lines draw on from left to right as they ease in; Points marks each value. With more than one series a legend names them, using Names. NaN and infinite values break a line.
type LineRange ¶
type LineRange struct{ From, To int }
LineRange is a span of lines in a Code block, 1-based and inclusive. A range with To < From, such as the zero value, selects nothing.
type Media ¶ added in v0.7.0
type Media struct {
Path string // a PNG, or an MP4 if Video
Video bool // a clip of the slide building, to play muted and looping, like a GIF
Alt string
W, H int // in pixels
}
Media is an image or a video of a slide that a Post attaches, rendered from the slide's pixel canvas as the video command draws it.
type PixelArt ¶
PixelArt is one frame of a pixel-art character: each letter in Rows picks a color from Colors; '.' (or any letter without a color) is transparent. Rows must be ASCII. For cell-based art in the character layer, see Sprite.
type Pixels ¶
type Pixels struct {
W, H int
Pix []RGB
BG RGB // the color the canvas was cleared to
// contains filtered or unexported fields
}
Pixels is a true-color framebuffer. The scene shows it as half blocks: each terminal cell is two stacked pixels, so 240×60 cells is 240×120 pixels. Coordinates are floats, edges are antialiased, and drawing methods blend at opacity a in 0..1.
func (*Pixels) Arc ¶
Arc strokes a ring of radius r around (cx, cy) from angle a0 to a1 (radians, 0 = 12 o'clock, clockwise) with round caps; a0=0, a1=2π is a full ring.
func (*Pixels) Art ¶
Art draws a at (x, y), scaled by scale (fractions are fine) at opacity alpha, mirrored if flip.
func (*Pixels) Bezier ¶
func (p *Pixels) Bezier(x0, y0, cx0, cy0, cx1, cy1, x1, y1, width float64, c RGB, a float64, prog float64)
Bezier strokes the cubic curve from (x0, y0) to (x1, y1) with control points (cx0, cy0) and (cx1, cy1), with round caps. prog (0..1) draws it on from the start to that fraction of its length: arc length, to within the accuracy of the flattened curve, so the pen moves at an even speed.
func (*Pixels) Box ¶
Box returns inclusive pixel bounds covering [x0,x1]×[y0,y1], clipped to the canvas.
func (*Pixels) DashedLine ¶
DashedLine strokes a line of dashes dash long with gap between them, with round caps, starting with a dash at (xa, ya). It is the dashing PlaceholderBox uses, so the two phase identically.
func (*Pixels) Ellipse ¶
Ellipse fills an antialiased ellipse centered on (cx, cy) with radii rx and ry, or only an outline of thickness stroke, drawn inward from the edge, if stroke > 0. With rx == ry it is Disc, or a ring.
func (*Pixels) LinearGradient ¶
func (p *Pixels) LinearGradient(x, y, w, h, radius, gx0, gy0, gx1, gy1 float64, from, to RGB, a float64)
LinearGradient fills the rounded rectangle at (x, y), w by h (radius 0 for square corners), with a color that runs from `from` at (gx0, gy0) to `to` at (gx1, gy1) and is constant beyond them.
func (*Pixels) Polygon ¶
Polygon fills the closed shape through pts, x0, y0, x1, y1 and so on, with antialiased edges. The last point joins back to the first. Concave shapes work, and the fill rule is even-odd: a region is inside when a ray from it crosses an odd number of edges, so where the outline crosses itself (a pentagram) the overlap is a hole. Fewer than three points draw nothing.
func (*Pixels) Polyline ¶
Polyline strokes the path through pts, x0, y0, x1, y1 and so on, with round joins and caps. The whole path is covered once, so at a < 1 the joints show no dark or bright dots where segments overlap. A single point draws a dot.
func (*Pixels) RadialGradient ¶
func (p *Pixels) RadialGradient(x, y, w, h, radius, gx, gy, gr float64, inner, outer RGB, a float64)
RadialGradient fills the rounded rectangle at (x, y), w by h (radius 0 for square corners), with a color that runs from inner at (gx, gy) to outer at distance gr from it and is constant beyond.
type Post ¶ added in v0.7.0
type Post struct {
// Slide is the slide the post is about, from 0; -1 for a post before
// the first slide's section, which opens the thread.
Slide int
Text string
// Media is what the post attaches: images, or one video.
Media []Media
// contains filtered or unexported fields
}
Post is one post of a live thread, from a post block in Deck.Notes.
type Process ¶
Process is a row of chevrons, one per step of a procedure, revealed one at a time: step i appears at step FirstStep+i, sliding in from the left. The newest is filled in Accent and earlier ones are outlined in Muted. Text is fitted inside each shape, all at one size.
type Publisher ¶ added in v0.7.0
type Publisher interface {
// Check holds every post the talk can make to the service's limits,
// without signing in or posting anything: decktest.Posts runs it, and
// so does a rehearsal, to show what posting for real would stop on. It
// may look things up, as bsky resolves @mentions, but keeps nothing for
// later calls.
Check(ctx context.Context, posts []Post) error
// SignIn signs in as account, the one the speaker typed into the
// posting dialog, picking up a session kept from an earlier run if it
// can, and returns the Session that posts as it. When the speaker must
// approve it in a browser, SignIn calls visit with the page's address,
// which the presenter view shows and opens, and waits until they do or
// ctx ends.
SignIn(ctx context.Context, account string, visit func(url string)) (Session, error)
}
Publisher posts a talk as a thread while it is given: when the speaker moves on from a slide, the post blocks in its Notes section go out as replies, in order. The presenter view's posting dialog (P) signs in and starts posting. Deck.Publisher sets one; the bsky package has one for Bluesky.
type RGB ¶
type RGB struct{ R, G, B float32 }
RGB is a color with 0..255 float channels, used for fast blending.
func Hex ¶
Hex parses a CSS-style hex color such as "#FFB000" or "#fb0"; unparseable input is black.
type Rect ¶
type Rect struct{ X, Y, W, H float64 }
Rect is a box on the pixel canvas: X, Y is its top-left corner and W, H its size, all in pixels. Layout is cutting rects out of rects: start from Ctx.Frame or Ctx.Rect, then Inset, Cut, Rows, Cols, Grid or Anchor, and hand the pieces to whatever draws there. Every method returns new rects; widths and heights never go below zero.
head, body := c.Frame().Inset(c.Unit(0.04), c.Unit(0.03)).CutTop(c.Y(0.18)) left, right := body.CutLeft(body.W * 0.4)
func (Rect) Anchor ¶
Anchor returns a w×h box inside r, positioned by ax and ay: 0 against r's left or top edge, 0.5 centered, 1 against its right or bottom edge. A box bigger than r overhangs it by the same rule.
func (Rect) CutRight ¶
CutRight splits r into a strip w wide along its right and the rest beside it.
func (Rect) Grid ¶
Grid splits r into cols×rows equal cells with gap pixels between them, in reading order: the cell at column i, row j is at index j*cols+i.
func (Rect) Inset ¶
Inset shrinks r by dx on the left and right and dy on the top and bottom; negative values grow it.
type Rich ¶
type Rich struct {
Font *Font // required: the base face, and what sets the baseline
Size int // pixels
Color RGB // fill for spans without a Color
Align Align // how x is interpreted
Leading float64 // line height as a multiple of Size (default 1.1)
MaxW float64 // if set, wraps lines to this width
// Glow is a soft glow strength, 0 (none) to ~1.5, in each span's color.
Glow float64
// FX animates glyphs. Indexes count every rune of every span as Text counts
// them: spaces included, plus one per line break.
FX GlyphEffect
}
Rich draws a block of raster type whose spans differ in font, color and decoration; like Text it is a value to fill in and Draw. Sizes below 4 pixels are drawn at 4.
A line breaks at "\n" inside a span and, with MaxW set, wraps at spaces across span boundaries (a word may start in one span and end in another). Every glyph on a line sits on the base font's baseline, so a Mono span shares its line with Body text without stepping up or down.
func (Rich) Baseline ¶
Baseline is the distance from the top of a line to its baseline, as Draw lays it out.
func (Rich) DrawMid ¶
DrawMid draws spans as one line with its ink centered vertically on cy (x as for Draw), as Text.DrawMid does.
func (Rich) Fit ¶
Fit returns r with MaxW set to w and Size set to the largest size, at most r.Size, at which spans wrapped to w fit w×h as Measure measures them, as Text.Fit does for plain text:
r.Fit(spans, w, h).Draw(p, spans, x, y)
Like Text.Fit it only shrinks, and stops at 6px wrapped to w when nothing fits. Results are remembered, so a View can call it every frame; a repeat allocates nothing.
type Scale ¶ added in v0.6.0
type Scale struct {
Min, Max float64 // the data range shown; NiceScale rounds it out to whole steps
Step float64 // the distance between ticks
From, To float64 // the pixel positions of Min and Max; To < From runs upward, for a y axis
}
Scale maps data values onto a span of pixels: the axis of a visual drawn by hand, like a trace waterfall's milliseconds. It draws nothing. At places a value, Ticks lists round values to mark and Label writes them:
ms := NiceScale(0, trace.Dur, 6, plot.X, plot.Right())
for _, v := range ms.Ticks() {
x := ms.At(v)
p.Rect(x, plot.Bottom(), 1, c.Unit(0.01), c.Theme.Faint, 1)
Text{Font: c.Theme.Body, Size: c.SmallText(c.Theme.Body), Color: c.Theme.Muted, Align: Center}.
Draw(p, ms.Label(v)+"ms", x, plot.Bottom()+c.Unit(0.015))
}
Its ticks and labels are the charts' gridlines and axis labels, so a hand-drawn axis agrees with a BarChart beside it. A Scale is a plain value: build one by hand, or adjust what NiceScale returns.
func NiceScale ¶ added in v0.6.0
NiceScale returns a Scale covering lo..hi with about maxTicks ticks at round numbers (1, 2 or 5 times a power of ten), its ends moved out to whole steps, mapped onto the pixels from..to. A range of one value is widened around it. To keep the data's own ends, say a trace that ran 347ms, set Min and Max back afterwards: the ticks stay round.
func (Scale) At ¶ added in v0.6.0
At returns the pixel position of v: From at Min, To at Max, in proportion between and beyond them. A scale with no range puts every value at From.
type Scene ¶
Scene is a fixed-size grid of terminal cells that a slide draws into, layered in drawing order. Off-screen drawing is clipped, so animating in from the edges is safe. Two layers:
- Px, a pixel framebuffer twice as tall as the scene, for big type, shapes, glows and pixel art.
- Character cells on top (Put, PutCenter, Overlay, Text, Cell, Fill, Sprite), for small native-terminal text. A cell replaces the two pixels beneath it; with no background of its own it takes their average color.
func NewScene ¶
NewScene returns an empty w×h-cell scene on the theme's background, for drawing off-screen; a slide draws on the scene View is given.
func (*Scene) Place ¶
Place adds an element to the scene: draw paints it into r after View returns, above View's own drawing, in the order placed. draw should size itself from r and stay inside it, give or take a glow, and must be frame-pure like View.
key names the element across slides. When a slide enters with TransitionMorph, an element whose key the slide before it also placed glides from its old rect to its new one, cross-fading between the old draw and the new; elements on only one side fade out or in. An empty key never matches. Keys should be unique within a slide; repeats pair up in order.
func (*Scene) Put ¶
Put draws a styled, possibly multi-line block at (x, y). Every cell is opaque, so spaces overwrite what was beneath.
func (*Scene) Release ¶
func (s *Scene) Release()
Release returns s to the pool without rendering. Don't use s afterwards or after Render, which releases it.
func (*Scene) Render ¶
Render returns the scene as exactly H lines of W cells, each with an explicit background, and releases it. Use it on scenes made with NewScene, never on the one a slide's View is given; placed elements are drawn first, but Theme.Overlay is not applied.
type Session ¶ added in v0.7.0
type Session interface {
// Account names the account in a way that doesn't change, as a handle
// can: the thread file records it, and a thread posted as one account
// isn't carried on as another.
Account() string
// Open readies posts to go out, as starting to post does: it checks
// them as Publisher.Check does, and what only the account can answer,
// such as whether it may upload that many clips today. The Thread it
// returns posts them, and holds whatever Open worked out for them.
Open(ctx context.Context, posts []Post) (Thread, error)
}
Session is a Publisher signed in to an account.
type Severity ¶ added in v0.6.0
type Severity int
Severity ranks an Issue: how much of what a slide meant to show is missing or worse than intended.
const ( // SeverityWarning is a slide that shows everything, but worse than // intended: text too small to read from the back, two things on top of // each other. SeverityWarning Severity = iota // SeverityError is content lost: lines clipped, rows dropped, text off // the canvas, a panic. SeverityError )
type Slide ¶
type Slide struct {
// Title is shown in the footer, the window title and the list command.
Title string
// Steps is the number of build states: Ctx.Step runs from 0 to Steps-1.
// For Steps: 2, one "next" reveals step 1 and the next advances to the
// following slide. Zero means 1.
Steps int
// Sources are the works this slide cites. The handout lists them under the
// slide, and gathers every source once at the end.
Sources []Source
// Hold is how many seconds each build step stays on screen in a video.
// Zero uses the video command's --hold.
Hold float64
// Transition is how this slide enters, and for how long
// (TransitionWipe.Over(0.6)); zero uses DefaultTransition. The ones that
// move or sweep take a side (TransitionPush.From(DirUp)). Going back to
// it plays it again, backwards: from the opposite side.
Transition Transition
// Section names the chapter this slide belongs to. A slide with no
// Section inherits the nearest one before it, so only the first slide of
// a chapter needs to set it. Ctx.Section is the resolved name, and the list
// command and the presenter view show it.
Section string
// Allow lists review issue codes this slide means to have, which
// Deck.Review then leaves out: "text-offcanvas" for a headline that
// bleeds off the edge on purpose, say.
Allow []string
// HideChrome hides the dev-mode footer on this slide. Theme.Overlay still
// draws, and presenter notes and previews remain available.
HideChrome bool
// View draws one frame onto sc, a Ctx.W x Ctx.H scene already filled
// with the theme's background; after it returns, the engine draws the
// elements it placed (Scene.Place), then Theme.Overlay. View must not
// Render or Release sc. A nil View is a blank
// slide, and a panic is caught and drawn on screen.
View func(c Ctx, sc *Scene)
}
Slide is one slide in the deck. View draws a frame and is called once per frame (--fps) with a fresh Ctx, so anything computed from Ctx.T or Ctx.StepT animates. View must be a pure function of Ctx: no time.Now or math/rand (use Hash01 for noise), so snapshots and golden tests can replay any frame.
type Source ¶ added in v0.6.0
type Source struct {
// Label is what is cited, as a reader should see it: "OpenTelemetry
// Logs Data Model, v1.40".
Label string
// URL is where to find it; optional. The handout links Label to it.
URL string
}
Source is one work a slide cites, in Slide.Sources.
type Span ¶
type Span struct {
Text string
Font *Font // nil inherits Rich.Font
Color *RGB // nil inherits Rich.Color
Underline bool // a rule under the glyphs, in the span's color
Strike bool // a rule through the glyphs, in the span's color
Mark *RGB // a highlighter-pen plate behind the glyphs; also how inline code gets its plate
}
Span is a run of text with its own style inside a Rich block. Its zero style inherits everything from the Rich.
func ParseSpans ¶
ParseSpans turns lightly marked-up text into spans styled from theme t, for Rich. The markup is small on purpose:
*bold* the theme's Display face, since a theme has no bold cut
_muted_ t.Muted
`code` t.Mono on a plate; nothing inside is markup
{accent:word} a color tag: text, muted, faint, accent, accent2, warn,
good, or "#rrggbb" / "#rgb"
{u:word} underline, in the span's color
{s:word} strikethrough
{mark:word} a highlighter pen: Accent plate, Background ink
\* a backslash makes the next marker character literal; the
markers are * _ ` { } and \ itself
Markers toggle wherever they appear, so "*bo*ld" is bold inside a word; write snake\_case with a backslash. Tags nest ({accent:a {u:b}}), and the innermost style wins. Inside code, only \` is an escape. A "{" that does not start a known tag is literal along with the "}" that matches it, so braces nest inside a tag ({accent:map{k}}); a stray "}" is literal too. A marker never closed styles to the end. Text is otherwise kept as written, including "\n".
type Sprite ¶
type Sprite struct {
Art []string
Paint []string
Colors map[rune]color.Color
Default color.Color
Bold bool
}
Sprite is multi-line ASCII art with per-character colors; spaces are transparent. Each character of Paint (optional, same shape as Art) selects a color from Colors for the matching Art character; others use Default. For pixel art, see PixelArt.
bee := Sprite{
Art: []string{`(o)##>`},
Paint: []string{`kkkyyk`},
Colors: map[rune]color.Color{'k': Hex("#222222").Color(), 'y': theme.Accent.Color()},
}
type Stat ¶
type Stat struct {
Value float64
Prefix string // before the number: "$"
Suffix string // after it: "%", " ms"
Decimals int // digits after the point
Label string // what the number is, under it
Step int // the build step it counts up on
Duration float64 // seconds to count; 0 is 1.2
}
Stat is a big number that counts up from zero to Value when its step begins, with a small Muted label under it. The number is drawn in Display and the theme's Accent at the largest size that fits, with every digit in a cell as wide as the widest, and right-aligned in the width of the final value, so nothing shifts while it counts.
type SyntaxColors ¶
type SyntaxColors struct {
Keyword RGB // control flow and declarations: if, func, return
String RGB // string and character literals
Comment RGB // comments
Number RGB // numeric literals and named constants
Name RGB // functions, builtins and decorators
Type RGB // type, class and namespace names
Punct RGB // operators and punctuation
Added RGB // background of a diff's "+" lines
Removed RGB // background of a diff's "-" lines
}
SyntaxColors is the palette Code colors tokens with, set on Theme.Syntax. Any field left zero falls back to the color derived from the theme's own palette, so a theme can override just the roles it cares about.
type Table ¶
type Table struct {
Header []string // optional column titles, in the Display font and the accent color
Rows [][]string // body cells, in the Body font
Weights []float64 // relative column widths; missing entries are 1
Align []Align // per column; missing entries are Left
Zebra bool // tint every other body row
Rules bool // thin lines between body rows
// FirstStep is the step at which the table starts to appear; Reveal says
// how the rest follows.
FirstStep int
Reveal TableReveal
// Highlight is the 1-based body row to emphasize with an accent bar while
// the other rows dim; 0 emphasizes none. It takes effect at once, so to
// animate a highlight over steps use Walk.
Highlight int
// Walk makes the highlight follow the build: step FirstStep+i emphasizes
// row i+1, gliding down from the row before it, and the last row stays
// emphasized once the steps run out. Walk overrides Highlight.
Walk bool
}
Table draws a grid of text: an optional header, rows of cells, columns sized by weight. Every cell is set at one text size, the largest that fits the rect, so the numbers and words on a slide read as one piece.
Rows and cells may be ragged: a missing cell is empty, and the column count is that of the longest row. A cell that cannot fit even at the smallest readable size is ellipsized, never drawn outside its column, and rows that would run past the rect are left out.
type TableReveal ¶
type TableReveal int
TableReveal is how a Table builds up over steps.
const ( // TableRevealAll shows the whole table at Table.FirstStep. TableRevealAll TableReveal = iota // TableRevealRows shows the header, then row i at step FirstStep+i. TableRevealRows // TableRevealCols shows column j, header cell included, at step // FirstStep+j. TableRevealCols )
type Text ¶
type Text struct {
Font *Font // required
Size int // pixels
Color RGB // fill color
To *RGB // if set, a left-to-right gradient from Color to To across the block's width
Align Align // how x is interpreted
Leading float64 // line height as a multiple of Size (default 1.1)
Glow float64 // soft glow strength, 0 (none) to ~1.5
GlowColor *RGB // defaults to Color
// MaxW, if set, wraps lines to this width.
MaxW float64
// Shine returns extra brightness (0..1) at horizontal position u, 0 at the
// block's left edge to 1 at its right; see ShineBand.
Shine func(u float64) float64
FX GlyphEffect
}
Text draws a block of raster type with a Font; sizes below 4 pixels are drawn at 4.
func (Text) Baseline ¶
Baseline is the distance from the top of a line to its baseline, as Draw lays it out.
func (Text) Draw ¶
Draw renders s (which may contain "\n") with its top edge at y and returns the block's size. With FX, glyph indexes count every rune of every line, spaces included, plus one per line break.
func (Text) DrawMid ¶
DrawMid draws one line of s with its ink centered vertically on cy (x as for Draw). Centering the line box instead leaves lowercase text low and descenders poking into borders.
func (Text) Fit ¶ added in v0.6.0
Fit returns t with MaxW set to w and Size set to the largest size, at most t.Size, at which s wrapped to w fits w×h as Measure measures it, so
t.Fit(s, w, h).Draw(p, s, x, y)
draws s as big as the box allows. Set Size to the largest you want: Fit only shrinks. It stops at 6px, wrapped to w, when nothing fits, since running taller beats running off the side of the screen, and a Size below 6, zero included, comes back as 6. Results are remembered, so a View can call it every frame; a repeat allocates nothing.
func (Text) Measure ¶ added in v0.6.0
Measure returns the size Draw would return for s, without drawing it: the widest line's width, and the height of its lines once wrapped to MaxW. Lay a block out with it before drawing, to size a plate behind it or center it in a box. It allocates nothing, so a View can call it every frame.
type Theme ¶
type Theme struct {
Background RGB // painted behind every slide, so the deck looks the same in any terminal
Text RGB // default text
Muted RGB // secondary text: notes, captions
Faint RGB // decoration only: rules, inactive dots
Accent RGB // primary highlight: the wipe transition, progress, numbers
Accent2 RGB // secondary highlight
Warn RGB // errors, placeholders
Good RGB // positive status, such as the presenter's "on pace"
Panel RGB // inset plates and the help box, a shade off Background
// Series are the colors of chart series, in order, for BarChart, LineChart
// and DonutChart; see Theme.SeriesColor. Empty uses Accent, Accent2, Good,
// Warn and Muted.
Series []RGB
Display *Font // headlines and numbers
Body *Font // supporting lines, labels, chips
Mono *Font // code
// Syntax colors [Code] with; nil derives a palette from the colors above.
Syntax *SyntaxColors
// Overlay, if set, draws after every slide into the full canvas p (a TV
// station's bug), with the slide's Ctx. Slides should leave its corner
// clear.
Overlay func(c Ctx, p *Pixels)
}
Theme is the deck's palette and typefaces. The engine paints its chrome (background, footer, help, notes, presenter view, wipe) with the colors; stock components use the fonts. Display, Body and Mono are required.
func (*Theme) SeriesColor ¶
SeriesColor returns the color of chart series i, cycling through Theme.Series; when that is empty it cycles Accent, Accent2, Good, Warn and Muted. A negative i counts from the end of the cycle.
type Thread ¶ added in v0.7.0
type Thread interface {
// Upload sends p's media ahead of Post, while its slide is up, so the
// post goes out quickly when the speaker moves on. It runs alongside
// Post and other Uploads. Post works whatever became of it: it waits
// for an upload still running, uploads what one didn't, and sends
// nothing twice.
Upload(ctx context.Context, p Post) error
// Post publishes p where d says, and returns a reference to it, which
// later posts get as their Parent (and Root, if it's the first). A try
// d marks as a Retry may have gone out already: Post finds it if it
// did, rather than posting it twice.
Post(ctx context.Context, p Post, d Delivery) (ref string, err error)
}
Thread posts the posts a Session opened it with.
type Timeline ¶
type Timeline struct {
Items []TimelineItem
FirstStep int
Vertical bool // items run down the rect with text beside the line, not across it
}
Timeline is a line with a dot per milestone, built one item per step: item i appears at step FirstStep+i, the line drawing on to its dot, the dot popping and the text fading up. The newest item is in Accent and earlier ones in Muted, as BulletList dims its lines. Text is fitted to its slot, all labels at one size and all details at another.
type TimelineItem ¶
type TimelineItem struct {
Label string // the milestone's name, in the display font
Detail string // optional supporting text beneath or beside it
}
TimelineItem is one milestone on a Timeline.
type Transition ¶
type Transition struct {
// contains filtered or unexported fields
}
Transition is how a slide enters: one of the kinds below, taking its default time or the one Over gives it, and the side From gives the ones that have a direction. Transitions are comparable values; the zero Transition is TransitionDefault.
Transition: decker.TransitionMorph.Over(1.2) Transition: decker.TransitionPush.From(decker.DirDown)
func (Transition) Duration ¶
func (t Transition) Duration() float64
Duration returns how long t takes, in seconds.
func (Transition) From ¶
func (t Transition) From(d Direction) Transition
From returns t starting from side d. Push, Cover and Uncover bring the new slide in from d (Uncover sends the old one out the opposite way), Wipe sweeps from d, and Split opens along d's axis; the other transitions ignore it. DirDefault restores each one's own side (Push, Cover and Uncover from the right, Wipe from the left, Split horizontal), and going back plays t from the opposite side.
func (Transition) Over ¶
func (t Transition) Over(secs float64) Transition
Over returns t taking secs seconds; zero or less restores its default.
Source Files
¶
- anim.go
- animate.go
- block.go
- blockfit.go
- blockfx.go
- blockglyph.go
- chart.go
- cli.go
- code.go
- color.go
- connector.go
- coverage.go
- ctx.go
- deck.go
- dev.go
- diagram.go
- dialog.go
- direction.go
- doc.go
- draw.go
- effects.go
- figlet.go
- fit.go
- font.go
- grid.go
- handout.go
- image.go
- keys.go
- kitty.go
- layer.go
- layout.go
- link.go
- memo.go
- model.go
- morph.go
- notes.go
- pdf.go
- pixelart.go
- pixels.go
- png.go
- pool.go
- posting.go
- present_window.go
- presenter.go
- presview.go
- preview.go
- publish.go
- render.go
- review.go
- reviewimage.go
- reviewlog.go
- reviewreport.go
- rich.go
- richmarkup.go
- scale.go
- scene.go
- shapes.go
- slide.go
- table.go
- termout.go
- text.go
- theme.go
- transfx.go
- transition.go
- video.go
Directories
¶
| Path | Synopsis |
|---|---|
|
bsky
module
|
|
|
Package decktest is the test suite every deck wants: every slide renders at every step, size and moment without panicking, and draws the same frame every time; every build shows all it means to (nothing clipped, dropped or off the canvas); the posts in its notes pass its publisher's checks; reference images catch unintended changes to how it looks; and a per-slide benchmark measures frame time.
|
Package decktest is the test suite every deck wants: every slide renders at every step, size and moment without panicking, and draws the same frame every time; every build shows all it means to (nothing clipped, dropped or off the canvas); the posts in its notes pass its publisher's checks; reference images catch unintended changes to how it looks; and a per-slide benchmark measures frame time. |
|
examples
|
|
|
hello
command
|
|
|
recipes
command
Command recipes is a deck of worked recipes for the visuals that carry a talk's explanation, starting with a trace waterfall.
|
Command recipes is a deck of worked recipes for the visuals that carry a talk's explanation, starting with a trace waterfall. |
|
starter
command
Command starter is a talk to copy: a theme, a slide template, three slides, their notes and the tests that keep them right.
|
Command starter is a talk to copy: a theme, a slide template, three slides, their notes and the tests that keep them right. |
|
internal
|
|
|
visual
Package visual checks rendered frames against reference images kept in the repository, and text against reference files.
|
Package visual checks rendered frames against reference images kept in the repository, and text against reference files. |



