org.nvim

Appearance and highlights

Options under ui:
  menus                  the Org menus (org-menus), default true
  choice_prompt          "float" (default): pick one of a fixed set of
                         values from a floating list (org-choice-list);
                         "input": the command line with <Tab> completion
  imenu_depth            headline levels of imenu (gO), default 2
  conceal_links          show only link descriptions (conceallevel=2)
  hide_emphasis_markers  hide * / _ = ~ + around emphasized text
  hide_leading_stars     show only the last star of each headline
                         (#+STARTUP: hidestars / showstars)
  bullets                list of symbols replacing the stars, per level
  checkboxes             { unchecked, partial, checked } icons
  indent_mode            virtual indentation like org-indent-mode: the
                         text of a level-n entry starts at column 2n and
                         headlines get n-1 columns of prefix; turns on
                         hide_leading_stars (#+STARTUP: indent / noindent)
  indent_mode_turns_off_adapt_indentation  adapt_indentation is off in
                         buffers with indent_mode (true)
  indent_indentation_per_level  columns per level of indent_mode (2):
                         the text of a level-n entry starts after
                         n + (per - 1)(n - 1) + 1 columns, headlines after
                         (per - 1)(n - 1); 0 = no indentation
  pretty_entities        \alpha → α for every entity of Emacs'
                         org-entities (#+STARTUP: entitiespretty /
                         entitiesplain); x^2 → x², a_{ij} → aᵢⱼ
                         (pretty_entities_include_sub_superscripts, and
                         use_sub_superscripts = true | "{}" | false):
                         Unicode super/subscript characters when all the
                         characters have one, else the script is
                         highlighted with OrgSuperscript / OrgSubscript and
                         only the markers are hidden (Neovim cannot raise
                         text). Not in blocks, code, verbatim or links.
  num                    number headlines with virtual text like
                         org-num-mode (#+STARTUP: num / nonum); num_max_level,
                         num_skip_commented, num_skip_footnotes,
                         num_skip_tags, num_skip_unnumbered and
                         num_format_function(numbers) -> text follow the
                         org-num options
  fontify_done_headline  dim DONE headlines
  fontify_todo_headline  highlight the text of TODO headlines with
                         OrgHeadlineTodo (org-fontify-todo-headline)
  level_color_stars_only the level color on the stars only
                         (org-level-color-stars-only)
  hidden_keywords        keywords shown without their "#+KEYWORD:" part:
                         { "title", "subtitle", "author", "date", "email" }
                         (org-hidden-keywords)
  hide_macro_markers     hide the {{{ }}} of macro calls
                         (org-hide-macro-markers)
  highlight_latex_and_related  what LaTeX-related syntax is highlighted
                         (org-highlight-latex-and-related), none by
                         default like Emacs: "latex" (fragments $..$,
                         \(..\), \[..\], $$..$$ and \begin{..}
                         environments, OrgLatex), "native" (the same with
                         Vim's tex syntax inside), "script" (x^2, a_{i}),
                         "entities" (\alpha)
  src_highlight          highlight src blocks with the language syntax
  src_block_faces        face of src block bodies by language, like
                         todo_keyword_faces: { python = { bg = "#e5ffb8" } }
                         ("" = blocks without a language)
                         (org-src-block-faces)
  todo_keyword_faces     { WAITING = ":foreground #e0af68 :weight bold" },
                         or a highlight table, or a group name
  priority_faces         the same per priority (org-priority-faces):
                         { A = "ErrorMsg", ["10"] = { fg = "gray" } }
  tag_faces              the same per tag (org-tag-faces)
<C-c><C-x>\     Toggle pretty entities in the buffer
                (org-toggle-pretty-entities, toggle_pretty_entities).
:Org entities_help  List every entity with its LaTeX and HTML code
                (org-entities-help).

entities_user (org-entities-user) adds entities of your own, or replaces built-in ones, for display, completion and export:

entities_user = {
  -- name, LaTeX, LaTeX needs math mode, HTML, ASCII, Latin-1, UTF-8
  { "snowman", "\\diamond", true, "&#9731;", "[snow]", "[snow]", "☃" },
}
:Org num_mode   Toggle headline numbering in the buffer (org-num-mode).
:Org indent_mode  Toggle virtual indentation in the buffer
                (org-indent-mode).

Turning indent mode or numbering on or off, also when a buffer starts with them, runs the User autocmd OrgIndentMode or OrgNumMode (org-indent-mode-hook, org-num-mode-hook), data.enabled telling which.

Images and LaTeX previews
Image links and LaTeX fragments can be shown as images in place of their
text, like Emacs (org-link-preview, org-latex-preview). A backend draws
them, chosen with ui.images.backend:
  "native"      vim.ui.img, Neovim 0.13+, in a terminal with the Kitty
                graphics protocol (kitty, Ghostty, WezTerm...). Support is
                checked once by asking the terminal. Not through tmux.
  "snacks"      Snacks.image from snacks.nvim (also inside tmux, with
                allow-passthrough on). For Neovim before 0.13.
  "image.nvim"  3rd/image.nvim.
  "auto"        (default) the first of these that works; false turns
                previews off. :checkhealth org tells which one is used.
With the native backend, the text of the link is concealed behind blank
inline text as wide as the image, virtual lines keep the rows the image
needs under the line free, and the images are placed on the screen after
every redraw, so they follow scrolling, folding, window splits and
resizes, also in floating windows. Images are sized for each window and
sized again when it is resized; in a window too narrow for an image the
image is not drawn. When a line wraps after an image, the image is drawn
under the line and the link text stays visible; on the first line of a
closed fold, an image taller than one row shows its link text.
An image is shown once all of it fits in the window, and hidden under
floating windows and the popup menu. Only PNG can be sent to the
terminal: other formats are converted with ImageMagick (magick). Sizes
come from the terminal's cell size in pixels. Editing a previewed link or
fragment removes its preview.
Placement, ui.images.placement:
  "inline"      (default) the image replaces the link or fragment: its
                top row is on the line, at the link's column, and the
                text after the link moves right to make room. The rows
                under the line are shared by the images of that line
                (side by side). An image is at most as wide as the
                columns left after the text before it. On the cursor line
                of the current window the text shows again, in every
                mode, with the image under the line, so it can be edited;
                moving off the line puts the image back in place. The
                windows showing the buffer get 'conceallevel' 2.
                Inline math ($x$, \(x\)) is scaled to one row, as
                tall as the text; other fragments keep their size.
                A fragment or environment over several lines is drawn
                in place too (Neovim 0.11+): its other lines are hidden
                (conceal_lines), the image starts on its first line
                and the text after it on its last line follows the
                image; the cursor on any of its lines shows the text
                again, with the image under its last line. Before 0.11
                such fragments use "below", and image.nvim always does.
  "below"       under the line, at the link's column, the text left as
                it is (images of one line are stacked).
<prefix>xv      org-link-preview (link_preview): on a link, toggle its
<C-c><C-x><C-v> preview; else preview the links of the current entry, or
                of the Visual selection, again when called again. A count
                like the Emacs prefix: 4 hides the preview at the cursor,
                else the entry's (or the selection's); 16 previews the
                whole buffer, 64 hides them all; 1 also previews links
                with a description (entry, link or selection), 11 in the
                whole buffer, any other count in the whole buffer too.
<prefix>xV      org-link-preview-refresh (link_preview_refresh): preview
<C-c><C-x><C-M-v>  every image link of the buffer again.
<prefix>xl      org-latex-preview (latex_preview): on a fragment, toggle
<C-c><C-x><C-l> its preview; else render the fragments of the current
                entry (or of the Visual selection). 4 hides the entry's
                (or selection's) previews, 16 previews the whole buffer,
                64 hides them all. Rendering runs in the background.
The same as ex commands; a range limits them, a number is the count:
  :[range]Org link_preview [N]       :[range]Org latex_preview [N]
  :[range]Org link_preview_region [linked]    (org-link-preview-region)
  :[range]Org link_preview_clear              (org-link-preview-clear)
  :Org link_preview_refresh
  :[range]Org clear_latex_preview             (org-clear-latex-preview)
Without a range the last three act on the whole buffer. The obsolete Emacs
names work too: toggle_inline_images, remove_inline_images,
redisplay_inline_images, toggle_latex_fragment, preview_latex_fragment.

Which links: links of a type with a preview function (org-link-set-parameters :preview), with no description, or whose description is a sole plain or angle link of such a type ([[https://example.com][file:thumb.png]] shows thumb.png); with a count of 1 (or linked) the links with a description are previewed by their own target. Built in: file: and attachment: links (bracket, plain or angle) to an existing file whose extension is in ui.images.extensions, and http(s) links to such a file name when ui.images.remote allows. Links in src, example, export and comment blocks, comments, fixed-width lines and property drawers are left alone, like Emacs.

Preview functions (org-link-set-parameters :preview) come from links.types.<type>.preview, else from org.ui.images.set_preview():

require("org.ui.images").set_preview("thumb", function(path, ctx)
  return vim.fn.expand("~/thumbs/" .. path .. ".png")
end)

The function gets the link's path and a context { bufnr, row (1-based), col, end_col (0-based), type, link, refresh, callback } and returns the image file to show, nil or false for none, or true when it calls ctx.callback(file) later (after a download, say). A type org.nvim does not know becomes a link type (links.types), and a function registered for file or attachment replaces the built-in one.

set_preview({type}, {fn}) registers {fn} for {type} links, or removes it when {fn} is nil.

Remote images (org-display-remote-inline-images), ui.images.remote:
  "skip"        (default) http(s) links are not previewed;
  "download"    the image is fetched with curl on every preview;
  "cache"       fetched once into stdpath("cache")/org/remote-images,
                and again by link_preview_refresh.
Emacs applies this to TRAMP files; org.nvim has no TRAMP and uses it for
http(s) image links instead.

Batches (org-link-preview-batch-size, org-link-preview-delay): the first ui.images.batch_size links (6) are previewed at once, the others in batches of that size every ui.images.preview_delay seconds (0.05), so a long file stays responsive; 0 previews all at once. Clearing previews (or editing the link) drops the links still waiting.

Size (org-display-inline-image--width): ui.images.actual_width is
  true         (default) the image's own size;
  a number     that many pixels;
  false, { n } the :width of the paragraph's #+ATTR_ORG, else of another
               #+ATTR_x with a readable width, else n pixels (or the own
               size). :width is pixels (300, 300px), a percentage (50%)
               or a fraction from 0 to 2 (0.5, 0.7\linewidth) of the text
               width ('textwidth', else the window), or t (own size).
An ORG-IMAGE-ACTUAL-WIDTH property (inherited: t, nil, a number or (n))
overrides it. ui.images.max_width (org-image-max-width) caps the width:
"fill-column" ('textwidth', else 70 columns), "window", a number of pixels
or a fraction of the window. ui.images.max_height caps the rows.

Alignment (org-image-align): an image link alone in its paragraph is drawn at ui.images.align ("left", "center" or "right"), or as its #+ATTR_ORG (else #+ATTR_x) says with :align center|right|left or :center t. Native backend only.

TAB cycling (org-cycle-link-previews-display): with ui.images.cycle_display, showing an entry's children previews its own links, showing the subtree previews all of them, and folding it removes them.

At startup: #+STARTUP: linkpreviews (inlineimages) and latexpreview preview a file when it opens, like ui.images.startup and ui.latex_preview.startup; the no... words turn that off, and the last word of a pair wins.

LaTeX fragments are those org-latex-preview renders: $x$ (no blank after the opening or before the closing dollar, no $ before it, a blank, punctuation or line end after it), $$x$$, \(x\) and \[x\], which may span lines of a paragraph, and \begin{env} ... \end{env} environments with the \end alone on its line. Fragments in verbatim or code markup, link targets, blocks other than quote/verse/special blocks, and keywords other than TITLE, CAPTION, AUTHOR and DATE are skipped.

Rendering follows org-create-formula-image with the process named by
ui.latex_preview.process (org-preview-latex-default-process), from
processes (org-preview-latex-process-alist):
  "dvipng"       latex + dvipng (the Emacs default)
  "dvisvgm"      latex + dvisvgm (SVG, converted to PNG for vim.ui.img)
  "xelatex"      xelatex + dvisvgm
  "imagemagick"  pdflatex + convert
  "tectonic"     tectonic + pdftocairo (org.nvim)
  "pdflatex"     pdflatex + pdftocairo (org.nvim)
"auto" (default) uses the first of dvipng, dvisvgm, tectonic, pdflatex,
imagemagick that is installed. A process is a table with programs,
message, image_input_type, image_output_type, image_size_adjust
({ buffer, html }), latex_header, latex_compiler, image_converter and
transparent_image_converter; commands run in a shell in a temporary
directory, with %f (input file), %F (its full path), %b (base name), %o
(output directory), %O (output file), %D (DPI) and %S (scale, DPI / 140).
processes adds or replaces entries.

The document is ui.latex_preview.header (org-format-latex-header, the Emacs header by default) with [DEFAULT-PACKAGES] and [PACKAGES] filled from export.latex and the file's #+LATEX_HEADER lines (SETUPFILE too), like org-latex-make-preamble for snippets. foreground is "default" (the Normal text), "auto" (the text at the fragment) or a color; background is "default" (Normal), "Transparent" or a color (:foreground, :background). Formulas are about as tall as a text line times scale. Images are written to ui.latex_preview.image_directory (org-preview-latex-image-directory, "ltximg/" next to the file; buffers without a file use stdpath("cache")/org/ltximg), or to cache_dir when set. When a step fails, its output is in the *Org Preview LaTeX Output* buffer.

Where images work Previews depend on three things outside org.nvim: the Neovim version, the terminal, and what sits between them (tmux, zellij, SSH). :checkhealth org shows what it found and which backend it uses.

Which backend draws the images ("auto"):
  1. "native" (vim.ui.img) when Neovim is 0.13 or newer AND the terminal
     answers the Kitty graphics query. The query is asked once, the first
     time a preview is made, and waits up to 1 s when nothing answers.
  2. else "snacks" when snacks.nvim is installed with its image module and
     the terminal supports it with unicode placeholders;
  3. else "image.nvim" when it is installed;
  4. else no previews, with a message saying why.
Set ui.images.backend to a name to skip the others (and the 1 s wait).
Setups:
  kitty, Ghostty (Neovim 0.13+)    native: everything below works.
  WezTerm (Neovim 0.13+)           native. WezTerm's Kitty graphics support
                                   is partial; snacks.nvim can't draw in it
                                   (no unicode placeholders): with an older
                                   Neovim use image.nvim.
  Neovim 0.11 and 0.12             no vim.ui.img: snacks.nvim or
                                   image.nvim, in a terminal they support.
  tmux                             vim.ui.img writes straight to the
                                   terminal and tmux drops it, so its query
                                   gets no answer (the 1 s wait) and "auto"
                                   falls back to snacks.nvim. It needs
                                   set -g allow-passthrough on in
                                   tmux.conf (snacks.nvim tries to set it).
                                   Or run Neovim outside tmux.
  zellij                           no passthrough: no backend can draw.
  SSH                              native and snacks.nvim send the image
                                   data through the connection. Images,
                                   ImageMagick and the LaTeX programs must
                                   be on the machine running Neovim.
  Terminal.app, iTerm2, Alacritty, no Kitty graphics protocol: no native
  Windows Terminal, GNU screen     or snacks.nvim previews. image.nvim may
                                   still work there (e.g. with ueberzug on
                                   Linux).
What each backend does:
                                   native      snacks        image.nvim
  image in place of its link       yes         yes (5)       no (below)
  image under its link             yes         yes (1)       yes
  :align / org-image-align         yes         no            no
  follows scrolling and folds      yes         yes           yes
  under floating windows, menus    hidden (2)  covered (4)   its backend
  partly visible images            hidden (3)  cut           cut
  several windows on one buffer    yes         yes           first only
  (1) A link alone on its line gets its image at the link's column. With
      text around the link, snacks.nvim draws the image at the start of
      the next line and puts an icon at the link.
  (2) So they don't cover menus; they come back when the float closes.
  (3) vim.ui.img can't crop: an image is drawn once all of it fits.
  (4) snacks.nvim draws images as text (unicode placeholders), so floats
      cover them like any text.
  (5) snacks.nvim conceals the text itself; an image with text after it
      on a line may go under the line with an icon at the link.
When it goes wrong:
  "no image backend" or "does not support the Kitty graphics protocol"
      Neovim is older than 0.13, the terminal lacks the protocol, or tmux
      or zellij is in between (see above). Install snacks.nvim or
      image.nvim, run Neovim outside tmux, or use another terminal.
  Nothing happens for a second on the first preview
      The terminal query waiting for an answer (tmux, unsupported
      terminals). Set ui.images.backend.
  Blank rows under the link (or a blank gap in place of it) but no image
      The native backend reserved the rows but the image is not fully
      visible, a float covers it, or the terminal ignored it. Scroll it
      into view; check :checkhealth org.
  An image is not where the link is, or everything looks centered
      :align and org-image-align only work with the native backend;
      with snacks.nvim see (1) above. Images starting where the link text
      ends was a bug fixed in org.nvim (update).
  "can't convert ... to PNG"
      The native backend only sends PNG: install ImageMagick (magick)
      for JPEG, SVG and the rest.
  An image vanished (the terminal was cleared or reset)
      <prefix>xV (link_preview_refresh) draws them again.
  Images the wrong size after changing the font size
      Sizes come from the terminal's cell size, read again when Neovim is
      resized; <prefix>xV redraws them.
  LaTeX: "no LaTeX renderer found" / "you need to install the programs"
      Install latex and dvipng (or tectonic and poppler for pdftocairo).
      When a render fails, its output is in *Org Preview LaTeX Output*.

Emphasis follows org-emphasis-regexp-components: the markers need a space, (, ', ", { or - (or the line start) before them, may span one line break, and bold, italic, underline and strike-through can nest.

Quote and verse block contents are highlighted as ordinary Org (lists, tables, timestamps, markup) on top of OrgQuoteBlock; center, special (#+begin_note...) and dynamic (#+BEGIN:) blocks highlight only their delimiter lines. Every block ends at the next headline, whether or not it has its #+end line. #+begin_export LANG blocks get LANG's syntax, as #+begin_src LANG blocks do. A buffer's #+OPTIONS: ^:t, ^:{} or ^:nil overrides ui.use_sub_superscripts, for pretty entities and for the "script" LaTeX highlighting (^:nil displays like ^:{}, as in Emacs). Complete statistics cookies ([2/2], [100%]) use OrgStatisticDone, others OrgStatistic (org-checkbox-statistics-done/-todo); OrgSexpDate is diary sexps (<%%(...)>, %%(...) lines) and OrgArchived the text of headlines tagged ARCHIVE.

Highlight groups (all default, override with nvim_set_hl()):
  OrgHeadlineLevel1..8   (linked to the colorscheme's markdown headings)
  OrgTodo OrgDone OrgHeadlineDone OrgHeadlineComment
  OrgPriority OrgPriorityA OrgPriorityB OrgPriorityC OrgTags
  OrgTimestamp OrgTimestampInactive OrgPlanning OrgClockDuration OrgClockSum
  OrgDrawer OrgPropertyKey OrgPropertyValue OrgKeyword OrgKeywordValue
  OrgTitle OrgComment OrgBlock OrgQuoteBlock OrgBlockDelimiter
  OrgBold OrgItalic OrgUnderline OrgStrikethrough OrgVerbatim OrgCode
  OrgLink OrgListBullet OrgListTerm OrgCheckbox OrgCheckboxChecked
  OrgCheckboxPartial OrgStatistic OrgStatisticDone OrgTable
  OrgTableSeparator OrgTableFormula OrgSexpDate OrgArchived
  OrgInlineSrc OrgInlineSrcMarker OrgInlineSrcLang
  OrgExportSnippetMarker OrgExportSnippetBackend
  OrgFootnote OrgTarget OrgLatex OrgHorizontalRule OrgMacro
  OrgHiddenStars OrgSuperscript OrgSubscript OrgInlinetask OrgSparseMatch
  OrgMenuKey OrgMenuHeading OrgMenuDesc OrgMenuMore OrgMenuOn OrgMenuOff
  OrgMenuValue OrgMenuSelected    (org-key-menus, org-choice-list)
  OrgAgenda*