Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

51 Commits

Folders and files

Repository files navigation

Neovim configuration

Personal Neovim configuration for Windows, organized into core settings, plugin configuration, and custom terminal support. It uses Neovim's built-in vim.pack package manager and sets both the global and local leader to Space.

See CHEATSHEET.md for the command and key reference

Requirements

  • Neovim 0.12 or newer
  • Git
  • ripgrep for Telescope live grep
  • lazygit for the floating Git interface
  • stylua and prettier on PATH for configured formatting
  • Git for Windows, for Git Bash and custom terminals — bash.exe is auto-detected from git on PATH or the standard Git for Windows install locations (see lua/config/shell.lua)
  • Optional: make for Telescope's native FZF extension and supported plugin build hooks
  • Node.js, for vtsls, eslint, oxlint, and :TSC
  • Optional: the Odin compiler on PATH, for ols's type checking and its core/vendor collections — ols and odinfmt themselves come from Mason

Run :checkhealth kickstart to verify all of the above at once — each optional tool it reports names the single feature that stops working without it.

nvim-pack-lock.json is tracked in this repository so plugin commits are pinned across machines (:help vim.pack-lockfile).

Configuration layout

Path Responsibility
init.lua Loads every module in dependency order
lua/config/options.lua Leaders, globals, and editor options
lua/config/shell.lua Shared Bash, Command Prompt, and PowerShell profiles
lua/config/keymaps.lua Global mappings and diagnostics
lua/config/autocmds.lua General autocmds: yank highlight, terminal highlight, trim-trailing-whitespace on save
lua/config/pack.lua vim.pack build hooks and GitHub URL helper
lua/plugins/ui.lua Theme, Bufferline, statusline, Gitsigns, Which-key, and Mini
lua/plugins/telescope.lua Search, picker, buffer, and LSP picker mappings
lua/plugins/lsp.lua LSP attachment, servers, Fidget, and Mason
lua/plugins/tsc.lua tsc.nvim: on-demand type-checking with the project's real tsc (:TSC)
lua/plugins/formatting.lua Conform setup and manual formatting (<leader>f)
lua/plugins/completion.lua Blink completion and LuaSnip
lua/plugins/treesitter.lua Parser installation, attachment, and folding
lua/plugins/neo-tree.lua File explorer setup
lua/custom/terminal.lua Persistent split terminals and floating commands
lua/custom/plugins/init.lua Auto-loads any extra plugin files dropped into lua/custom/plugins/
lua/kickstart/health.lua :checkhealth kickstart — Neovim version, required/optional external tools, and shell-profile resolution

Key notation

Notation Meaning
<leader> Space
<C-x> Hold Ctrl and press x
<A-x> Hold Alt and press x
<S-x> Hold Shift and press x
Normal Normal mode
Visual Visual or selection mode
Insert Insert mode
Terminal Terminal-input mode

Shell selection

The shell used by :!, filters such as :.!command, and custom terminal windows is selected in lua/config/shell.lua:

M.selected = 'bash'

Change that value to one of the configured profiles:

Value Shell Example command
'bash' Git Bash :!ls
'cmd' Command Prompt :!dir
'powershell' Windows PowerShell :!Get-ChildItem

Each profile sets its executable, command flag, quoting, redirection, and terminal arguments together. Restart Neovim after changing the selected profile.

Useful forms:

  • :!command runs a command and displays its output.
  • :.!command replaces the current line with the command output.
  • :read !command inserts the command output below the current line.
  • :%!command filters the entire buffer through the command.
  • :set shell? shellcmdflag? displays the active executable and command flag.

General editing and windows

Mode Key Action
Normal <S-h> Open the previous buffer
Normal <S-l> Open the next buffer
Normal <leader>v Create a vertical split
Normal <leader>h/j/k/l Focus the window to the left/down/up/right
Normal <C-h/j/k/l> Focus the window to the left/down/up/right
Normal <A-j> Move the current line down and reindent it
Normal <A-k> Move the current line up and reindent it
Visual <A-j> Move the selected lines down and preserve the selection
Visual <A-k> Move the selected lines up and preserve the selection
Normal <Esc> Clear search highlighting
Visual s Replace the selection, using Vim's c operation

Buffers

Key Action
<leader>bn Open the next buffer
<leader>bp Open the previous buffer
<leader>bd Delete the current buffer, leaving its window in place
<leader>bb Create a new empty buffer
<leader>sb Search open buffers with Telescope

Deleting a buffer never takes its window with it. :bdelete on its own closes every window showing the buffer, so with the terminal panel open the editor window above it would disappear and the 12-line panel would stretch over the whole screen. <leader>bd points those windows at something else first -- the buffer they were on before, the next one in the buffer list, or an empty buffer once the last file is gone -- so the split layout survives the delete. lua/custom/buffer.lua has it.

File explorer

Key Action
\ Reveal the current file in Neo-tree
\ inside Neo-tree Close the Neo-tree window
<leader>e Toggle Neo-tree and reveal the current file

Useful commands:

  • :Neotree reveal reveals the current file.
  • :Neotree toggle reveal toggles the explorer while revealing the current file.

Search and Telescope

Mode Key Action
Normal <leader><leader> Find files
Normal <leader>sh Search Neovim help tags
Normal <leader>sk Search active keymaps
Normal <leader>sf Find files
Normal <leader>ss Select a Telescope picker
Normal/Visual <leader>sw Search for the word under the cursor or selection
Normal <leader>sg Search project text with live grep, with ripgrep flag support (live-grep-args)
Normal <leader>sd Search diagnostics
Normal <leader>sr Resume the previous Telescope picker
Normal <leader>s. Search recently opened files
Normal <leader>sc Search available commands
Normal <leader>sn Search files in the Neovim configuration
Normal <leader>/ Fuzzy-search the current buffer in a dropdown
Normal <leader>s/ Live-grep only the currently open files

Use :Telescope keymaps to inspect all active mappings or :Telescope builtin to choose any available picker.

<leader>sg uses telescope-live-grep-args.nvim, which lets ripgrep flags be typed directly into the prompt.

The flags must come first, or the search word must be quoted first. The plugin decides how to parse the whole prompt based on its first character: if the prompt doesn't start with -, ', or ", the entire line — search word and all — is treated as one literal search string and flags are not applied. So useState -tjs silently searches for the literal text useState -tjs instead of filtering. Put the flag(s) before the search word instead, or quote the word first (which is what <C-k> does for you).

Example prompts:

Prompt Effect
-tjs useState Search useState, only in JavaScript files
-Tjs useState Search useState, in every file except JavaScript
-g '*.md' foo Search foo, only in Markdown files
-g '!vendor/*' foo Search foo, skip anything under vendor/
-tlua -g '!vendor/*' foo Search foo, only in Lua files, and skip vendor/
"TODO: fix" -tjs Search the exact phrase TODO: fix, only in JavaScript files (quoting first also works)

-t (lowercase) means "only these file types"; -T (uppercase) means "every file type except these." -g matches by filename/path glob instead of file type, and a leading ! in the glob excludes rather than includes. Flags can be combined in one prompt.

Diagnostics and LSP

The LSP mappings below are buffer-local and appear only after a language server attaches.

Mode Key Action
Normal <leader>q Put diagnostics into the location list
Normal <leader>d Open a focused diagnostic float for the current line
Normal grn Rename the symbol under the cursor
Normal/Visual gra Request a code action
Normal grr Find references with Telescope
Normal gri Find implementations with Telescope
Normal grd Find definitions with Telescope
Normal grD Go to the declaration with LSP
Normal grt Find type definitions with Telescope
Normal go Search document symbols
Normal gw Search workspace symbols
Normal grx Run the code lens under the cursor
Normal <leader>th Toggle inlay hints when the server-support check succeeds
Normal <leader>tl Toggle code lens for the current buffer

grn, gra, grr, gri, grt, and grx are Neovim defaults (0.11+), not defined by this config. grr, gri, grt, and grd are re-mapped buffer-locally in lua/plugins/telescope.lua so results land in a Telescope picker instead of the quickfix list; grD is added in lua/plugins/lsp.lua because Neovim has no default for it.

Code lens is enabled on attach for servers that support it (lua/plugins/lsp.lua) — Neovim keeps it off by default, so the referencesCodeLens and implementationsCodeLens settings requested from vtsls would otherwise never render. <leader>tl turns it off per buffer.

Configured language servers:

  • TypeScript: vtsls, for every project regardless of its own TypeScript version. tsc (TypeScript 7+'s native --lsp server) was tried and removed after it crashed independently in testing and in real use — see commit f5e9eb3 to revive the per-project version gate if that ever proves stable.
  • Linting: eslint and oxlint, run alongside each other; fixes are applied on demand via :LspEslintFixAll and :LspOxlintFixAll
  • HTML (html)
  • CSS (cssls)
  • Lua (lua_ls)
  • Odin (ols)

Use :Mason to inspect installed language tooling. Diagnostic jumps use Neovim's normal diagnostic mappings; the configuration opens a rounded diagnostic float after a jump.

A long diagnostic message (a TypeScript union type, especially) can run off the edge of the window: inline diagnostics (virtual_lines, scoped to the current line only — other lines just get an underline) don't wrap, by design — 'wrap' does not apply to virtual lines (:h nvim_buf_set_extmark()). <leader>d is the reliable way to read one in full: it opens the same kind of floating window as hover, which does wrap. Press it once to see the float, press it again to move the cursor inside — from there it's a normal (read-only) buffer, so y/visual-select copies out of it normally.

Neovim 0.12 ships a native :lsp command, which makes nvim-lspconfig skip its plugin/ script — so :LspInfo and :LspStart/:LspStop/:LspRestart do not exist (:lsp and :checkhealth vim.lsp replace them). :LspLog is redefined in lua/plugins/lsp.lua to open the client log at its newest entries. :LspEslintFixAll and :LspOxlintFixAll are unaffected — those are buffer-local commands created from each server's on_attach, not from the skipped plugin/ script.

eslint, oxlint, html, and cssls get their cmd from node_bin_cmd in lua/plugins/lsp.lua instead of taking nvim-lspconfig's default. Upstream prefers a project-local server by joining <root>/node_modules/.bin/<name>, which on Windows is npm's POSIX shell-script shim — executable() reports it as runnable, then the spawn fails with "The language server is either not installed, missing from PATH, or not executable." node_bin_cmd looks for the .cmd (then .exe) shim npm writes alongside it and falls back to Mason/PATH if neither exists. Off Windows it resolves exactly as upstream does.

vtsls always type-checks against its own bundled TypeScript, never the project's own pinned version — TypeScript 7's package no longer ships tsserver.js at all, so there's no setting that changes this. lua/plugins/tsc.lua (tsc.nvim) closes that gap on demand: :TSC runs the project's real, pinned tsc --noEmit across every tsconfig.json in the tree and reports results as both quickfix entries and normal diagnostics. It never runs automatically — only on :TSC; :TSCStop cancels a run in progress.

Formatting

Mode Key Action
Normal/Visual <leader>f Format the buffer or selection synchronously with Conform

Formatting is manual: there is no format-on-save, so <leader>f is the only way to format. It's configured for Lua, Odin, JavaScript, JSX, TypeScript, TSX, HTML, CSS, JSON, and JSONC. Lua uses stylua, Odin uses odinfmt; the other configured filetypes use prettier. LSP formatting is used as a fallback.

odinfmt is defined by hand in lua/plugins/formatting.lua — Conform has no built-in for it, and it comes from Mason's ols package rather than from PATH. It reads its settings from an odinfmt.json found by walking up from the process working directory, and under -stdin it is never told which file it is formatting; Conform therefore runs it from the buffer's own directory, so a project's odinfmt.json applies no matter where Neovim's :pwd happens to be. Without one, odinfmt's own defaults (tabs, 100 columns) apply.

Use :ConformInfo to see the formatter selected for the current buffer and whether its executable is available.

Trailing whitespace is stripped automatically on every save (lua/config/autocmds.lua), independent of Conform. Markdown and diff buffers are excluded, since Markdown uses trailing double-spaces as an intentional hard line break.

Completion and snippets

Mode Key Action
Insert <C-l> Explicitly show the Blink completion menu
Insert <C-y> Accept the selected completion using Blink's default preset
Insert <C-Space> Open completion, or documentation when completion is already open
Insert <C-n> / <C-p> Select the next or previous completion item
Insert <Down> / <Up> Select the next or previous completion item
Insert <C-e> Hide completion
Insert <C-k> Toggle signature help
Insert/Snippet <Tab> / <S-Tab> Move forward or backward through snippet positions

Completion sources are LSP, filesystem paths, and LuaSnip snippets. Documentation does not open automatically, while signature help is enabled.

Mini text objects and surrounds

Mode Key Action
Operator/Visual aa Use the next “around” text object
Operator/Visual ii Use the next “inside” text object
Normal/Visual gsa Add surrounding characters
Normal gsd Delete surrounding characters
Normal gsf Find a surrounding character
Normal gsh Highlight surrounding characters
Normal gsr Replace surrounding characters
Normal gsn Change the number of lines searched for surroundings

vim-visual-multi is installed with its upstream default mappings. Use :help vm-mappings for its complete multi-cursor key reference.

Folding

Folds are calculated from Treesitter syntax and start open, so files remain fully visible until a fold command is used.

Mode Key Action
Normal zc Close the fold under the cursor
Normal zo Open the fold under the cursor
Normal za Toggle the fold under the cursor
Normal zM Close all folds
Normal zR Open all folds
Normal zj Move to the next fold
Normal zk Move to the previous fold

Custom terminals and Git

Mode Key Action
Normal <leader>` Focus the terminal split, or hide it when it already has focus; creates one when necessary
Normal <leader>tf Show the terminal full screen on its own tab page, or close that tab when already on it
Normal <leader>tn Create a new terminal
Normal <leader>tv Create a new terminal in a vertical split beside the current pane
Normal <leader>t] Show the next managed terminal
Normal <leader>t[ Show the previous managed terminal
Normal <leader>tc Close the current managed terminal; the last terminal is protected
Normal <leader>gg Open lazygit in a centered floating terminal
Terminal-Normal i Enter Terminal mode and type commands
Terminal <Esc><Esc> Leave terminal-input mode and return to Normal mode

Managed terminals open in Terminal-Normal mode in a 12-line bottom split, remain alive when hidden, and use Git Bash as an interactive login shell. <leader>tf is the same terminal at a second size: it moves onto a tab page of its own, where it fills the editor area, and the layout it came from waits untouched on the tab underneath. This lets terminal switching and window-navigation mappings work immediately; press i when you want to type. Floating commands close their window automatically when the command exits.

Inside lazygit, o and e open the file under the cursor in this Neovim, in the window <leader>gg was pressed from, and the float closes with it. lua/custom/lazygit.lua arranges that: it writes a lazygit config with this instance's RPC address baked in and points lazygit at it with LG_CONFIG_FILE, next to the personal config in %LOCALAPPDATA%\lazygit\config.yml. Without it o hands the file to whatever application the extension is associated with, and e opens a second Neovim nested inside the float.

Plugin and maintenance commands

Command Purpose
:lua vim.pack.update(nil, { offline = true }) Inspect plugin state and pending updates without fetching
:lua vim.pack.update() Fetch and update managed plugins
:Mason Inspect and manage external LSP tools
:TSUpdate Update installed Treesitter parsers
:Telescope keymaps Search all active keymaps
:ConformInfo Inspect formatting for the current buffer
:checkhealth Run Neovim and plugin health checks
:checkhealth kickstart Check this config's own required and optional external tools
:messages Review recent notifications and errors

Which-key opens immediately after a recognized prefix and groups search under <leader>s, terminal actions under <leader>t, and LSP actions under gr.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages