- commit
- 6252ea8e458186e6ae8320f866fd12bd627518bf
- parent
- 17704157b87f766535290a151c5ea259aa92afe5
- author
- Dami <dami.etoile@gmail.com>
| M | README.md | 188 | +++++++++++------------------- |
| A | docs/ | 18 | +++ |
| A | docs/ | 58 | +++++++++ |
| A | docs/ | 48 | ++++++++ |
| A | docs/ | 70 | +++++++++++ |
| A | docs/ | 38 | ++++++ |
| A | docs/ | 75 | ++++++++++++ |
| A | docs/ | 39 | ++++++ |
| A | docs/ | 72 | +++++++++++ |
| A | docs/ | 51 | ++++++++ |
@@ -1,132 +1,84 @@
11 # 01222 33 A spreadsheet for the terminal with a Lotus 1-2-3 look and Google Sheets4-behavior, built on Bubble Tea v2.4+behavior, built on [Bubble Tea v2](https://github.com/charmbracelet/bubbletea).5+6+Inside the grid it works the way Sheets does: typing replaces a cell, `=`7+starts a formula, Enter and Tab move you on, Shift+arrows and the mouse8+select, and Sheets' shortcuts do what you expect. Around the grid, the9+control panel, the mode indicator and the character grid keep 1-2-3's look.10+It is one pure-Go binary.11+12+## Install513 614 ```sh7-make run # build (pure Go, CGO_ENABLED=0) and start8-./bin/012 budget.0129-./bin/012 sales.xlsx # or .csv, .tsv, .sqlite, .parquet, .wk1: imported15+go install github.com/FelineStateMachine/012/cmd/012@latest1016 ```1117 12-## Keys13-14-Inside the grid, 012 works like Google Sheets.15-16-| Key | Action |17-|---|---|18-| Type | Replace the cell. `=` starts a formula, `'` forces text; `$1,200`, `12%`, `9/26/2026` and `14:30` are numbers that keep their format |19-| Enter / Tab | Accept and move down / right (Enter returns to where a run of Tabs began) |20-| Enter or F2, double-click | Edit the cell |21-| Arrows while typing a formula | After an operator, pick a cell; Shift+arrows pick a range |22-| Shift+arrows, drag, Shift+click | Select; the status line shows Sum, Avg and Count |23-| Ctrl+arrows | Jump to the edge of the data (add Shift to select) |24-| Click a header, Ctrl+Space, Shift+Space | Select whole columns or rows |25-| Ctrl+A | Select the data, then everything |26-| Del / Backspace | Clear the selection (formatting stays) |27-| Ctrl+Z, Ctrl+Y or Ctrl+Shift+Z | Undo, redo |28-| Ctrl+C, Ctrl+X, Ctrl+V | Copy, cut, paste; references adjust as in Sheets, and copies also go to the system clipboard |29-| Ctrl+Shift+V | Paste values only |30-| Paste from the terminal | Tab-separated or multi-line text fills a block of cells |31-| Ctrl+D, Ctrl+R | Fill down, fill right; top rows that start a series (1, 2 over blanks) continue it |32-| Drag the fill handle | The ▟ at the selection's corner, shown on hover: continue a series (1, 2, 3; Jan, Feb; Mon, Tue; dates; Item 1, Item 2) or copy |33-| View > Freeze | Keep rows or columns on screen while the rest scrolls |34-| Data > Sort sheet, Sort range | Sort by the active column A to Z or Z to A, or pick columns and order on a bar (Left/Right column, Space order, Alt+A add, Alt+H header row) |35-| Alt+Down, click ▾ in a header | With a filter (Data > Create a filter): pick the column's values (Space checks, type to search) or a condition |36-| Ctrl+Alt+= / Ctrl+Alt+- | Insert rows above / delete the selected rows (columns when whole columns are selected) |37-| Ctrl+Enter while typing | Enter the same entry in every selected cell |38-| F4 while typing a formula | Cycle the reference at the caret through A1, $A$1, A$1, $A1 |39-| Typing a function or range name | Suggestions drop down: Up/Down pick, Tab or Enter insert, Esc hides them; inside a function's parentheses the context line shows its arguments with the current one marked |40-| Alt+, / Alt+. | Trace precedents / dependents: highlight the cells a formula reads, or the formulas that read the cell, and jump to the first; press again for the next, Esc to go back (Excel's Ctrl+[ and Ctrl+], which terminals send as Esc) |41-| Data > Named ranges | Name ranges for formulas (`=SUM(Sales)`): Enter goes to one, F2 renames or repoints it, Ctrl+D deletes it; Data > Define named range names the selection |42-| Ctrl+Shift+1 ... 6 | Number, time, date, currency, percent, scientific format |43-| Ctrl+B, Ctrl+I, Ctrl+U, Alt+Shift+5 | Bold, italic, underline, strikethrough |44-| Ctrl+Shift+L / E / R | Align left, center, right |45-| Ctrl+\ | Clear formatting |46-| Ctrl+S, Ctrl+O, Ctrl+Q | Save, open (imports other formats), quit |47-| Ctrl+G or F5 | Go to a cell, a range or a named range |48-| Alt+F, Alt+E, Alt+V, Alt+I, Alt+O, Alt+H, F10, click a title | Open a menu (arrows move, Enter runs, Esc closes) |49-| Ctrl+K, Alt+/, Ctrl+Shift+P | Search the menus: find and run any command |50-| Right-click, Shift+F10 | Cell, column or row menu |51-| F1 or Ctrl+/ | Keyboard shortcuts |52-| Insert > Chart | Chart the selection (or the table around the active cell); the editor bar picks the type with Left/Right, S switches rows and columns, H and L toggle the header row and labels, R changes the range, T the title |53-| Click a chart, then Arrows / Shift+arrows / Del | Move, resize or delete it; drag the chart or its corner with the mouse; Enter edits it |54-| Cmd- or Ctrl-click a URL | Open it: cells holding a URL, and `=HYPERLINK(url, [label])`, are terminal hyperlinks |55-56-Charts float over the grid and redraw as their data changes. In terminals57-with the kitty graphics protocol (kitty, Ghostty, WezTerm; detected by58-asking the terminal at startup) the plot is a real image, drawn in the59-terminal's own palette; elsewhere, and in tmux without passthrough, it is60-drawn with block and braille characters. Error cells get a curly underline61-and the context line explains them, e.g. `#DIV/0! Division by zero in62-B3/0`. When a long job such as JEV answers finishes while the window is in63-the background, 012 sends a desktop notification (OSC 9).64-65-The top three lines are the menu bar and mode indicator, the formula bar66-(name box, then the cell's contents or the entry being typed) and the67-context line (prompts, key hints, formula errors).68-69-## Files70-71-Sheets save as `.012` files (JSON, one line per cell). Other formats come72-in through File > Import, File > Open or the command line, and go out73-through File > Download. Imports run in the background with a progress74-bar; Esc cancels. Saving an imported sheet asks whether to save it as a75-`.012` file or download it back in its format.76-77-| Format | Import | Download |78-|---|---|---|79-| CSV, TSV | Delimiter (`,` `;` tab `\|`), UTF-8 BOM, UTF-16 and Windows-1252 detected; entries become numbers, dates, currency and percentages as if typed; formulas stay text | Values as shown, as Sheets' Download does |80-| Excel `.xlsx` | First sheet: values, formulas, number formats, bold, italic, underline, strikethrough, alignment, column widths. Formulas 012 can't read (other sheets, unknown functions) keep their values | The same, with formulas in Excel's syntax and their results cached. JEV functions and `#AND#` save as values |81-| SQLite | Pick a table or view, or type a query; a header row names the columns | The sheet or the selection as a table, first row as column names; a table of that name is replaced |82-| Parquet | Every column, with dates and timestamps; lists joined with commas | |83-| Lotus 1-2-3 `.wk1`, `.wks` | Numbers, labels with their alignment, formats, column widths, formulas translated (references, operators, `@SUM`, `@AVG`, `@IF`, `@ROUND`, `@PMT` and 60 more) or kept as values | |84-85-## JEV functions86-87-With a TypeSafe API key, four functions ask the hosted JEV model about a88-value (a cell, a range or text). They follow Sheets' argument style: the89-value, the question, then what the answers mean.90-91-| Function | Returns | Like |92-|---|---|---|93-| `=JEV.TEST(A2, "Is this a complaint?", [yes means], [no means])` | TRUE or FALSE | an `IF` condition, a boolean mask |94-| `=JEV.PROB(A2, "Is this a complaint?")` | probability of yes, as a percent | `predict_proba` |95-| `=JEV.CLASSIFY(A2, "Sentiment", "negative, positive", [descriptions])` | the best label | `SWITCH`, `pd.cut` |96-| `=JEV.SCORE(A2, "Urgency", "low, mid, high")` | a score from 0 to levels-1 | a rating scale |97-98-Labels, descriptions and levels can also be ranges. Answers arrive in the99-background (cells show `Loading…`), are cached by question, and the context100-line shows the confidence for the selected cell. Data > Ask JEV again101-re-asks the selection.102-103-Set `TYPESAFE_API_KEY` in the environment or a `.env` file in the current104-directory or next to the sheet; `TYPESAFE_BASE_URL` and105-`TYPESAFE_DEFAULT_MODEL` are optional. Without a key the functions show106-`#N/A` and say why. `JEV_LIVE_TEST=1 go test ./internal/jev -run TestLive`107-checks the real service.108-109-## Layout18+Requires Go 1.27. Or from a clone: `make build` puts the binary in `bin/012`.11019 111-```112-cmd/012 entry point113-internal/sheet engine: addresses, Pratt parser, evaluator, recalc, file format114-internal/fileio import and export: CSV, TSV, XLSX, SQLite, Parquet, Lotus .wk1115-internal/ui Bubble Tea model: modes, menu, prompts, rendering116-e2e/ end-to-end tests: real binary on a pty, rendered by libghostty-vt117-oracle/ differential tests of formulas and formats against excelize20+```sh21+012 # a new sheet22+012 budget.012 # open or create a sheet23+012 sales.xlsx # import .xlsx, .csv, .tsv, .sqlite, .parquet or Lotus .wk111824 ```11925 120-## Tests26+F1 shows every shortcut, F10 or Alt+letter opens the menus, and Ctrl+K27+searches every command.28+29+## What it does30+31+- **Sheets-style editing.** Formulas with 120 Sheets-compatible functions,32+ autocomplete and argument hints, pointing at cells with the arrows or the33+ mouse, named ranges, undo and redo for everything, copy and paste with34+ reference adjustment and the system clipboard, fill series, insert and35+ delete rows and columns.36+- **Formats and styles.** Currency, percent, dates and times detected as you37+ type; number formats, bold, italic, underline, strikethrough, alignment.38+- **Data tools.** Freeze rows and columns, multi-column sort, filters with39+ value pickers and conditions, find and replace with regular expressions,40+ tracing precedents and dependents.41+- **Charts.** Column, bar, line and pie charts that float over the grid and42+ update live; real images in terminals with the kitty graphics protocol43+ (kitty, Ghostty, WezTerm), text elsewhere.44+- **Files.** A diff-friendly JSON format, plus import from CSV, TSV, XLSX,45+ SQLite, Parquet and Lotus 1-2-3 `.wk1`, and export to CSV, TSV, XLSX and46+ SQLite.47+- **JEV functions.** `JEV.TEST`, `JEV.PROB`, `JEV.CLASSIFY` and `JEV.SCORE`48+ ask TypeSafe's hosted JEV model about your data, answered in the background49+ and cached ([docs](docs/jev.md)).50+- **Made for terminals.** Mouse with hover and resize handles, hyperlinks,51+ light and dark themes that follow the terminal, desktop notifications,52+ menus and a command palette styled like terminal software, not a GUI.53+54+## Documentation55+56+- [Keys and mouse](docs/keys.md)57+- [Entries and formulas](docs/formulas.md) and [functions](docs/functions.md)58+- [Working with data](docs/data.md)59+- [Charts, links and the terminal](docs/charts.md)60+- [Files](docs/files.md)61+- [JEV functions](docs/jev.md)62+- [Architecture](docs/architecture.md), [UX bar](docs/UX.md) and [testing](docs/testing.md)63+- [Roadmap](ROADMAP.md)64+65+## Development12166 12267 ```sh123-make test # engine and UI unit tests124-make fuzz # fuzz the formula parser125-make e2e # builds libghostty-vt from source with Zig, then runs e2e tests126-make oracle # compare formulas and number formats with excelize68+make build # pure Go, CGO_ENABLED=069+make test # unit tests70+make e2e # the real binary in libghostty, Ghostty's terminal core (needs Zig 0.16+ and pkg-config)71+make screens # golden screens and the review gallery72+make oracle # formulas and formats against excelize12773 ```12874 129-`make e2e` needs Zig 0.16+ and `pkg-config`. It is a separate Go module so the130-cgo dependency never reaches the main binary; so is `oracle`, which keeps131-its calculation engine out of the tests. `oracle/oracle_test.go` lists the formulas skipped132-because Sheets and Excel disagree or excelize departs from Excel.75+See [docs/testing.md](docs/testing.md).76+77+## Status78+79+Young and moving quickly. The file format is versioned and older files keep80+loading; the Go packages are internal and may change at any time.81+82+## License83+84+[MIT](LICENSE)@@ -0,0 +1,18 @@
1+# 012 documentation2+3+**Using 012**4+5+- [Keys and mouse](keys.md): every shortcut, the mouse, and what's on screen6+- [Entries and formulas](formulas.md): what you type, references, names, errors7+- [Functions](functions.md): all of them, generated from the engine8+- [Working with data](data.md): selection, copy and fill, undo, freeze, sort, filter, find9+- [Charts, links and the terminal](charts.md): charts, hyperlinks, terminal features used10+- [Files](files.md): the `.012` format, import and export11+- [JEV functions](jev.md): asking a hosted model from formulas12+13+**Working on 012**14+15+- [Architecture](architecture.md): how the engine and UI fit together16+- [UX and visual bar](UX.md): the rules every change follows17+- [Testing](testing.md): unit, end-to-end through libghostty, golden screens, the excelize oracle18+- [Roadmap](../ROADMAP.md)@@ -0,0 +1,58 @@
1+# Architecture2+3+012 is a single pure-Go binary (`CGO_ENABLED=0`) built on Bubble Tea v2 and4+Lip Gloss v2.5+6+```7+cmd/012 entry point: flags, JEV setup, opening or importing a file8+internal/sheet the engine: cells, parsing, evaluation, recalculation, undo, files9+internal/fileio import and export: CSV, TSV, XLSX, SQLite, Parquet, Lotus .wk110+internal/chart chart layout, text rendering and kitty image encoding11+internal/jev JEV configuration, answer cache and TypeSafe client12+internal/ui the Bubble Tea model: modes, menus, overlays, rendering13+e2e/ end-to-end tests through libghostty (separate module, cgo)14+oracle/ differential tests against excelize (separate module)15+```16+17+## The engine18+19+`internal/sheet` knows nothing about terminals. Cells live in a sparse map20+from address to cell; each cell keeps what was typed, its parsed expression,21+its computed value, and its format and style.22+23+- **Parsing.** A hand-written Pratt parser turns formulas into an AST,24+ keeping absolute markers so references can be rewritten when cells move.25+ A printer turns ASTs back into text in Sheets' spelling.26+- **Recalculation.** Formulas record the cells and ranges they read.27+ Changing a cell marks it and everything that transitively depends on it,28+ then evaluates the marked cells lazily in dependency order; a cell reached29+ again while it is being evaluated is part of a cycle. Volatile functions30+ (TODAY, RAND, the JEV functions) are recomputed on every recalculation.31+- **Functions.** One table (`FuncDef`) holds every function's name,32+ signature, description and arity; it drives parsing, evaluation,33+ autocomplete, in-app help and [functions.md](functions.md).34+- **Undo.** Every mutation goes through a small set of paths that snapshot35+ the cells, widths, names, charts and view state they change, so a step can36+ be reversed exactly; multi-cell operations are one step.37+- **JEV.** The engine never touches the network. JEV functions describe a38+ question and look up the answer in a pluggable source; `internal/jev`39+ answers from a cache and queues new questions, and the UI sends them as40+ background commands.41+42+## The UI43+44+`internal/ui` is one Bubble Tea model. Inside the grid it follows Google45+Sheets; around it, the control panel keeps a 1-2-3 look. Every action is a46+registered command with a title and description, reached from key bindings,47+the menu bar, context menus, the command palette and the help overlay, so48+they can't disagree. Menus, the palette and pickers are overlays composited49+with Lip Gloss layers over the grid, which never shifts under them. Only the50+visible cells are rendered. Styles come from a small set of theme roles51+with dark and light variants built on the terminal's 16 ANSI colors, so the52+user's palette applies.53+54+See [UX.md](UX.md) for the rules every change follows.55+56+## Testing57+58+See [testing.md](testing.md).@@ -0,0 +1,48 @@
1+# Charts, links and the terminal2+3+## Charts4+5+Insert > Chart charts the selection, or the table around the active cell,6+guessing the header row, the label column and a title. The chart floats over7+the grid, pinned to a cell, and redraws when its data changes.8+9+The chart editor is a bar on the context line: Left/Right (or 1 to 4) picks10+column, bar, line or pie; S switches series between rows and columns; H and11+L toggle the header row and labels; R points at a new range; T edits the12+title. Enter keeps the changes, Esc undoes them.13+14+Click a chart to select it. Drag it to move it, drag its corner to resize it,15+or use the arrows and Shift+arrows; Enter edits it, Del deletes it, and16+right-click offers both. Charts follow inserted and deleted rows and17+columns, and save with the sheet.18+19+**Images or text.** At startup 012 asks the terminal whether it supports the20+kitty graphics protocol. Where it does (kitty, Ghostty, WezTerm) the plot is21+a real image, drawn in the terminal's own palette and placed with Unicode22+placeholders, so redraws never erase it. Elsewhere, and usually inside tmux,23+the plot is drawn with block and braille characters. Axis labels, the24+legend and the frame are text either way.25+26+## Links27+28+Cells that hold an `http`, `https` or `mailto` URL, and `=HYPERLINK(url,29+[label])`, are terminal hyperlinks (OSC 8): Cmd- or Ctrl-click opens them in30+terminals that support it.31+32+## Terminal features 012 uses33+34+| Feature | What for | Where it works |35+|---|---|---|36+| Kitty keyboard protocol | telling apart keys like Ctrl+I and Tab, Shift+Enter | kitty, Ghostty, WezTerm, foot, Alacritty, iTerm2 |37+| Mouse, all motion | hover highlights, drag, resize | most terminals |38+| Pointer shape (OSC 22) | resize and text cursors over the grid | Ghostty, kitty, foot, xterm |39+| Kitty graphics | chart images | kitty, Ghostty, WezTerm |40+| Hyperlinks (OSC 8) | links in cells | most modern terminals |41+| Clipboard (OSC 52) | copying ranges | most terminals; tmux needs `set-clipboard on` |42+| Progress (OSC 9;4) | JEV and import progress in the tab | Ghostty, Windows Terminal, iTerm2 |43+| Notifications (OSC 9) | when JEV or an import finishes in the background | iTerm2, Ghostty, WezTerm |44+| Curly, colored underlines | error cells | kitty, Ghostty, WezTerm, iTerm2, Alacritty |45+| Background color query and mode 2031 | light and dark themes, following system changes | most terminals; 2031 in Ghostty and kitty |46+| Synchronized output (2026) | flicker-free redraws | kitty, Ghostty, WezTerm, iTerm2, Alacritty |47+48+Everything degrades quietly where it isn't supported.@@ -0,0 +1,70 @@
1+# Working with data2+3+## Selection4+5+Shift+arrows, a mouse drag or Shift+click select a range; Ctrl+arrows jump6+to the edge of the data (add Shift to select as you go); Ctrl+A selects the7+data around the active cell, then everything; Ctrl+Space and Shift+Space8+select whole columns and rows. The active cell stays distinct from the rest9+of the selection, and the status line shows Sum, Avg and Count, dropping the10+ones that don't fit on a narrow terminal.11+12+## Copy, paste and fill13+14+Ctrl+C, Ctrl+X and Ctrl+V work as in Sheets: relative references shift,15+absolute ones don't, cut and paste moves cells and the formulas that point16+at them follow. Ctrl+Shift+V pastes values only. Copies also go to the17+system clipboard as tab-separated text (OSC 52, so it works over SSH), and18+pasting tab-separated or multi-line text from the terminal fills a block.19+20+Ctrl+D and Ctrl+R fill down and right. The fill handle, shown when you hover21+the corner of the selection, can be dragged to continue a series: 1, 2, 3;22+2, 4, 6; Jan, Feb; Mon, Tue; dates by day or month; Item 1, Item 2. Ctrl+Enter23+while typing enters the same entry into every selected cell.24+25+## Undo26+27+Ctrl+Z undoes and Ctrl+Y or Ctrl+Shift+Z redoes, 100 steps deep. Every change28+is covered: typing, clearing, paste, fill, sort, insert and delete, formats,29+widths, names, charts, freeze and filters. A multi-cell change is one step,30+and the context line says what was undone, e.g. `Undid: clear B3:B5`.31+32+## Rows and columns33+34+Insert and delete rows and columns from the Insert and Edit menus, the35+right-click menus, or Ctrl+Alt+= and Ctrl+Alt+- (rows, or columns when whole36+columns are selected). Formulas, names, charts, filters and widths follow.37+Drag a column header's edge to resize it, or use Format > Column width.38+39+## Freeze40+41+View > Freeze keeps rows or columns on screen while the rest scrolls, marked42+by thin divider lines. The mouse and keys treat the frozen area as Sheets43+does.44+45+## Sort46+47+Data > Sort sheet sorts by the active column A to Z or Z to A, keeping frozen48+rows on top. Data > Sort range sorts the selection, or the block of data49+around the active cell; its advanced option opens a bar to sort by several50+columns (Left/Right picks a column, Space flips the order, Alt+A adds a51+column, Alt+H toggles the header row). The order follows Sheets: numbers,52+then text ignoring case, then booleans, then errors, with blanks last.53+54+## Filter55+56+Data > Create a filter puts a filter on the selection or the table around57+the active cell; headers show `▾`. Alt+Down or a click on `▾` opens the58+column's filter: check values in a searchable list, or pick a condition such59+as "greater than" or "text contains". Filtered-out rows are hidden, not60+deleted: row numbers show the gap, navigation skips them, formulas still61+count them, and the status line says how many rows are hidden.62+63+## Find and replace64+65+Ctrl+F opens a find bar on the context line: matches highlight as you type,66+the active cell follows the current one, and Enter and Shift+Enter step67+through them. Ctrl+H adds a replacement field; Enter replaces and moves on,68+Ctrl+Enter replaces all as one undo step. Chips toggle match case (Alt+C),69+whole cell (Alt+W), regular expressions (Alt+R, with `$1` in replacements),70+searching formulas (Alt+=), and limiting the search to the selection (Alt+S).@@ -0,0 +1,38 @@
1+# Files2+3+Sheets save as `.012` files (JSON, one line per cell). Other formats come4+in through File > Import, File > Open or the command line, and go out5+through File > Download. Imports run in the background with a progress6+bar; Esc cancels. Saving an imported sheet asks whether to save it as a7+`.012` file or download it back in its format.8+9+| Format | Import | Download |10+|---|---|---|11+| CSV, TSV | Delimiter (`,` `;` tab `\|`), UTF-8 BOM, UTF-16 and Windows-1252 detected; entries become numbers, dates, currency and percentages as if typed; formulas stay text | Values as shown, as Sheets' Download does |12+| Excel `.xlsx` | First sheet: values, formulas, number formats, bold, italic, underline, strikethrough, alignment, column widths. Formulas 012 can't read (other sheets, unknown functions) keep their values | The same, with formulas in Excel's syntax and their results cached. JEV functions and `#AND#` save as values |13+| SQLite | Pick a table or view, or type a query; a header row names the columns | The sheet or the selection as a table, first row as column names; a table of that name is replaced |14+| Parquet | Every column, with dates and timestamps; lists joined with commas | |15+| Lotus 1-2-3 `.wk1`, `.wks` | Numbers, labels with their alignment, formats, column widths, formulas translated (references, operators, `@SUM`, `@AVG`, `@IF`, `@ROUND`, `@PMT` and 60 more) or kept as values | |16+17+## The native format18+19+`.012` files are JSON with one line per cell, keyed by address, so diffs20+read naturally and files merge reasonably in version control:21+22+```json23+{24+ "version": 2,25+ "widths": {"A": 14},26+ "cells": {27+ "A1": "Rent",28+ "B1": {"input":"1450","format":"currency","decimals":2},29+ "B3": "=SUM(B1:B2)"30+ }31+}32+```33+34+A cell without formatting is just what was typed; a formatted cell is a35+small object. Version 3 adds named ranges, frozen panes and a filter, and is36+only written when a sheet uses one of them, so older builds of 012 can open37+everything else. Charts are an optional `charts` field that older builds38+ignore. Saves are atomic: 012 writes a temporary file and renames it.@@ -0,0 +1,75 @@
1+# Entries and formulas2+3+## What you type4+5+Typing replaces the active cell, as in Google Sheets. 012 decides what the6+entry is the way Sheets does:7+8+| You type | You get |9+|---|---|10+| `Rent`, `Q3 total` | text |11+| `42`, `-3.5`, `1,234`, `1e3` | a number |12+| `$1,200`, `12%` | a number with currency or percent format |13+| `9/26/2026`, `2026-09-26`, `Sep 26, 2026`, `14:30`, `2pm` | a date or time (a serial number with a date or time format) |14+| `TRUE`, `false` | a boolean |15+| `=A1*2`, `+A1*2` | a formula |16+| `'42` | text, even though it looks like a number |17+18+A formula that doesn't parse isn't accepted: 012 stays in EDIT mode with the19+caret on the problem and says what's wrong on the context line, e.g.20+`Expected , or ) in SUM`.21+22+## References23+24+- Cells: `A1`, ranges: `A1:B3` (1-2-3's `A1..B3` also works).25+- Absolute parts: `$A$1`, `A$1`, `$A1`. F4 while typing cycles the reference26+ at the caret through them. Copying, filling, sorting and inserting or27+ deleting rows and columns adjust the relative parts, as in Sheets;28+ references to deleted cells become `#REF!`.29+- Named ranges: `=SUM(Sales)`. Define them from Data > Named ranges or Data >30+ Define named range. Names are case-insensitive, follow the selection when31+ rows move, and renaming one rewrites the formulas that use it.32+- The worksheet is 256 columns (A to IV) by 8,192 rows, 1-2-3's size; see33+ [limits.md](limits.md) for what that means in practice.34+35+## Building formulas36+37+- After an operator or `(`, arrow keys (or a click) pick a cell and insert38+ its reference; Shift+arrows (or a drag) pick a range. Keep typing to go on.39+- While you type a name, suggestions drop down: named ranges first, then40+ functions with their arguments. Tab or Enter inserts `NAME(`.41+- Inside a function's parentheses the context line shows its signature with42+ the current argument marked, e.g. `SUMIF(range, criterion, [sum_range])`.43+- Alt+, and Alt+. trace precedents and dependents: the cells a formula reads44+ and the formulas that read a cell. Press again to step through them.45+46+## Operators47+48+`+ - * / ^` for arithmetic, `&` to join text, `= <> < > <= >=` to compare49+(giving TRUE or FALSE), `%` after a number divides by 100. Unary minus binds50+tighter than `^` as in Sheets and Excel, so `=-2^2` is 4. 1-2-3's `#AND#`,51+`#OR#` and `#NOT#` still work; `AND()`, `OR()` and `NOT()` are the Sheets way.52+53+## Values and errors54+55+Text in arithmetic is `#VALUE!` unless it reads as a number (`="3"*2` is 6);56+blanks count as 0 or empty text. Aggregates such as `SUM` over a range skip57+text. Errors use Sheets' codes:58+59+| Error | Meaning |60+|---|---|61+| `#DIV/0!` | division by zero |62+| `#VALUE!` | the wrong kind of value, e.g. text in arithmetic |63+| `#NAME?` | an unknown name |64+| `#REF!` | a reference to deleted cells, or a circular reference |65+| `#N/A` | not available, e.g. a lookup found nothing |66+| `#NUM!` | a number out of range, e.g. `SQRT(-1)` |67+68+Error cells are red with a curly underline, and the context line explains the69+active cell's error and where it came from, e.g.70+`#DIV/0! From B3: division by zero in B5/0`, or names the chain of a71+circular reference.72+73+## Functions74+75+See [functions.md](functions.md) for all of them, generated from the engine.@@ -0,0 +1,39 @@
1+# JEV functions2+3+With a TypeSafe API key, four functions ask the hosted JEV model about a4+value (a cell, a range or text). They follow Sheets' argument style: the5+value, the question, then what the answers mean.6+7+| Function | Returns | Like |8+|---|---|---|9+| `=JEV.TEST(A2, "Is this a complaint?", [yes means], [no means])` | TRUE or FALSE | an `IF` condition, a boolean mask |10+| `=JEV.PROB(A2, "Is this a complaint?")` | probability of yes, as a percent | `predict_proba` |11+| `=JEV.CLASSIFY(A2, "Sentiment", "negative, positive", [descriptions])` | the best label | `SWITCH`, `pd.cut` |12+| `=JEV.SCORE(A2, "Urgency", "low, mid, high")` | a score from 0 to levels-1 | a rating scale |13+14+Labels, descriptions and levels can also be ranges. Answers arrive in the15+background (cells show `Loading…`), are cached by question, and the context16+line shows the confidence for the selected cell. Data > Ask JEV again17+re-asks the selection.18+19+Set `TYPESAFE_API_KEY` in the environment or a `.env` file in the current20+directory or next to the sheet; `TYPESAFE_BASE_URL` and21+`TYPESAFE_DEFAULT_MODEL` are optional. Without a key the functions show22+`#N/A` and say why. `JEV_LIVE_TEST=1 go test ./internal/jev -run TestLive`23+checks the real service.24+25+## How requests behave26+27+- Requests run in the background, eight at a time; the status line counts28+ them and terminals that support it (OSC 9;4) show progress in the tab.29+- Answers are cached by the exact question (value, question and criteria),30+ so recalculating, undo and redo never ask twice, and `JEV.TEST` and31+ `JEV.PROB` on the same question share one request.32+- Errors in the inputs (`#DIV/0!` in the value, an empty question, fewer33+ than two labels, more than the service's 255 labels or 10 score levels)34+ show as errors at once and are never sent.35+- A failed request shows `#ERROR!`, and the context line says why.36+- 012 never logs or saves the API key; `.env` files are read for37+ `TYPESAFE_*` settings only.38+39+The client is [typesafe-go](https://github.com/FelineStateMachine/typesafe-go).@@ -0,0 +1,72 @@
1+# Keys and mouse2+3+Inside the grid, 012 behaves like Google Sheets: if you know a Sheets4+shortcut, try it. Everything is also reachable from the menus (F10 or5+Alt+letter) and the command palette (Ctrl+K), which shows each command's6+shortcut. F1 or Ctrl+/ lists every binding, generated from the same table7+the app uses, so it never drifts from what the keys do.8+9+Inside the grid, 012 works like Google Sheets.10+11+| Key | Action |12+|---|---|13+| Type | Replace the cell. `=` starts a formula, `'` forces text; `$1,200`, `12%`, `9/26/2026` and `14:30` are numbers that keep their format |14+| Enter / Tab | Accept and move down / right (Enter returns to where a run of Tabs began) |15+| Enter or F2, double-click | Edit the cell |16+| Arrows while typing a formula | After an operator, pick a cell; Shift+arrows pick a range |17+| Shift+arrows, drag, Shift+click | Select; the status line shows Sum, Avg and Count |18+| Ctrl+arrows | Jump to the edge of the data (add Shift to select) |19+| Click a header, Ctrl+Space, Shift+Space | Select whole columns or rows |20+| Ctrl+A | Select the data, then everything |21+| Del / Backspace | Clear the selection (formatting stays) |22+| Ctrl+Z, Ctrl+Y or Ctrl+Shift+Z | Undo, redo |23+| Ctrl+C, Ctrl+X, Ctrl+V | Copy, cut, paste; references adjust as in Sheets, and copies also go to the system clipboard |24+| Ctrl+Shift+V | Paste values only |25+| Paste from the terminal | Tab-separated or multi-line text fills a block of cells |26+| Ctrl+D, Ctrl+R | Fill down, fill right; top rows that start a series (1, 2 over blanks) continue it |27+| Drag the fill handle | The ▟ at the selection's corner, shown on hover: continue a series (1, 2, 3; Jan, Feb; Mon, Tue; dates; Item 1, Item 2) or copy |28+| View > Freeze | Keep rows or columns on screen while the rest scrolls |29+| Data > Sort sheet, Sort range | Sort by the active column A to Z or Z to A, or pick columns and order on a bar (Left/Right column, Space order, Alt+A add, Alt+H header row) |30+| Alt+Down, click ▾ in a header | With a filter (Data > Create a filter): pick the column's values (Space checks, type to search) or a condition |31+| Ctrl+Alt+= / Ctrl+Alt+- | Insert rows above / delete the selected rows (columns when whole columns are selected) |32+| Ctrl+Enter while typing | Enter the same entry in every selected cell |33+| F4 while typing a formula | Cycle the reference at the caret through A1, $A$1, A$1, $A1 |34+| Typing a function or range name | Suggestions drop down: Up/Down pick, Tab or Enter insert, Esc hides them; inside a function's parentheses the context line shows its arguments with the current one marked |35+| Alt+, / Alt+. | Trace precedents / dependents: highlight the cells a formula reads, or the formulas that read the cell, and jump to the first; press again for the next, Esc to go back (Excel's Ctrl+[ and Ctrl+], which terminals send as Esc) |36+| Data > Named ranges | Name ranges for formulas (`=SUM(Sales)`): Enter goes to one, F2 renames or repoints it, Ctrl+D deletes it; Data > Define named range names the selection |37+| Ctrl+Shift+1 ... 6 | Number, time, date, currency, percent, scientific format |38+| Ctrl+B, Ctrl+I, Ctrl+U, Alt+Shift+5 | Bold, italic, underline, strikethrough |39+| Ctrl+Shift+L / E / R | Align left, center, right |40+| Ctrl+\ | Clear formatting |41+| Ctrl+S, Ctrl+O, Ctrl+Q | Save, open (imports other formats), quit |42+| Ctrl+G or F5 | Go to a cell, a range or a named range |43+| Alt+F, Alt+E, Alt+V, Alt+I, Alt+O, Alt+H, F10, click a title | Open a menu (arrows move, Enter runs, Esc closes) |44+| Ctrl+K, Alt+/, Ctrl+Shift+P | Search the menus: find and run any command |45+| Right-click, Shift+F10 | Cell, column or row menu |46+| F1 or Ctrl+/ | Keyboard shortcuts |47+| Insert > Chart | Chart the selection (or the table around the active cell); the editor bar picks the type with Left/Right, S switches rows and columns, H and L toggle the header row and labels, R changes the range, T the title |48+| Click a chart, then Arrows / Shift+arrows / Del | Move, resize or delete it; drag the chart or its corner with the mouse; Enter edits it |49+| Cmd- or Ctrl-click a URL | Open it: cells holding a URL, and `=HYPERLINK(url, [label])`, are terminal hyperlinks |50+51+## Mouse52+53+Click a cell to select it, drag to select a range, Shift+click to extend,54+and click a column or row header (or the corner) to select whole columns,55+rows or everything. Double-click edits. Drag a column header's right edge56+to resize it; double-click the edge to fit the contents. Dragging past the57+edge of the grid scrolls. Right-click opens the cell, column or row menu.58+The mouse pointer changes shape over cells, resize handles and the formula59+bar in terminals that support it (OSC 22).60+61+In Ghostty and xterm, Shift+click normally starts the terminal's own text62+selection; 012 asks the terminal to pass it through (XTSHIFTESCAPE) and63+restores that on exit.64+65+## The screen66+67+The top three lines are the **menu bar** with the mode indicator on the68+right, the **formula bar** (name box, then the cell's contents or the entry69+being typed) and the **context line**, which holds prompts, key hints,70+formula errors and explanations. The bottom line is the **status line**:71+the file name, whether it's modified, and Sum, Avg and Count for a72+selection.@@ -0,0 +1,51 @@
1+# Testing2+3+```sh4+make test # engine, file formats and UI unit tests5+make fuzz # fuzz the formula parser and the CSV and .wk1 readers6+make oracle # compare formulas and number formats with excelize7+make e2e # run the real binary in a terminal emulator (needs Zig and pkg-config)8+make screens # rewrite the golden screens and build the review gallery9+```10+11+## Unit tests12+13+The engine is tested directly: parsing, every function, recalculation,14+undo, reference rewriting, file round trips. The UI is tested by sending15+Bubble Tea messages (keys, mouse, paste, window size) to the model and16+reading what `View` renders, without a terminal.17+18+## End to end, through libghostty19+20+`e2e/` builds the real `012` binary, runs it on a pseudo-terminal and feeds21+its output into [libghostty-vt](https://github.com/ghostty-org/ghostty),22+Ghostty's terminal emulator core. Keystrokes and mouse events are encoded23+by libghostty itself from the modes the app turned on, so they are the bytes24+Ghostty would send. Tests assert on what a user would see: screen text,25+cursor position, window title, hyperlinks, which screen is active after26+quitting. A fake TypeSafe server answers JEV questions, and the harness27+clears `TYPESAFE_API_KEY` so tests never reach the real service.28+29+`make e2e` builds libghostty-vt from source with Zig into `.deps/` on first30+use. It is its own Go module so cgo never reaches the main binary.31+32+## Golden screens33+34+`e2e/screens_test.go` records key UI states as HTML drawn from libghostty's35+cell grid (colors as palette variables, so one golden serves every theme),36+with light-terminal variants. `make screens` rewrites them and builds37+`e2e/testdata/screens/gallery.html` with dark and light reference palettes.38+Every visual change is reviewed there before it's committed.39+40+## The excelize oracle41+42+`oracle/` translates formulas to Excel syntax, computes them with43+[excelize](https://github.com/xuri/excelize), and compares results and44+formatted values with 012's. Known differences between Sheets and Excel,45+and places where excelize departs from Excel, are listed as skips with a46+reason.47+48+## Live checks49+50+`JEV_LIVE_TEST=1 go test ./internal/jev -run TestLive` asks the real JEV51+service one question of each kind, using `TYPESAFE_API_KEY`.