org.nvim

Tables and formulas

Start a row with |. |- becomes a separator line (hline) when the table is aligned.

Insert mode:  <Tab>/<S-Tab>  next / previous field (realigns; creates rows)
              <CR>           same column in the next row
              <S-CR>         copy the field down (see below)
              <M-CR>         move the text after the cursor to the start
                             of the field below (org-table-wrap-region;
                             meta_return_split_line false or per context
                             { table = false }: just go to that field)
Like Emacs, <Tab> jumps over hlines (table_tab_jumps_over_hlines = false
adds a row before them instead). <Tab>, <S-Tab>, <CR> and leaving Insert
mode realign the table; with table_automatic_realign = false only adding
a row and <C-c><C-c> do (org-table-automatic-realign). A # row is
recalculated by <Tab> and <CR> unless
table_allow_automatic_line_recalculation is false. The first character
typed right after
one of them replaces the field's text (table_auto_blank_field), and a
character typed into a field ending with two or more spaces takes the place
of one of them, so the table stays aligned. <BS> and <Del> in Insert mode
put a space before the field's separator for the character they delete
(org-delete-backward-char, org-delete-char), and | is inserted as it is
(org-force-self-insert).
Normal mode:
  <C-c><C-c>      realign; in a row marked # recalculate that row; with a
                  count recalculate the table (4) or iterate it (16); on
                  a #+TBLFM line apply that line (see below); on
                  #+PLOT: plot; on #+ORGTBL: recalculate and send
  <C-c>*          recalculate the current row (column formulas of the row
                  and every field formula); count 4: the whole table;
                  count 16: until it no longer changes (org-table-iterate)
  <M-h/l>         move column left / right (also <M-Left/Right>)
  <M-k/j>         move row up / down (also <M-Up/Down>)
  <M-H>/<M-L>     delete / insert column
  <M-K>/<M-J>     delete row / insert row above
  <M-CR>          go to the same field in the row below (adding one
                  before an hline or at the end); in Visual mode (and
                  :Org table_wrap_region) wrap the text of the selected
                  column like a paragraph into as many lines (a count:
                  that many); with a count, append the field to the field
                  above (org-table-wrap-region)
  <S-Up/Down/Left/Right>  swap the field with its neighbour
  <S-CR>          copy the field one row down and move there; in an empty
                  field, copy the nearest non-empty field above (count: the
                  Nth). Numbers, text starting or ending with a number and
                  dates are incremented (table_copy_increment)
                  In tmux, <S-CR> arrives as <CR> unless extended keys
                  are on: set -s extended-keys on and
                  set -as terminal-features 'xterm*:extkeys'
  <C-c>+          sum the column (or the Visual selection) into the
                  unnamed register: every row, header included; as soon as
                  one field is H:MM[:SS], plain numbers count as hours and
                  the sum is H:MM:SS (org-table-sum)
  <C-c><Tab>      shrink / expand the column (see org-table-shrink)
  <C-c>`          edit the field in a prompt; count 4: show a shrunk
                  column in full; count 16: follow-field mode
  <C-c>{          toggle the formula debugger (org-table-debugger)
  <C-c>"a <C-c>"g ASCII bar plot / gnuplot plot (org-plot)
  <prefix>Tc      create a table (table_default_size, "5x2"), or convert
                  CSV/TSV/whitespace (Visual mode; count 4: comma, 16:
                  tab, N: N+ spaces; at most
                  table_convert_region_max_lines lines, also for
                  table_import)
  <prefix>T-      insert a hline (<C-c>- with a count: above)
  <prefix>Tf      recalculate the whole table
  <prefix>Ts      sort rows (<C-c>^, see below)
  <prefix>Tr/TR   insert / delete row
  <prefix>Ti/TI   insert / delete column
  <prefix>Tt      transpose the table (hlines are dropped)
  <prefix>T#      rotate the recalculation mark  # * ! $ _ ^ of the row
                  (Visual mode: set a mark on every selected row); a
                  marker column is added when needed
  <prefix>'       the formula editor (org-table-formula-editor)
  :Org table_import   insert a CSV/TSV/whitespace file as a table
  :Org table_export   write the table with a translator: the file and
                      format come from the TABLE_EXPORT_FILE and
                      TABLE_EXPORT_FORMAT (orgtbl-to-latex :splice t)
                      properties when set, else from prompts: the format
                      is picked from a list (org-choice-list; e adds
                      parameters) that starts on the one matching the
                      file extension, else table_export_default_format
  :Org table_iterate  :Org table_recalc_buffer (all tables, iterated)
  :Org table_goto_column  go to field N (the count) of the row
                      (org-table-goto-column)

Inserting, deleting and moving rows and columns rewrites the references of every #+TBLFM line below the table like Emacs org-table-fix-formulas: $3=$1+$2 becomes $2=$INVALID+$1 when column 1 is deleted, formulas that assign to a deleted row or column are removed, references inside remote() are left alone. Set table_fix_formulas_confirm to be asked first. A new row copies a #, * or $ mark of the current row.

Sorting (<C-c>^, org-table-sort-lines) sorts the rows between the hlines around the cursor, or the rows of the Visual selection: a text (emphasis markers and link brackets ignored; case-insensitive, case-sensitive with a count), n numbers, t timestamps, durations and H:MM, f a key function typed as Lua (function(s) return #s end) with an optional comparison function; the uppercase letters sort in reverse.

Alignment: a column is right-aligned when at least table_number_fraction (0.5) of its fields are numbers, i.e. match table_number_regexp (an Emacs regexp, matched ignoring case; the default is Emacs's). #+STARTUP: align (or startup_align_all_tables) aligns every table when the file is opened (noalign turns it off). <l>, <r> and <c> cookies (<r10> with a width) fix the alignment; cookie cells are aligned like the column.

Type =formula in a field and press <Tab>, <CR> or <C-c><C-c>: it becomes the column formula of that column (:=formula a field formula for that field), is stored in #+TBLFM and the field is computed (<C-c>* updates the rest). table_formula_evaluate_inline turns this off. Like Emacs, a formula computed this way (or with <C-c>=) replaces $name names only with table_formula_use_constants (true); recalculating the table always does.

<C-c>= reads the formula of the current column (count: of the current field, or its ^/_ name; count 16: put the active formula into the field as =... for editing), stores it and computes the field. An empty formula removes it. A1-style references (B3, C&) are accepted when typed (table_use_standard_references).

Formulas go in #+TBLFM: lines below the table:

| Item  | Qty | Price | Total |
|-------+-----+-------+-------|
| Apple |   3 |  0.50 |  1.50 |
| Pear  |   2 |  0.75 |  1.50 |
|-------+-----+-------+-------|
| Sum   |     |       |  3.00 |
#+TBLFM: $4=$2*$3;%.2f::@>$4=vsum(@I..@II);%.2f
Only the first #+TBLFM: line is used. Keep alternatives in more lines
below it and press <C-c><C-c> on one of them to apply it once
(org-table-calc-current-TBLFM). Storing formulas (<C-c>=, inline formulas,
the formula editor) rewrites only the first line (or the edited one), with
the formulas sorted like Emacs.
References:
  $2  $>  $<  $>> $+1 $-1    columns
  @3  @>  @<  @<< @-1 @I @II rows / hlines
  @2$3                       a single field
  @2$1..@4$3  $1..$3         ranges
  @# $#                      the current row / column number
  remote(name, @2$1)         a field of a named table (#+NAME:)
  $name                      a named column, field, parameter or constant
Names, looked up in this order:
  ! row           | ! | | qty | price | names the columns below it
  ^ / _ rows    name the field in the row above / below (a formula
                    sees the value it had before the recalculation, like
                    Emacs, so iterate to use a fresh one)
  $ row           | $ | max=50 | defines a parameter
  constants         #+CONSTANTS: tax=0.16 rate=18.5, then the
                    table_formula_constants option
  $PROP_Name        the Name property of the entry (inherited)
  header row        (extension) $Total=$Qty*$Price uses the header above
                    the first hline when there is no ! row
Column formulas run on the rows below the first hline (all rows without
one); when the first column holds marks (! $ ^ _ # *), only on rows
marked # or *. Rows marked ! ^ _ $ / are never changed. Formulas run
row by row in the order of their sorted left sides, column formulas first,
then field formulas. A relative row reference (@-1, @+2) may cross an
hline (table_relative_ref_may_cross_hline: false stops at the row next to
the hline, "error" stops the recalculation). table_formula_field_format
("%s") formats every result, e.g. "~%s~".
A column formula beyond the last column adds the
column; a field formula does so only with table_formula_create_columns
(true, "warn" or "prompt"; false: an error).
Formulas are GNU Calc expressions, evaluated by a Lua reimplementation of
the parts Org tables use. As in Emacs, each reference is replaced by the
field text ((3); ranges [1,2,3], empty fields dropped) before the
formula is evaluated, so:
- Calc precedence: / binds looser than *, a/b*c is a/(b*c); ^
  binds tighter than unary minus (-2^2 is -4); 2 3 and 2(3+1)
  multiply; a ? b : c; ! factorial, % percent (10%) or modulo.
- Numbers: exact integers of any size (2^100), floats with 12 digits and
  Calc's display with 8 (3., 0.33333333, 1e-3, 1.2345679e12);
  calc_default_modes (org-calc-default-modes) changes the precision,
  the float display, the angle mode ("deg"/"rad") and fractions,
  fractions 3:4 (F flag), modulo forms 3 mod 7 ((3 mod 7)^100 is
  4 mod 7, makemod(10, 7)).
- Vectors and matrices: [1, 2] ([1 2] without commas), [[1, 2], [3,
  4]]. + - work elementwise, a number scales, * is the matrix product
  (of two plain vectors the dot product), ^ a matrix power (^-1 the
  inverse), / by a square matrix solves, | concatenates. Functions:
  trn det inv tr cross head tail rhead rtail cons rcons append vconcat rev
  sort rsort rdup index cvec idn diag arrange vflat find subvec mrow mcol
  getdiag rnorm cnorm abs (the length) vlen vcov vpcov vcorr map reduce.
  A range $1..$3 is a vector, so [$1..$3] is a one-row matrix.
- Dates: <2024-01-10 Wed> (also [...] fields) is a date; subtracting
  two gives days ($2-$1), adding a number gives a date (written as an
  inactive timestamp), date(<...>) gives the day number.
- Complex numbers (2, 3) and polar (2; 30) (angle in the angle mode):
  sqrt(-4) is (0, 2), ln(-1) is (0., 3.1415927), (1,2)*(3,4)
  is (-5, 10); abs arg re im conj polar rect, exp ln log10 sqrt sin cos
  tan and powers work on them. i is only a symbol, as in Calc.
- HMS forms 2@ 30' 15": added (to each other or to hours), multiplied
  and divided by numbers, compared; hms(2.5) and hms(2, 30, 0) make
  one, deg(2@ 30') is 2.5, trig functions take them as degrees.
- Error forms 3 +/- 0.5 propagate through + - * / ^ sqrt exp ln abs;
  intervals [1 .. 3), (0 .. 1] through + - * and / by a number.
- Units: usimplify(3 m + 20 cm) is 3.2 m (the units of the first
  term), usimplify(1 in / 1 cm) is 2.54, usimplify(3 m * 2 m / 4 s)
  is 1.5 m^2 / s, for common units (m, in, ft, yd, mi, nmi, g, lb, oz,
  t, s, min, hr, day, wk, yr, Hz, l, gal, qt, pt, cup, ha, acre, mph,
  kph, knot, N, lbf, J, cal, Btu, Wh, eV, W, hp, Pa, bar, atm, Torr,
  psi, A, V, ohm, S, F, T, Wb, mol, ...) with SI prefixes (km, mA, kWh),
  and temperature differences (K, degC, degF: usimplify(1 K + 1 degC)
  is 2 K). As in Calc, usimplify is the only unit function of
  formulas (Calc's unit conversion is a keyboard command), and elsewhere
  units are plain symbols (3 m + 20 cm stays).
- Formulas with variables are Calc's symbolic algebra: text stays symbolic
  and is normalized like Calc ($1*2 on x gives 2 x, x*y/x is y,
  (x+1)*2 is 2 x + 2); if($1>3, big, small) returns big/small;
  pi and e stay symbols (evalv(pi) is 3.1415927); a = b is an
  equation. simplify(x*y - y*x) is 0, expand((x+1)^2) is
  x^2 + 2 x + 1, collect(a x + b x, x) is (a + b) x, subst(x^2, x, 3)
  is 3^2, deriv(x^2, x) is 2 x (trig derivatives in degrees:
  cos(x) pi / 180), integ(x^2, x) is x^3 / 3 (also definite:
  integ(x^2, x, 0, 1)), solve(x^2 - 4 = 0, x) is x = 2 (one solution,
  like Calc; linear to quartic polynomials, inverse functions,
  inequalities: solve(x + 1 < 3, x) is x < 2), nroot(x, 3) is x^1:3.
  With N a non-numeric result is #ERROR.
- Functions: vsum vmean vmin vmax vcount vprod vmedian vsdev vpsdev vvar
  vpvar vgmean vhmean vlen rev sort, abs sqrt nroot exp ln log (also
  log(x, b)) log10 exp10 floor ceil round rounde roundu trunc frac
  (a float as a fraction: frac(0.25) is 1:4)
  float fdiv idiv mod \ gcd lcm fact dfact choose perm gamma prime
  nextprime prevprime totient sign min max hypot, sin cos tan sec csc cot
  arcsin arccos arctan arctan2 sinh cosh tanh arcsinh arccosh arctanh deg
  rad (degrees unless R), and or xor diff not lsh rsh ash (32-bit
  words), if lnot evalv, date year month day hour minute second weekday
  now incmonth incyear newmonth newyear newweek julian unixtime (local
  time zone). Unknown functions stay symbolic, e.g. foo(x).
Flags after ; (org-table-eval-formula): Calc modes p20 (precision),
n3 (significant digits), f2 (fixed), s3 / e3 (scientific /
engineering), N (fields as numbers), E (keep empty fields, as nan in
Calc), R / D (radians / degrees), F (fractions), T / t / U
(fields and results as durations: H:MM:SS, hours (see
table_duration_custom_format) and H:MM; table_duration_hour_zero_padding),
L (Lisp literal). Like Emacs, these letters are removed from the rest,
which is a printf format applied to the result: %.2f, %.1f%%, %d.
Lisp formulas: '(+ $1 $2);N, '(concat $1 "-" $2): fields become Lisp
strings, numbers with N, verbatim text with L; ranges become several
arguments; a list result is #ERROR. They run on a small Lisp interpreter,
never in Emacs (see org-differences). Lua formulas (extension): $3='(string.upper($1)) (a '(...)
that is not Lisp).
Errors show as #ERROR.
<C-c>' (or <prefix>') in a table, or on a #+TBLFM line, opens the
formula editor in a split below (org-table-edit-formulas): one lhs = rhs
per line under "# Column Formulas", "# Field and Range Formulas" and
"# Named Field Formulas". Lines starting with a blank continue the formula
above. As the cursor moves, the fields the formula uses are highlighted in
the table (OrgTableFormulaRef, OrgTableFormulaRefCursor for the reference
at the cursor, OrgTableFormulaTarget for the target), for column formulas
on the row of the table window's cursor.
  <C-c><C-c> <C-c>' <C-c><C-s> <C-x><C-s> :w   store (a count: also
                                              recalculate the table)
  <C-c><C-q>          abort
  <C-c>?              show the references, move the table cursor there
  <S-Up/Down/Left/Right>  shift the reference at the cursor
  <M-S-Up> <M-S-Down> change the table row used for column formulas
  <M-Up> <M-Down>     scroll the table window
  <Tab>               pretty-print the Lisp formula
  <C-c><C-r>          show references as B3 / as @3$2
  <C-c>}              toggle the table coordinates

<C-c>{ toggles the formula debugger: each evaluation then shows the original formula, the formula with the references replaced, the result, the format and the final text in a *Substitution History* window and asks whether to go on; answering no stops the recalculation.

<C-c><Tab> in a table shrinks the current column, or shows it again (org-table-toggle-column-width): a shrunk column shows the first W characters of each field (W from a <W>/<lW> cookie in the column, one character without one) followed by table_shrunk_column_indicator (…). Before the first or after the last column it asks for column ranges (2-4 6-). Count 4 shrinks the columns with a width cookie and expands the others (org-table-shrink), count 16 expands all (org-table-expand). #+STARTUP: shrink (or startup_shrink_all_tables) shrinks every table with cookies when a file is opened; columnview blocks with widths are shrunk after an update. Neovim has no overlays that hide text, so shrunk fields are concealed ('conceallevel' is set to 2) and drawn as inline virtual text; the text itself is unchanged. Fields are cut on their displayed text, so a link shows its description. In Insert mode the table is shown in full, and it shrinks again when you leave Insert mode. Aligning a table pads fields to their displayed width (org-string-width): a link counts as its description while links are shown descriptively, and hidden emphasis markers and prettified entities count as displayed.

Follow-field mode (<C-c> with count 16): a small window below shows the full text of the current field and follows the cursor. Edit the text there and write it back with <C-c><C-c> or :w (moving to another field writes it too). Leaving the table ends the mode (table_exit_follow_field_mode_when_leaving_table). Header-line mode (:Org table_header_line_mode, or table_header_line_p for every buffer): while the first row of the table at the top of the window is scrolled out of view, it is shown in the 'winbar' (Emacs draws it over the first visible line). Turning the modes on or off fires the User autocmds OrgTableFollowFieldMode and OrgTableHeaderLineMode (org-table-follow-field-mode-hook, org-table-header-line-mode-hook), with data = { enabled, bufnr }; orgtbl-mode fires OrgtblMode` (orgtbl-mode-hook).

Translators turn a table into another format (Emacs orgtbl-to-*): orgtbl-to-tsv, -csv, -latex (:booktabs, :environment), -html (:attributes), -texinfo (:columns), -orgtbl, -table.el (the aligned table with + crossings), -unicode (drawn like the ASCII export with UTF-8 rules and column-group bars; :narrow t cuts columns to their width cookie with =>) and -generic. Parameters of orgtbl-to-generic: :splice, :skip N (rows, hlines included), :skipcols (2 3), :hline, :sep, :hsep, :tstart :tend, :lstart :lend, :llstart :llend, :hlstart :hlend :hllstart :hllend, :lfmt :llfmt :hlfmt :hllfmt, :fmt :hfmt (a format or (2 "$%s$" 4 "%s")), :efmt ("%s\\times10^{%s}"), :raw. As in Emacs export, a column of recalculation marks is dropped, and so are the ! ^ _ $ / rows and cookie rows, except by the translators without a backend (tsv, csv, generic: Emacs exports them with the Org backend, which keeps special rows). The latex, html and texinfo translators transcode cells with the matching exporter (links, entities, LaTeX fragments, sub/superscripts), and align columns like the export: the last alignment cookie, else by the share of numbers among all transcoded cells. From Lua, the format parameters may be functions: require("org.table.orgtbl").translate("orgtbl-to-generic", rows, {...}); a global Lua function can be used as a translator by name.

Radio tables: a table below #+ORGTBL: SEND name translator :params is sent, translated, between the lines containing BEGIN RECEIVE ORGTBL name and END RECEIVE ORGTBL name (anywhere in the buffer) whenever <C-c><C-c> recalculates or realigns it. :Org orgtbl_mode turns on the table editor in buffers of any filetype (Emacs orgtbl-mode): on table lines <Tab>, <S-Tab>, <CR> (Insert mode), <S-CR>, <C-c><C-c>, <C-c>|, <C-c>-, <C-c><CR>, <C-c>=, <C-c>', <C-c>, <C-c>*, <C-c>^, <C-c>?, <C-c><Space>, <C-c>+, <C-c>}, <C-c>{, <C-c><Tab>, <C-#>, <C-c><C-x><M-w>/<C-w>/<C-y>, <M-arrows>, <M-S-arrows>, <M-hjkl>, <M-HJKL>, <C-c>"a and <C-c>"g work like in org buffers; elsewhere the keys keep their meaning. :Org orgtbl_insert_radio_table inserts a template for the filetype (orgtbl_radio_table_templates: tex, texinfo, html, org), :Org orgtbl_toggle_comment comments or uncomments the table with 'commentstring', :Org orgtbl_send_table` sends it.

Tables in the format of Emacs's table.el package are grids of +, - (or =) and | whose cells can span rows and columns and hold several lines:

+-----+--+
|0    |1 |
+--+--+  |
|2 |3 |  |
+--+--+--+

A table.el table starts and ends with a full rule (+--+---+). Org table commands leave it alone: <Tab> and <C-c><C-c> only say to use <C-c>'. <C-c>~ converts the Org table at the cursor to table.el after aligning it (horizontal rules are dropped, every row gets a border above and below), converts a table.el table back to Org by removing its border lines (spanned and multi-line cells are split, as in Emacs), and elsewhere inserts a new table.el table after asking for the number of columns and rows and the cell widths and heights (lists like 5 10 give each column its own width; the last value repeats). <C-c>' edits the table in a special buffer; when leaving Insert mode there and when writing it back, the grid is realigned: columns and rows grow so that the text of every cell fits, spanned cells are kept, and a copy of a line of a row adds a line to that row. A | typed in a cell, or a change that breaks the grid lines, is refused with an error (fix the grid or abort with <C-c><C-k>). Exports: HTML and Markdown get the <table border="1"> table.el generates (colspan/rowspan, spaces as &nbsp;, every cell align="left" valign="top"), LaTeX its tabular with \multicolumn and \cline, ASCII, Org and Texinfo keep the text, ODT strips the table with a warning, as in Emacs.

<C-c>"a (orgtbl-ascii-plot) adds a column after the current one with a bar plot of its numbers, drawn by '(orgtbl-ascii-draw $2 MIN MAX 12) (a count sets the width, count 4 asks); it follows the table on recalculation. orgtbl-uc-draw-grid and orgtbl-uc-draw-cont draw with Unicode blocks. <C-c>"g (or <C-c><C-c> on a #+PLOT: line) plots the table with gnuplot (plot_gnuplot_program, plot_gnuplot_script_preamble, plot_gnuplot_term_extra), using the #+PLOT: options above it:

#+PLOT: title:"Sales" ind:1 deps:(2 3) type:2d with:lines
#+PLOT: file:"sales.png" set:"yrange [0:]" labels:("x" "a" "b")

More types can be defined in plot_preset_plot_types (org-plot/preset-plot-types):

plot_preset_plot_types = {
  bars = {
    plot_cmd = "plot",
    plot_pre = "set style fill solid", -- or a function
    plot_func = function(rows, data_file, ncols, opts, plot_str)
      return { ("'%s' using 1:%d with boxes"):format(data_file, ncols) }
    end,
    -- data_dump = function(rows, data_file, ncols, opts) return text end,
    -- check_ind_type = true, plot_str = "...",
  },
}

The lines plot_func returns are joined in order. Options: type (2d, 3d, grid, radar), title, ind, deps, with, file, labels, line, set, map, script (a gnuplot script; $datafile is replaced), timefmt, transpose, and for radar min, max and ticks. The header row gives the labels; an independent column of timestamps is plotted as time. type:radar draws a spider chart like Emacs: each row is an axis named by its first cell, each other column a series.