| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
rooter.nvim changes the working directory to the project root when you open a file. It is inspired by vim-rooter.
This plugin also provides telescope and picker.nvim extensions to fuzzy find recently opened projects.
using nvim-plug
require('plug').add({
{
'wsdjeg/rooter.nvim',
config = function()
require('rooter').setup({
root_patterns = { '.git/' },
})
end,
}
})require('rooter').setup({
root_patterns = { '.git/' },
outermost = true,
enable_cache = true,
project_non_root = '',
command = 'lcd',
exclude_patterns = {
'%[denite%]',
'denite%-filter',
'%[defx%]',
'^git://', -- git.vim
'^neo%-tree', -- neo-tree.nvim
'^NvimTree_', -- nvim-tree.nvim
'^__Tagbar__', -- tagbar.vim
},
})| Option | Type | Default | Description |
|---|---|---|---|
| root_patterns | table<string> | { '.git/' } | Patterns to identify project root. Directories end with /, files do not. |
| outermost | boolean | true | When true, find the outermost matching directory. When false, find the nearest (innermost). |
| enable_cache | boolean | true | Persist project history to stdpath('data')/nvim-rooter.json for cross-session persistence. |
| project_non_root | string | '' | Behavior for files outside any project: '' = keep cwd, 'home' = switch to $HOME, 'current' = switch to file's directory. |
| command | string | 'lcd' | Vim command used to change directory: 'cd', 'tcd', or 'lcd'. |
| exclude_patterns | table<string> | see above | Lua patterns matched against the buffer name; matching buffers (filetrees, popups...) are skipped by root detection. Remember to escape magic characters (- → %-). |
Note: list options (root_patterns, exclude_patterns) are replaced as a whole when you set them, they are not merged with the defaults.
require('rooter').setup({
root_patterns = { '.git/', '.hg/', 'Cargo.toml', 'go.mod', 'package.json' },
outermost = false, -- find nearest root
command = 'tcd', -- use tab-local cd
})require('rooter').setup({
exclude_patterns = {
'^neo%-tree', -- lua pattern, escape the magic `-`
'^NvimTree_',
'^myfiletree://', -- add your own plugin buffers
},
})Once setup() is called, rooter.nvim automatically changes the working directory whenever you open a file or switch buffers. You can also use the commands and APIs below.
This plugin provides a user command :Rooter:
| Command | Description |
|---|---|
| :Rooter | Manually trigger root detection for current buffer. |
| :Rooter toggle | Toggle root detection on/off. |
| :Rooter enable | Enable root detection. |
| :Rooter disable | Disable root detection (keeps current cwd). |
| :Rooter clear | Clear all cached projects. |
| :Rooter kill project1 project2 | Delete all buffers belonging to the specified project(s). |
Requires telescope.nvim.
:Telescope project
Lists all cached projects sorted by last opened time. Press <CR> to open a project in a new tab.
Requires picker.nvim.
:Picker project
Key bindings for picker project:
| Key binding | Description |
|---|---|
| <CR> | Open project in a new tab (default action) |
| <C-f> | Browse project files |
| <C-d> | Delete project from history |
| <C-s> | Search text in project, requires flygrep.nvim |
To run custom logic when the project changes, register a callback with rooter.reg_callback:
-- Update code-runner config based on project's .clang file
local c_runner = {
exe = 'gcc',
targetopt = '-o',
usestdin = true,
opt = { '-std=c11', '-xc', '-' },
}
require('code-runner').setup({
runners = {
c = { c_runner, '#TEMP#' },
},
})
local function update_clang_flag()
if vim.fn.filereadable('.clang') == 1 then
local flags = vim.fn.readfile('.clang')
local opt = { '-std=c11' }
for _, v in ipairs(flags) do
table.insert(opt, v)
end
table.insert(opt, '-xc')
table.insert(opt, '-')
c_runner.opt = opt
end
end
require('rooter').reg_callback(update_clang_flag, 'update clang flags')The callback receives the current project object:
| Field | Description |
|---|---|
| path | Absolute root path (with trailing /) |
| name | Project name (same as b:rooter_project_name) |
| opened_time | Timestamp when the project was opened |
Callbacks are called via pcall so errors won't crash the root detection flow. You can also pass a Vimscript function name as a string; it receives the project as a dict argument.
Per-project settings can be implemented right inside the callback, by matching project.name (or project.path for an exact match):
-- Per-project options: map project name -> option table
local project_options = {
['my-blog'] = {
shiftwidth = 2,
expandtab = true,
makeprg = 'hugo server',
},
['dotfiles'] = {
shiftwidth = 4,
},
}
-- Options applied when entering a project that is not in the table above
local default_options = {
shiftwidth = 4,
}
local function apply_options(opts)
for key, value in pairs(opts) do
vim.opt[key] = value
end
end
require('rooter').reg_callback(function(project)
-- project = { path = '/home/me/my-blog/', name = 'my-blog', opened_time = 1712345678 }
apply_options(project_options[project.name] or default_options)
end, 'per-project options')Of course you can do much more than options, for example loading a project-local keymap file, starting an LSP server only for certain projects, etc.
| Function | Description |
|---|---|
| setup(opt) | Initialize rooter.nvim with config options and set up autocmds. |
| current_root() | Detect and switch to the project root for the current buffer. Returns the root path. |
| current_name() | Returns the current project name (from b:rooter_project_name). |
| toggle() | Toggle root detection, returns the new state. |
| enable() | Enable root detection, returns true. |
| disable() | Disable root detection, returns false. |
| is_enabled() | Returns whether root detection is currently enabled. |
| list() | Open the project picker (Picker.nvim or Telescope, whichever is available). |
| open(project_path) | Open a project by its path in a new tab. |
| clear() | Clear all cached projects and write empty cache to disk. |
| kill_project(name) | Delete all buffers belonging to the named project. |
| reg_callback(func, desc?) | Register a callback function (or Vimscript function name) to run on project switch. The callback receives the project object (path, name, opened_time). desc is an optional description for logging. |
| get_project_history() | Returns the table of all cached projects. |
make test # run the test suite
make coverage # run tests with luacov, enforces 100% line coverageThe coverage gate covers lua/rooter/*.lua and plugin/rooter.lua. The telescope/picker integration files are excluded since they cannot be loaded without their host plugins.
Install logger.nvim as a dependency. Logging is automatically enabled when logger.nvim is available - no extra config needed.
require('plug').add({
{
'wsdjeg/rooter.nvim',
config = function()
require('rooter').setup({
root_patterns = { '.git/' },
})
end,
depends = {
{
'wsdjeg/logger.nvim',
config = function()
vim.keymap.set(
'n',
'<leader>hL',
'<cmd>lua require("logger").viewRuntimeLog()<cr>',
{ silent = true }
)
end,
},
},
},
})Sample runtime log:
[ rooter ] [23:22:50:576] [ Info ] start to find root for: D:/wsdjeg/rooter.nvim/lua/rooter/init.lua [ rooter ] [23:22:50:576] [ Info ] (.git/):D:/wsdjeg/rooter.nvim/ [ rooter ] [23:22:50:576] [ Info ] switch to project:[rooter.nvim] [ rooter ] [23:22:50:576] [ Info ] rootdir is:D:/wsdjeg/rooter.nvim/
If you encounter any bugs or have suggestions, please file an issue in the issue tracker
Like this plugin? Star the repository on GitHub.
Love this plugin? Follow me on GitHub.
Licensed under GPL-3.0.
| Back | FazBrowse Home | New Git URL |