The goal of this neovim-plugin is to implement project-dependent settings in a feature-complete and flexible manner.
Relevant features:
- Declaratively define options (not just buffer-local or global
vim.opt
-options, but any arbitrary code that changes a buffers state) to apply to some buffer based on predicates.
For example, set a keybinding for all buffers whose filename matches.*README.md
, or configure a specific lsp for allpython
files in some directory.
Special care is taken to allow these options to be very minimal (quick to create!), unloadable (remove them completely), and have well-defined merging behaviour (in case more than one option applies to some buffer). - Quickly edit currently-loaded options.
It is possible to quickly jump to any option that applies to the current buffer, edit it, and reload the options for all open buffers.
This is definitely very pre-1.0, so best only use it by pinning it to a commit, so it's excluded when more stable plugins are updated. Whenever a new breaking change is pushed, it, and a way to adapt to it will be posted to this issue, so consider following it.
The following code shows a few of the basic concepts of matchconfig:
-- Setup some local variables
local matchconfig = require("matchconfig")
local matchers = matchconfig.matchers
local extra_matchers = require("matchconfig.extras.matchers.projects")
local c = matchconfig.config
local actions = matchconfig.actions
local nnoremapsilent_buf = actions.nnoremapsilent_buf
local usercommand_buf = actions.usercommand_buf
-- For all buffers that belong to a cmake-project, register a keybinding for
-- running `cmake --build build`.
-- A buffer belongs to a cmake project if a `CMakeLists.txt` can be found in any
-- of its parent-directories.
-- Note that ideally, this would be improved by using some repl-plugin for more
-- interactivity.
local cmake_generic = matchconfig.register(extra_matchers.cmake(), c{
run_buf = function(args)
-- nnoremapsilent_buf registers a buffer-local keybinding that can be
-- removed upon reload.
-- for the cmake-matcher, args.match_args is the directory where the
-- Makefile resides.
nnoremapsilent_buf("<Space>b", ":!cd " .. args.match_args .. " && cmake --build build<Cr>")
end
})
-- this time, register a keybinding on the same key-combo as before, but for
-- Makefile-based projects (again, identified by searching upwards for a
-- `Makefile`)
local make_generic = matchconfig.register(extra_matchers.make(), c{
run_buf = function(args)
nnoremapsilent_buf("<Space>b", ":!cd " .. args.match_args .. " && make build<Cr>")
end
})
-- make sure that (arbitrarily) the cmake-binding supersedes the make-binding.
-- So in projects that have both a CMakeLists.txt and a Makefile, <space>b would
-- run `make build`.
-- Here this is achieved trivially by registering the cmake-keybind after the
-- make-keybind, but this merging behaviour can be completely customized for
-- every option.
cmake_generic:after(make_generic)
-- for filenames that match README.md$ or DOC.md$ (ie. files named
-- `README.md/DOC.md`), register two usercommands, `:Gr` and `:S`, for starting and
-- stopping a grip-server (https://github.com/joeyespo/grip) (it can render
-- markdown as it appears on github, very useful for previewing changes).
matchconfig.register(matchers.pattern("README.md$") + matchers.pattern("DOC.md$"), c{
run_buf = function(args)
usercommand_buf("Gr", function()
io.popen(
"systemd-run --user -u $(systemd-escape grip_" .. args.file .. ") " ..
"grip -b " .. args.file .. " 0 2> /dev/null")
end, {})
usercommand_buf("S", function()
io.popen(
"systemctl --user stop $(systemd-escape grip_" .. args.file .. ")")
end, {})
end
})
And the short session below shows the hot-reload and editing capabilities of
nvim-matchconfig
with the config shown above:
demo.mp4
Note the following things:
:C
opens a telescope-based picker for all options loaded for the current buffer.- After changing the
Makefile
-matchingrun_buf
for the first time, the old keybinding is removed and the new one (make build_debug
) is registered. When thennoremapsilent_buf
is commented out, no keybinding exists for<space>b
. pick_current
only shows the most up-to-date information and no older, no-longer effective options.
-
Make sure you're running Neovim version 0.10+.
-
Install
nvim-matchconfig
using your favorite package-manager. Optionally follow a specific version (we adhere to semantic versioning) by providing a tag. -
Find your config-directory via
:lua =vim.fn.stdpath("config")
(very, very likely this is~/.config/nvim
) and create the fileconfig.lua
in it. For a quick check that everything works correctly, try the following:local mc = require("matchconfig") local c = mc.config local matchers = mc.matchers mc.register(matchers.filetype("python"), c{ run_buf = function() print("Hello from nvim-matchconfig") end })
You should now see a short message upon opening a python-file.
-
Define your own configs. Reading the remainder of this README and DOC.md should give you some solid ideas on how to use
nvim-matchconfig
and what it is capable of.
nvim-matchconfig
can be configured using a setup
-function:
require("matchconfig").setup({
path = "config.lua",
options = {
require("matchconfig.options.run_buf")
require("matchconfig.options.run_session")
}
})
More information on setup
and its various keys can be found in
DOC.md in the chapter API-Setup
.
The chapter Tips
in DOC.md has suggestions for a good workflow with
nvim-matchconfig
as well as mappings and commands that may come in handy.
My dotfiles also contain a pretty large nvim-matchconfig
-config
here, with
the setup
here