This is my minimal(?), clutter-free, less-than-a-million-keymaps Neovim configuration for day-to-day programming.
Tip
Best used with Kitty terminal (or Alacritty if you prefer that), running a PowerLine font (or at least, a font that has some ligatures support)
Important
Want to get started? -> Press <space> and discover what's possible from there
Here are a few programming languages I usually write in:
- C++/C (and OpenFOAM code)
- Python, Lua as scripting languages
- HTML, CSS, JavaScript/TypeScript for web development
- Markdown for writing READMEs and other documentation, LATEX for academic writing
- GdScript, GLSL for game development
- Obviously, Bash for shell scripting
This configuration intentionally avoids:
- Format-on-Save (too complex and opinionated)
- AI assistants (Copilot, CodeCompanion, Avante - removed for simplicity)
- DAP debugging plugins (removed in favor of simpler debugging workflows)
Important
Check out the Screenshots for a preview of what this configuration has to offer.
- Requirements
- Set up
- List of plugins and important configs
- Configuration Presets
- Documentation
- User Configuration Integration
- Plugin Version Management
Run :checkhealth config (or :ConfigHealth) to verify your setup, see what's missing and how to install
them; here is a list of what fuels this configuration:
Required dependencies:
- Neovim nightly (v0.11.4 or newer), NodeJS v22 (or newer), preferably installed with NVM,
- Python 3 and (optionally) Rust
- The tree-sitter CLI. Install with
npm install -g tree-sitter-cli, or withcargo - For installing some LSP servers, you will need the
unzipcommand - For Todo-comments and various other searching tasks, you will want RIPGrep
- A terminal with ligature support (Kitty, Warp, Alacritty, etc.)
- For kitty, I like to set (after installing Comic Code Ligatures, Font Awesome and Symbols Nerd Font Mono):
font_family ComicCodeLigatures symbol_map U+f000-U+f0e2 fontawesome symbol_map U+23FB-U+23FE,U+2665,U+26A1,U+2B58,U+E000-U+E00A,U+E0A0-U+E0A3,U+E0B0-U+E0D4,U+E200-U+E2A9,U+E300-U+E3E3,U+E5FA-U+E6AA,U+E700-U+E7C5,U+EA60-U+EBEB,U+F000-U+F2E0,U+F300-U+F32F,U+F400-U+F4A9,U+F500-U+F8FF,U+F0001-U+F1AF0 Symbols Nerd Font Mono
- For kitty, I like to set (after installing Comic Code Ligatures, Font Awesome and Symbols Nerd Font Mono):
Optional:
- ImageMagick for in-terminal image display, if your terminal supports it
latex2textcommand if you want to render Tex equations in Markdown- Also mermaid-cli for mermaid charts in markdown files
- Note that on Ubuntu 23+ this requires changes to apparmor policies on retricting user namespaces; if you don't write mermaid charts often, don't bother with this. Otherwise, you'll have to do the policy changes manually
- Then, applying this configuration is as easy as:
# Backup old configs and clone the new ones
mv ~/.config/nvim ~/.config/nvim.bak
git clone https://github.com/FoamScience/configs.nvim ~/.config/nvim
# also, update with git pull- Run
:checkhealth configto see what dependencies you are missing. this docker file shows how to install most of the required ones on latest Ubuntu LTS release.
From there, the :ConfigNews command helps you keep your configuration up-to-date with this repo by checking for new commits and displaying a changelog.
Or you can give it a try in a Docker container:
cd dockerImages
docker build -t nvim-config:latest -f config.dockerfile .
docker run -it --rm nvim-config:latest bash
(container)> USER=me nvim- The canonical way to move between open buffers is
<tab>and<S-tab>in normal mode. - The canonical way to move on the visible screen portion is by pressing
sandSin normal mode. - The canonical way to move between windows and splits is
<C-w><C-w>; too fundamental to change. - Typically, you'll want to set Tmux to move between panes with
<C-s><arrows>. - You can bookmark files (Press
,) within each project for faster workflow. This was preferred over session management. - You can see registers content by pressing
", and marks positions by pressing the back-tick '`' <space>is the leader key, which is used to openwhich-keymenu in normal mode<leader>fklists all available key bindings and<leader>fClists commands.<leader>fPwill take you to individual plugin configuration!<leader>kkbrings up a sticky-notes sidebar. it persists; and it's project-specific!- you can create mutiple notes per projects and notes content is in Markdown
- keymaps.lua: very few key bindings to get you started
<tab>and<S-tab>in normal mode are used for buffer switching
- which-key.lua: shows all available keymaps
- Press
<leader>to check available keymaps - Shows Vim keymaps on
`(marks),"(registers),z(folds and spelling),g(operators) and<c-w>(window navigation)
- Press
- snacks.lua: fuzzy finder via snacks.picker for files, buffers, etc.
<leader>fto access fuzzy finding features<leader>fkshows all configured keymaps<leader>fgopens file from its Git history without checking out earlier commits<leader>fubrowses the Undo tree with diffs<leader>fPopens Plugin configuration files- Note: Excluded from SSH preset due to performance considerations
- projects.lua: a project manager, mostly for detecting root directories
<leader>fpto open recent projects list
- dial.lua: a plugin for incrementing and decrementing stuff
- Overhauled
<c-a>and<c-x>to increment and decrement things (numbers, dates, ..., etc)
- Overhauled
- colorscheme.lua is where the color scheme is set
- Press
<leader>fcto see a live demo of all available color schemes - By default, we are using Catppuccin-Mocha
- Press
- undo.lua is an Undo tree visualizer, with diff views.
<leader>euto toggle. - news.lua provides the
:ConfigNewscommand to check for configuration updates- Shows commits you're behind and displays a changelog
- Helps keep your config in sync with the upstream repository
- snacks.lua a collection of UI niceties from folke (includes fuzzy finder)
- nvimtree.lua: a file explorer
<leader>eeto toggle
- mini-statusline.lua fast and minimal statusline with enhanced LSP status
- tpipeline.lua unified statusline for Neovim and Tmux
- Displays single statusline across both Neovim and Tmux for seamless integration
- Only loaded in "full" preset
- incline.lua floating buffer names at top-right corners of windows
- noice.lua: nicer UI. Not relevant for users
- colorizer.lua: colorizes color codes in CSS, HTML, etc.
- cinnamon.lua: optional scrolling cursor animations.
- render-markdown.lua: prettifying Markdown document editing.
- With support for Latex equation rendering
- guess-indent.lua to guess indentation style (tabs/spaces)
for current file and setting global options accordingly.
- Should be automatic, but
:GuessIndenthelps
- Should be automatic, but
image.lua: optionally render Markdown images- Enabled only if running on
kittyterminal and usingimagemagickbackend. - Replaced with
snacks.imagewhich has similar constraints
- Enabled only if running on
- todo-comments.lua: highlights
@todo:,@body:,@warn:, etc. in comments:TodoTelescopecommand opens a fuzzy finder for all such comments in the current buffer- Use todo-issue Github action to convert your committed Todos to Github issues.
- jira.lua: is a custom plugin, functionning as a thin Jira client
- Its backbone ships with this configuration (jira-interface)
- Opinionated jira structure, but customizable
- Loaded only if
JIRA_API_TOKENis set - Have to set
JIRA_API_TOKEN,JIRA_URLandJIRA_EMAIL/JIRA_USER <leader>jto get started
- confluence.lua: is a custom plugin, functionning as a thin Confluence client
- Uses same environment variables as the Jira client; or you can also supply
CONFLUENCE_*versions <leader>cto get started
- Uses same environment variables as the Jira client; or you can also supply
- flash.lua: fast word hopping
s(orgs) to hop to words in normal modeS(orgS) to hop using tree-sitter syntax tree in normal moderin operator mode to do operations between flash hopsRin operator mode to do operations between flash tree-sitter searches<ctrl-s>to toggle flash in regular search mode<leader>vfor incremental treesitter selection (next:<leader>v, prev:<BS>)
- tree-climb.lua: treesitter-based code navigation
- Navigate through code structure using treesitter nodes with
<M-n>and<M-N> - Enhanced structural movement commands
- Navigate through code structure using treesitter nodes with
- outline.lua: fast local code navigation
<leader>nnto toggle?to see keymaps for the outline window
- treesitter.lua: syntax highlighting and code folding
- Sets up a few languages by default; such as C++, Python, Lua and OpenFOAM
- Auto-installs tree-sitter grammars for languages the first time they are encountered
- with
xonshsupport through the xonsh-lsp
- mason.lua: sets up a few language servers to support common languages
- C++/C: with
clangd, OpenFOAM withfoam_ls, Lua withlua_lsand a few moreclangdis not managed through Mason on ARM machines, runapt install clangdinstead
- Python:
pyrightorpylsp, with support for ParaView Python (pvpython) environments - Type
:Masonin normal mode for more.
- C++/C: with
- lspconfig.lua: configures the LSP servers and sets up keymaps for some features
gdandgDfor go to definition and declarationKfor hover info- Enhanced keybindings for type hierarchy, call graphs, and symbol navigation
- You can also get to similar functionality through
<leader>lwhich uses which-key
- cmp.lua: autocompletion engine using blink.cmp (faster than nvim-cmp)
<tab>to cycle through suggestions,<cr>to confirm- Autocompletes file paths, snippets, and LSP-related things
- Includes Unicode character completion provider for special characters
- Buffer completion is left to vim's native:
<c-x>-nmenu - Also provides command line completion on
:
- garbage.lua: a garbage collection for inactive LSP servers
- navic.lua: shows code structure at the cursor in the winbar
- remote-nvim.lua: connect to remote Neovim instances over SSH
- Commands:
:RemoteStart,:RemoteStop,:RemoteInfo - Uses telescope for UI (only plugin requiring telescope in this config)
- Commands:
- gitsigns.lua: shows git diff in the sign column
- diffview.lua: a diff viewer for Git diffs
<leader>gdto open, or:DiffviewOpenin normal mode
- gitconflicts.lua: shows better diffs for git conflicts.
<leader>gtto open, or:DiffConflictsin normal mode
- autopairs.lua: automatically inserts closing brackets, quotes, etc.
- csv.lua: a CSV viewer which uses CSVView plugin.
- haunt.lua: Line notes that do not affect the code source.
- cloak.lua: Hiding environment variables.
:CloackDisableto see the variables' values.
This configuration supports multiple presets to adapt to different usage scenarios. Currently available presets:
- full (default): All plugins enabled, full feature set
- ssh: Minimal preset optimized for remote SSH connections
- Excludes plugins that don't work well over SSH, mostly for adding latency overhead
There are three ways to select a preset (in order of priority):
-
Local preset file (recommended for per-machine configuration):
# Copy the example file and edit it cp ~/.config/nvim/preset.lua.example ~/.config/nvim/preset.lua # Edit preset.lua and change the return value to "ssh" or "full"
-
Environment variable (useful for one-time overrides):
NVIM_PRESET=ssh nvim
-
Default: Falls back to "full" if neither of the above is set
For remote editing over SSH, use the ssh preset to improve performance:
# On your remote machine, create a preset file
echo 'return "ssh"' > ~/.config/nvim/preset.lua
# Or use environment variable
export NVIM_PRESET=ssh
nvim myfile.cppA few tutorials can be accessed by <leader>tt when nvim command had no files
passed in. These are not meant to teach people basic Vim skills but
rather explain my current approach to editing efficiency.
Even though the tutorials act on Lua files, they hold on any other filetype.
Occasionally, you'd have to :TutorialNext to continue a tutorial, either becausse
I was too lazy to implement proper step validation or implementing it would not
have provided a good experience.
You can seamlessly extend this configuration by using a separate user configuration repository.
-
Create your own configuration repository with this structure:
my-nvim-config/ ├── init.lua # Optional: runs before lazy.nvim loads └── plugins/ # Optional: custom plugin specs ├── my-plugin.lua └── another.lua -
Symlink your repository to the user-config directory:
ln -s /path/to/my-nvim-config ~/.config/nvim/user-configOr you could just do to get my configuration (may super niche stuff and mostly experimental):
ln -s user-config.elwardi user-config
-
Your configuration will be loaded automatically:
init.luais executed before lazy.nvim initialization- All files in
plugins/are loaded as plugin specs
Create ~/.config/nvim/user-config/plugins/my-theme.lua:
return {
"username/my-colorscheme",
config = function()
vim.cmd("colorscheme my-colorscheme")
end
}This approach allows you to:
- Keep your customizations in a separate git repository
- Pull updates from this main config without conflicts
- Share settings across multiple machines with different needs
All plugins are locked to specific versions using Lazy.nvim's lockfile feature. This ensures:
- Consistent plugin versions across all installations
- Protection against breaking changes from plugin updates
- Reproducible development environment
Use the :ConfigNews command to check for configuration updates:
:ConfigNewsThis will:
- Fetch the latest changes from the remote repository
- Show how many commits you're behind
- Display a changelog of recent commits
- Provide instructions for updating
The recommended workflow for keeping plugins up-to-date:
- Check for config updates:
:ConfigNews - Pull config updates:
git pullin~/.config/nvim - Review changes in
lazy-lock.jsonif any - Restart nvim to apply changes
Alternatively you could just run :Lazy update; although this will diverge from this repo's plugin versions.
