Documentation
¶
Overview ¶
Package headless works on workbook files without the screen, for 012 get, set, recalc and export (see docs/files/scripts.md): it opens a .012 file, finds the cells a reference names, reads and writes them, lists the errors formulas show and saves atomically. Nothing here runs a program or reaches the network unless its caller asks: notebook cells run through RunNotebooks and JEV functions through AnswerJEV, which the command line calls only behind flags.
Index ¶
- Variables
- func AddPivot(w *sheet.Workbook, spec PivotSpec) (string, error)
- func AnswerJEV(ctx context.Context, w *sheet.Workbook, client jev.Client, ...) int
- func AnswerJEVFrom(ctx context.Context, w *sheet.Workbook, client jev.Client, cache *jev.Cache, ...) int
- func Apply(w *sheet.Workbook, ops []Operation, o SetOptions) (warnings []string, err error)
- func ChartTitle(c sheet.Chart) string
- func Encode(w io.Writer, format string, v any) error
- func Filter(w *sheet.Workbook, ref string, cols []FilterColumn, remove bool) error
- func FindChart(s *sheet.Sheet, which string) (int, error)
- func Get(out io.Writer, t Target, o GetOptions) error
- func MissingOutputs(s *sheet.Sheet) []string
- func ResolveCell(w *sheet.Workbook, ref string) (*sheet.Sheet, sheet.Addr, error)
- func RunNotebooks(ctx context.Context, w *sheet.Workbook, o NotebookOptions) []string
- func Set(w *sheet.Workbook, entries []Entry, o SetOptions) (warnings []string, err error)
- func Sort(w *sheet.Workbook, ref string, keys []SortKey, header bool) error
- func SyncOutputs(w *sheet.Workbook)
- func Trusted(w *sheet.Workbook, machine string) bool
- func WriteAtomic(path string, mode fs.FileMode, write func(io.Writer) error) error
- func WriteDescription(w io.Writer, d Description) error
- type CellRun
- type Change
- type ChartDescription
- type ChartMade
- type ChartSpec
- type Description
- type Entry
- type Evaluated
- type ExportResult
- type File
- type FilterColumn
- type FindOptions
- type Found
- type GetOptions
- type Match
- type NameDescription
- type NotebookCell
- type NotebookOptions
- type Operation
- type PivotDescription
- type PivotSpec
- type PivotValue
- type Problem
- type ProblemRecord
- type Range
- type ReadOptions
- type RecalcResult
- type RegionDescription
- type SetOptions
- type SetResult
- type SheetDescription
- type SortKey
- type TableDescription
- type Target
Constants ¶
This section is empty.
Variables ¶
var Formats = []string{"text", "csv", "tsv", "json", "nuon"}
Formats are what Get writes: text as the sheet shows it, or a table as 012 --pipe and exports write it.
Functions ¶
func AddPivot ¶ added in v0.4.0
AddPivot adds a pivot table's sheet after its source's, returning its name.
func AnswerJEV ¶
func AnswerJEV(ctx context.Context, w *sheet.Workbook, client jev.Client, timeout time.Duration) int
AnswerJEV answers w's JEV functions with client, asking what the workbook's formulas ask, a few questions at a time, until none is waiting, each within timeout. It returns how many were asked.
func AnswerJEVFrom ¶ added in v0.4.0
func AnswerJEVFrom(ctx context.Context, w *sheet.Workbook, client jev.Client, cache *jev.Cache, timeout time.Duration) int
AnswerJEVFrom is AnswerJEV with the answers kept in cache, which a caller opening the workbook again and again (012 mcp) keeps, so each question is asked once.
func Apply ¶ added in v0.4.0
Apply makes ops as one change, in order, stopping at the first that fails with an error naming it; the workbook should then be thrown away rather than saved, as after Set.
func ChartTitle ¶ added in v0.4.0
ChartTitle is a chart's title, or its type's name when it has none.
func Encode ¶ added in v0.4.0
Encode writes v, a value of this package's result types, as JSON (indented, one value) or NUON, the forms --format json and nuon ask for. NUON is the JSON read as nushell reads it, so both carry the same schema (docs/reference/json.md).
func Filter ¶ added in v0.4.0
Filter puts a filter on the range ref names (its first row the header) with the columns' criteria, replacing the sheet's filter, as Data > Create a filter does; remove takes the sheet's filter off.
func FindChart ¶ added in v0.4.0
FindChart finds a chart of s by its number, 1 for the first in the order the sheet keeps them, or by its title, ignoring case.
func Get ¶
func Get(out io.Writer, t Target, o GetOptions) error
Get writes the target's values. One cell is written alone: as it shows, or as a JSON or NUON value typed by its format (a number, a date, a file size). A range or sheet is written as a table: aligned columns as text, or as CSV, TSV, JSON or NUON, whose columns take their names from the first row (see GetOptions.NoHeader).
func MissingOutputs ¶
MissingOutputs names the notebook outputs sent to s that show no rows because the file holds no output for their cells: never run, too large to save, or their cells gone.
func ResolveCell ¶
ResolveCell is Resolve for a reference that must be one cell.
func RunNotebooks ¶
RunNotebooks runs the code cells of each notebook tab, each after the cells it reads, as Run all does on the screen: each cell's output replaces the one the file kept and goes on to the sheet it was sent to. A failure stops its notebook's run, as on the screen. It returns a line for each cell that failed or couldn't run.
func Set ¶
Set types each entry into its cell, in order, as one change. An entry a cell can't take (a formula that doesn't parse, a validation rule that rejects it, part of an array, a pivot table or a region, a protected range without Force) stops it with an error naming the cell, and the workbook should then be thrown away rather than saved. Entries a rule would only mark invalid are set, and returned as warnings.
func Sort ¶ added in v0.4.0
Sort sorts the rows of the range ref names by keys, as Data > Sort range does, leaving its first row in place when header is set.
func SyncOutputs ¶
SyncOutputs sends the outputs a file kept to the sheets they were sent to, as opening the file on the screen does: reading, not running.
func Trusted ¶
Trusted reports whether the workbook's commands may run here without asking, by the rule macros follow: they were made or trusted on this computer, whose id is machine.
func WriteAtomic ¶
WriteAtomic writes a file with write into a temporary file of its own beside path, then renames it over path with mode.
func WriteDescription ¶ added in v0.4.0
func WriteDescription(w io.Writer, d Description) error
WriteDescription writes d as text: a line for each sheet saying what it holds, with what's on it indented below, then the named ranges.
Types ¶
type CellRun ¶ added in v0.4.0
type CellRun struct {
Notebook string `json:"notebook"`
Cell int `json:"cell"`
Name string `json:"name"`
State string `json:"state"` // "ran" or "failed"
Error string `json:"error"`
Output string `json:"output"` // NUON
Cut bool `json:"cut"` // Output was longer and is cut
}
CellRun is what running a notebook cell gave: its state, its output as NUON (cut at maxShownOutput), or why it failed.
func RunCell ¶ added in v0.4.0
func RunCell(ctx context.Context, w *sheet.Workbook, name string, n int, o NotebookOptions) (CellRun, error)
RunCell runs cell n (1 for the first) of the notebook tab named, as Run does on the screen: its output replaces the one kept and goes on to the sheet it was sent to. Whether it may run at all (trust, the shell setting) is the caller's to decide first.
type Change ¶ added in v0.4.0
type Change struct {
Kind string `json:"kind"`
Sheet string `json:"sheet"`
Item string `json:"item"`
Field string `json:"field"`
Old json.RawMessage `json:"old"`
New json.RawMessage `json:"new"`
}
Change is one change as 012 diff --format json lists it: what kind of thing changed (cell, sheet, region, name, macro or a layout field), on which sheet, which item, which field of it, and its old and new values, null where it wasn't or isn't there.
type ChartDescription ¶ added in v0.4.0
type ChartDescription struct {
Number int `json:"number"`
Title string `json:"title"`
Type string `json:"type"`
Data string `json:"data"`
At string `json:"at"`
}
ChartDescription is a chart: Number is what 012 export --chart and the MCP tools call it.
type ChartMade ¶ added in v0.4.0
type ChartMade struct {
Sheet string `json:"sheet"`
Number int `json:"number"`
Title string `json:"title"`
}
ChartMade says which chart AddChart made: its sheet and number, as describe lists it.
type ChartSpec ¶ added in v0.4.0
type ChartSpec struct {
Data string `json:"data" jsonschema:"the range to chart, e.g. Q3!A1:C9"`
Type string `json:"type,omitempty" jsonschema:"column, bar, line, pie, area or scatter; column when empty"`
Title string `json:"title,omitempty" jsonschema:"the title; guessed from the series when empty"`
At string `json:"at,omitempty" jsonschema:"the cell under the chart's top-left corner; right of the data when empty"`
Width int `json:"width,omitempty" jsonschema:"the width in terminal cells, 20 to 240; 60 when 0"`
Height int `json:"height,omitempty" jsonschema:"the height in terminal cells, 8 to 120; 18 when 0"`
ByRow bool `json:"by_row,omitempty" jsonschema:"series run along rows rather than down columns"`
Stack string `json:"stack,omitempty" jsonschema:"stacked or percent, for column, bar and area charts"`
}
ChartSpec is a chart to add, as Insert > Chart makes one: over Data, with the header row, category labels and title guessed as Sheets guesses them unless given.
type Description ¶ added in v0.4.0
type Description struct {
Sheets []SheetDescription `json:"sheets"`
Names []NameDescription `json:"names"`
}
Description is what a workbook holds, for 012 describe and the MCP describe tool: enough for agents (or people) to know which references to read and write without reading every cell. Its JSON form is a stable schema (docs/reference/json.md): fields are only added, never renamed or removed.
func Describe ¶ added in v0.4.0
func Describe(w *sheet.Workbook) Description
Describe describes the workbook as it is.
type Entry ¶
type Entry struct {
Ref string `json:"ref" jsonschema:"one cell, as formulas write it: B7, Q3!B7, 'Q3 plan'!B7"`
Input string `json:"input" jsonschema:"what to type, in en-US form: 1.5, =SUM(A1:A6), $1,200, 12%, 2026-09-29; empty clears the cell"`
}
Entry is one cell to set: a reference to one cell, and what to type in it, as the file stores entries (numbers and dates in en-US's form, formulas with commas, whatever the workbook's locale); "" clears it.
type Evaluated ¶ added in v0.4.0
type Evaluated struct {
Cell string `json:"cell"` // where it was computed
Value json.RawMessage `json:"value"` // typed as ReadRange types values
Text string `json:"text"` // as the cell would show it
Error string `json:"error"` // why, when Value is an error
Spill *Range `json:"spill,omitempty"`
}
Evaluated is a formula's result, computed without keeping it.
type ExportResult ¶ added in v0.4.0
type ExportResult struct {
File string `json:"file"`
Format string `json:"format"`
Rows int `json:"rows"`
Notes []string `json:"notes"`
}
ExportResult is what 012 export --report writes.
type File ¶
type File struct {
Path string
Book *sheet.Workbook
// New is set when there was no file at Path and Book is empty.
New bool
// contains filtered or unexported fields
}
File is a workbook opened from a .012 file.
func Open ¶
Open reads the workbook at path, with the notebook outputs it kept sent on to their sheets, as the screen opens it. With create, a path with no file opens as an empty workbook that Save writes there, as opening a new name in 012 does.
func (*File) Changes ¶ added in v0.4.0
Changes compares the workbook as it is with its file as it was opened (nothing, for a new file), before it's saved.
type FilterColumn ¶ added in v0.4.0
type FilterColumn struct {
Column string `json:"column" jsonschema:"a column letter (B) or the header's text"`
Condition string `` /* 139-byte string literal not displayed */
Value string `json:"value,omitempty" jsonschema:"what the condition compares with, as typed: 100, 2026-01-31, North"`
Hide []string `json:"hide,omitempty" jsonschema:"values to hide, as the cells show them"`
}
FilterColumn is one column's criteria for Filter: a condition (as Data > Create a filter's "Filter by condition" names them) with its value, and values to hide ("Filter by values").
type FindOptions ¶ added in v0.4.0
type FindOptions struct {
Ref string `json:"ref,omitempty" jsonschema:"a sheet or range to search; every sheet when empty"`
MatchCase bool `json:"match_case,omitempty"`
WholeCell bool `json:"whole_cell,omitempty" jsonschema:"the whole cell must match"`
Regex bool `json:"regex,omitempty" jsonschema:"the query is a regular expression"`
InFormulas bool `json:"in_formulas,omitempty" jsonschema:"search formulas' text rather than their values"`
Limit int `json:"limit,omitempty" jsonschema:"the most matches to return; 100 when 0"`
}
FindOptions tune Find.
type Found ¶ added in v0.4.0
Found is what Find returns: the first matches, and how many there are in all.
type GetOptions ¶
type GetOptions struct {
Format string // one of Formats; "" is text
// Input writes what was typed (a formula, or an entry as stored)
// rather than the value.
Input bool
// NoHeader names a JSON or NUON table's columns by their letters and
// makes every row a record, rather than taking the names from the
// first row.
NoHeader bool
}
GetOptions say how Get writes.
type Match ¶ added in v0.4.0
type Match struct {
Cell string `json:"cell"`
Text string `json:"text"`
Input string `json:"input"`
}
Match is a cell Find found: where, what it shows and what was typed.
type NameDescription ¶ added in v0.4.0
type NameDescription struct {
Name string `json:"name"`
Range string `json:"range"` // with its sheet: Q3!B2:B9, or #REF!
}
NameDescription is a named range.
type NotebookCell ¶ added in v0.4.0
type NotebookCell struct {
Number int `json:"number"`
Kind string `json:"kind"` // "code" or "note"
Name string `json:"name,omitempty"`
Source string `json:"source"`
// State is "ran", "failed" or "not run"; Error says why it failed.
State string `json:"state,omitempty"`
Error string `json:"error,omitempty"`
}
NotebookCell is one cell of a notebook tab.
type NotebookOptions ¶
type NotebookOptions struct {
Runner nushell.Runner // nu, or a fake in tests
Timeout time.Duration // for each cell
NuConfig bool // run nu with the user's config files
}
NotebookOptions say how RunNotebooks runs cells.
type Operation ¶ added in v0.4.0
type Operation struct {
Op string `` /* 151-byte string literal not displayed */
Ref string `` /* 135-byte string literal not displayed */
Input string `` /* 126-byte string literal not displayed */
Count int `json:"count,omitempty" jsonschema:"for insert_rows and insert_columns: how many; 0 inserts as many as ref spans"`
Name string `json:"name,omitempty" jsonschema:"for add_sheet and rename_sheet the sheet's name, for define_name the range's"`
Keys []SortKey `json:"keys,omitempty" jsonschema:"for sort: the columns to sort by, first first"`
Header bool `json:"header,omitempty" jsonschema:"for sort: the range's first row is a header and stays in place"`
}
Operation is one change of an Apply: what the MCP apply_operations tool takes, each the same engine call a menu command makes. Op says which, and the other fields are its arguments:
set Ref (one cell) and Input, as 012 set types it clear Ref: the range's contents, keeping formats and notes insert_rows before Ref's first row, Count rows (Ref's rows when 0) delete_rows Ref's rows insert_columns before Ref's first column, Count columns delete_columns Ref's columns add_sheet Name, after the last sheet rename_sheet Ref (a sheet) to Name delete_sheet Ref (a sheet) define_name Name for the range Ref sort Ref's rows by Keys, the first row left in place with Header
type PivotDescription ¶ added in v0.4.0
type PivotDescription struct {
Source string `json:"source"` // Sheet!A1:D99
}
PivotDescription is where a pivot table's data comes from.
type PivotSpec ¶ added in v0.4.0
type PivotSpec struct {
Source string `json:"source" jsonschema:"the data, header row included, e.g. Sales!A1:F99"`
Name string `json:"name,omitempty" jsonschema:"the new sheet's name; Pivot Table N when empty"`
Rows []string `json:"rows,omitempty" jsonschema:"columns whose values become rows, by header or letter"`
Columns []string `json:"columns,omitempty" jsonschema:"columns whose values become columns, by header or letter"`
Values []PivotValue `json:"values" jsonschema:"columns to summarize"`
Totals bool `json:"totals,omitempty" jsonschema:"add grand totals"`
}
PivotSpec is a pivot table to add, as Insert > Pivot table makes one: a new sheet summarizing Source, whose first row names its columns.
type PivotValue ¶ added in v0.4.0
type PivotValue struct {
Column string `json:"column" jsonschema:"by header or letter"`
Summarize string `json:"summarize,omitempty" jsonschema:"sum, counta, count, countunique, average, max or min; sum when empty"`
}
PivotValue is a column to summarize, and how.
type Problem ¶
type Problem struct {
Sheet string
Addr sheet.Addr
Value string // the error as the cell shows it: #DIV/0!
Why string // what the screen's context line says about it, or ""
// JEV is set when the error is a JEV function's with nothing to
// answer it: --jev asks the model.
JEV bool
}
Problem is a cell whose formula shows an error after recalculating.
func Errors ¶
Errors returns the cells of w showing errors, without recalculating. A cell an array spilled an error into is its formula's problem, so only formulas are listed.
type ProblemRecord ¶ added in v0.4.0
type ProblemRecord struct {
Cell string `json:"cell"` // with its sheet: Q3!B7
Sheet string `json:"sheet"`
Addr string `json:"addr"`
Value string `json:"value"` // #DIV/0!
Why string `json:"why"`
JEV bool `json:"jev"` // a JEV function's, answered with --jev
}
ProblemRecord is a formula showing an error.
func Problems ¶ added in v0.4.0
func Problems(ps []Problem) []ProblemRecord
Problems are problems as records.
type Range ¶ added in v0.4.0
type Range struct {
// Range is what was read, with its sheet: Q3!A1:D9; a whole sheet is
// read from A1 to its last cell with contents.
Range string `json:"range"`
Rows int `json:"rows"`
Cols int `json:"cols"`
// Values are the cells row by row, typed as 012 get --format json
// types one cell: numbers, strings, true or false, null for blank,
// dates as ISO 8601 strings, errors as their text (#DIV/0!).
Values [][]json.RawMessage `json:"values"`
// Text is each cell as the sheet shows it, when asked for.
Text [][]string `json:"text,omitempty"`
// Formulas are the formulas in the range by cell (B7: =SUM(B1:B6)).
Formulas map[string]string `json:"formulas"`
// Truncated is set when the range held more than the most cells a
// read returns; Rows says how many rows came back.
Truncated bool `json:"truncated"`
}
Range is a range's values as a grid, for agents: what ReadRange returns and the MCP read_range tool gives back. Its JSON form is a stable schema (docs/reference/json.md).
func ReadRange ¶ added in v0.4.0
func ReadRange(t Target, o ReadOptions) Range
ReadRange reads t's cells as a grid.
type ReadOptions ¶ added in v0.4.0
type ReadOptions struct {
MaxCells int // the most cells to return, whole rows at a time; 0 is 10,000
Text bool // also return each cell as shown
}
ReadOptions tune ReadRange.
type RecalcResult ¶ added in v0.4.0
type RecalcResult struct {
File string `json:"file"`
Errors []ProblemRecord `json:"errors"`
Circular bool `json:"circular"`
// NotebookFailures are the notebook cells --notebooks couldn't run.
NotebookFailures []string `json:"notebook_failures"`
}
RecalcResult is what 012 recalc writes.
type RegionDescription ¶ added in v0.4.0
type RegionDescription struct {
Name string `json:"name"`
Kind string `json:"kind"` // "output" or "linked"
Range string `json:"range"`
File string `json:"file,omitempty"` // a linked region's file
}
RegionDescription is a linked file or a notebook cell's output sent to the sheet.
type SetOptions ¶
type SetOptions struct {
// Force sets cells in protected ranges, which are refused otherwise,
// as the screen asks before editing them.
Force bool
}
SetOptions tune Set.
type SetResult ¶ added in v0.4.0
type SetResult struct {
File string `json:"file"`
Saved bool `json:"saved"`
Changes []Change `json:"changes"`
Warnings []string `json:"warnings"`
}
SetResult is what 012 set writes: the file, whether it was saved (not with --dry-run), what changed, and the warnings of entries a rule marks invalid.
type SheetDescription ¶ added in v0.4.0
type SheetDescription struct {
Name string `json:"name"`
Kind string `json:"kind"` // "sheet", "notebook" or "pivot"
Shown bool `json:"shown"`
Hidden bool `json:"hidden"`
// Used is the range from A1 to the last cell with contents, "" when
// the sheet is empty; Rows and Cols are its size.
Used string `json:"used"`
Rows int `json:"rows"`
Cols int `json:"cols"`
Cells int `json:"cells"`
Formulas int `json:"formulas"` // -1 on sheets too large to count them
Errors int `json:"errors"` // formulas showing errors; -1 when not counted
// Header is the row guessed to name the used range's columns, and
// Columns its names; 0 and none when no row looks like one.
Header int `json:"header_row"`
Columns []string `json:"columns"`
Frozen [2]int `json:"frozen"` // rows, columns
Filter string `json:"filter"` // the filtered range, or ""
Tables []TableDescription `json:"tables"`
Regions []RegionDescription `json:"regions"`
Charts []ChartDescription `json:"charts"`
Pivot *PivotDescription `json:"pivot,omitempty"`
Notebook []NotebookCell `json:"notebook_cells,omitempty"`
}
SheetDescription is one tab: a sheet or a notebook.
type SortKey ¶ added in v0.4.0
type SortKey struct {
Column string `json:"column" jsonschema:"a column letter (B) or the header's text"`
Descending bool `json:"descending,omitempty"`
}
SortKey is a column to sort by: a letter (B) or, with a header, the header's text.
type TableDescription ¶ added in v0.4.0
type TableDescription struct {
Name string `json:"name"`
Range string `json:"range"` // header row included
Columns []string `json:"columns"`
}
TableDescription is a named table.
type Target ¶
Target is what a reference names: a range of one sheet, or the whole sheet (from A1 to its last cell with contents).
func Resolve ¶
Resolve finds what ref names in w: a cell or range (B7, A1:C9, A:A), on a sheet (Q3!B7, 'Q3 plan'!A1:C9) or else the sheet shown when the file was saved; a named range (Sales); a table by name, all of it with its header row, or by a structured reference as formulas read it (Sales[Amount]); or a sheet by name (Q3, or Q3!), meaning all of it. "" is the whole sheet shown.