Why “Ultimate”? A Philosophy, Not a Dump of Settings Top
An ultimate Neovim configuration isn’t the one with the most plugins—it’s
the one that starts in under 100 ms, behaves identically on any machine,
and feels like a custom‑built engineering console rather than a text editor.
This article presents the full architecture of the setup I’ve refined over
years of daily use: writing LaTeX, Python, shell scripts, HTML, and Markdown.
It’s modular, lazy‑loaded, and completely deterministic. Download the included zip file at the end of the article,
run :Lazy sync, and every keybinding, colour, and snippet is
exactly as intended.
The configuration is split into logical modules—each file has a single
responsibility. This article walks through every piece, explaining not just
the “what” but the “why”. All file contents are included; copy them directly
into your own ~/.config/nvim and you’ll have a fully functional
developer environment.
Directory Tree Top
Neovim respects ~/.config/nvim/ and expects Lua modules under
lua/. The tree below shows every file that makes up this
configuration. Central files are highlighted in bold.
~/.config/nvim/
├── init.lua ← entry point
├── lazy-lock.json ← pinned plugin versions
├── lua/
│ ├── config/
│ │ ├── lazy.lua ← bootstraps lazy.nvim
│ │ ├── colors.lua ← themes & highlights
│ │ ├── commands.lua ← user commands
│ │ ├── functions.lua ← automation utilities
│ │ ├── keymaps.lua ← global keybindings
│ │ ├── html_markdown_maps.lua ← shared visual wrappers
│ │ ├── html_snippets.lua ← HTML / Markdown snippets
│ │ ├── tex_snippets.lua ← LaTeX snippets
│ │ └── options.lua
│ └── plugins/
│ └── core.lua ← plugin specification
└── ftplugin/
├── python.lua
├── tex.lua
├── html.lua
├── markdown.lua
└── lua.lua
Nothing is loaded until it’s needed. Global options live in
init.lua; everything else is deferred by lazy.nvim or
triggered by filetype events.
The Bootstrapper — init.lua Top
init.lua is the first file Neovim reads. It sets the
baseline: leader keys, editor options, persistent history and undo,
a fallback colourscheme, and the lazy‑loading schedule.
Here is the complete file.
-- Leader keys
vim.g.mapleader = ","
vim.g.maplocalleader = " "
-- Basic settings
vim.o.number = true
vim.o.relativenumber = true
vim.o.termguicolors = true
vim.o.wrap = true
vim.o.tabstop = 2
vim.o.shiftwidth = 2
vim.o.expandtab = true
vim.o.mouse = "a"
vim.o.cmdheight = 1
vim.opt.ignorecase = true
vim.opt.smartcase = true
-- Disable netrw (we use ranger / telescope)
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
-- Maximum history and persistent undo
vim.opt.history = 10000
vim.opt.undolevels = 10000
vim.opt.undoreload = 100000
vim.opt.undofile = true
vim.opt.undodir = vim.fn.stdpath("data") .. "/undo"
vim.opt.shadafile = vim.fn.stdpath("data") .. "/shada/main.shada"
vim.opt.shada = "'100000,<1000,s100,h"
vim.cmd("silent! rshada")
-- Fallback colourscheme – editor never looks broken
vim.cmd("colorscheme desert")
-- Bootstrap lazy.nvim, then schedule the rest
require("config.lazy")
vim.schedule(function()
require("config.colors").setup()
require("config.keymaps")
require("config.commands")
end)
-- Autocommands
-- Remove trailing whitespace on save
vim.api.nvim_create_autocmd("BufWritePre", {
pattern = "*",
callback = function()
vim.cmd([[%s/\s\+$//e]])
end
})
-- Remember last cursor position
vim.api.nvim_create_autocmd("BufReadPost", {
pattern = "*",
callback = function()
local last_pos = vim.fn.line([['"]])
if last_pos > 1 and last_pos <= vim.fn.line("$") then
vim.cmd("normal! g`\"")
end
end,
})
-- Automatically set filetype for .tex files
vim.api.nvim_create_autocmd({"BufEnter", "BufNew", "BufNewFile", "BufRead"}, {
pattern = "*.tex",
callback = function()
vim.bo.filetype = "tex"
end
})
-- Change current directory to the directory of the current file (except /tmp)
vim.api.nvim_create_autocmd("BufReadPost", {
callback = function()
local dir = vim.fn.expand("%:p:h")
if dir ~= "" and not dir:match("^/tmp") then
vim.cmd("silent! lcd " .. dir)
end
end,
})
-- Briefly highlight yanked text
vim.api.nvim_create_autocmd("TextYankPost", {
pattern = "*",
callback = function()
vim.highlight.on_yank({
higroup = "IncSearch",
timeout = 500,
})
end,
})
- Leader keys –
,for global,Spacefor local – keep custom mappings under the left hand. - Persistent state – undo files and
shada(command/search history, marks) are stored in Neovim’s data directory and set to very high limits so nothing is ever lost. - Fallback colourscheme –
desertis set synchronously to eliminate any flash of unstyled text. The real theme loads later. - Scheduled callback –
vim.schedule()defers the remaining setup until after plugins are loaded, preventing “module not found” errors. - Autocommands – small infrastructure pieces that keep diffs clean, restore cursor position, auto‑detect
.texfiles, and provide instant yank feedback.
Lazy Loading with lazy.nvim Top
lua/config/lazy.lua is the only file that touches plugin
management. It clones lazy.nvim if missing, then loads the plugin
specification from lua/plugins/core.lua.
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git", "clone", "--filter=blob:none",
"https://github.com/folke/lazy.nvim.git", lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
spec = { { import = "plugins" } },
ui = { border = "rounded" },
})
The companion lazy-lock.json (included in the zip file at the end of the article)
pins every plugin commit, making the whole plugin set reproducible.
The Visual Stack — colors.lua Top
lua/config/colors.lua applies the chosen theme (Nordic),
sets custom highlights, makes most UI elements transparent, and
re‑applies critical highlights after every colour scheme change.
local M = {}
function M.setup()
vim.o.background = "dark"
local ok, err = pcall(vim.cmd, "colorscheme nordic")
if not ok then
vim.cmd("colorscheme desert")
vim.notify("Warning: Falling back to 'desert'. " .. tostring(err), vim.log.levels.WARN)
end
vim.wo.cursorline = true
-- Explicit hex colours (independent of theme palette)
vim.api.nvim_set_hl(0, "CursorLine", { bg = "#3b4261", bold = true })
vim.api.nvim_set_hl(0, "Cursor", { bg = "#434C5E", fg = "#ECEFF4", blend = 60 })
vim.api.nvim_set_hl(0, "StatusLine", { bg = "#1f2335", fg = "#c0caf5", bold = true })
vim.api.nvim_set_hl(0, "Visual", { bg = "#FFD966", fg = "black" })
vim.api.nvim_set_hl(0, "Search", { bg = "#ff9e64", fg = "black", bold = true })
vim.api.nvim_set_hl(0, "LineNr", { fg = "#FFFF00" })
vim.api.nvim_set_hl(0, "CursorLineNr", { fg = "#c0caf5", bold = true })
-- … plus many more (see the full file)
-- Transparency: structural UI gets no background
local transparent = {
"Normal", "NormalNC", "NormalFloat", "SignColumn", "MsgArea",
"TelescopeNormal", "TelescopeBorder", "StatusLine", "StatusLineNC",
"BufferLineFill", "BufferLineBackground", "LineNr", "CursorLineNr",
"FloatBorder",
}
for _, grp in ipairs(transparent) do
vim.api.nvim_set_hl(0, grp, { bg = "none" })
end
-- Re‑apply matching bracket highlights after every theme change
vim.api.nvim_create_autocmd({ "ColorScheme", "User" }, {
pattern = { "LazyDone", "VeryLazy" },
callback = function()
vim.api.nvim_set_hl(0, "MatchParen", { bg = "#ff33aa", fg = "#000000", bold = true })
vim.api.nvim_set_hl(0, "MatchParenCur", { bg = "#ff33aa", fg = "#000000", bold = true })
vim.api.nvim_set_hl(0, "MatchWord", { bg = "#5555ff", fg = "#000000" })
end,
})
end
return M
By using raw hex codes, the highlights stay identical whether you run
Nordic, Tokyonight, or the fallback Desert. The autocommand on
ColorScheme ensures that even if a plugin reloads the
theme, your custom highlights survive.
Global Keymaps & User Commands Top
lua/config/keymaps.lua and
lua/config/commands.lua form a unified toolbelt.
Every keybinding has a corresponding user command, and every
command delegates to a single function. This makes the system
auditable, remappable, and self‑documenting.
keymaps.lua
local opts = { noremap = true, silent = true }
local functions = require("config.functions")
-- Clipboard
vim.keymap.set("n", "cc", 'gg"+yG', opts)
vim.keymap.set("v", "<C-c>", '"+y', opts)
vim.keymap.set("i", "<C-v>", '<C-r>+', opts)
-- Buffer / window navigation
vim.keymap.set("n", "<Tab>", ":bn<CR>", opts)
vim.keymap.set("n", "<S-Tab>", ":bp<CR>", opts)
vim.keymap.set("n", "<C-h>", "<C-w>h", opts)
vim.keymap.set("n", "<C-j>", "<C-w>j", opts)
vim.keymap.set("n", "<C-k>", "<C-w>k", opts)
vim.keymap.set("n", "<C-l>", "<C-w>l", opts)
-- Automation tools
vim.keymap.set("n", "<leader>wc", functions.word_count, opts)
vim.keymap.set("n", "<leader>cc", functions.command_history_explorer, opts)
vim.keymap.set("n", "<leader>rr", functions.output_regs, opts)
vim.keymap.set("n", "<leader>hh", functions.wrap_code_in_buffer, opts)
vim.keymap.set("n", "<leader>ranger",functions.ranger_chooser, opts)
vim.keymap.set("n", "<leader>mm", functions.output_old_files, opts)
-- etc. (see the full file)
commands.lua
local functions = require("config.functions")
vim.api.nvim_create_user_command("WC", functions.word_count, {})
vim.api.nvim_create_user_command("Mm", functions.output_old_files, {})
vim.api.nvim_create_user_command("Cc", functions.command_history_explorer, {})
vim.api.nvim_create_user_command("Ss", functions.search_command_history, {})
vim.api.nvim_create_user_command("Rr", functions.output_regs, {})
vim.api.nvim_create_user_command("HH", functions.wrap_code_in_buffer, {})
vim.api.nvim_create_user_command("RangerChooser", functions.ranger_chooser, {})
vim.api.nvim_create_user_command("SaveVimInfo", functions.save_vim_bindings_and_functions, {})
vim.api.nvim_create_user_command("EngType", functions.eng_type, {})
vim.api.nvim_create_user_command("FrType", functions.fr_type, {})
Mnemonic prefixes make the system self‑documenting:
<leader>wc → word count,
<leader>cc → command history, etc.
Automation Functions — functions.lua Top
lua/config/functions.lua is the heart of the automation
layer. It provides async Python/LaTeX runners, a searchable command
history, a register inspector, an “old files” browser, a ranger
file‑chooser, buffer‑wrapping utilities, and more. All are written in
pure Lua with no plugin dependencies.
Asynchronous Python Execution
function M.run_python_selection()
local mode = vim.fn.mode()
if mode ~= 'v' and mode ~= 'V' then return end
local save_reg = vim.fn.getreg('"')
vim.cmd('normal! gvy')
local code = vim.fn.getreg('"')
vim.fn.setreg('"', save_reg)
code = "from math import *\n" .. code:gsub('^%s*', ''):gsub('%s*$', '')
local output = vim.fn.system({'python3', '-c', code})
vim.cmd('enew')
vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n"))
vim.bo.buftype = 'nofile'
vim.bo.bufhidden = 'wipe'
end
Command History Explorer
function M.command_history_explorer()
local history = {}
for i = vim.fn.histnr(':'), 1, -1 do
local cmd = vim.fn.histget(':', i)
if cmd ~= "" then table.insert(history, cmd) end
end
vim.cmd('enew')
local buf = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines(buf, 0, -1, false, history)
vim.bo[buf].buftype = 'nofile'
vim.bo[buf].modifiable = false
vim.keymap.set('n', '<CR>', function()
local cmd = vim.fn.getline('.')
vim.cmd('bd! ' .. buf)
vim.cmd(cmd)
end, { buffer = buf })
vim.cmd('normal! gg')
end
Register Inspector
function M.output_regs()
vim.cmd('enew')
local content = {}
for reg = string.byte('a'), string.byte('z') do
local ch = string.char(reg)
local val = vim.fn.getreg(ch)
if val ~= '' then
table.insert(content, ch .. ":")
table.insert(content, val)
table.insert(content, "")
end
end
vim.api.nvim_buf_set_lines(0, 0, -1, false, content)
vim.bo.buftype = 'nofile'
vim.bo.bufhidden = 'wipe'
vim.cmd('normal! gg')
end
The file also contains run_python_and_replace,
output_old_files, ranger_chooser,
wrap_code_in_buffer, word_count,
select_inside_any_pair, and several language‑specific
helpers. You can find the complete source in the included zip file at the end of the article.
Per‑Filetype Engines — ftplugin Top
Filetype‑specific behaviour lives in ftplugin/. Each file
sets buffer‑local options and defines insert‑mode expansions. Visual‑mode
wrappers for HTML and Markdown are centralised in a shared module to
avoid duplication.
Python ftplugin
-- ftplugin/python.lua
vim.bo.tabstop = 4
vim.bo.shiftwidth = 4
vim.bo.expandtab = true
vim.bo.textwidth = 88
-- Run buffer asynchronously (full function omitted for brevity)
vim.keymap.set('n', '<leader>c', run_python_buffer, { buffer = true })
-- Insert-mode expansions
local imaps = {
['if'] = 'if :<++><ESC>F:a',
['for'] = 'for in :<++><ESC>F:i',
['def'] = 'def ():<++><ESC>F(a',
['class'] = 'class :<++><ESC>F:a',
['imp'] = 'import ',
['from'] = 'from import <++><ESC>F:i',
-- … many more
}
for lhs, rhs in pairs(imaps) do
vim.keymap.set('i', lhs, rhs, { buffer = true })
end
LaTeX ftplugin
-- ftplugin/tex.lua (excerpt)
vim.bo.tabstop = 2
vim.bo.shiftwidth = 2
-- Async compilation and PDF viewer
vim.keymap.set('n', '<leader>c', run_tex, { buffer = true })
vim.keymap.set('n', '<leader>o', view_tex, { buffer = true })
vim.keymap.set('n', '<leader>w', wrap_buffer_in_html_tags, { buffer = true })
-- Insert-mode shortcuts for commands, environments, and symbols
local imaps = {
['!'] = '\\',
['qq'] = '\\quad ',
[',bf'] = '\\textbf{}<++><ESC>F{a',
[',u'] = '\\underline{}<++><ESC>F{a',
-- … dozens more
}
for lhs, rhs in pairs(imaps) do
vim.keymap.set('i', lhs, rhs, { buffer = true })
end
HTML & Markdown ftplugins
-- ftplugin/html.lua
vim.bo.tabstop = 2
vim.bo.shiftwidth = 2
local imaps = {
['!'] = '<!-- --><++><Esc>F i',
['<'] = '<><++><Esc>F>a',
}
for lhs, rhs in pairs(imaps) do
vim.keymap.set('i', lhs, rhs, { buffer = true })
end
require("config.html_markdown_maps")()
-- ftplugin/markdown.lua
vim.bo.tabstop = 2
vim.bo.shiftwidth = 2
require("config.html_markdown_maps")()
Shared Visual Wrappers — html_markdown_maps.lua
This module registers visual‑mode mappings that work identically in
HTML and Markdown buffers. It uses a pure‑Lua wrap_visual_text
function that handles linewise, characterwise, and blockwise selections.
-- lua/config/html_markdown_maps.lua (core wrapping function)
local function wrap_visual_text(open_tag, close_tag)
local mode = vim.fn.visualmode()
-- … normalises start/end, gets the visual selection,
-- and wraps it with open_tag .. text .. close_tag
-- (full implementation in the included zip file at the end of the article)
end
return function()
vim.keymap.set('v', '<leader>pp', function() wrap_visual_text('<p>', '</p>') end)
vim.keymap.set('v', '<leader>hh', function() wrap_visual_text('<h2>', '</h2>') end)
-- … and many more wrapping / escaping shortcuts
end
Additionally, the file defines a set of number‑prefixed visual maps
(1–9) for common transformations: escaping
symbols, wrapping in code blocks, URL‑encoding, and more. See the
included zip file at the end of the article for the full content.
Snippets as Code — LuaSnip Integration Top
Snippets are defined in two files: tex_snippets.lua and
html_snippets.lua. They use LuaSnip’s function nodes for
dynamic behaviour, read legacy snippet files on demand, and auto‑number
LaTeX exercises based on buffer content.
LaTeX Snippets
-- tex_snippets.lua (excerpt)
local ls = require("luasnip")
local s = ls.snippet
local i = ls.insert_node
local t = ls.text_node
local f = ls.function_node
-- Auto‑numbered exercise environment
s("exe", {
t("\\begin{exe}{"), i(1, "<++>"), t("}"),
t({"", " "}), f(function()
local count = 0
for _, line in ipairs(vim.api.nvim_buf_get_lines(0, 0, -1, false)) do
if line:match("\\begin{exe}") then count = count + 1 end
end
return tostring(count)
end),
t({"", " <++>", "\\end{exe}"}),
})
The file also wraps legacy snippet files from
~/.vim/snippets/latex/ so they appear as native LuaSnip
snippets, and exports functions that can be called directly from
insert‑mode mappings (e.g., ,tcb in the LaTeX ftplugin).
HTML / Markdown Snippets
-- html_snippets.lua
local snippets = {
s("fig", {
t("<figure>"),
t({ "", " " }),
t('<img src="/theme/images/articles/'), i(1, "image.png"),
t('" alt="'), i(2, "description"), t('" style="max-width:100%;height:auto;" >'),
t({ "", " " }),
t("<figcaption>"), i(3, "caption"), t("</figcaption>"),
t({ "", "</figure>" }),
i(0),
}),
-- … anchor link, code block with raw tags, etc.
}
ls.add_snippets("html", snippets)
ls.add_snippets("markdown", snippets)
The Plugin Dashboard — core.lua Top
lua/plugins/core.lua lists every plugin. Each one
lazy‑loads on an event, command, or filetype. The full specification
is shown below.
return {
-- Themes (loaded immediately)
{ "AlexvZyl/nordic.nvim", lazy = false, priority = 1000 },
{ "folke/tokyonight.nvim", lazy = false, priority = 1000 },
-- Telescope (fuzzy finder)
{
"nvim-telescope/telescope.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
cmd = "Telescope",
config = function()
local builtin = require("telescope.builtin")
vim.keymap.set("n", "<leader>ff", builtin.find_files)
vim.keymap.set("n", "<leader>fg", builtin.live_grep)
vim.keymap.set("n", "<leader>fb", builtin.buffers)
vim.keymap.set("n", "<leader>fh", builtin.help_tags)
end,
},
-- Treesitter (syntax highlighting and indentation)
{
"nvim-treesitter/nvim-treesitter",
build = ":TSUpdate",
event = { "BufReadPost", "BufNewFile" },
config = function()
require("nvim-treesitter.configs").setup({
ensure_installed = {
"lua", "python", "javascript", "html", "css", "bash", "c", "cpp", "json", "yaml",
},
highlight = { enable = true },
indent = { enable = true },
})
end,
},
-- Mason (LSP/DAP/linter manager)
{
"williamboman/mason.nvim",
build = ":MasonUpdate",
config = function() require("mason").setup() end,
},
-- nvim-cmp + LuaSnip (completion & snippets)
{
"hrsh7th/nvim-cmp",
dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
"hrsh7th/cmp-path",
"saadparwaiz1/cmp_luasnip",
"L3MON4D3/LuaSnip",
},
event = "InsertEnter",
config = function()
local cmp = require("cmp")
local luasnip = require("luasnip")
vim.o.completeopt = "menu,menuone,noselect"
cmp.setup({
snippet = {
expand = function(args) luasnip.lsp_expand(args.body) end,
},
mapping = cmp.mapping.preset.insert({
['<C-Space>'] = cmp.mapping.complete(),
['<CR>'] = cmp.mapping.confirm({ select = true }),
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then cmp.select_next_item()
elseif luasnip.expand_or_jumpable() then luasnip.expand_or_jump()
else fallback() end
end, { "i", "s" }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then cmp.select_prev_item()
elseif luasnip.jumpable(-1) then luasnip.jump(-1)
else fallback() end
end, { "i", "s" }),
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
{ name = 'buffer' },
{ name = 'path' },
}),
})
-- Load our custom snippets
require("config.tex_snippets")
require("config.html_snippets")
end,
},
-- Minimal bufferline
{
"akinsho/bufferline.nvim",
version = "*",
config = function()
require("bufferline").setup({
options = {
mode = "buffers",
show_buffer_close_icons = false,
show_close_icon = false,
truncate_names = false,
diagnostics = false,
separator_style = { "|", "|" },
always_show_bufferline = true,
numbers = "none",
},
})
end,
},
}
Equally important is what’s not included: no file‑tree plugin (ranger and Telescope cover navigation), no statusline plugin (the built‑in one plus custom highlights suffice), and no AI‑powered completion. Every plugin must justify its presence.
Putting It All Together Top
When you start Neovim:
init.luasets options, loadslazy.nvim, and schedules the colour setup.- Lazy.nvim parses
plugins/core.luaand begins loading plugins by their lazy‑load triggers. - The scheduled callback applies the theme, defines global keymaps and commands.
- When a buffer is opened, Treesitter attaches, the appropriate ftplugin fires, and snippets register for that filetype.
- On
InsertEnter, nvim‑cmp activates with all snippet and LSP sources ready.
At no point does the user wait for a progress bar. The entire plugin set, once cached, starts in under 100 milliseconds.
Reproducibility & Final Thoughts Top
This configuration is a build artifact. The lazy-lock.json
pins every plugin version, the colours are hard‑coded hex values, and
every snippet and function is defined in Lua. To replicate the
environment on a new machine, you only need:
# extract the zip file and
cp nvim ~/.config/nvim
nvim --headless "+Lazy sync" +qa
After that, your editor will start in under 100 ms and behave exactly as it does today.
The seven companion articles dive deeper into each subsystem: the bootstrapping layer, filetype engines, custom functions, snippets, colours, keymaps/commands, and the plugin ecosystem. But the article you’ve just read contains the complete source and the reasoning you need to build your own ultimate Neovim setup.
Leave a comment