- Tree-sitter only. No regex fallbacks for parsing. If tree-sitter doesn't provide the node, fix the query or walk the AST.
- Markdown + tex filetypes only. No typst, rnoweb, vimwiki, or other formats.
.bib.jsonis an equal method, not a fallback. Same priority as YAML frontmatter and LaTeX commands.
Every backend implements these five functions:
load(bufnr) → nil | throws error # open the data source
match(prefix) → BibEntry[] # case-insensitive prefix match
get(key) → BibEntry|nil # single entry lookup
definition(key) → {uri, range} # LSP go-to location
hover(key) → string|nil # formatted hover content- Named modules. No
M = {}patterns. Return a named table directly. - No re-exports. Every consumer imports the correct module directly.
require("bib.patterns"), neverutils.patterns. - Lookup tables over if/else chains. Use
{[condition] = handler}dictionaries. - vim.iter over manual loops. Use
:map,:find,:fold,:each. Plainforloops only whenvim.iterwould hurt readability (recursive tree walks use:fold). - No global variables. No
vim.g.*outside of config default access. - No section comments. No
-- =====or decorative separators. - Patterns in
bib.patterns. All regex lives inlua/bib/patterns.luawith---@fieldannotations. No raw regex strings in code. - No SQL in Lua code. Queries go in
sql/directory as named.sqlfiles. - Helpers go to
bib.utils. No local functions unless the logic is specific to a single module and not reusable.
---@typeon every table:---@type table<string, BibEntry>---@paramand---@returnon every function---@classfor named structured types- Types go in
types.luawhen consumed by multiple modules (e.g.,bib/types.lua,bib/backends/types.lua). Keep in-module otherwise.
- No diagnostic disables. Fix the root cause. Never suppress warnings with
---@diagnosticor---@type any.
- TDD always. RED → GREEN → REFACTOR. No code without a failing test.
- Table-driven with vim.iter. Use
vim.iter({cases}):each(...). - One test group per function under test.
- Child process isolation.
tu.new_child_set()for every test module.--nopluginon the child. - Clean temp dirs. Temp directories cleaned in
post_casehooks.
- Bibtex only. No biblatex support (
\addbibresource). - No regex-based extraction. Citation keys extracted via tree-sitter node text + character scanning from cursor position, not pattern matching.
- Query files are lazy.
lua/bib/queries.luauses metatable to load on first access (avoids crashing when optional parsers aren't available).
- Baby steps. Stop and ask if a diff exceeds ~300 lines.
- Deletion over addition. Prefer removing code over adding it.
- Never patch symptoms. Find the root cause, prove it with a failing test, then fix.
sqlite.luaby kkharji — FFI to systemlibsqlite3.so.- No luarocks dependencies — users install plugins alongside bib.nvim.
- Devenv provides parsers —
tree-sitter.withPluginsindevenv.nix, registered viavim.treesitter.language.add.