Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyTheme(light bool)
- func BackupDir() (string, error)
- func DataPath() (string, error)
- func DitherShade(x, y int, density float32) rune
- func ModeAttr(_ TextStyleMode) uint8
- func ResolveTheme(mode ThemeMode) bool
- func Run()
- func SaveWorkspace(w *Workspace) error
- func ScreenDeltaToWorld(d, zoom int) int
- func ScreenX(worldX, zoom int) int
- func ScreenY(worldY, zoom int) int
- func SpliceOverlay(bg, overlay string, x, y int) string
- func StyleText(s string, mode TextStyleMode) string
- func StyleViewText(s string, mode TextStyleMode) string
- func WorldX(screenX, zoom int) int
- func WorldY(screenY, zoom int) int
- type Background
- type BackgroundColor
- type BackgroundMenu
- func (m *BackgroundMenu) HexBackspace()
- func (m *BackgroundMenu) HexInput(runes []rune)
- func (m *BackgroundMenu) Label() string
- func (m *BackgroundMenu) Move(delta int)
- func (m *BackgroundMenu) OnCork() bool
- func (m *BackgroundMenu) OnCustom() bool
- func (m *BackgroundMenu) Selected() Background
- func (m *BackgroundMenu) ToggleCork()
- type Board
- func (b *Board) ApplyGlobalBorder()
- func (b *Board) Connect(fromID, toID string) *StringConn
- func (b *Board) ConnectToWall(fromID string, worldX, worldY int) *StringConn
- func (b *Board) Cycle(direction int)
- func (b *Board) Delete(id string)
- func (b *Board) DeleteStringAt(i int) bool
- func (b *Board) DeleteStringsTouching(id string) int
- func (b *Board) FindNote(id string) *Note
- func (b *Board) HitTopmost(cx, cy int) int
- func (b *Board) NewNote(screenW, screenH int) *Note
- func (b *Board) Raise(i int)
- func (b *Board) Select(id string)
- func (b *Board) Selection() *Note
- func (b *Board) StringsTouching(id string) []int
- type BorderChoice
- type Canvas
- func (c *Canvas) BlankRect(x, y, w, h int)
- func (c *Canvas) BlitAt(src *Canvas, dx, dy int)
- func (c *Canvas) Dim(f float32)
- func (c *Canvas) Get(x, y int) Cell
- func (c *Canvas) Inside(x, y int) bool
- func (c *Canvas) Serialize() string
- func (c *Canvas) SetBlank(x, y int)
- func (c *Canvas) SetRune(x, y int, r rune, fg RGB, attr uint8)
- func (c *Canvas) WriteText(x, y int, s string, fg RGB, attr uint8)
- type Cell
- type Editor
- type FontMenu
- type History
- func (h *History) CanRedo() bool
- func (h *History) CanUndo() bool
- func (h *History) Clear()
- func (h *History) Len() int
- func (h *History) Push(ws *Workspace, label string)
- func (h *History) Redo(current *Workspace) (*Workspace, string, bool)
- func (h *History) Undo(current *Workspace) (*Workspace, string, bool)
- type Mode
- type Note
- func (n *Note) Dims(zoom int) NoteDims
- func (n *Note) EffectiveX(zoom int) int
- func (n *Note) EffectiveY(zoom int) int
- func (n *Note) Hit(cx, cy, zoom int) bool
- func (n *Note) OnResizeHandle(cx, cy, zoom int) bool
- func (n *Note) PinPos(zoom int) (int, int)
- func (n *Note) ScreenRect(zoom int) Rect
- func (n *Note) SetWorldSize(w, h int)
- func (n *Note) WorldSize() (int, int)
- type NoteDims
- type Palette
- type PinOverride
- type PullState
- type RGB
- type Rect
- type Saver
- type Star
- type StringConn
- type StringEnd
- type TextStyleMode
- type ThemeMode
- type Tint
- type Transition
- type TransitionMode
- type VimMode
- type VimState
- type Workspace
- func (w *Workspace) ActiveBoard() *Board
- func (w *Workspace) AddBoard(name string) *Board
- func (w *Workspace) BgColor() (*RGB, bool)
- func (w *Workspace) CanMoveActive(delta int) bool
- func (w *Workspace) CorkOn() bool
- func (w *Workspace) CycleActive(delta int)
- func (w *Workspace) DeleteBoard(i int) bool
- func (w *Workspace) MoveActive(delta int) bool
- func (w *Workspace) SetThemeMode(m ThemeMode)
- func (w *Workspace) ThemeMode() ThemeMode
- func (w *Workspace) ToggleTheme() ThemeMode
Constants ¶
const ( ZoomMin = -3 ZoomMax = +1 )
ZoomMin / ZoomMax — 5 levels total, all clamped here.
const ( BgCork = "cork" BgTransparent = "transparent" BgSolid = "solid" )
Legacy background-mode strings from an earlier single-"mode" design. Read on load and migrated into Cork/Color; never written.
const ( AttrBold = 1 << 0 AttrFaint = 1 << 1 AttrItalic = 1 << 2 AttrUnder = 1 << 3 AttrStrike = 1 << 4 )
Attr bits for a cell.
Variables ¶
var BackgroundColors = []BackgroundColor{
{"terminal (transparent)", ""},
{"true black", "#000000"},
{"github dark", "#0d1117"},
{"tokyo night", "#1a1b26"},
{"catppuccin", "#1e1e2e"},
{"one dark", "#282c34"},
{"dracula", "#282a36"},
{"gruvbox", "#282828"},
{"nord", "#2e3440"},
{"solarized", "#002b36"},
{"paper", "#faf8f3"},
{"github light", "#ffffff"},
{"solarized light", "#fdf6e3"},
{"latte", "#eff1f5"},
{"gruvbox light", "#fbf1c7"},
}
BackgroundColors — the fill colors offered in the background menu, in order. "terminal" keeps today's transparency; the rest are the background colors of the editor/terminal themes developers actually use, so the picker feels familiar. Dark themes first, then light ones. The menu appends a "custom hex" entry after these. Cork is an independent toggle, not a list entry.
var Bayer4x4 = [4][4]int{
{0, 8, 2, 10},
{12, 4, 14, 6},
{3, 11, 1, 9},
{15, 7, 13, 5},
}
Bayer 4x4 ordered-dither matrix (0..15).
var BlotchChars = []rune{'░', '▒'}
Extremely rare cork blotches (imperfections).
var CorkShades []RGB
CorkShades — weighted shade pool for the cork texture. Duplicates bias the random pick toward common mid tones, with occasional brighter or rustier accents. Rebuilt by ApplyTheme.
var FiberChars = []rune{'.', '·', ',', '\'', '˙'}
Chars used for the note's own paper-fiber flecks.
var PoreChars = []rune{'∘', '°', '◦', '○'}
Rare bigger cork pores / pinholes.
var SelBorderChoices []BorderChoice
SelBorderChoices — the 9 border colors available for notes. Keys 1-9 map to these in order; `c` cycles through them. Set by ApplyTheme; the names are identical in both palettes so a saved highlightColor index keeps meaning the same thing when the theme changes.
var StarChars = []rune{
'.', ',', '·', '\'', ':', ';', '`', '~', '˙',
'ˏ', 'ˎ', '‚', '„', '•',
}
Chars used to texture the cork surface — main pool. More variety gives the cork a busier, more ASCII-art feel.
var TextModes = []TextStyleMode{ TextPlain, TextBold, TextItalic, TextBoldIt, TextScript, TextFraktur, TextDouble, TextMono, }
var TintOrder = []string{
"yellow", "pink", "blue", "green", "purple",
"orange", "teal", "cream", "coral",
}
TintOrder — 1-9 in order.
var Tints map[string]Tint
Tints — the active tint set, swapped by ApplyTheme. Both palettes use the same nine keys so a note's saved tint name always resolves.
Functions ¶
func ApplyTheme ¶
func ApplyTheme(light bool)
ApplyTheme installs a palette into the package-level color vars that every draw site reads. Call it once at startup, before the first render.
func BackupDir ¶
BackupDir returns the directory holding rotated copies of notes.json, creating it on demand.
func DitherShade ¶
DitherShade returns a halftone char for a given (x,y) and density 0..1.
func ModeAttr ¶
func ModeAttr(_ TextStyleMode) uint8
ModeAttr returns attribute bits to OR into cell renders. Unicode-math modes provide no ANSI attributes of their own (the visual "boldness" comes from the codepoint itself), so this always returns 0.
func ResolveTheme ¶
ResolveTheme is resolveTheme against the real terminal.
func SaveWorkspace ¶
SaveWorkspace writes the workspace as a v4 file (workspace envelope), rotating the previous content into the backup directory first.
func ScreenDeltaToWorld ¶
ScreenDeltaToWorld converts a 1-cell screen delta into a world delta, ensuring a non-zero input always moves at least 1 world cell.
func SpliceOverlay ¶
SpliceOverlay splices `overlay` onto `bg` at visual cell position (x, y). Both strings are newline-separated; ANSI CSI escapes are preserved. Style state active at the cut point is re-emitted before the suffix so chars just past the overlay keep their original styling (otherwise they'd render in terminal default, often appearing white).
func StyleText ¶
func StyleText(s string, mode TextStyleMode) string
StyleText maps ASCII letters/digits to the mode's Unicode variant.
func StyleViewText ¶
func StyleViewText(s string, mode TextStyleMode) string
StyleViewText applies styleRune to a pre-rendered string while passing through ANSI CSI escape sequences untouched. Useful when post-processing the output of a third-party widget (e.g. bubbles/textarea) so the visible glyphs reflect the board's font without breaking cursor highlighting.
Types ¶
type Background ¶
type Background struct {
Cork bool `json:"cork"`
Color string `json:"color,omitempty"` // hex (e.g. "#1c2233"); "" = transparent
// Legacy dev-only field — read on load, migrated by normalizeLegacy,
// never written.
Mode string `json:"mode,omitempty"`
}
Background is the workspace-wide board background. The two axes are independent: Cork toggles the ASCII texture overlay, and Color is the fill drawn behind it ("" = transparent, i.e. the terminal background shows through). Any combination is valid — cork on over a solid color, cork off over transparent for a clean terminal, etc.
type BackgroundColor ¶
BackgroundColor is one fill option in the background picker. Hex "" means transparent — the terminal/tmux background shows through (the default).
type BackgroundMenu ¶
type BackgroundMenu struct {
Cursor int
Saved Background // background at open time; restored on esc
Cork bool // working cork toggle
Color string // working fill color (hex, or "" for transparent)
Hex string // custom-hex buffer, e.g. "#1c2233"
}
BackgroundMenu is the stateful background picker. nil on model = closed. Two independent axes: a cork on/off toggle (row 0) and the fill color (the BackgroundColors rows, then a custom-hex row). Row layout:
0 → cork toggle 1 .. len(colors) → color rows (color index = cursor-1) len(colors)+1 → custom hex
func NewBackgroundMenu ¶
func NewBackgroundMenu(current Background) *BackgroundMenu
func (*BackgroundMenu) HexBackspace ¶
func (m *BackgroundMenu) HexBackspace()
func (*BackgroundMenu) HexInput ¶
func (m *BackgroundMenu) HexInput(runes []rune)
HexInput appends valid hex characters to the custom buffer (single leading '#'), capping at "#rrggbb", and live-previews the result.
func (*BackgroundMenu) Label ¶
func (m *BackgroundMenu) Label() string
Label returns a human-readable summary for the toast.
func (*BackgroundMenu) Move ¶
func (m *BackgroundMenu) Move(delta int)
func (*BackgroundMenu) OnCork ¶
func (m *BackgroundMenu) OnCork() bool
OnCork / OnCustom report which special row the cursor is on.
func (*BackgroundMenu) OnCustom ¶
func (m *BackgroundMenu) OnCustom() bool
func (*BackgroundMenu) Selected ¶
func (m *BackgroundMenu) Selected() Background
Selected returns the Background described by the working state.
func (*BackgroundMenu) ToggleCork ¶
func (m *BackgroundMenu) ToggleCork()
ToggleCork flips the cork overlay (used by left/right/space on the cork row).
type Board ¶
type Board struct {
Name string `json:"name"`
GrainSeed int64 `json:"grainSeed,omitempty"`
Notes []*Note `json:"notes"`
Strings []*StringConn `json:"strings,omitempty"`
Selected string `json:"-"`
TextMode TextStyleMode `json:"textMode,omitempty"`
Zoom int `json:"zoom,omitempty"`
HighlightColor int `json:"highlightColor,omitempty"`
}
func (*Board) ApplyGlobalBorder ¶
func (b *Board) ApplyGlobalBorder()
ApplyGlobalBorder syncs the package-level SelBorder with this board's HighlightColor. Call on load and whenever HighlightColor changes.
func (*Board) Connect ¶
func (b *Board) Connect(fromID, toID string) *StringConn
func (*Board) ConnectToWall ¶
func (b *Board) ConnectToWall(fromID string, worldX, worldY int) *StringConn
ConnectToWall creates a string from a note to a WORLD-coord wall-pin. The caller is responsible for converting a mouse click (screen) to world before calling this.
func (*Board) DeleteStringAt ¶
func (*Board) DeleteStringsTouching ¶
func (*Board) HitTopmost ¶
func (*Board) NewNote ¶
NewNote places a note at screen-centre converted to world coords, so it appears centred at whatever zoom level the user is on.
func (*Board) StringsTouching ¶
type BorderChoice ¶
BorderChoice pairs a display name with an RGB for the border palette.
type Canvas ¶
type Canvas struct {
W, H int
// DefaultBg, when non-nil, is the background color emitted for every
// cell that has no fill of its own — i.e. a solid board background.
// nil keeps the original fully-transparent behavior (tmux shows through).
DefaultBg *RGB
// contains filtered or unexported fields
}
func (*Canvas) BlitAt ¶
BlitAt copies every cell from `src` into this canvas at offset (dx, dy). Cells that fall outside this canvas are clipped. Source-empty cells (Rune == 0 && Fg == nil) overwrite the destination just the same — the caller is expected to pass a freshly-allocated dst canvas if it wants the off-screen area to read as terminal default.
func (*Canvas) Dim ¶
Dim applies a multiplier to every cell's foreground color, preserving transparency on bare cells. Used for blurring the backdrop during edit.
func (*Canvas) Serialize ¶
Serialize walks the grid, coalescing adjacent cells that share style. Returns a string containing ANSI SGR + text, suitable for Bubble Tea's View() return value.
type Editor ¶
type Editor struct {
Ta textarea.Model
NoteID string
// Vim is non-nil when modal editing is on. It owns the buffer in
// normal and visual mode; the textarea takes over for insert.
Vim *VimState
}
func NewVimEditor ¶
NewVimEditor is NewEditor with modal editing enabled, starting in normal mode as vim does.
func (*Editor) Split ¶
Split returns the live (title, body) from the textarea content. First non-empty line is the title; the rest (skipping one separator blank) is the body.
func (*Editor) SyncFromTextarea ¶
func (e *Editor) SyncFromTextarea()
SyncFromTextarea pulls edits made in insert mode back into the vim buffer, so normal mode sees what was typed.
func (*Editor) SyncToTextarea ¶
func (e *Editor) SyncToTextarea()
SyncToTextarea pushes the vim buffer into the textarea, for entering insert mode. The textarea's own cursor cannot be placed across wrapped lines, so this positions it as closely as the widget allows: the right row when lines are short, and the right column within that row.
type FontMenu ¶
type FontMenu struct {
Cursor int // index into TextModes
SavedMode TextStyleMode // mode at time of opening; restored on Esc
}
FontMenu is the stateful popup. nil on model = closed.
func NewFontMenu ¶
func NewFontMenu(current TextStyleMode) *FontMenu
func (*FontMenu) Selected ¶
func (m *FontMenu) Selected() TextStyleMode
type History ¶
type History struct {
// contains filtered or unexported fields
}
History is a bounded undo stack with a redo branch. Entries are whole *workspace* states as they were before a mutation, so Undo restores the previous state and stashes the current one for Redo.
Workspace rather than Board because deleting a board (`D`) destroys far more than deleting a note, and a board-level snapshot could not bring it back.
func NewHistory ¶
func (*History) Push ¶
Push records the workspace's current state, to be restored by a later Undo. Call it *before* applying a mutation. label describes the mutation and is surfaced in the toast ("undo: paste into note").
type Note ¶
type Note struct {
ID string `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
X int `json:"x"` // WORLD coord
Y int `json:"y"` // WORLD coord
Tint string `json:"tint"`
W int `json:"w,omitempty"` // WORLD size; 0 = default
H int `json:"h,omitempty"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
// Runtime-only:
Bob float32 `json:"-"` // SCREEN-cell vertical bob
BobX float32 `json:"-"` // SCREEN-cell lateral wobble
Lifted bool `json:"-"`
Flash float32 `json:"-"`
}
func (*Note) EffectiveX ¶
EffectiveX: SCREEN X = world→screen projection + bob.
func (*Note) EffectiveY ¶
EffectiveY: SCREEN Y = world→screen projection + bob.
func (*Note) OnResizeHandle ¶
OnResizeHandle reports whether screen cell (cx, cy) is on the note's bottom-right corner grip.
func (*Note) ScreenRect ¶
ScreenRect — drawing rect (no bob, stable for shadow/hit-test).
func (*Note) SetWorldSize ¶
SetWorldSize clamps and stores a new world size.
type Palette ¶
type Palette struct {
// Cork texture, scattered directly over the terminal background.
CorkDark RGB
CorkMid RGB
CorkLight RGB
CorkRust RGB
CorkWarm RGB
CorkPore RGB
CorkBlotch RGB
CorkPatchFg RGB
// Pins and strings.
PinRed RGB
PinHi RGB
PinDark RGB
StringRd RGB
StringHi RGB
// Drop shadow under notes.
ShadowBG RGB
ShadowMi RGB
// Chrome: footer text, dimmed labels, the bright highlight, and the
// tint used by the darken/vignette passes.
DimText RGB
Flash RGB
DarkTint RGB
Tints map[string]Tint
SelBorderChoices []BorderChoice
}
Palette is a complete set of board colors. darkPalette() reproduces the colors redthread has always shipped; lightPalette() is its counterpart for a pale terminal background.
type PinOverride ¶
PinOverride lets callers substitute the screen position used for a specific note's string endpoints — used during the zoom-to-edit transition so strings follow the morphing rect instead of the original pin location.
type PullState ¶
type RGB ¶
type RGB struct{ R, G, B uint8 }
RGB is a 24-bit color.
var ( CorkDark RGB CorkMid RGB CorkLight RGB CorkRust RGB // warmer reddish-brown CorkWarm RGB // honey highlight CorkPore RGB // rare pores / holes CorkBlotch RGB // cork blotches CorkPatchFg RGB // bigger brown "patch" fg (with `▒` density) PinRed RGB PinHi RGB PinDark RGB StringRd RGB StringHi RGB // brighter accent for the pulled-end tip ShadowBG RGB ShadowMi RGB DimText RGB Flash RGB DarkTint RGB // for darken/vignette passes // SelBorder — legacy default (first entry of SelBorderChoices). // Per-note colors are preferred: Note.BorderColor picks an index. SelBorder RGB )
func ParseHexColor ¶
ParseHexColor parses "#rrggbb" or "rrggbb" (case-insensitive) into an RGB. Returns ok=false for any malformed input.
func (RGB) BgSGR ¶
BgSGR emits the background-color SGR for this color. The renderer is otherwise foreground-only; this is used for the optional solid board background.
func (RGB) Brightness ¶
Brightness — Rec 601 luma, used by the monochrome dither pass.
type Rect ¶
type Rect struct{ X, Y, W, H int }
func BackgroundMenuRect ¶
func FontMenuRect ¶
func RectFromNote ¶
RectFromNote builds the source rect for a note at the board's zoom (SCREEN coords, no bob — transitions should start from the stable resting position, not mid-bounce).
func TargetRect ¶
TargetRect returns the centered edit-card rect for a given canvas size.
type Saver ¶
type Saver struct {
// contains filtered or unexported fields
}
Saver debounces writes. Touch snapshots the workspace on the caller's goroutine and hands the copy to a timer, so the timer never reads the live workspace that the update loop keeps mutating (that was a data race, and with backups a torn marshal could be rotated into the ring). A generation counter lets a stale timer step aside when a newer Touch, Flush or Cancel has happened, and writeMu keeps writes in order.
type Star ¶
func GenStarsForBoard ¶
GenStarsForBoard returns a cork-texture stable across resizes-of-equal-size AND distinct per `grainSeed`. Row 0 is reserved for the tab bar — no stars are placed there.
type StringConn ¶
type StringConn struct {
A StringEnd `json:"a"`
B StringEnd `json:"b"`
Tight bool `json:"tight"`
InFront bool `json:"front,omitempty"`
// legacy v2 fields (loaded, never written)
FromID string `json:"from,omitempty"`
ToID string `json:"to,omitempty"`
}
func (*StringConn) InvolvesNote ¶
func (s *StringConn) InvolvesNote(id string) bool
type StringEnd ¶
type TextStyleMode ¶
type TextStyleMode int
const ( TextPlain TextStyleMode = iota // plain TextBold // 𝗕𝗼𝗹𝗱 — math sans-serif bold TextItalic // 𝘐𝘵𝘢𝘭𝘪𝘤 — math sans-serif italic TextBoldIt // 𝘽𝙤𝙡𝙙 𝙄𝙩 — math sans-serif bold italic TextScript // 𝓢𝓬𝓻𝓲𝓹𝓽 — math bold script TextFraktur // 𝕱𝖗𝖆𝖐𝖙𝖚𝖗 — math bold fraktur TextDouble // 𝔻𝕠𝕦𝕓𝕝𝕖 — math double-struck TextMono // 𝙼𝚘𝚗𝚘 — math monospace )
func (TextStyleMode) Name ¶
func (m TextStyleMode) Name() string
func (TextStyleMode) Sample ¶
func (m TextStyleMode) Sample() string
type ThemeMode ¶
type ThemeMode int
ThemeMode is the user's stated preference for palette selection.
func ParseThemeMode ¶
ParseThemeMode reads "auto" / "light" / "dark", case-insensitively. The empty string means auto.
type Tint ¶
type Tint struct {
Name string
Paper RGB // main ink / border color
Ink RGB // body text color (slightly lighter or darker for contrast)
Fiber RGB // paper-fiber dot color
Tape RGB // tape strip color (tape on top of the note)
Edge RGB // edge highlight when selected
}
A Tint is a named color set for a sticky-note look.
type Transition ¶
type Transition struct {
Mode TransitionMode
Start time.Time
Source Rect
NoteID string
Duration time.Duration
}
func NewTransitionIn ¶
func NewTransitionIn(n *Note, zoom int) *Transition
func NewTransitionOut ¶
func NewTransitionOut(n *Note, zoom int) *Transition
type TransitionMode ¶
type TransitionMode int
const ( TransitionIn TransitionMode = iota TransitionOut )
type VimState ¶
VimState is the buffer plus everything the key handler needs to interpret the next keystroke.
func NewVimState ¶
func (*VimState) Key ¶
Key feeds one key to the state machine. Keys are bubbletea's names ("a", "esc", "backspace", "enter", …).
type Workspace ¶
type Workspace struct {
Boards []*Board `json:"boards"`
ActiveIdx int `json:"activeIdx,omitempty"`
Background Background `json:"background,omitempty"`
// Theme is the saved palette preference: "light", "dark", or "" for
// auto-detect. Omitted from the file when empty, so a workspace that
// has never expressed a preference keeps getting detection.
Theme string `json:"theme,omitempty"`
// Vim enables modal editing in the note card. Off by default and
// omitted when off, so nobody's muscle memory changes without asking.
Vim bool `json:"vim,omitempty"`
}
Workspace is a list of named cork boards the user can cycle between. One is "active"; everything in the running model points at that one.
func LoadWorkspace ¶
LoadWorkspace reads notes.json, migrating older schemas on the way in. Returns (nil, nil) when the file simply doesn't exist yet.
func (*Workspace) ActiveBoard ¶
ActiveBoard returns the currently-focused board, never nil while the workspace has at least one board.
func (*Workspace) AddBoard ¶
AddBoard appends a fresh board with a unique grain seed and makes it active. Returns the new board.
func (*Workspace) BgColor ¶
BgColor returns the solid fill color when one is set and parses; otherwise (nil, false) — meaning transparent (terminal shows through).
func (*Workspace) CanMoveActive ¶
MoveActive shifts the active board by `delta` positions in the workspace order (negative = move left, positive = move right). Wraps around. The active index follows the moved board so the tab bar's `●` stays on it. Returns true if a swap happened. CanMoveActive reports whether MoveActive(delta) would actually reorder anything. Callers snapshot for undo before mutating, so they need to know in advance rather than from the return value.
func (*Workspace) CycleActive ¶
CycleActive moves the active index by `delta`, wrapping around.
func (*Workspace) DeleteBoard ¶
DeleteBoard removes the board at index i. Refuses to delete the last remaining board.
func (*Workspace) MoveActive ¶
func (*Workspace) SetThemeMode ¶
SetThemeMode records a palette preference. Auto clears the field rather than writing "auto", keeping the key out of the file entirely.
func (*Workspace) ThemeMode ¶
ThemeMode returns the saved palette preference, defaulting to auto for an absent or unrecognized value.
func (*Workspace) ToggleTheme ¶
ToggleTheme flips between the light and dark palettes, applies the new one immediately, and records the choice. A workspace still on auto resolves to whatever is currently rendered before flipping, so the first toggle always visibly changes something.