Neovim :: M Λ C R O is a collection of Neovim configuration files inspired by Emacs / N Λ N O.
The goal of macro-neovim is to provide a clean and elegant user interface while remaining practical for daily tasks, striking a balance between a streamlined design and effective functionality. See showcases to get a glimpse of the basic usage and what this configuration looks like.
This is a highly personalized and opinionated Neovim configuration, not a distribution. While it's not meant for direct use, you're welcome to fork, experiment, and adapt it to your liking. Feel free to use it as a starting point for your configuration or borrow elements you find useful. Issues and PRs are welcome.
Currently only supports Linux (X11/Wayland/TTY).
- Features
- Requirements and Dependencies
- Installation
- Troubleshooting
- Uninstallation
- Config Structure
- Tweaking this Configuration
- Appendix
- Modular design
- Install and manage packages in groups
- Make it easy to use different set of configuration for different use cases
- Clean and uncluttered UI, including customized versions of:
- VSCode-Neovim integration, makes you feel at home in VSCode when you occasionally need it
- Massive TeX math snippets
- Jupyter Notebook integration: edit notebooks like markdown files, run code in cells with simple commands and shortcuts
- Fine-tuned plugins with custom patches
- Optimization for large files, open any file larger than 100 MB and edit like butter
- Fast startup around ~25 ms
- Neovim 0.10, for exact version see nvim-version.txt
- Git
- GCC or Clang for building treesitter parsers and some libs
- Fd, Ripgrep, and Fzf for fuzzy search
- Pandoc, custom scripts and TexLive (for ArchLinux users, it is
texlive-core
andtexlive-extra
) for markdown → PDF conversion (:MarkdownToPDF
) - Draw.io desktop for creating and inserting simple PNG diagrams in markdown files (
:MarkdownInsertImage
) - Node.js for installing dependencies for markdown-preview.nvim and launching copilot.lua
- Pynvim, Jupyter Client, and IPython Kernel for Python support
- Jupytext for editing Jupyter notebooks
- A decent terminal emulator
- A nerd font, e.g. JetbrainsMono Nerd Font
(one can set the environment variable
$NVIM_NONF
to disable nerd icons if nerd font is not available, see environment variables)
Tree-sitter installation and configuration are handled by nvim-treesitter.
Requires a C compiler, e.g. GCC or Clang, for building parsers.
To add or remove support for a language, install or uninstall the corresponding
parser using :TSInstall
or :TSUninstall
.
To make the change permanent, add or remove corresponding parsers in the
ensure_installed
field in the call to nvim-treesitter's setup()
function,
see lua/configs/nvim-treesitter.lua.
For LSP support, install the following language servers manually using your favorite package manager:
-
Bash: BashLS
Example for ArchLinux users:
sudo pacman -S bash-language-server
-
C/C++: Clang
-
Lua: LuaLS
-
Python: one of
-
Rust: Rust Analyzer
-
LaTeX: TexLab
-
VimL: VimLS
-
Markdown: Marksman
-
General-purpose language server: EFM Language Server
- Already configured for Black, Shfmt, Fish-indent, and StyLua
To add support for other languages, install corresponding language servers
manually then add lsp.lua
files under after/ftplugin to automatically launch
them for different filetypes.
Some examples of lsp.lua
files:
- after/ftplugin/lua/lsp.lua
- after/ftplugin/python/lsp.lua
- after/ftplugin/rust/lsp.lua
- after/ftplugin/sh/lsp.lua
Install the following debug adapters manually:
-
Bash:
Go to vscode-bash-debug release page, download the latest release (
bash-debug-x.x.x.vsix
), extract (change the extension from.vsix
to.zip
then unzip it) the contents to a new directoryvscode-bash-debug/
and put it under stdpathdata
(see:h stdpath
).Make sure
node
is executable. -
C/C++: install CodeLLDB.
Example for ArchLinux users:
yay -S codelldb # Install from AUR
-
Python: install DebugPy
Example for ArchLinux users:
sudo pacman -S python-debugpy
or
pip install --local debugpy # Install to user's home directory
For more information on DAP installation, see Debug Adapter Installation.
- Bash: install Shfmt*
- C/C++: install Clang to use
clang-format
- Lua: install StyLua*
- Rust: install Rust to use
rustfmt
- Python: install Black*
- LaTeX: install texlive-core to use
latexindent
*Need EFM Language Server to work with vim.lsp.buf.format()
-
Make sure you have required dependencies installed.
-
Clone this repo to your config directory
git clone https://github.com/Bekaboo/nvim ~/.config/nvim-macro
-
Open neovim using
NVIM_APPNAME=nvim-macro nvim
On first installation, neovim will prompt you to decide whether to install third-party plugins, press
y
to install,n
to skip,never
to skip and disable the prompt in the future (aka "do not ask again").The suggestion is to use
n
to skip installing plugins on first launch, and see if everything works OK under a bare minimum setup. Depending on your needs, you can choose whether to install third-party plugins later usingy
/yes
ornever
on the second launch.Some notes about third-party plugins
Installing third-party plugins is known to cause issues in some cases, including:
- Partially cloned plugins and missing dependencies due to slow network connection
- Building failure especially for plugins like telescope-fzf-native.nvim and markdown-preview.nvim due to missing building dependencies or slow installation process
- Some plugins like copilot.lua needs authentication to work
- Treesitter plugins can easily cause issues if you are on a different nvim version, check nvim-version.txt for the version of nvim targeted by this config
To avoid these issues,
- Ensure you have a fast network before installing third-party plugins
- If the building process failed, go to corresponding project directory
under
g:package_path
and manually run the build command from there. The build commands are declared in module specification files under lua/modules - Disable copilot.lua if you do not have access to it
- Ensure you are on the same version of nvim as specified in nvim-version.txt if you encounter any issue related to treesitter
-
After entering neovim, Run
:checkhealth
to check potential dependency issues. -
Enjoy!
If you encounter any issue, please try the following steps:
-
Run
:Lazy restore
once to ensure that all packages are properly installed and patched -
Run
:checkhealth
to check potential dependency issues -
Check
:version
to make sure you are on the same (of above) version of neovim as specified in nvim-version.txt -
Try removing the following paths then restart Neovim:
:echo stdpath('cache')
:echo stdpath('state')
:echo stdpath('data')
-
If still not working, please open an issue and I will be happy to help
You can uninstall this config completely by simply removing the following paths:
:echo stdpath('config')
:echo stdpath('cache')
:echo stdpath('state')
:echo stdpath('data')
.
├── colors # colorschemes
├── plugin # custom plugins
├── ftplugin # custom filetype plugins
├── init.lua # entry of config
├── lua
│ ├── core # files under this folder is required by 'init.lua'
│ │ ├── autocmds.lua
│ │ ├── general.lua # options and general settings
│ │ ├── keymaps.lua
│ │ └── packages.lua # bootstraps package manager and specifies what packages to include
│ ├── modules # all plugin specifications and configs go here
│ │ ├── lib.lua # plugin specifications in module 'lib'
│ │ ├── completion.lua # plugin specifications in module 'completion'
│ │ ├── debug.lua # plugin specifications in modules 'debug'
│ │ ├── lsp.lua # plugin specifications in module 'lsp'
│ │ ├── markup.lua # ...
│ │ ├── misc.lua
│ │ ├── tools.lua
│ │ ├── treesitter.lua
│ │ └── colorschemes.lua
│ ├── configs # configs for each plugin
│ ├── snippets # snippets
│ ├── plugin # the actual implementation of custom plugins
│ └── utils
└── syntax # syntax files
In order to enable or disable a module, one need to change the table in
lua/core/packages.lua passed to enable_modules()
, for example
enable_modules({
'lib',
'treesitter',
'edit',
-- ...
})
To install plugin foo
under module bar
, just insert the corresponding
specification to the big table lua/modules/bar.lua
returns, for instance,
lua/modules/bar.lua
:
return {
-- ...
{
'foo/foo',
dependencies = 'foo_dep',
},
}
To install plugin foo
under module bar
, one should first
create module bar
under lua/modules:
.
└── lua
└── modules
└── bar.lua
a module should return a big table containing all specifications of plugins under that module, for instance:
return {
{
'goolord/alpha-nvim',
cond = function()
return vim.fn.argc() == 0 and
vim.o.lines >= 36 and vim.o.columns >= 80
end,
dependencies = 'nvim-web-devicons',
},
{
'romgrk/barbar.nvim',
dependencies = 'nvim-web-devicons',
config = function() require('bufferline').setup() end,
},
}
After creating the new module bar
, enable it in lua/core/packages.lua:
enable_modules({
-- ...
'bar',
-- ...
})
See lua/core/general.lua.
$NVIM_NO3RD
: disable third-party plugins if set$NVIM_NONF
: disable nerd icons and use ascii symbols if set
See lua/core/keymaps.lua, or see module config files for corresponding plugin keymaps.
cockatoo
, nano
, and macro
are three builtin custom colorschemes, with
separate palettes for dark and light background.
Neovim is configured to restore the previous background and colorscheme settings on startup, so there is no need to set them up in the config file explicitly.
To disable the auto-restore feature, remove the plugin plugin/colorscheme.lua.
To tweak this colorscheme, edit corresponding colorscheme files under colors.
See lua/utils/lsp.lua and lsp.lua
files under after/ftplugin.
See lua/configs/dap-configs, lua/configs/nvim-dap.lua, and lua/configs/nvim-dap-ui.lua.
This configuration use LuaSnip as the snippet engine, custom snippets for different filetypes are defined under lua/snippets.
VSCode integration takes advantages of the modular design, allowing to use a different set of modules when Neovim is launched by VSCode, relevant code is in autoload/plugin/vscode.vim and lua/core/packages.lua.
To make VSCode integration work, please install VSCode-Neovim in VSCode and configure it correctly.
After setting up VSCode-Neovim, re-enter VSCode, open a random file and it should work out of the box.
-
File manager using oil.nvim
-
DAP support powered by nvim-dap and nvim-dap-ui
-
Jupyter Notebook integration using jupytext and molten-nvim
-
Winbar with IDE-like drop-down menus using dropbar.nvim
-
LSP hover & completion thanks to Neovim builtin LSP client and nvim-cmp
-
Git integration: fugitive and gitsigns.nvim
Total # of plugins: 47 (package manager included).
- Lib
- Completion
- Markup
- Edit
- Tools
- LSP
- Treesitter
- Debug
- nvim-dap
- nvim-dap-ui
- nvim-nio (dependency)
- one-small-step-for-vimkind
- Colorschemes
- colorcolumn
- Shows color column dynamically based on current line width
- Released as deadcolumn.nvim
- colorscheme
- im
- Switches and restores fcitx state in each buffer asynchronously
- jupytext
- Edits jupyter notebook like markdown files
- Writes into jupyter notebook asynchronously, which gives a smoother experience than jupytext.vim
- intro
- Shows a custom intro message on startup
- lsp
- Sets up LSP and diagnostic options and commands on
LspAttach
orDiagnosticChanged
- Sets up LSP and diagnostic options and commands on
- readline
- Readline-like keybindings in insert and command mode
- statuscolumn
- Custom statuscolumn, with git signs on the right of line numbers
- statusline
- Custom statusline inspired by nano-emacs
- tabout
- Tab out and in with
<Tab>
and<S-Tab>
- Tab out and in with
- term
- Some nice setup for terminal buffers
- tmux
- Integration with tmux, provides unified keymaps for navigation, resizing, and many other window operations
- vscode
- Integration with VSCode-Neovim
- winbar
- A winbar with drop-down menus and multiple backends
- Released as dropbar.nvim
- markdown-capitalized-title
- Automatically capitalize the first letter of each word in markdown titles
- Use
:MarkdownSetCapTitle enable/disable
to enable or disable this feature
-
Neovim Version:
NVIM v0.10.0-dev-2363+gb76a01055f Build type: Release LuaJIT 2.1.1702233742
-
Config Commit:
5970178e
-
System: Arch Linux 6.7.4-arch1-1
-
Machine: Dell XPS 13-7390
-
Startup time with
--clean
:hyperfine 'nvim --clean +q'
Benchmark 1: nvim --clean +q Time (mean ± σ): 9.4 ms ± 1.9 ms [User: 6.3 ms, System: 3.2 ms] Range (min … max): 6.5 ms … 15.1 ms 185 runs
-
Startup time with this config:
hyperfine 'nvim +q'
Benchmark 1: nvim +q Time (mean ± σ): 18.1 ms ± 1.3 ms [User: 13.6 ms, System: 4.5 ms] Range (min … max): 15.5 ms … 22.0 ms 127 runs
startuptime log
--- Startup times for process: Primary/TUI --- times in msec clock self+sourced self: sourced script clock elapsed: other lines 000.002 000.002: --- NVIM STARTING --- 000.168 000.166: event init 000.252 000.083: early init 000.305 000.053: locale set 000.352 000.047: init first window 000.615 000.263: inits 1 000.624 000.009: window checked 000.626 000.002: parsing arguments 001.130 000.063 000.063: require('vim.shared') 001.229 000.057 000.057: require('vim.inspect') 001.281 000.037 000.037: require('vim._options') 001.282 000.148 000.053: require('vim._editor') 001.284 000.258 000.048: require('vim._init_packages') 001.290 000.405: init lua interpreter 001.872 000.583: expanding arguments 001.908 000.036: inits 2 002.302 000.394: init highlight 002.306 000.003: --- NVIM STARTED --- --- Startup times for process: Embedded --- times in msec clock self+sourced self: sourced script clock elapsed: other lines 000.002 000.002: --- NVIM STARTING --- 000.165 000.163: event init 000.242 000.077: early init 000.295 000.053: locale set 000.336 000.041: init first window 000.568 000.232: inits 1 000.582 000.015: window checked 000.589 000.007: parsing arguments 001.084 000.038 000.038: require('vim.shared') 001.192 000.047 000.047: require('vim.inspect') 001.239 000.036 000.036: require('vim._options') 001.241 000.154 000.070: require('vim._editor') 001.242 000.261 000.069: require('vim._init_packages') 001.244 000.394: init lua interpreter 001.299 000.054: expanding arguments 001.316 000.017: inits 2 001.554 000.238: init highlight 001.555 000.001: waiting for UI 001.649 000.094: done waiting for UI 001.652 000.003: clear screen 001.688 000.006 000.006: require('vim.keymap') 001.947 000.293 000.287: require('vim._defaults') 001.950 000.005: init default mappings & autocommands 002.376 000.051 000.051: sourcing /usr/share/nvim/runtime/ftplugin.vim 002.433 000.025 000.025: sourcing /usr/share/nvim/runtime/indent.vim 002.499 000.010 000.010: sourcing /usr/share/nvim/archlinux.vim 002.502 000.030 000.020: sourcing /etc/xdg/nvim/sysinit.vim 003.043 000.041 000.041: require('vim.fs') 003.205 000.133 000.133: require('vim.uri') 003.222 000.243 000.069: require('vim.loader') 003.756 001.216 000.973: require('core.general') 005.768 002.008 002.008: require('core.keymaps') 006.053 000.282 000.282: require('core.autocmds') 006.262 000.089 000.089: require('utils') 006.343 000.078 000.078: require('utils.static') 006.695 000.221 000.221: require('utils.static.icons._icons') 006.699 000.353 000.133: require('utils.static.icons') 007.039 000.076 000.076: require('modules.lib') 007.189 000.065 000.065: require('modules.edit') 007.287 000.060 000.060: require('modules.debug') 007.355 000.064 000.064: require('modules.tools') 007.408 000.047 000.047: require('modules.markup') 007.455 000.042 000.042: require('modules.completion') 007.519 000.060 000.060: require('modules.treesitter') 007.559 000.036 000.036: require('modules.colorschemes') 008.221 000.658 000.658: require('lazy') 008.250 000.011 000.011: require('ffi') 008.336 000.081 000.081: require('lazy.stats') 008.450 000.094 000.094: require('lazy.core.util') 008.536 000.083 000.083: require('lazy.core.config') 008.680 000.062 000.062: require('lazy.core.handler') 008.798 000.115 000.115: require('lazy.core.plugin') 008.812 000.274 000.098: require('lazy.core.loader') 010.241 000.085 000.085: require('lazy.core.handler.cmd') 010.349 000.103 000.103: require('lazy.core.handler.event') 010.532 000.178 000.178: require('lazy.core.handler.keys') 010.698 000.160 000.160: require('lazy.core.handler.ft') 011.196 000.024 000.024: sourcing /home/zeng/.local/share/nvim/packages/vimtex/ftdetect/cls.vim 011.247 000.017 000.017: sourcing /home/zeng/.local/share/nvim/packages/vimtex/ftdetect/tex.vim 011.288 000.021 000.021: sourcing /home/zeng/.local/share/nvim/packages/vimtex/ftdetect/tikz.vim 012.812 000.190 000.190: sourcing /usr/share/nvim/runtime/filetype.lua 012.886 000.006 000.006: require('vim.F') 013.509 000.127 000.127: sourcing /home/zeng/.config/nvim/plugin/_load.lua 013.677 000.064 000.064: require('utils.hl') 013.762 000.226 000.162: sourcing /home/zeng/.config/nvim/plugin/colorcolumn.lua 013.915 000.041 000.041: require('utils.json') 013.991 000.073 000.073: require('utils.fs') 015.510 000.962 000.962: sourcing /home/zeng/.config/nvim/colors/macro.lua 015.701 001.914 000.838: sourcing /home/zeng/.config/nvim/plugin/colorscheme.lua 016.132 000.098 000.098: require('vim.highlight') 016.280 000.550 000.452: sourcing /home/zeng/.config/nvim/plugin/intro.lua 016.466 000.063 000.063: sourcing /usr/share/nvim/runtime/plugin/editorconfig.lua 016.531 000.018 000.018: sourcing /usr/share/nvim/runtime/plugin/gzip.vim 016.626 000.069 000.069: sourcing /usr/share/nvim/runtime/plugin/man.lua 016.672 000.013 000.013: sourcing /usr/share/nvim/runtime/plugin/matchit.vim 016.831 000.136 000.136: sourcing /usr/share/nvim/runtime/plugin/matchparen.vim 016.873 000.012 000.012: sourcing /usr/share/nvim/runtime/plugin/netrwPlugin.vim 016.954 000.060 000.060: sourcing /usr/share/nvim/runtime/plugin/nvim.lua 017.030 000.054 000.054: sourcing /usr/share/nvim/runtime/plugin/osc52.lua 017.061 000.008 000.008: sourcing /usr/share/nvim/runtime/plugin/rplugin.vim 017.135 000.052 000.052: sourcing /usr/share/nvim/runtime/plugin/shada.vim 017.190 000.016 000.016: sourcing /usr/share/nvim/runtime/plugin/spellfile.vim 017.226 000.010 000.010: sourcing /usr/share/nvim/runtime/plugin/tarPlugin.vim 017.256 000.008 000.008: sourcing /usr/share/nvim/runtime/plugin/tohtml.vim 017.284 000.006 000.006: sourcing /usr/share/nvim/runtime/plugin/tutor.vim 017.326 000.011 000.011: sourcing /usr/share/nvim/runtime/plugin/zipPlugin.vim 017.410 011.355 005.044: require('core.packages') 017.413 014.890 000.028: sourcing /home/zeng/.config/nvim/init.lua 017.419 000.473: sourcing vimrc file(s) 017.522 000.051 000.051: sourcing /usr/share/nvim/runtime/filetype.lua 017.665 000.056 000.056: sourcing /usr/share/nvim/runtime/syntax/synload.vim 017.767 000.209 000.153: sourcing /usr/share/nvim/runtime/syntax/syntax.vim 017.779 000.101: inits 3 017.959 000.129 000.129: require('plugin.statuscolumn') 018.237 000.329: opening buffers 018.258 000.020: BufEnter autocommands 018.259 000.002: editing files in windows 018.280 000.021: VimEnter autocommands 018.340 000.060: UIEnter autocommands 018.567 000.179 000.179: sourcing /usr/share/nvim/runtime/autoload/provider/clipboard.vim 018.573 000.053: before starting main loop 018.911 000.074 000.074: require('utils.stl') 019.334 000.379 000.379: require('plugin.statusline') 019.542 000.130 000.130: require('utils.git') 019.754 000.197 000.197: require('vim._system') 021.197 001.843: first screen update 021.201 000.004: --- NVIM STARTED ---