19 KiB
Neovim Config Reference
Living reference for session management, keymaps, commands, and plugin-specific features in this config.
The active runtime is Neovim 0.12.6 through ~/.local/bin/nvim. Neovim 0.11.5 remains available at /opt/neovim/nvim-linux-x86_64/bin/nvim for emergency rollback; the config starts there with 0.12-only native completion and Undotree disabled.
Session Management
Session support is automatic but user-controlled:
Manual session creation (one-time):
:mksession # Creates Session.vim in current directory
Auto-load/save (via lua/autocmds.lua):
- On startup: auto-loads
Session.vimif it exists (unless files specified on command line) - On exit: auto-saves to
Session.vimif it already exists - Sessions are per-directory and opt-in (just create one to start using)
Stop using a session:
rm Session.vim # Won't auto-create a new one
Keymaps
:KeymapsGuide (lua/keymaps_reference.lua)
| Command | Description |
|---|---|
:KeymapsGuide |
Open a floating window with a dynamically generated list of all user-defined keymaps |
lua/keymaps.lua
Core keymaps available globally (not plugin-specific). These provide fallbacks for LSP features and diagnostic navigation.
| Mode | Key | Description | Notes |
|---|---|---|---|
| n | gd |
Vim goto-definition fallback | Executes normal! gd for tags/include jumps when no LSP |
| n | gD |
Vim goto-declaration fallback | Executes normal! gD |
| n | gr |
LSP references placeholder | <Nop> so LSP buffers can override cleanly |
| n | gI |
LSP implementation placeholder | <Nop> so LSP buffers can override cleanly |
| n | K |
Keyword help fallback | Uses keywordprg (e.g., man) when LSP hover is unavailable |
| n | <leader>co |
Quickfix: Open | Opens quickfix window |
| n | <leader>cc |
Quickfix: Close | Closes quickfix window |
| n | <leader>lo |
Location list: Open | Opens location list window |
| n | <leader>lc |
Location list: Close | Closes location list window |
| n | <leader>xx |
Diagnostics → location list | Populates current buffer diagnostics |
| n | <leader>xX |
Diagnostics → quickfix | Populates project-wide diagnostics |
| n | <leader>xe |
Diagnostics → buffer errors | Location list filtered to errors |
| n | <leader>xE |
Diagnostics → all errors | Quickfix filtered to errors |
| n | [d |
Diagnostics: previous item | Uses vim.diagnostic.jump with a negative count |
| n | ]d |
Diagnostics: next item | Uses vim.diagnostic.jump with a positive count |
| n | <leader>xd |
Diagnostic float | Opens hover window for cursor diagnostic |
| n | <leader>xt |
Toggle diagnostics | Flips vim.diagnostic.enable() |
| n | <leader>gg |
Git: Changed files → quickfix | Lists all modified/deleted/untracked files with status |
| n | <leader>hi |
Highlight inspector | Shows highlight/capture stack under cursor |
| n | <leader>bg |
Toggle background (light/dark) | Switches between light and dark colorscheme modes |
lua/netrw-config.lua
:Ex Command Variants
| Command | Opens netrw at |
|---|---|
:Ex |
Current working directory (:pwd) |
:Ex . |
Current file's directory |
:Ex %:h |
Current file's directory (explicit) |
:Ex /path/to/dir |
Specific path |
Custom Keymaps
| Mode | Key | Description |
|---|---|---|
| n | <leader>nt |
Open netrw in new tab at current file's directory |
| n | <leader>nT |
Open netrw in new tab at project root |
| n | <leader>nr |
Open netrw in current window at project root |
| n | <C-6> / <C-^> |
Jump to alternate file, skipping netrw explorer buffers |
Note: Project root is stored as the initial working directory when Neovim starts. This allows navigation back to the project root even after following symlinks to external directories.
Default Netrw Keymaps
Navigation & View
| Key | Description |
|---|---|
<CR> |
Open file/directory under cursor |
- |
Go up to parent directory |
gh |
Toggle hidden files visibility (dotfiles) |
i |
Cycle through view types (thin/long/wide/tree) |
s |
Cycle sort order (name/time/size/extension) |
r |
Reverse current sort order |
I |
Toggle netrw banner (help text) |
Preview & Splits
| Key | Description |
|---|---|
p |
Preview the selected file or directory below and enable live cursor updates |
j / k |
Update an existing preview to the newly selected entry |
:pclose / <C-w>z |
Close the preview and stop live updates |
P |
Open file in previous window |
o |
Open file in horizontal split below |
v |
Open file in vertical split |
t |
Open file in a new tab |
Regular files use netrw's native preview. Directories show a read-only summary of their immediate children, including type, file size, modification time, and a total for immediate files. Directories appear first, output is capped at 200 entries, and symbolic links are displayed without following them recursively. File previews use Vim's syntax highlighting while Tree-sitter is suspended to avoid asynchronous parser races during rapid replacement; normal Tree-sitter highlighting resumes automatically when a previewed file is opened for editing. Diagnostics are hidden in previews and restored to their prior state on edit. Preview-only file buffers remain loaded but unlisted until Neovim exits, avoiding the parser detachment that triggers this Neovim 0.12 race.
Opening a file with <CR>, o, v, or t, or otherwise leaving netrw, closes
the preview. Closing it manually also disables live updates until p is pressed
again. Enhanced directory summaries apply to local paths (including local paths
when Neovim runs over SSH); netrw URI browsing retains its native preview
behavior.
File Operations
| Key | Description |
|---|---|
% |
Create new file (prompts for name) |
d |
Create new directory (prompts for name) |
D |
Delete file/directory under cursor |
R |
Rename/move file under cursor |
Marking & Batch Operations
| Key | Description |
|---|---|
mf |
Mark file (for batch operations) |
mr |
Mark files using regex pattern |
mu |
Unmark all marked files |
mt |
Set mark target directory (for move/copy destination) |
mc |
Copy marked files to target directory |
mm |
Move marked files to target directory |
qf |
Display file info |
Plugin Reference
LSP lua/plugins/lsp.lua
Keymaps
Buffer-local keymaps available when an LSP client attaches:
| Mode | Key | Description |
|---|---|---|
| n | gd |
LSP: go to definition |
| n | gr |
LSP: references |
| n | gD |
LSP: declaration |
| n | gI |
LSP: implementation |
| n | K |
LSP hover |
Conform (Formatting) lua/plugins/conform.lua
Keymaps
| Mode | Key | Description |
|---|---|---|
| n | <leader>lt |
Toggle format-on-save flag |
| n | <leader>lf |
Format current buffer (synchronous) |
| v | <leader>lf |
Format visual selection |
Nvim-lint lua/plugins/nvim-lint.lua
Commands
| Command | Description |
|---|---|
:MarkdownLintEnable |
Enable automatic markdown linting (runs on BufEnter, BufWritePost, InsertLeave) |
:MarkdownLintDisable |
Disable automatic markdown linting and clear diagnostics |
Note: Markdown linting is disabled by default. Spellcheck is always enabled for markdown files.
Gitsigns lua/plugins/gitsigns.lua
Keymaps
Buffer-local keymaps available when inside a git repository:
| Mode | Key | Description |
|---|---|---|
| n | ]h |
Next hunk (expr mapping that respects diff windows) |
| n | [h |
Previous hunk |
| n | <leader>hs |
Stage current hunk |
| n | <leader>hr |
Reset current hunk |
| v | <leader>hs |
Stage visually selected range as hunk |
| v | <leader>hr |
Reset visually selected range |
| n | <leader>hS |
Stage entire buffer |
| n | <leader>hu |
Undo last staged hunk |
| n | <leader>hR |
Reset entire buffer |
| n | <leader>hp |
Preview hunk |
| n | <leader>hd |
Diff against index |
| n | <leader>hD |
Diff against previous commit (~) |
| n | <leader>hq |
Send all hunks to quickfix list |
| o/x | ih |
Text object: select git hunk |
Telescope lua/plugins/telescope.lua
Keymaps
Launcher mappings (normal mode)
| Key | Description |
|---|---|
<leader>ff |
Find files |
<leader>fg |
Live grep |
<leader>fb |
Open buffers picker (<C-d> deletes buffers in picker) |
<leader>fh |
Help tags |
<leader>fr |
Recent files (oldfiles) |
<leader>/ |
Fuzzy search current buffer |
<leader>fk / <leader>? |
Telescope keymaps picker |
<leader>fc |
Commands picker |
<leader>fs |
LSP document symbols |
<leader>fS |
LSP workspace symbols |
Telescope prompt mappings (defaults.mappings)
| Mode | Key | Description |
|---|---|---|
| i | <C-n> / <C-j> |
Move selection down |
| i | <C-p> / <C-k> |
Move selection up |
| i | <C-c> |
Close picker |
| i | <CR> |
Accept selection |
| i | <C-x> |
Open selection in horizontal split |
| i | <C-v> |
Open selection in vertical split |
| i | <C-t> |
Open selection in tab |
| n | <Esc> |
Close picker |
| n | <CR> |
Accept selection |
| n | <C-x> |
Horizontal split |
| n | <C-v> |
Vertical split |
| n | <C-t> |
New tab |
| n | j |
Move selection down |
| n | k |
Move selection up |
Picker-specific overrides
| Context | Mode | Key | Description |
|---|---|---|---|
buffers picker |
i | <C-d> |
Delete highlighted buffer |
UFO (Folding) lua/plugins/ufo.lua
Keymaps
| Mode | Key | Description |
|---|---|---|
| n | zR |
Open all folds |
| n | zM |
Close all folds |
| n | zr |
Open folds except configured kinds |
| n | zm |
Close folds with configured kinds |
| n | K |
Peek fold under cursor; falls back to LSP hover |
| preview window | <C-u> / <C-d> |
Scroll within UFO preview |
| preview window | [ / ] |
Jump to top/bottom of preview |
Native Undotree lua/keymaps.lua
Keymaps
| Mode | Key | Description |
|---|---|---|
| n | <leader>u |
Toggle Neovim's native Undotree panel (:Undotree) |
Treesitter lua/plugins/treesitter.lua
Keymaps
Incremental selection
| Key | Description |
|---|---|
+ |
Initialize/expand selection |
g+ |
Expand to scope |
- |
Shrink selection |
Textobject selection (select.keymaps)
| Key | Target |
|---|---|
af / if |
Function outer / inner |
ac / ic |
Class outer / inner |
aa / ia |
Parameter outer / inner |
ai / ii |
Conditional outer / inner |
al / il |
Loop outer / inner |
a/ |
Comment outer |
Textobject movement (move mappings)
| Key | Action |
|---|---|
]f / ]F |
Next function start / end |
[f / [F |
Previous function start / end |
]c / ]C |
Next class start / end |
[c / [C |
Previous class start / end |
]a / ]A |
Next parameter start / end |
[a / [A |
Previous parameter start / end |
Parameter swapping
| Key | Description |
|---|---|
<leader>a |
Swap parameter with next |
<leader>A |
Swap parameter with previous |
Comment.nvim lua/plugins/comment.lua
Keymaps
| Mapping | Description |
|---|---|
gcc |
Toggle line comment |
gbc |
Toggle block comment |
gc |
Operator-pending line comment |
gb |
Operator-pending block comment |
gcO / gco / gcA |
Insert comment above / below / end-of-line |
Nvim-surround lua/plugins/surround.lua
The configuration uses nvim-surround v4's default mappings.
Keymaps
| Mode | Mapping | Description |
|---|---|---|
| normal | ys{motion}{char} |
Add surround to motion |
| normal | yss |
Surround current line |
| normal | yS |
Surround motion with linewise behavior |
| normal | ySS |
Surround current line linewise |
| insert | <C-g>s |
Surround following text object |
| insert | <C-g>S |
Surround current line |
| visual | S |
Surround selection |
| visual line | gS |
Surround visual-line selection |
| normal | ds{char} |
Delete surround |
| normal | cs{old}{new} |
Change surround |
| normal | cS{old}{new} |
Change surround (linewise) |
Native Completion lua/completion.lua
Keymaps
| Mode | Key | Description |
|---|---|---|
| insert | <C-Space> |
Manually trigger LSP completion |
| insert | <C-n> |
Next completion item |
| insert | <C-p> |
Previous completion item |
| insert | <C-y> |
Accept the explicitly selected completion item |
| insert | <C-e> |
Dismiss the completion menu |
| insert | <C-x><C-n> |
Complete words from the current buffer |
| insert | <C-x><C-f> |
Complete a filesystem path |
| insert/select | <Tab> / <S-Tab> |
Jump forward/backward through native snippet tabstops |
Completion opens automatically after a 150 ms delay, uses fuzzy matching, and does not preselect an item. LSP buffers prioritize language-aware results exclusively; buffer words remain available explicitly with <C-x><C-n>. Buffers without an LSP autocomplete from a bounded set of nearby words.
Copilot Inline Suggestions lua/plugins/copilot.lua
Copilot appears as ghost text rather than as an item in the native completion menu. Suggestions are hidden while that menu is visible.
| Mode | Key | Description |
|---|---|---|
| insert | <M-l> |
Accept the visible Copilot suggestion |
| insert | <M-]> |
Show the next Copilot suggestion |
| insert | <M-[> |
Show the previous Copilot suggestion |
| insert | <C-]> |
Dismiss the Copilot suggestion |
Nvim-autopairs lua/plugins/autopairs.lua
Keymaps
| Mode | Key | Description |
|---|---|---|
| insert | <M-e> |
Fast wrap the previous text with a pair |
Configuration
Colorscheme
paper-tonic-modern is built into this repository and loaded from colors/paper-tonic-modern.lua. Its modular highlight definitions live under lua/paper-tonic-modern/ and cover the editor UI, traditional syntax, Tree-sitter captures, LSP diagnostics, and the configured plugins.
The theme follows the system light/dark preference at startup. Use <leader>bg to toggle the background manually. Custom HTML and CSS Tree-sitter queries keep matching classes and IDs visually consistent across both languages.
Project-Local LSP Settings
Native exrc and secure support are enabled. A trusted .nvim.lua can return an lsp table keyed by server name; settings are securely read from the attached LSP client's root and sent through workspace/didChangeConfiguration.
return {
lsp = {
intelephense = {
settings = {
intelephense = {
environment = {
includePaths = { "vendor/package/src" },
},
},
},
},
},
}
Formatting & Linting
This config uses conform.nvim for formatting and nvim-lint for diagnostics. Both prefer project-local tools over global installations.
Executable Resolution Order
When looking for formatters/linters, the config searches in this priority:
- Project-local (e.g.,
node_modules/.bin/,vendor/bin/) - Mason-managed (
~/.local/share/nvim/mason/bin/) - System PATH (globally installed tools)
Conform.nvim handles this resolution automatically via its built-in util.find_executable(). nvim-lint uses a custom find_executable() helper in lua/plugins/nvim-lint.lua.
Configured Tools
Formatters (lua/plugins/conform.lua):
- JavaScript/TypeScript/CSS/JSON/HTML/Markdown:
prettier - PHP:
phpcbf(WordPress standard by default) - Lua:
stylua - Python:
ruff_format
Linters (lua/plugins/nvim-lint.lua):
- JavaScript/TypeScript:
eslint_d - PHP:
phpcs(WordPress standard by default) - Markdown:
markdownlint(disabled by default; use:MarkdownLintEnable) - Python: handled by
ruffLSP (not nvim-lint)
Project-Specific Overrides
Both formatters and linters respect project-level configuration files:
PHP (phpcbf + phpcs):
- Create
phpcs.xmlorphpcs.xml.distin your project root - When present, this file controls the coding standard (e.g., PSR-12, WordPress, custom)
- When absent, defaults to
--standard=WordPress
Example phpcs.xml:
<?xml version="1.0"?>
<ruleset name="Custom">
<description>Project-specific PHP rules</description>
<rule ref="PSR12"/>
<!-- or: <rule ref="WordPress-Core"/> -->
<!-- Customize rules -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="120"/>
</properties>
</rule>
</ruleset>
JavaScript/TypeScript (prettier + eslint):
- Project config files:
.prettierrc,.eslintrc.json,eslint.config.js, etc. - Global fallback:
~/.eslintrc.json(when no project config exists)
Lua (stylua):
- Project config:
stylua.tomlor.stylua.toml - Falls back to stylua defaults if not present
Markdown (markdownlint):
- Project config:
.markdownlint.json,.markdownlintrc
Changing Standards Per-Project
To switch a PHP project from WordPress to PSR-12:
-
Create
phpcs.xmlin project root:<?xml version="1.0"?> <ruleset name="PSR-12"> <rule ref="PSR12"/> </ruleset> -
Restart Neovim (or reload config:
:source $MYVIMRC)
Both phpcs and phpcbf will now use PSR-12 rules in that project.
Format-on-Save
- Enabled by default for all supported filetypes
- Toggle:
<leader>lt(see keymaps below) - Manual format:
<leader>lf(buffer or visual selection)
Linting Behavior
- Automatic: Runs on
BufEnter,BufWritePost,InsertLeave - Per-filetype: Configured in
lint.linters_by_fttable - Markdown: Opt-in only (
:MarkdownLintEnable/:MarkdownLintDisable)
Configuration Options
Tabline Display
Custom tabline shows intelligent path shortening with two configurable options.
Location: lua/settings.lua (configured via utils.tabline_full_parents and utils.tabline_shorten_length)
Configuration Options:
utils.tabline_full_parents(default:1) - Number of parent directories to show in fullutils.tabline_shorten_length(default:3) - Number of characters to show for shortened directories
Examples:
With full_parents = 1, shorten_length = 3:
/path/to/my/project/src/file.txt→pat/to/my/project/src/file.txt
With full_parents = 2, shorten_length = 3:
/path/to/my/project/src/file.txt→pat/to/my/project/src/file.txt
With full_parents = 1, shorten_length = 1:
/path/to/my/project/src/file.txt→p/t/m/project/src/file.txt
With full_parents = 0, shorten_length = 3:
/path/to/my/project/src/file.txt→pat/to/my/pro/src/file.txt
The last N parent directories are shown in full, earlier directories are shortened to the specified number of characters. The filename itself is always shown in full.
To customize: Edit utils.tabline_full_parents and utils.tabline_shorten_length values in lua/settings.lua
Working Directory Behavior
The working directory (:pwd) is locked to the directory where you opened Neovim and does NOT change when switching files:
autochdiris disabled (working directory stays fixed at project root)netrw_keepdir = 1prevents netrw from changing directory when browsing- Project root is captured at startup in
vim.g.project_root(used by Telescope and netrw) - Telescope searches from the initial project root regardless of current buffer
- Use
:cd <path>to manually change directory if needed (affects Telescope search scope)