Skip to content

Latest commit

 

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Neovim configuration for Linux

Targets the latest stable Neovim (0.12) on Debian/Ubuntu, x86_64 or aarch64. Everything that can live in ~/.local is installed there by a script, no root needed except for a handful of apt packages.

features

  • plugin manager: lazy.nvim, locked versions in lazy-lock.json
  • colors: kanagawa by default; tokyonight, catppuccin, rose-pine and gruvbox are a keypress away (t on the dashboard, previewed live, remembered across restarts). statusline: lualine
  • syntax: nvim-treesitter (main branch, parsers built with the tree-sitter cli)
  • language servers: native vim.lsp with nvim-lspconfig, installed by mason; per-server settings in lsp/
  • completion: blink.cmp with lsp, path, snippet and buffer sources
  • fuzzy finding: telescope with the native fzf sorter
  • files: oil.nvim (edit directories like buffers, replaces netrw)
  • formatting on demand: conform.nvim
  • markdown rendered in place with plain glyphs: render-markdown.nvim; no browser, no terminal image protocol, works over ssh
  • quarto: completion, hover and diagnostics inside code chunks with quarto-nvim and otter.nvim
  • debugging: nvim-dap with a ui, adapters for python, rust, c/c++, go, javascript/typescript, haskell
  • pinned files: harpoon, todo highlighting: todo-comments
  • zen mode (snacks), built-in undo tree and difftool
  • git: gitsigns, fugitive, lazygit through snacks
  • sessions per directory: auto-session
  • dashboard with a cow and a random quote (like vim-startify, no cowsay needed), notifications, indent guides: snacks.nvim
  • keymap hints: which-key
  • plain text throughout, no nerd-font icons, so any monospace font works
  • tmux: shared pane navigation, matching dotfiles/.tmux.conf
  • languages: Lua, LaTeX, Python, R, Quarto, Julia, OCaml, Haskell, Rust, Go, Zig, C/C++, Fortran, Bash, TypeScript/JavaScript, Markdown, TOML, YAML, JSON, SQL, CSV

install

git clone https://github.com/cb-g/nvim ~/nvim
~/nvim/scripts/install.sh

The script downloads the latest release of neovim, the tree-sitter cli, ripgrep, fd, stylua, lazygit and yq into ~/.local/opt and ~/.local/bin, symlinks ~/.config/nvim and ~/.tmux.conf to this repository and clones the tmux plugin manager. Any terminal with true color works; the config uses no icons, so any monospace font does too. Rerun it to update those tools. Make sure ~/.local/bin is on your PATH.

Nothing else is required: a stock Ubuntu already has the compiler, curl, git and unzip that parsers and servers need. The following are optional, each unlocks one thing:

apt package unlocks
tmux the tmux integration and dotfiles/.tmux.conf
wl-clipboard (wayland) or xclip (x11) the "+ register in a local session; over ssh neovim uses OSC 52 through the terminal instead
nodejs npm the bash, typescript, eslint, html, json, yaml, docker and sql servers and the javascript debug adapter
golang-go gopls and the go debug adapter
gfortran a compiler for fortls to check against
clangd C and C++ on aarch64, where mason has no build
python3-venv python3-pip lets mason install basedpyright and black; not needed if you use uv tool install basedpyright black
zathura biber chktex texlive-extra-utils LaTeX: pdf viewer with synctex, bibliography, texlab's chktex diagnostics, latexindent formatting

Everything at once:

sudo apt install tmux wl-clipboard xclip nodejs npm clangd python3-venv python3-pip zathura biber chktex texlive-extra-utils

Then start nvim. lazy.nvim installs the plugins, treesitter compiles the parsers and mason installs the servers whose runtime it can find (see language servers). :checkhealth tells you what is missing.

Shell aliases that go well with this:

alias vim=nvim
alias vimc='cd ~/nvim'
alias cleantex=~/nvim/scripts/rm_latex_aux.sh

layout

init.lua                  leader keys, loads lua/config
lua/config/options.lua    editor options
lua/config/keymaps.lua    global keymaps
lua/config/autocmds.lua   autocommands
lua/config/lazy.lua       lazy.nvim bootstrap and settings
lua/config/tools.lua      helper: is an executable available
lua/config/theme.lua      colorscheme picker and the remembered choice
lua/config/fortune.lua    the cow and its quotes for the dashboard
lua/plugins/ui.lua        kanagawa, lualine, which-key, snacks
lua/plugins/editor.lua    oil, telescope, harpoon, todo-comments, autopairs, surround, auto-session
lua/plugins/treesitter.lua
lua/plugins/completion.lua blink.cmp
lua/plugins/lsp.lua       lspconfig, mason, mason-lspconfig, lazydev, mason-tool-installer
lua/plugins/dap.lua       nvim-dap, dap-ui, adapters
lua/plugins/format.lua    conform
lua/plugins/git.lua       gitsigns, fugitive
lua/plugins/tmux.lua      nvim-tmux-navigation
lua/plugins/lang.lua      vimtex, R.nvim, quarto, julia-vim, vim-ocaml, haskell-tools, render-markdown, rainbow_csv
lsp/<server>.lua          per-server settings, picked up by vim.lsp.config
after/ftplugin/<ft>.lua   buffer-local keymaps and options (tex, ocaml, markdown, quarto)
dotfiles/                 .tmux.conf
scripts/install.sh        linux bootstrap
scripts/rm_latex_aux.sh   delete latex auxiliary files in the cwd

a typical session

  1. nvim in a project directory. The dashboard shows the cow, pinned actions and recent files; s restores the last session for that directory, t picks a theme.
  2. <leader>fs to jump to a file, <leader>fg to grep for a symbol, - to browse and reorganise the directory in oil.
  3. Language servers attach on their own once the file type is known: K for docs, gd to the definition, grr for references, grn to rename, gra for code actions, <leader>e to read a diagnostic, <leader>cf to format.
  4. <leader>a pins the files you keep coming back to, <leader>1 to <leader>4 jump between them, <C-e> shows the list.
  5. <leader>gs for staging and committing in fugitive, <leader>gg for lazygit, ]h and <leader>hp to walk through changes.
  6. <leader>dt sets a breakpoint, <F5> starts the debugger with the ui, <F10> steps.
  7. In LaTeX <leader>ll compiles on every save and <leader>lv opens the pdf; in markdown and quarto <leader>cp toggles the rendered view; <leader>z for writing without distractions.
  8. Sessions save on exit, so the next nvim in that directory picks up where you left off.

<leader>fk lists every keymap with its description, and pressing <leader> and waiting shows the groups. Everything below is also visible there.

keymaps

Leader is space, local leader is backslash. j and k are swapped: j moves up, k moves down, in normal, visual and select mode. The same orientation is used for pane navigation and resizing in tmux and for moving through telescope results.

general

key action
<C-h/j/k/l> move between splits and tmux panes (j up, k down)
<C-\>, <C-Space> last / next pane
<leader>|, <leader>- split right / below
<leader>m, <leader>n next / previous buffer
<leader>x close buffer
<leader>w, - file explorer (oil) in the current file's directory; edit the listing like text and :w to rename, move or delete, <C-r> refreshes, q closes
<leader>y, <leader>Y yank to the system clipboard
<leader>p (visual) paste over selection without losing the register
<leader>/ toggle comment
<C-d>, <C-u>, n, N as usual, with the cursor kept centered
<Esc> clear search highlight
<leader>u undo tree
<leader>z, <leader>Z zen mode, zoom the current window
<leader>a, <C-e> harpoon: pin the current file, open the pinned list
<leader>1 … <leader>4 harpoon: jump to pinned file 1 to 4
]t, [t, <leader>ft next / previous todo comment, list them
<leader>nh, <leader>nd notification history, dismiss notifications
<leader>L lazy
<leader>tt pick a colorscheme (also t on the dashboard)
q close help, quickfix, man and fugitive windows

find (telescope)

key action
<leader>fs files
<leader>fv git files
<leader>fg live grep
<leader>fw grep word under cursor
<leader>fo recent files
<leader>fb buffers
<leader>fh help tags
<leader>fd diagnostics
<leader>fk keymaps
<leader>fr resume last picker
<leader>fS sessions

Inside a picker <C-j> moves up and <C-k> moves down.

code (lsp, formatting)

Neovim's built-in lsp keymaps apply: K hover, grn rename, gra code action, grr references, gri implementation, grt type definition, gO document symbols, [d ]d diagnostics, <C-s> signature help in insert mode. On top of that:

key action
gd, gD definition, declaration
<leader>cr rename
<leader>ca code action
<leader>cf format buffer or selection (conform, lsp fallback)
<leader>cd, <leader>cR definitions, references (telescope)
<leader>cs, <leader>cS document, workspace symbols (telescope)
<leader>e line diagnostics
<leader>q diagnostics to the location list
<leader>th toggle inlay hints
<leader>td toggle diagnostics

completion (blink.cmp)

key action
<CR> accept
<C-n>, <C-p>, arrows next / previous item
<C-Space> open menu, toggle documentation
<C-e> close menu
<Tab>, <S-Tab> jump through snippet fields
<C-b>, <C-f> scroll documentation
<C-k> toggle signature help

git

key action
<leader>gg lazygit
<leader>gl, <leader>gf git log, git log for the current file
<leader>gs :Git (fugitive status)
<leader>gb :Git blame
<leader>gd diff against the index
<leader>gD :DiffTool for two files or directories, type the paths and press enter
]h, [h next / previous hunk
<leader>hs, <leader>hr stage / reset hunk (also in visual mode)
<leader>hS, <leader>hR stage / reset buffer
<leader>hp preview hunk
<leader>hb blame line
<leader>hd diff the current file against the index (gitsigns)
<leader>tb toggle current line blame
ih hunk text object

debug

key action
<F5>, <leader>dd start or continue
<F10>, <leader>do step over
<F11>, <leader>di step into
<F12>, <leader>dO step out
<leader>dt toggle breakpoint
<leader>dB conditional breakpoint
<leader>de evaluate expression under the cursor or selection
<leader>du toggle the debugger ui
<leader>dR repl
<leader>dl run the last configuration
<leader>dq terminate

Adapters: codelldb for Rust, C and C++ (asks for the executable to launch), debugpy for Python (<leader>dd on a file runs it with the project's interpreter), delve for Go, js-debug-adapter for JavaScript and TypeScript, haskell-tools for Haskell.

latex (tex buffers)

key action
<leader>ll compile continuously (latexmk, output in build/)
<leader>ss compile once
<leader>lv view pdf (zathura if installed, otherwise xdg-open)
<leader>lc clean the build directory
<leader>le errors
<leader>lt table of contents
<leader>cl delete auxiliary files in the cwd (scripts/rm_latex_aux.sh)

markdown

key action
<leader>cp toggle in-place rendering (headings, lists, code blocks, tables, links)

quarto (qmd buffers)

key action
<leader>cp, <leader>cP quarto preview, close it (needs the quarto cli)

Code chunks get completion, hover and diagnostics from the language servers of R, Python, Julia and Bash. R.nvim's console keys work in R chunks.

ocaml (ml buffers)

key action
<leader>db dune build
<leader>dr dune exec ./bin/main.exe

r

R.nvim's defaults, all with the local leader (backslash): \rf starts R, \d sends the line, \l sends the line and moves down, \aa sends the file, :RMapsDesc lists everything.

language servers

Mason installs these on first start when the language's runtime is present, so nothing fails on a machine that lacks it:

server language needs
lua_ls Lua nothing
texlab LaTeX nothing (compiling needs texlive and latexmk)
markdown_oxide Markdown nothing
rust_analyzer Rust a toolchain from rustup; rustup component add rust-analyzer rust-src is used when present
taplo TOML nothing
zls Zig nothing
clangd C, C++ mason on x86_64, apt install clangd on aarch64
basedpyright Python uv tool install basedpyright (no sudo), or python3-venv and python3-pip for mason
bashls Bash nodejs, npm; shellcheck and shfmt come from mason
vtsls, eslint TypeScript, JavaScript nodejs, npm
html, jsonls, yamlls, dockerls, sqlls nodejs, npm
gopls Go go
fortls Fortran python3-venv, python3-pip
julials Julia julia
elixirls, elp Elixir, Erlang elixir, erl

Servers that are already on the path (ocamllsp, clangd, basedpyright, rust-analyzer) are enabled directly and not installed again by mason. Handled outside mason:

  • OCaml: opam install ocaml-lsp-server ocamlformat ocp-indent. The server from the active switch is used, ocp-indent's vim plugin is picked up from opam var share.
  • Haskell: install haskell-language-server with ghcup, haskell-tools.nvim starts it.
  • R: R.nvim ships its own language server, install.packages("languageserver") is not needed.
  • Rust: rust-analyzer only works with a toolchain, so install rustup first. rustfmt comes with it and is what <leader>cf uses.
  • Python: uv tool install basedpyright black puts both on the path. The interpreter is taken from $VIRTUAL_ENV, then .venv/ in the project root, then ~/.config/venvs_py/.default, then python3.

Formatters used by <leader>cf: stylua (Lua), black (Python), ocamlformat, rustfmt, fourmolu or ormolu (Haskell), shfmt; anything else falls back to the language server. stylua comes from the install script, the others from their toolchains.

toolchains

# latex
sudo apt install texlive-full latexmk zathura biber chktex texlive-extra-utils
# python
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install basedpyright black
# rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup component add rust-analyzer rust-src
# r
sudo apt install r-base
# go
sudo apt install golang-go
# fortran
sudo apt install gfortran
# quarto
# https://quarto.org/docs/get-started/
# julia
curl -fsSL https://install.julialang.org | sh
# haskell
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
# ocaml
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
opam init && opam install ocaml-lsp-server odoc ocamlformat ocp-indent utop

dotfiles

tmux

dotfiles/.tmux.conf, symlinked to ~/.tmux.conf by the install script. Prefix is ctrl-s.

key action
prefix |, prefix - split right / below in the current path
ctrl-h/j/k/l move between panes, also from inside nvim (j up, k down)
prefix h/j/k/l resize the pane
prefix r reload the config
prefix I install plugins
v, y in copy mode select, copy to the system clipboard

The window-name plugin needs mikefarah's yq, which the install script provides (the yq in apt is a different program).

maintenance

# update plugins (writes lazy-lock.json)
nvim "+Lazy sync"
# update parsers and servers
nvim "+TSUpdate" "+MasonUpdate"
# format the lua files
stylua .

Reset everything the config generated:

rm -rf ~/.local/share/nvim ~/.local/state/nvim ~/.cache/nvim

references

Contributors

Languages