Gridline β¨
Gridline is a proof-of-concept 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.
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
- Load/reload user functions from a
.rhaifile (-fat startup,:sourceat runtime) - Two keymaps:
vim(default) andemacs - Plain text storage format (one cell per line)
- Simple plotting in a modal (bar/line/scatter)
Project status: this is a POC. Expect rough edges (especially around plotting and any non-trivial spreadsheet ergonomics).
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
Quick Start π
Build and run:
Open an example file:
Load custom Rhai functions at startup:
Reload / load functions at runtime:
:source examples/functions.rhai
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,MAXBARCHART,LINECHART,SCATTERVEC(convert a range to an array; respects direction:VEC(A3:A1)returns[A3, A2, A1])
Other built-ins:
RAND()- random float in[0.0, 1.0)RANDINT(min, max)- random integer in[min, max]inclusive
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
Useful commands:
:wor:w <path>save:qquit (warns if modified):q!force quit:wqsave and quit:e <path>open file:goto A100(alias:g A100) jump to a cell:colwidth 15set current column width:colwidth A 15set a specific column width:source <file.rhai>(alias:so) load functions;:soreloads the last functions file
Keymaps πΊοΈ
Select keybindings:
Status bar has an always-on cheat sheet, but the core controls are:
Vim:
hjklmove,i/Enteredit,Esccancelvvisual select,yyank,ppaste:wsave,:qquit
Emacs:
C-n/p/f/bmove,Enteredit,C-gcancelC-SPCset mark (visual),M-wcopy,C-ypasteC-ssave
File Format π
Gridline files are plain text. Non-empty, non-comment lines look like:
CELLREF: VALUE
Comments start with #. Values follow the same input rules as interactive editing.
Development π§
License π
Licensed under either of:
- Apache License, Version 2.0 (
LICENSE-APACHE) - MIT license (
LICENSE-MIT)