ui

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 73 Imported by: 0

Documentation

Overview

Package ui is the Bubble Tea front end. Inside the grid it behaves like Google Sheets (keys, selection, entry); around it, the control panel and mode indicator give it a 1-2-3 look.

Index

Constants

View Source
const (
	// FrameRate is how many frames a second Bubble Tea may draw, its
	// maximum (tea.WithFPS). A key's answer waits for the next frame, so
	// this halves the wait at the default 60. The renderer writes a frame
	// only when the view changed, so an idle screen costs no more.
	FrameRate = 120
	// FrameInterval is the time between frames.
	FrameInterval = time.Second / FrameRate
)
View Source
const RecoveryDir = ".012-recovery"

RecoveryDir is the directory, inside the served one, recovery files are kept in.

View Source
const StdinName = "stdin"

StdinName is what a table read from standard input is called: its sheet's name.

Variables

This section is empty.

Functions

This section is empty.

Types

type Crash added in v0.3.0

type Crash struct {
	Where string // "update", "view", "init" or "a command"
	Value any    // what was panicked with
	Stack []byte // the panicking goroutine's stack; nil when Bubble Tea caught it
}

Crash is a panic Guard caught.

func (*Crash) Report added in v0.3.0

func (c *Crash) Report(dir, version, file, kept string, keepErr error, now time.Time) (string, error)

Report writes a short report of the crash into dir, for the user to send with an issue, and returns its path. It says where the panic was, what with, the stack, the build (version), the system, the file open and where its unsaved work was kept; never the workbook's contents.

type Guarded added in v0.3.0

type Guarded struct {
	// contains filtered or unexported fields
}

Guarded is a model run under Guard.

func Guard added in v0.3.0

func Guard(m *Model) *Guarded

Guard wraps m so a panic in it stops the program without losing the terminal; see Finish for what's left afterwards.

func (*Guarded) Finish added in v0.3.0

func (g *Guarded) Finish(runErr error) *Crash

Finish is called once the program has stopped, with what Run returned. It reports the crash that stopped it, if one did: one Guard caught, or one only Bubble Tea caught (a panic in a sequence's command), whose stack it printed on the terminal.

func (*Guarded) Init added in v0.3.0

func (g *Guarded) Init() (cmd tea.Cmd)

Init implements tea.Model.

func (*Guarded) Keep added in v0.3.0

func (g *Guarded) Keep(now time.Time) (kept string, err error)

Keep writes the model's unsaved work to a recovery file, returning its name ("" when there was nothing unsaved). A model a panic left too broken to write is reported as an error rather than panicking again.

func (*Guarded) Model added in v0.3.0

func (g *Guarded) Model() *Model

Model is the model guarded.

func (*Guarded) Update added in v0.3.0

func (g *Guarded) Update(msg tea.Msg) (next tea.Model, cmd tea.Cmd)

Update implements tea.Model.

func (*Guarded) View added in v0.3.0

func (g *Guarded) View() tea.View

View implements tea.Model. It keeps showing the last frame while the program quits after a crash.

type Model

type Model struct {
	// contains filtered or unexported fields
}

Model is the root of the UI, the tea.Model Bubble Tea runs. It holds the file, the mode and the grid, owns a component for everything that takes input or draws a part of the screen, routes each message to the one it's for, and composes the screen from what they draw (panel.go, view.go, overlay.go).

func New

func New(s *sheet.Sheet, filename string) *Model

New returns a model editing s. filename may be empty.

func (*Model) AllowEditor

func (m *Model) AllowEditor()

AllowEditor lets the user edit macro scripts in their own editor ($VISUAL or $EDITOR), which runs as a program of theirs with the screen handed over. Only the local app allows it: a session served over SSH must not start programs on the server.

func (*Model) Configure

func (m *Model) Configure(s Settings)

Configure applies settings: the theme, chart images, notifications, and notes for the context line.

func (*Model) EnableJEV

func (m *Model) EnableJEV(client jev.Client, cache *jev.Cache)

EnableJEV turns on JEV functions: the cache answers them, for this workbook and those opened later, and the client asks what it lacks.

func (*Model) Filename

func (m *Model) Filename() string

Filename is the open file's name as typed, "" for a book never saved.

func (*Model) Import

func (m *Model) Import(name string)

Import sets a file to import when the program starts, e.g. from "012 sales.csv".

func (*Model) Init

func (m *Model) Init() tea.Cmd

Init implements tea.Model. It asks the terminal for its background color, so the theme can adapt to light terminals, and holds the screen until it knows (termbg.go).

func (*Model) LeaveRoom added in v0.5.0

func (m *Model) LeaveRoom() bool

LeaveRoom gives up the session's seat as it ends, reporting whether it was the last one there (or had a workbook of its own), whose unsaved changes are then its to keep: others keep a room's workbook open. The last one out stops what the room ran.

func (*Model) Listen added in v0.6.0

func (m *Model) Listen()

Listen has the session listen for agents from the start, letting them suggest changes to the whole workbook: 012 --listen.

func (*Model) OfferKept added in v0.3.0

func (m *Model) OfferKept()

OfferKept makes a local session offer, once it starts, the changes kept for its file (or for an untitled book) when 012 last stopped on an internal error. cmd/012 asks for it when started on a file or on nothing, not on an import or standard input.

func (*Model) OpenNotebook added in v0.3.0

func (m *Model) OpenNotebook()

OpenNotebook starts on the workbook's notebook, as 012 nu does: a new file's empty sheet becomes the notebook, with a code cell ready to type in; a workbook without one gets one.

func (*Model) OpenOnStart

func (m *Model) OpenOnStart(name string)

OpenOnStart makes a served session start on name, as `ssh -t host name` asks: a sheet to open (or a new one to save as name, when there's no such file) or a file to import. Either way, or with name empty, the session then offers unsaved changes kept for that name.

func (*Model) Others added in v0.5.0

func (m *Model) Others() (int, string)

Others is how many others share the session's workbook, and their names.

func (*Model) Piped added in v0.3.0

func (m *Model) Piped() (*fileio.Snapshot, fileio.Kind, bool)

Piped is what quitting sent: the table and its format, or false when the user quit without sending.

func (*Model) ReadStdin added in v0.3.0

func (m *Model) ReadStdin(r io.Reader)

ReadStdin sets a table to read from r, standard input, as the program starts, into a new unsaved sheet named stdin.

func (*Model) Recover

func (m *Model) Recover(now time.Time) (string, error)

Recover writes the workbook to a new recovery file for its name, removing the oldest beyond recoveryKeep, and returns the file's name: relative to the served directory in 012 serve, its full path in a local session. It's for when the program has stopped; a local model without Settings.RecoveryDir has nowhere to put one.

func (*Model) Serve

func (m *Model) Serve(root confine.Root, env []string)

Serve prepares m for a session served over SSH: file names resolve inside root, and env (KEY=value pairs) is the client's environment, used instead of the server's to learn about the client's terminal. Notebooks' commands run only when the server's serve-shell allows.

func (*Model) SetMachine

func (m *Model) SetMachine(id string)

SetMachine tells the model which computer it runs on, as an id kept in the user's configuration, so macros saved here run without asking and macros from files made elsewhere ask once.

func (*Model) SetPipe added in v0.3.0

func (m *Model) SetPipe(to fileio.Kind)

SetPipe makes quitting send a table to standard output, in format to (a text format; 0 for the input's, or NUON when the input isn't text).

func (*Model) SetSend added in v0.3.0

func (m *Model) SetSend(s Send)

SetSend makes quitting in a pipeline send s rather than ask.

func (*Model) SetShellRunner added in v0.3.0

func (m *Model) SetShellRunner(r nushell.Runner)

SetShellRunner makes cells run, and the code editor ask, with r rather than nu, for tests; it's set before anything is asked.

func (*Model) SetVimKeys

func (m *Model) SetVimKeys(on bool)

SetVimKeys turns vim keys on or off, as the setting does, for callers that know the user's choice at startup.

func (*Model) ShareRooms added in v0.5.0

func (m *Model) ShareRooms(reg *room.Registry, user string)

ShareRooms makes a served session open files in the rooms of reg, as user: sessions opening the same file share its workbook.

func (*Model) StopListening added in v0.6.0

func (m *Model) StopListening()

StopListening closes the session's socket; agents attached leave.

func (*Model) TraceUnder

func (m *Model) TraceUnder(p telemetry.Parent)

TraceUnder nests every span the model starts under p for good: 012 serve's session span holds each session's commands.

func (*Model) Unsaved

func (m *Model) Unsaved() bool

Unsaved reports whether the workbook has changes a recovery file would keep: it was changed since it was last saved or opened, and isn't empty.

func (*Model) Update

func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model.

func (*Model) View

func (m *Model) View() tea.View

View implements tea.Model: the screen, once the theme is known.

type Send added in v0.3.0

type Send int

Send is what quitting sends in a pipeline (012 --pipe --send).

const (
	SendAsk       Send = iota // ask: the selection, the sheet, or nothing
	SendSelection             // the selection, or the sheet when only one cell is selected
	SendSheet                 // the sheet, whatever is selected
)

type Settings

type Settings struct {
	Config    *config.Config
	Reload    func() *config.Config // reads the config file again; nil disables Reload config
	ThemesDir string                // the user's theme files
	Keys      keyring.Store         // where JEV API key stores the key; nil disables it
	// Connect makes a JEV client for the configured service with key.
	Connect func(key string) (jev.Client, error)
	Notes   []string // said on the context line at startup, e.g. config warnings
	// RecoveryDir is where a local session keeps its unsaved work when
	// it stops on an internal error, and finds it again: recovery.go.
	// "" keeps none; 012 serve keeps them in the served directory.
	RecoveryDir string
	// Version is 012's, which live mode's MCP server reports to agents.
	Version string
}

Settings are what the app takes from outside the workbook: the config file's options, and the credential store the JEV API key lives in. cmd/012 passes them to Configure; tests pass fakes, so the user's own config and keychain are never touched.

type Shared added in v0.5.0

type Shared struct {
	// contains filtered or unexported fields
}

Shared is a served session's guarded model as Bubble Tea runs it when workbooks are shared: every turn the model takes (Init, Update, View) holds its room's lock (room.Seat.Do), with its steps made in its own name, so sessions act on the workbook one at a time, in the order the server takes them. Between turns it joins and leaves rooms, never holding two locks. It also holds back input while someone else's step is open (a macro they run spans several turns) and hands it on once the step ends, and in a one-writer room it takes back what a follower changed by a way no check stopped.

func InRooms added in v0.5.0

func InRooms(g *Guarded) *Shared

InRooms runs g's model in the rooms it was given (Model.ShareRooms).

func (*Shared) Attach added in v0.5.0

func (s *Shared) Attach(ctx context.Context, p *tea.Program)

Attach sends the program a roomMsg whenever the model's room changes, until ctx ends.

func (*Shared) Init added in v0.5.0

func (s *Shared) Init() tea.Cmd

Init implements tea.Model.

func (*Shared) Model added in v0.5.0

func (s *Shared) Model() *Model

Model is the model run.

func (*Shared) Update added in v0.5.0

func (s *Shared) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model.

func (*Shared) View added in v0.5.0

func (s *Shared) View() tea.View

View implements tea.Model.

Directories

Path Synopsis
Package choicebar is a small question asked on the context line and answered with a key, the way terminal programs confirm things, e.g.
Package choicebar is a small question asked on the context line and answered with a key, the way terminal programs confirm things, e.g.
Package cmdhelp is a nushell command's help, F1 on a command in a notebook's cell: a scrollable box over the notebook with what the command does, a link to its page in nushell's docs, its usage, flags, parameters, input and output types and examples, as nu's help has them.
Package cmdhelp is a nushell command's help, F1 on a command in a notebook's cell: a scrollable box over the notebook with what the command does, a link to its page in nushell's docs, its usage, flags, parameters, input and output types and examples, as nu's help has them.
Package cmdline is the command line (: with vim keys, or from the palette): what's typed on the context line, with completions from the command registry in a box under it.
Package cmdline is the command line (: with vim keys, or from the palette): what's typed on the context line, with completions from the command registry in a box under it.
Package evalview is Data > Evaluate formula, after Excel's Evaluate Formula: a box over the grid showing the active cell's formula with the part computed next underlined and its value below.
Package evalview is Data > Evaluate formula, after Excel's Evaluate Formula: a box over the grid showing the active cell's formula with the part computed next underlined and its value below.
Package filterpick is the values list and condition of one column of a filter, in the manner of fzf: a condition on top, then the column's values with checkboxes, narrowed by a fuzzy search as you type.
Package filterpick is the values list and condition of one column of a filter, in the manner of fzf: a condition on top, then the column's values with checkboxes, narrowed by a fuzzy search as you type.
Package findbar is find and replace: a bar on the context line rather than a dialog, in the spirit of less and vim.
Package findbar is find and replace: a bar on the context line rather than a dialog, in the spirit of less and vim.
Package formula reads the formula being typed in the UI: the reference F4 cycles through absolute markers, and the word and function call around the caret that formula assistance follows.
Package formula reads the formula being typed in the UI: the reference F4 cycles through absolute markers, and the word and function call around the caret that formula assistance follows.
Package lineedit is the one-line text editor behind every text field of the UI.
Package lineedit is the one-line text editor behind every text field of the UI.
Package nbview draws a notebook tab and takes its keys and clicks, as Jupyter does: cells one under another, a code cell's pipeline in a box with its [n]: prompt and a ▶ that runs it, its output under it after Out[n]:, and a note cell's Markdown drawn as text.
Package nbview draws a notebook tab and takes its keys and clicks, as Jupyter does: cells one under another, a code cell's pipeline in a box with its [n]: prompt and a ▶ that runs it, its output under it after Out[n]:, and a note cell's Markdown drawn as text.
Package overlay is the contract between the UI's root model and the components that take over input while open: menus, pickers, bars on the context line and dialogs.
Package overlay is the contract between the UI's root model and the components that take over input while open: menus, pickers, bars on the context line and dialogs.
Package picker is the searchable list behind the command palette and every other picker of the UI (functions, sheets, named ranges, macros, themes, files to import): a search field on top, results below with matched characters highlighted, in the manner of fzf.
Package picker is the searchable list behind the command palette and every other picker of the UI (functions, sheets, named ranges, macros, themes, files to import): a search field on top, results below with matched characters highlighted, in the manner of fzf.
Package review is live mode's suggestions panel (docs/agents/live.md): a box at the right of the grid listing the agents' suggestions waiting for the person, each by agent and message with the cells it would set, to accept or reject whole or cell by cell, with keys or the mouse.
Package review is live mode's suggestions panel (docs/agents/live.md): a box at the right of the grid listing the agents' suggestions waiting for the person, each by agent and message with the cells it would set, to accept or reject whole or cell by cell, with keys or the mouse.
Package rowtext lays out the text of one row of cells across the columns on screen, as Sheets does: values formatted and aligned, text running on into blank neighbors, cut to column boundaries in a single pass.
Package rowtext lays out the text of one row of cells across the columns on screen, as Sheets does: values formatted and aligned, text running on into blank neighbors, cut to column boundaries in a single pass.
Package rules is the side panel for a sheet's rules, as Sheets' Conditional formatting and Data validation sidebars: a list of the rules, and a form to add or edit one.
Package rules is the side panel for a sheet's rules, as Sheets' Conditional formatting and Data validation sidebars: a list of the rules, and a form to add or edit one.
Package shortcuts is the keyboard shortcuts view: a scrollable box over the grid listing every key by what it does, in two columns when the screen is wide enough.
Package shortcuts is the keyboard shortcuts view: a scrollable box over the grid listing every key by what it does, in two columns when the screen is wide enough.
Package sortbar is the bar that picks the columns and order to sort a range by, as Sheets' "Advanced range sorting options" dialog, on the context line.
Package sortbar is the bar that picks the columns and order to sort a range by, as Sheets' "Advanced range sorting options" dialog, on the context line.
Package srcview is a linked source's tab: a window of the source's rows drawn as a sheet with a frozen header row, the row numbers and a scrollbar over the whole source, however many millions of rows it has.
Package srcview is a linked source's tab: a window of the source's rows drawn as a sheet with a frozen header row, the row numbers and a scrollbar over the whole source, however many millions of rows it has.
Package suggest is formula assistance, as in Sheets: while a function, range or sheet name is being typed, a list of matching functions, named ranges and other sheets drops down from the formula bar at the caret, and while the caret is inside a function's parentheses the context line shows its signature with the current argument marked.
Package suggest is formula assistance, as in Sheets: while a function, range or sheet name is being typed, a list of matching functions, named ranges and other sheets drops down from the formula bar at the caret, and while the caret is inside a function's parentheses the context line shows its signature with the current argument marked.
Package tabstrip is the sheet tabs at the left of the status line, the way tmux lists windows: the sheet shown is highlighted, a + adds a sheet, and when the tabs don't all fit, ‹ and › step through them.
Package tabstrip is the sheet tabs at the left of the status line, the way tmux lists windows: the sheet shown is highlighted, a + adds a sheet, and when the tabs don't all fit, ‹ and › step through them.
Package theme is the look of the UI: the style roles every view draws with, and the small widgets built from them (framed boxes, key chips, key hints).
Package theme is the look of the UI: the style roles every view draws with, and the small widgets built from them (framed boxes, key chips, key hints).
Package themepicker is File > Settings > Theme: every theme in a picker, fuzzy searched by name, narrowed to one kind by a search starting with "dark" or "light".
Package themepicker is File > Settings > Theme: every theme in a picker, fuzzy searched by name, narrowed to one kind by a search starting with "dark" or "light".
Package transfer runs imports in the background and draws their progress: the mode indicator says WAIT, the context line offers Esc, the status line counts rows with a progress bar, and the terminal shows its own progress indicator.
Package transfer runs imports in the background and draws their progress: the mode indicator says WAIT, the context line offers Esc, the status line counts rows with a progress bar, and the terminal shows its own progress indicator.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL