orgstar

Tables

Org tables are plain text that orgstar keeps aligned, edits by row and column, and recalculates with the same formulas Emacs uses.

Tables in Org

A table is a run of lines that start with |. Fields are separated by |, and a line that starts with |- is a horizontal rule:

| Name  | Qty | Price |
|-------+-----+-------|
| Apple |   3 |  0.50 |
| Pear  |  12 |  0.75 |

orgstar follows org-table.el from Org 9.8.7, with org-table-automatic-realign on, org-table-tab-jumps-over-hlines on, and formulas adjusted without asking when rows and columns move (org-table-fix-formulas-confirm nil). Tables inside dynamic blocks count as tables; tables inside other blocks don't.

Creating a table

Type |, a few field names separated by |, and press TAB: orgstar aligns the line as a table and moves to the next field, adding a row after the last one. Type |- on the line below a row and press TAB to turn it into a full-width rule.

org-table-create-or-convert-from-region builds one for you: C-c | in the Emacs and Doom presets, ⌃⌘\ in the Mac preset.

With no selection it asks Table size Columns x Rows [e.g. 5x2]:. An empty answer makes a 5 × 2 table. When there is more than one row, a rule follows the first row.

With text selected, the command converts the selected lines to a table instead (org-table-convert-region). The separator is guessed:

Moving around and alignment

KeyOrg commandAction
TABorg-table-next-fieldAligns the table and moves to the next field, skipping rules. In the last field it adds a row.
S-TABorg-table-previous-fieldAligns the table and moves to the previous field.
RETorg-table-next-rowAligns the table and moves down a row in the same column. Before a rule or at the end of the table it inserts a row.

These keys work the same in the Emacs and Mac presets. In Doom they apply in insert state; in normal state RET is Doom's "act at point" (see Recalculating).

Alignment (org-table-align) pads every field to its column's width and redraws rules to match. A column is right-aligned when at least half of its non-empty fields are numbers, and left-aligned otherwise. A field that holds only a cookie <l>, <c> or <r> (optionally with a width, such as <r10>) fixes the column's alignment. Widths count display columns, so wide characters and hidden link markup are measured as they appear.

Alignment happens when you press TAB, S-TAB or RET in a table and after every table command, not while you type. To align without moving, use Org ▸ Align Table:

PresetKey
EmacsC-c C-c in a table
Mac⌃⌘X in a table
DoomC-c C-c, or SPC m b a

C-c C-c (Mac ⌃⌘X) in a table is org-ctrl-c-ctrl-c, as in Emacs. It first evaluates a formula typed in the current field (see Entering formulas). Then, in a row marked # (see Names, parameters and constants), it recalculates that row, which also aligns the table; in any other row it aligns the table. With the caret at the table's very first character, it recalculates the whole table instead.

To align every table when a file opens, set org-startup-align-all-tables to true in the config file (default false), or put #+STARTUP: align in the file; #+STARTUP: noalign turns it off for that file. See Configuration.

Editing rows and columns

ActionOrg commandEmacsMacDoom
Move row uporg-table-move-row-upM-<up>⌃⌘↑M-<up>, M-k
Move row downorg-table-move-row-downM-<down>⌃⌘↓M-<down>, M-j
Move column leftorg-table-move-column-leftM-<left>⌃⌘←M-<left>, M-h
Move column rightorg-table-move-column-rightM-<right>⌃⌘→M-<right>, M-l
Insert columnorg-table-insert-columnM-S-<right>⌃⌥⌘→M-S-<right>, SPC m b i c
Delete columnorg-table-delete-columnM-S-<left>⌃⌥⌘←M-S-<left>, SPC m b d c
Insert row aboveorg-table-insert-rowM-S-<down>⌃⌥⌘↓M-S-<down>, SPC m b i r
Delete roworg-table-kill-rowM-S-<up>⌃⌥⌘↑M-S-<up>, SPC m b d r
Insert rule beloworg-table-insert-hlineC-c -⌃⌘-C-c -, SPC m b -, SPC m b i h
Sort rowsorg-table-sort-linesC-c ^⌃⇧⌘SC-c ^
Transposeorg-table-transpose-table-at-pointOrg ▸ Transpose TableOrg ▸ Transpose TableOrg ▸ Transpose Table
Edit field in its own editororg-table-edit-fieldC-c `Org ▸ Edit Table FieldC-c `

The new column goes to the left of the caret's column, empty. Deleting a row deletes the line; it doesn't go to the clipboard. When rows and columns move, are inserted or are deleted, the #+TBLFM line is updated to match: references are renumbered, and formulas for a deleted row or column are removed.

The Mac preset uses the same keys for headings and list items; in a table they act on the table.

Sorting

C-c ^ in a table asks Sort Table: [a]lphabetic, [n]umeric, [t]ime. A/N/T means reversed: and sorts the rows between the rules around the caret by the caret's column. If the caret isn't in a field, it asks for the column first. Sorting is stable.

Transposing

Org ▸ Transpose Table swaps rows and columns. Rules are dropped.

The field editor

C-c ` opens the field at the caret in an editor of its own, which is easier for long text. C-c ' or ⌘Return puts it back; Escape or C-c C-k leaves it unchanged. Line breaks become single spaces and lines that start with # are dropped, as org-table-finish-edit-field does.

Narrow columns

A field that holds a width cookie <N>, optionally with an alignment letter (<l10>, <c8>, <r12>), marks the column for narrowing. Narrowed fields show their first N display columns followed by …. The text itself is unchanged.

CommandOrg commandKeys
Org ▸ Shrink or Expand Table Columnorg-table-toggle-column-widthEmacs and Doom C-c TAB
Org ▸ Shrink Table Columns with Widthsorg-table-shrinkNo default key
Org ▸ Expand Table Columnsorg-table-expandNo default key

C-c TAB in a field toggles that column. Outside a column, for example on the leading |, it asks for Column ranges (e.g. 2-4 6-):, where 6- means column 6 to the end. A column without a width cookie shrinks to a bare … when toggled. Typing in a narrowed field widens its column again, as editing Org's overlays does. #+STARTUP: shrink narrows every column with a width cookie when the file opens.

The iOS editor narrows columns the same way, with #+STARTUP: shrink and the three commands, which are in Commands when the caret is in a table. The iOS reader shows tables at full width.

Importing and exporting

CommandOrg command
Import Table from File… (command palette)org-table-import
Export Table to File… (command palette)org-table-export

Open the command palette with ⇧⌘P (M-x in the Emacs preset, SPC : in Doom). On iOS, both are under More › Table in the editor, as Import Table from File…, Export Table as CSV… and Export Table as TSV…, and in Commands; the file comes from, and goes to, the Files app.

Import asks for a CSV, TSV or plain text file, inserts its contents at the caret on a line of its own, and converts them to a table with the separator guessed as for a region (see Creating a table).

Export writes the table at the caret. A file name ending in .csv gets CSV: fields separated by commas, with fields that contain a comma or a double quote quoted and inner quotes doubled. Any other name gets TSV. Rules are left out.

Import and export are Mac only.

Formulas

orgstar evaluates Org's spreadsheet formulas, org-table-recalculate and org-table-eval-formula, natively: Calc expressions in a reimplementation of the part of Emacs Calc that tables use, and Lisp formulas in a small Emacs Lisp evaluator. What falls outside them is handed to Emacs on the Mac (see When Emacs is needed).

Formulas live in a #+TBLFM: line right after the table, separated by :::

| Item  | Qty | Price | Total |
|-------+-----+-------+-------|
| Apple |   3 |  0.50 |  1.50 |
| Pear  |  12 |  0.75 |  9.00 |
|-------+-----+-------+-------|
| Sum   |     |       | 10.50 |
#+TBLFM: $4=$2*$3;%.2f::@>$4=vsum(@I..@II);%.2f

Blank lines between the table and #+TBLFM: are allowed. If there are several #+TBLFM: lines, recalculating the table uses the first; C-c C-c on another applies that line instead (org-table-calc-current-TBLFM).

Kinds of formula

Left sideKindApplies to
$3Column formulaEvery data row of column 3, except rows marked !, ^, _, $ or / in the first column.
$<, $>Column formulaThe first or last column.
@2$3, @>$3Field formulaOne field. Field formulas override column formulas.
@2$2..@4$3Range formulaEvery field in the rectangle.
@4Row formulaEvery field of data row 4.
$nameNamed field formulaThe field named by a ^ or _ row (see Names, parameters and constants).

A left side relative to the current row, such as @-1$2, is an error (Unknown field), and so is one relative to a rule, such as @I$2, as in Org. Two formulas for the same field are an error.

References

Rows count data lines from 1; rules don't count. Columns count from 1.

ReferenceMeaning
$2Column 2 in the current row.
$-1, $+1The column before or after the current one.
$<, $>, $>>The first column, the last, the one before last.
@3Row 3 in the current column.
@-1, @+1The row above or below.
@<, @>The first or last data row.
@I, @II, @IIIThe first, second, third rule; as a row, the line after it.
@-IThe rule above the current row.
@I+2Two data rows after the first rule.
@2$3Row 2, column 3.
$0The current column.
@0The current row: @0$2 is $2.
@#, $#The current row's or column's number, as a value.
@2$1..@4$3A range: the fields of the rectangle, as a vector.
$1..$3Columns 1 to 3 of the current row.
@I..@IIThe current column from the first rule to the second.

In a Calc formula a single field becomes a number in parentheses, and a range becomes a vector such as [1,2,3]. Without the E flag, empty fields count as 0 on their own and are left out of ranges.

Fields in a Calc formula must hold numbers, timestamps or nan, unless the N flag reads every field as a number. A reference to a field with other text needs Emacs, because Calc would treat the text as a symbol.

Names, parameters and constants

The first column can mark special rows, as in Org's spreadsheet:

MarkRow
#Marked for recalculation.
*Marked for recalculation.

When any row's first field is one of !, ^, _, $, # or *, column formulas in a whole-table recalculation apply only to the rows marked # or *, as org-table-calculate-mark-regexp decides in Org. So a table with a ! names row and no # rows gets no column formulas applied; mark the rows to calculate. Field formulas apply either way. Rows marked !, ^, _, $ or / are never changed by column formulas.

| ! | qty | price | total |
|---+-----+-------+-------|
| # |   2 |     3 |     6 |
| # |   4 |   0.5 |     2 |
#+TBLFM: $4=$qty*$price

A $name that isn't a column name, parameter or named field is looked up as org-table-get-constant does:

A name that isn't found becomes #UNDEFINED_NAME. A parameter named % in a $ row, for example %=%.2f, is put in front of the flags of every formula that has a ;, so $3=$2/3; is formatted with %.2f.

Remote references

remote(NAME, REF) reads a field or range from another table:

#+NAME: rates
| item | rate |
|------+------|
| a    |    2 |
| b    |    3 |

| x | y | z |
|---+---+---|
| 4 | 8 | 5 |
#+TBLFM: $2=$1*remote(rates,@2$2)::$3=vsum(remote(rates,@2$2..@>$2))

NAME is found in this order:

  1. a table after #+NAME: NAME or #+TBLNAME: NAME in the same file;
  2. the first table in the entry whose ID property is NAME, in the same file;
  3. the first table in the entry with that ID in any indexed file in your sidebar folders, read from the file on disk.

REF may use spreadsheet-style references such as B3 (column B, row 3), which become @3$2. A REF without a row, such as $1..$2, reads the row of the other table that has the current row's number. NAME can itself be a reference: in remote($1,@1$1), the current row's first field holds the table's name.

Calc expressions

Calc formulas use Calc's number rules: integers are exact, and decimal numbers are rounded to 12 significant digits after every operation. Results are shown with up to 8 significant digits unless a format flag says otherwise (org-calc-default-modes).

Operators, from lowest to highest precedence (the lowest, ||, is logical or, giving 1 or 0):

OperatorMeaning
&&Logical and.
==, !=, <, >, <=, >=Comparisons, giving 1 or 0. They can't be chained.
+, -Addition and subtraction.
/, %, \Division, modulo (sign of the divisor), integer division rounding down.
*Multiplication.
unary -Negation.

Parentheses group, [a, b, c] writes a vector, <2026-10-05 Mon> writes a date, and nan is "not a number".

Functions:

FunctionResult
vsum, vprodSum or product of a vector.
vcountNumber of elements.
vmean, vmedianMean, median.
vmax, vminLargest, smallest element.
vvar, vsdevSample variance, sample standard deviation.
vpvar, vpsdevPopulation variance, population standard deviation.
max(a, b, …), min(a, b, …)Largest, smallest argument.
if(c, a, b)a if c is nonzero, else b.
absAbsolute value.
floor, ceil, truncRound down, up, toward zero, to an integer.
round(x), round(x, n)Round to an integer, or to n decimal places.
mod(a, b), idiv(a, b)As % and \.
factFactorial of a non-negative integer.
sqrt, exp, ln, log10Square root, exponential, natural and base-10 logarithm.
sin, cos, tanTrigonometry, in degrees unless the R flag is set.
arcsin, arccos, arctanInverse trigonometry, in degrees unless R.

Other Calc functions, variables such as pi or e, symbolic results, complex results and division by zero need Emacs.

Mode flags and formats

After the formula, a ; starts its flags, as in $3=$1/$2;%.2f or $4=$1*2;f2:

FlagMeaning
nNFloat format with N significant digits.
fNFixed format with N decimal places.
sNScientific format with N digits.
eNEngineering format with N digits.
pNCalc precision. Only p12, the default, is evaluated natively; others need Emacs.
D, RAngles in degrees (the default) or radians.
FPrefer fractions: 1/3 stays 1:3.
NTreat every field as a number; text counts as 0.
EKeep empty fields: in ranges they stay in, and count as nan in Calc.
LLiteral: in Lisp formulas, insert fields as they are written.
TDurations: read H:MM and H:MM:SS fields as times, show the result as HH:MM:SS.
UAs T, showing HH:MM.
tAs T, showing decimal hours with two places, such as 1.50.

The flags S (symbolic) and u need Emacs. Any other text after the flags is a format string applied to the result, such as %.2f or %d; format supports %s, %S, %d, %o, %x, %X, %c, %e, %f and %g.

Durations

With T, U or t, fields like 1:30 or 10:00:30 are read as hours, minutes and seconds:

| start    | end     | sum      | diff  | hours |
|----------+---------+----------+-------+-------|
| 1:30     | 0:45    | 02:15:00 | 00:45 |  3.00 |
| 10:00:30 | 2:15:10 | 12:15:40 | 07:45 | 20.02 |
#+TBLFM: $3=$1+$2;T::$4=$1-$2;U::$5=$1*2;t

Dates

Timestamps in fields, active or inactive, take part in Calc arithmetic as dates. The difference of two dates is a number of days, with a fraction when the timestamps have times. A date plus a number is a date, written back as an inactive timestamp:

| start            | end              | days | later            |
|------------------+------------------+------+------------------|
| <2026-10-05 Mon> | <2026-10-12 Mon> |    7 | [2026-10-12 Mon] |
#+TBLFM: $3=$2-$1::$4=$1+7

Lisp formulas

A formula that starts with '( is Emacs Lisp. Each reference becomes a Lisp string, or a number with N, or the field's text inserted as is with L. A range becomes the values separated by spaces, so wrap it in a quoted list:

| name  | greeting |
|-------+----------|
| Ada   | Ada!     |
| Grace | Grace!   |
#+TBLFM: $2='(concat $1 "!")

| n |
|---|
| 1 |
| 2 |
|---|
| 3 |
#+TBLFM: @>$1='(apply '+ '(@I..@II));N

The evaluator supports:

Any other function needs Emacs. An error inside a Lisp formula writes #ERROR in the field, as does a Calc error.

Entering formulas

There are three ways to set a formula.

In the field. Type =expr in a field and press TAB or RET: orgstar stores $N=expr as the column's formula and evaluates it, as org-table-maybe-eval-formula does. Type :=expr instead to store a field formula @R$C=expr.

With a prompt. org-table-eval-formula asks for the formula (Column formula $N= or Field formula @R$C=) with the stored one filled in, stores it and evaluates it in the current field. Clearing the prompt and pressing Return removes the stored formula, as in Emacs, and the echo area shows Formula removed. You can also delete a formula in the formula editor below or from the #+TBLFM: line.

CommandEmacsMacDoom
Org ▸ Set Column FormulaC-c =Org ▸ Set Column FormulaC-c =
Org ▸ Set Field FormulanoneOrg ▸ Set Field Formulanone

Org's C-u C-c = for field formulas has no equivalent key, because orgstar has no prefix argument; use the menu item or type := in the field.

In the formula editor. C-c ' in a table or on its #+TBLFM: line (org-table-edit-formulas) opens the formulas in an editor of their own, one per line, grouped under # Column Formulas, # Field and Range Formulas and # Named Field Formulas. A formula can continue on indented lines. C-c ' or ⌘Return installs the formulas; Escape or C-c C-k leaves them unchanged. Installing doesn't recalculate. The echo area says so and points to Recalculate Table: C-c C-c on the #+TBLFM: line, or ⌃⌘X there in the Mac preset.

The formulas are stored sorted the way org-table-formula-less-p sorts them.

Recalculating

CommandOrg commandEmacsMacDoom
Recalculate Tableorg-table-recalculate with C-uC-c C-c on #+TBLFM:⌃⌘X on #+TBLFM:SPC m b r, C-c C-c on #+TBLFM:
Recalculate Table Roworg-table-recalculateC-c *⌃⌘* (⌃⇧⌘8 on a US keyboard)C-c *
Iterate Table Formulasorg-table-iterateC-u C-u C-c *——

In Doom's normal state, RET in a table recalculates it when it has a #+TBLFM: line and aligns it otherwise; on a #+TBLFM: line it recalculates.

When the table has a rule below its first data row, recalculating the whole table leaves the rows above that rule, the header, alone. With marked rows, the marks decide instead (see Names, parameters and constants). Each command evaluates the column formulas row by row, then the field formulas, then aligns the table. Each formula is evaluated once. Iterate Table Formulas recalculates the whole table again and again until it stops changing, for formulas that depend on each other's results, at most ten times. The echo area says Convergence after 3 iterations, or Table was already stable; after ten passes that still change the table it says No convergence after 10 iterations, and the ten passes stay. C-u C-c * also recalculates the whole table in the Emacs preset.

A row marked # is recalculated when you press TAB, S-TAB or RET in it, before the caret moves (org-table-maybe-recalculate-line), and with C-c C-c (Mac ⌃⌘X). Other rows are recalculated only by the commands above. Emacs skips a second automatic recalculation of the same row by the same command in a row; orgstar recalculates each time, which gives the same result unless a formula depends on its own value.

When Emacs is needed

When a formula uses something the native evaluator doesn't have, the command reports what it was and the Mac recalculates the table in Emacs instead. This happens for:

The echo area shows Recalculating in Emacs (reason)…, then Recalculated in Emacs. orgstar runs emacs -Q --batch on a copy of the file, so your Emacs init file, packages and customizations are not loaded, then replaces the table with Emacs's result. It looks for Emacs at the path in the ORGSTAR_EMACS environment variable, then /opt/homebrew/bin/emacs, /usr/local/bin/emacs, /Applications/Emacs.app/Contents/MacOS/Emacs, /run/current-system/sw/bin/emacs and /usr/bin/emacs. If none is found, the echo area says Emacs isn't installed and the table is unchanged. Emacs gets your PATH with /opt/homebrew/bin, /usr/local/bin, /Library/TeX/texbin, /usr/bin and /bin added, as code blocks and export do, so programs a formula starts are found when orgstar was opened from the Dock. The run stops after 60 seconds. If you edit the table while Emacs is working, its result is discarded.

Edit ▸ Cancel Running Task (⌘.) stops the recalculation; the echo area shows Recalculation canceled and the table is unchanged. Starting another recalculation or export in Emacs cancels the one that is running.

If the table's formulas contain Lisp, orgstar asks first: This table's formulas run Lisp. Run them? (yes, no, always). always trusts this table's text in this file, so the question isn't asked again until the text changes.

Entering a formula that needs Emacs with C-c =, Set Field Formula or = in a field is not handed to Emacs. The formula is stored in the #+TBLFM: line and the field is left as it was; the echo area shows The formula was stored; recalculating it needs Emacs and the reason. TAB and RET still move to the next field. Recalculate the table to run the formula in Emacs.

For how orgstar and Emacs share files, see Using orgstar alongside Emacs.

table.el tables

Tables drawn with + corners and - and | borders, as the table.el package makes them, are recognized and kept as written:

+-------+-------+
| Name  | Value |
+-------+-------+
| a     | 1     |
+-------+-------+

Edit the text in the cells as usual. TAB and S-TAB line the borders up, then move to the next or previous cell, wrapping around at the ends of the table, as table.el's table-forward-cell and table-backward-cell do; the caret goes to the cell's first character. C-c C-c (Mac ⌃⌘X) lines the borders up without moving. Lining up makes each column as wide as its widest text, and never narrower than its rules: text typed into a cell uses up the spaces at its end first, as table.el does when you type.

Org edits table.el tables in table.el's own buffer, with C-c ', and says so for TAB and C-c C-c; orgstar does the editing in place instead. Tables with merged cells, which span rows or columns, can be moved through but not lined up ("Can't align a table.el table with merged cells"). Formulas, sorting and the other table commands don't apply.

HTML export renders them as tables, with cells that span rows and columns, and Markdown export writes them as a code block. See Export.

Plotting

Plot Table (org-plot/gnuplot, C-c " g in the Emacs and Doom presets, and in the command palette; More › Table on iOS) draws the table at the caret, or the first table after it, as the #+PLOT: lines above it say:

#+PLOT: title:"Sales" ind:1 deps:(2 3) type:2d with:linespoints file:"sales.png"
| month | north | south |
|-------+-------+-------|
|     1 |    20 |    12 |
|     2 |    25 |    18 |
OptionMeaning
type2d (the default), 3d or grid
indThe column of x values, counting from 1; 0 (the default) plots against row numbers
depsThe columns to plot, as a list such as (2 3); all but ind by default
withlines (the default), points, linespoints, impulses, boxes, histograms, steps, fsteps
titleThe plot's title
fileWhere the image goes, relative to the Org file's folder; without it the plot shows in a sheet
labelsNames for the columns, as a list; a header row above a rule names them otherwise
mapWith t, a 3d plot is seen from above
ymin, ymax, xmin, xmaxThe axes' ranges; min and max are ymin and ymax
ticksHow many marks the y axis has
transposeWith yes, rows become columns
set, line, script, timefmtgnuplot commands, a line of gnuplot, a gnuplot script file and the time format, for gnuplot

Options are read as Org reads them, quirks included: an option's name also matches inside a longer word (timeind:t sets ind), an unquoted value ends at a ., , or ;, set: options before the last line: are dropped, and each set: and line: that's kept comes twice, as Org reads the options twice. An ind column of timestamps is plotted as dates, and one of text as labels.

On the Mac, when gnuplot is installed (orgstar looks on the same PATH as code blocks), the table goes to gnuplot as Emacs sends it: the same data file and script, so every option and gnuplot's own terminals and styles apply. A plot without file: is drawn to an image and shown in a sheet. Without gnuplot, and on iOS, orgstar draws the plot itself with Swift Charts: 2d as lines, points or bars by with:, grid as a heat map, 3d as a surface (a wireframe in a file). file: then takes .png, .jpg or .pdf, 640 by 480 points as gnuplot's default; the gnuplot-only options are ignored. If inline images are showing, a link to the file shows the new plot.

type:radar needs gnuplot; orgstar reports it.

On iOS

The iOS app evaluates formulas natively with the same engine. Tables that need Emacs are not recalculated there; the app reports This table needs Emacs, which runs on the Mac with the reason. Import and export are under More › Table, with Plot Table. Narrow columns work in the editor, as described under Narrow columns. See iOS.