13 releases
Uses new Rust 2024
| 0.3.3 | Feb 6, 2026 |
|---|---|
| 0.3.2 | Feb 6, 2026 |
| 0.2.1 | Feb 5, 2026 |
| 0.1.6 | Feb 1, 2026 |
| 0.1.5 | Jan 31, 2026 |
#28 in Text editors
575KB
12K
SLoC
Gridline β¨
Gridline is a terminal spreadsheet with Rhai support. Cells can contain numbers, text, or formulas powered by the Rhai scripting language. Your sheet lives in a plain text file, and your reusable logic can live in a separate .rhai functions file.
Interfaces: TUI is the default and primary experience (cargo run, cargo install gridline) and is fairly mature. The GUI is behind a feature flag, still experimental, and subject to breaking changes as the vision evolves. webui is a planned future interface.
What you get (today):
- TUI grid with a formula bar and command mode
- A1-style references in formulas (
=A1 + B2) and range functions (=SUM(A1:B5)) - Dependency tracking and recalculation with undo/redo support
- Load/reload user functions from a
.rhaifile (-fat startup,:sourceat runtime) - Vim keybindings by default, optional Emacs keymap
- Regex cell search (
/pattern,:find,n/N) - Vim-style key sequences (
gg,dd,yy,cc,zf/zF) with count prefixes (5j,3p) - Custom keymaps via TOML (optional override)
- Plain text storage format (one cell per line)
- CSV import/export (
:import,:export) - Markdown export with ASCII charts (
-oflag or command mode) - Command-line evaluation mode (
-cflag) - Row/column insertion and deletion
- Simple plotting in a modal (bar/line/scatter)
- Interactive help system (
:help)
Why it's fun:
- π§Ύ Plain-text sheets you can diff and version
- π§ Formulas are real Rhai scripts (with spreadsheet sugar)
- π Quick plots right in the terminal
Screenshots
Fast, keyboard-first spreadsheets in your terminal: formulas, ranges, and a real formula bar.
Turn data into insight without context-switching: quick plots right where you work.
Go beyond cell-by-cell: SPILL + Rhai lets you generate and reshape tables with reusable logic.
Quick Start π
Build and run:
cargo run
Open an example file:
cargo run -- examples/plot.grid
# GUI (experimental, breaking changes expected)
cargo run --features gui --bin gridline-gui -- examples/plot.grid
# WebUI (stub / future)
cargo run --features webui --bin gridline-webui
Command-line Evaluation
Evaluate formulas without opening the TUI:
# Evaluate and print to stdout
cargo run -- -c "SUM(0..100)"
# Evaluate and export to markdown
cargo run -- -c "VEC(1..20).map(|x| POW(x, 2))" -o squares.md
# Export existing file to markdown
cargo run -- examples/plot.grid -o plot.md
Loading Functions
Load custom Rhai functions at startup (can specify multiple files):
cargo run -- -f examples/default.rhai examples/plot.grid
cargo run -- -f lib1.rhai -f lib2.rhai examples/plot.grid
Recommended default setup:
- Gridline looks for
default.rhaiin your OS config directory on startup. - Linux: typically
~/.config/gridline/default.rhai - If missing, Gridline prints the path it tried to stderr.
- Gridline still works without it, but this file is the intended baseline defaults.
- Disable auto-lookup with
--no-default-functions.
Install the repo's default file (Linux):
mkdir -p ~/.config/gridline
cp examples/default.rhai ~/.config/gridline/default.rhai
Load or reload functions at runtime:
:source examples/default.rhai
:so # reload all loaded files
Cell Input Rules π§Ύ
Gridline interprets cell input like this:
- empty / whitespace => empty cell
- leading
==> formula (Rhai script; stored without the=) - quoted
"text"=> text (quotes stripped) - otherwise, parseable as
f64=> number - else => text
Examples:
A1: 10
A2: "hello"
A3: =A1 * 2
A4: =SUM(A1:A3)
Formulas (Rhai + Spreadsheet Sugar) π§
Inside formulas:
A1becomescell(0, 0)(0-indexed internally)@A1becomesvalue(0, 0)(typed access: numbers/text/bools)SUM(A1:B5)becomessum_range(0, 0, 4, 1)
Arrays "spill" down the column.
If you need to do an in-place operation that returns () (like Rhai's Array.sort()), use OUTPUT:
A1: 30
A2: 10
A3: 20
B1: =OUTPUT(VEC(A1:A3), |v| { v.sort(); v })
Typed refs are useful when a referenced cell contains text (or a formula that returns text):
B1: =if C1 > 100 { "expensive" } else { "cheap" }
A1: =len(@B1)
Built-in range functions (ALL CAPS):
SUM,AVG,COUNT,MIN,MAXSUMIF(range, |x| condition)- sum values where predicate is trueCOUNTIF(range, |x| condition)- count cells where predicate is trueVEC(convert a range to an array; respects direction:VEC(A3:A1)returns[A3, A2, A1])SPILL(arr)orSPILL(range)- convert ranges/arrays to spillable arrays (also available as method:arr.SPILL())- Chart functions:
BARCHART,LINECHART,SCATTER(support optional title and axis labels)
Other built-ins:
ROW()- current cell's row (1-indexed)COL()- current cell's column (1-indexed)RAND()- random float in[0.0, 1.0)RANDINT(min, max)- random integer in[min, max]inclusivePOW(base, exp)- exponentiation (base^exp)SQRT(x)- square rootFIXED(n, decimals)- format number with fixed decimal places (returns text)MONEY(n, symbol[, decimals])- format as currency like"Β£15.04"(returns text)OUTPUT(value, fn)- apply function to value and return result (useful for in-place operations likesort())
Custom Functions Example π§©
Create a .rhai file:
fn fib(n) {
if n < 2 { n } else { fib(n - 1) + fib(n - 2) }
}
Load it (either -f or :source), then use it in a cell:
A1: "Fibonacci"
B1: 10
C1: =fib(B1)
Plotting π
Plotting works by making a formula cell return a tagged plot spec. The grid shows a placeholder (e.g. <BAR>), and you can open the plot modal.
Example (examples/plot.grid):
C1: =SCATTER(A1:B5, "title", "xaxis", "yaxis")
D1: =BARCHART(B1:B5)
Open the plot modal:
- Vim keymap:
P - Emacs keymap:
M-p
Commands β¨οΈ
Command mode:
- Vim:
: - Emacs:
M-x
File Operations
:wor:w <path>(alias:save) - save:q- quit (warns if modified):q!- force quit:wq- save and quit:new- create a new empty document (warns if modified):new!- create a new document and discard unsaved changes:e <path>(alias:open,:load) - open file:import <file.csv>- import CSV data at current cursor position:export <file.csv>- export grid to CSV format
Navigation
:goto A100(alias:g A100) - jump to a cell
Search
/pattern- regex search by displayed cell text (case-insensitive by default):find <pattern>(alias:search <pattern>) - run regex searchn/N(Vim keymap) - next / previous match
Grid Editing
:iror:insertrow- insert row above current row:dror:deleterow- delete current row:icor:insertcol- insert column to the left of current column:dcor:deletecol- delete current column:freeze(alias:fr) - freeze formula/spill at cursor to current value:freezeall(alias:fa) - freeze all formulas/spills to current values:colwidth 15(alias:cw) - set current column width:colwidth A 15- set a specific column width
Functions and Help
:source <file.rhai>(alias:so) - load functions;:sowith no args reloads all loaded files:call <expr>- execute a Rhai function/script expression in sheet context:rhai <expr>- execute an arbitrary Rhai expression in sheet context:helpor:h- open help modal
Keymaps πΊοΈ
Select keybindings:
gridline --keymap vim
gridline --keymap emacs
gridline --keymap vim --keymap-file /path/to/keymaps.toml
Keymap files (optional):
- Default location: config directory
gridline/keymaps.toml(platform-specific) - Override with
--keymap-file <path> - If a keymap name is not found in the file, Gridline falls back to the built-in map (
vimoremacs)- Linux:
~/.config/gridline/keymaps.toml - macOS:
~/Library/Application Support/gridline/keymaps.toml - Windows:
%APPDATA%\\gridline\\keymaps.toml
- Linux:
Sample keymap file:
examples/keymaps.toml
Status bar has an always-on cheat sheet, but the core controls are:
Vim Mode (default)
hjkl- move cursor[count]hjkl- move by count (5j,12l, etc.)Tab/Shift+Tab- move right / leftgthen any non-gkey - open:gotopromptgg/G- jump to first cell / last row with data/- open regex search promptn/N- next / previous search resultiorEnter- edit cellI- edit cell with cursor at startccorS- clear cell and enter edit modexorDelete- clear current cellEsc- cancel editv- visual select (start range selection)V- select current rowy- yank (copy)yy- yank current rowp- paste[count]p- paste repeatedlydd- delete current rowzf- freeze formula/spill at cursorzF- freeze all formulas/spillsu- undoCtrl+r- redo>or+- increase column width<or-- decrease column widthP- open plot modal:w- save:q- quit:help- open help modal
Emacs Mode (experimental)
Note: Emacs mode is incomplete and must be enabled with --keymap emacs. Some documented keybindings may not work as expected.
C-n/p/f/b- move cursor (next/previous/forward/back)C-v/M-v- page down / upC-a/C-e- first / last columnM-g- open goto promptEnter- edit cellC-g- cancel editC-dorDelete- clear current cellC-SPC- set mark (start visual selection)M-w- copyC-y- pasteM-sor/- open search promptM-r- next search resultM-p- open plot modalM-x- command mode
Use :w and :q in command mode for save/quit operations.
File Formats π
Grid Files (.grd / .grid)
Plain text format with one cell per line:
CELLREF: VALUE
Comments start with #. Values follow the same input rules as interactive editing.
CSV Import/Export
Import CSV data into your grid:
# In command mode
:import data.csv
Export grid to CSV:
# In command mode
:export output.csv
CSV features:
- Preserves leading zeros in numeric strings
- Handles quoted fields and escaped quotes
- Imports at current cursor position
Markdown Export
Export your grid as a markdown table with ASCII charts:
# Command-line export
cargo run -- examples/plot.grid -o output.md
# Or evaluate formula and export
cargo run -- -c "VEC(1..10).map(|x| x * x)" -o squares.md
The markdown export includes:
- Grid data as a markdown table
- ASCII renderings of any charts
- Row and column labels
Development π§
cargo fmt
cargo clippy --all-targets -- -D warnings
cargo test
License π
Licensed under either of:
- Apache License, Version 2.0 (
LICENSE-APACHE) - MIT license (
LICENSE-MIT)
Dependencies
~9β56MB
~841K SLoC