Open-Source Wikis

/

Neovim

/

Systems

/

Options

neovim/neovim

Options

Purpose

Vim has a single setting mechanism — the option — that scales from set tabstop=4 to per-window state like 'colorcolumn' and per-buffer state like 'fileencoding'. Neovim refactored Vim's hand-coded option tables into a single Lua data file (src/nvim/options.lua, ~10,956 lines) that drives code generation. This is the canonical place to change anything option-related.

Directory layout

src/nvim/
├── options.lua (~450k bytes)     The Lua data file. Single source of truth.
├── option.c (~206k bytes)        Generic option get/set, validation
├── option.h, option_defs.h
├── option_vars.h (~31k bytes)    Macros for accessing each option from C
├── optionstr.c (~73k bytes)      String-typed option handlers
├── optionstr.h
└── api/options.c                 The nvim_*_option API surface

build/src/nvim/auto/options.generated.h        Generated table
build/src/nvim/auto/options_enum.generated.h   Generated enum

The pattern is the same as for events, ex commands, eval functions, and v: variables — Lua data file, code-generator, regenerate on build.

Key abstractions

Concept Description
Scope global, buffer, window. Some options have a "global-local" hybrid (set globally, override per buffer).
Type boolean, number, string. Strings can be enums, comma-separated lists, or free-form.
Short name Two-letter abbreviation (tabstopts).
Cb (callback) A C function called when the value changes. Used for revalidation, side effects (e.g. switching the active syntax).
Enable_if A compile-time gate; some options only exist if a feature is built in.

Format of options.lua

Each option is a Lua table:

{
  full_name = 'tabstop',
  abbreviation = 'ts',
  short_desc = N_("number of spaces a <Tab> in the file counts for"),
  type = 'number',
  scope = { 'buffer' },
  varname = 'p_ts',
  defaults = { if_true = 8 },
},
{
  full_name = 'fileencoding',
  abbreviation = 'fenc',
  short_desc = N_("file encoding for multi-byte text"),
  type = 'string',
  scope = { 'buffer' },
  varname = 'p_fenc',
  alloced = true,
  redraw = { 'statuslines' },
  defaults = { if_true = "" },
  cb = 'did_set_fileencoding',
},

Fields are documented at the top of options.lua and in runtime/doc/dev_arch.txt. The generator (src/gen/gen_options.lua) consumes this and produces:

  • An OPT_* enum, one entry per option.
  • A C array of vimoption_T structs with all metadata.
  • A header (option_vars.h) that includes per-option access macros (e.g., p_ts, curbuf->b_p_ts).

How it works

The runtime path:

graph LR
    User[":set tabstop=4"]
    User --> Parse[option.c#do_set]
    Parse --> Lookup[lookup in vimoption_T table]
    Parse --> Validate[validate type/value]
    Validate --> Store[store in p_ts<br/>or curbuf->b_p_ts]
    Validate --> CB[did_set_tabstop callback]
    CB --> Side[Redraw, update internal state]

option.c#do_set is the entry point for :set. It tokenizes the argument list, looks up each option, dispatches to option_set_value, and runs the per-option callback. For string options, the validation and side-effect code is mostly in optionstr.c#did_set_* functions — one per option that needs special handling.

Option scope

The scope of an option determines where the value lives:

Scope Storage Examples
global A p_* global in globals.h. 'magic', 'shell', 'updatetime'.
buffer b_p_* field on buf_T. 'tabstop', 'filetype', 'modified'.
window w_p_* field on win_T. 'cursorline', 'foldenable', 'wrap'.
global-local Both p_* and b_p_*/w_p_*; the latter shadows. 'undolevels', 'colorcolumn'.

When you :setlocal foo=..., only the local field changes; :setglobal only the global. Bare :set writes both.

Option callbacks

Most string options have a callback like did_set_filetype, did_set_completeopt, etc. Their job:

  • Re-tokenize comma-separated values.
  • Validate enum members.
  • Trigger side effects (load syntax, update internal flags).

Callbacks live in optionstr.c and a small handful in option.c. They are looked up by name from the cb field in options.lua.

API surface

vim.o.tabstop = 4         -- vim.o = global view (read writes both global and current local)
vim.bo.tabstop = 4        -- vim.bo = current buffer-local
vim.wo.cursorline = true  -- vim.wo = current window-local
vim.opt.list = true       -- vim.opt = a table-with-methods view
vim.opt.listchars:append { tab = '> ' }

The Lua wrappers (runtime/lua/vim/_options.lua and friends) call vim.api.nvim_get_option_value / nvim_set_option_value. The C side ends up in src/nvim/api/options.c, which delegates to the same option.c#option_set_value that :set uses.

Documentation generation

make doc runs src/gen/gen_eval_files.lua which parses options.lua and renders the user-facing help in runtime/doc/options.txt. The short_desc, desc, and metadata fields in each option entry become the documentation. Don't edit options.txt directly — it gets clobbered on the next make doc.

Integration points

  • :setdo_set in option.c tokenizes and dispatches.
  • :setlocal, :setglobal — same path, different scope flag.
  • vim.opt, vim.o, vim.bo, vim.wo — Lua front ends that resolve to nvim_get/set_option_value.
  • OptionSet autocmd — fired after every successful option change.
  • Modeline parsingsrc/nvim/main.c#chk_modeline calls into option setting at BufReadPost time.
  • Persistence — option values are NOT saved in shada; users persist them via init.lua or session files.

Entry points for modification

  • Change a default. Edit the defaults table in options.lua. Rebuild.
  • Add a new option. Append a new entry to options.lua. Implement the callback in optionstr.c (string) or option.c (number/bool). Add doc text in the entry's desc field. Run make. Run make doc to regenerate runtime/doc/options.txt.
  • Add a new flag to an existing comma-list option. Edit the option's cb. Touch the relevant validator (e.g. expand_set_listchars).
  • Tweak :set parser. option.c#do_set is dense but well-isolated.

Key source files

File Purpose
src/nvim/options.lua Single source of truth — every option, its type/scope/default
src/nvim/option.c :set parser, option lookup, generic get/set
src/nvim/optionstr.c String-option validators and did_set_* callbacks
src/nvim/option_vars.h Per-option C access macros (generated)
src/nvim/api/options.c The nvim_*_option_value and nvim_*_option_info API
src/gen/gen_options.lua Generator
runtime/lua/vim/_options.lua Lua wrapper (vim.opt, vim.o, etc.)
runtime/doc/options.txt User-facing docs (regenerated)

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Options – Neovim wiki | Factory