Navigation Plugins
Beyond Telescope and Harpoon (covered in Module 10), these plugins enhance file navigation, project management, and workspace persistence.
1. oil.nvim — Edit the Filesystem Like a Buffer
Oil.nvim is a file manager where the directory listing IS a buffer. You edit filenames, move lines to rename/move files, delete lines to delete files — and save with :w.
lua/plugins/navigation.lua
return {
{
"stevearc/oil.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
cmd = "Oil",
keys = {
{ "-", "<cmd>Oil<cr>", desc = "Open parent directory (Oil)" },
{ "<leader>ef", function() require("oil").open_float() end, desc = "Open oil (float)" },
},
opts = {
default_file_explorer = true, -- replace netrw
columns = {
"icon",
"permissions",
"size",
{ "mtime", highlight = "Comment", format = "%Y-%m-%d %H:%M" },
},
buf_options = {
buflisted = false,
bufhidden = "hide",
},
win_options = {
wrap = false,
signcolumn = "no",
cursorcolumn = false,
foldcolumn = "0",
spell = false,
list = false,
conceallevel = 3,
concealcursor = "nvic",
},
delete_to_trash = true, -- use trash instead of permanent delete
skip_confirm_for_simple_edits = false,
prompt_save_on_select_new_entry = true,
cleanup_delay_ms = 2000,
lsp_file_methods = {
timeout_ms = 1000,
autosave_changes = false,
},
constrain_cursor = "editable",
watch_for_changes = false,
keymaps = {
["g?"] = "actions.show_help",
["<CR>"] = "actions.select",
["<C-s>"] = "actions.select_vsplit",
["<C-h>"] = "actions.select_split",
["<C-t>"] = "actions.select_tab",
["<C-p>"] = "actions.preview",
["<C-c>"] = "actions.close",
["<C-l>"] = "actions.refresh",
["-"] = "actions.parent",
["_"] = "actions.open_cwd",
["`"] = "actions.cd",
["~"] = "actions.tcd",
["gs"] = "actions.change_sort",
["gx"] = "actions.open_external",
["g."] = "actions.toggle_hidden",
["g\\"] = "actions.toggle_trash",
},
use_default_keymaps = true,
view_options = {
show_hidden = false,
is_hidden_file = function(name, _)
return vim.startswith(name, ".")
end,
is_always_hidden = function(name, _)
return name == ".." or name == ".git"
end,
natural_order = true,
sort = {
{ "type", "asc" },
{ "name", "asc" },
},
},
float = {
padding = 2,
max_width = 90,
max_height = 0,
border = "rounded",
win_options = { winblend = 0 },
override = function(conf) return conf end,
},
preview = {
max_width = 0.9,
min_width = { 40, 0.4 },
width = nil,
max_height = 0.9,
min_height = { 5, 0.1 },
height = nil,
border = "rounded",
win_options = { winblend = 0 },
update_on_cursor_moved = true,
},
progress = {
max_width = 0.9,
min_width = { 40, 0.4 },
width = nil,
max_height = { 10, 0.9 },
min_height = { 5, 0.1 },
height = nil,
border = "rounded",
minimized_border = "none",
win_options = { winblend = 0 },
},
},
},
}
Oil Workflow
- → open parent directory of current file
Enter → open file or directory
- → go up to parent
<C-p> → preview file
g. → toggle hidden files
Create file: Type new filename on empty line → :w
Delete file: Delete the line → :w
Rename file: Edit the name in place → :w
Move file: Cut line, paste in target dir, :w
tip
Oil treats directory operations like text editing. This is the most intuitive file manager for Vim users.
2. project.nvim — Project Root Detection
Automatically detects your project root and integrates with Telescope:
{
"ahmedkhalf/project.nvim",
config = function()
require("project_nvim").setup({
-- Methods to detect project root
detection_methods = { "lsp", "pattern" },
-- Patterns to look for
patterns = {
".git", ".hg", ".svn",
"package.json", "Makefile",
"pyproject.toml", "setup.py",
"composer.json", "artisan",
".nvimrc", ".luarc.json",
},
-- Ignore LSP if server didn't set root correctly
ignore_lsp = {},
-- Exclude these dirs
exclude_dirs = {},
-- Show hidden files
show_hidden = false,
-- Silently change directory?
silent_chdir = true,
-- Scope to change directory: global | tab | win
scope_chdir = "global",
-- Datapath for storing recent projects
datapath = vim.fn.stdpath("data"),
})
-- Integrate with Telescope
local ok, telescope = pcall(require, "telescope")
if ok then
telescope.load_extension("projects")
end
vim.keymap.set("n", "<leader>fp", function()
require("telescope").extensions.projects.projects()
end, { desc = "Find projects" })
end,
},
3. Auto-session — Save and Restore Sessions
{
"rmagatti/auto-session",
lazy = false,
keys = {
{ "<leader>sr", "<cmd>SessionRestore<cr>", desc = "Restore session for cwd" },
{ "<leader>ss", "<cmd>SessionSave<cr>", desc = "Save session for cwd" },
{ "<leader>sd", "<cmd>SessionDelete<cr>", desc = "Delete session" },
{ "<leader>sS", "<cmd>Autosession search<cr>", desc = "Search sessions (Telescope)" },
},
opts = {
auto_session_suppress_dirs = { "~/", "~/Projects", "~/Downloads", "/" },
auto_session_use_git_branch = true,
auto_save_enabled = true,
auto_restore_enabled = false, -- don't auto-restore, user decides
session_lens = {
buftypes_to_ignore = {},
load_on_setup = true,
theme_conf = { border = true },
previewer = false,
},
},
},
4. Leap.nvim — Alternative to Flash
If you prefer Leap (by the original vim-sneak author) over Flash:
{
"ggandor/leap.nvim",
event = "VeryLazy",
config = function()
local leap = require("leap")
leap.add_default_mappings() -- s and S for leap
-- Leap anywhere including current window
leap.add_repeat_mappings(";", ",", {
relative_directions = true,
modes = { "n", "x", "o" },
})
-- Bidirectional leap with gs
vim.keymap.set({ "n", "x", "o" }, "gs", function()
require("leap").leap({ target_windows = { vim.fn.win_getid() } })
end, { desc = "Leap bidirectional" })
-- Leap across all windows
vim.keymap.set({ "n", "x", "o" }, "gS", function()
require("leap").leap({
target_windows = vim.tbl_filter(function(win)
return vim.api.nvim_win_get_config(win).focusable
end, vim.api.nvim_tabpage_list_wins(0)),
})
end, { desc = "Leap across windows" })
end,
},
{
"ggandor/flit.nvim", -- better f/t with leap
dependencies = { "ggandor/leap.nvim" },
opts = { multiline = true, labeled_modes = "nx" },
},
Flash vs Leap Comparison
| Feature | Flash.nvim | Leap.nvim |
|---|---|---|
| Type | 2-char jump + labels | 2-char search with labels |
| Treesitter integration | ✅ excellent | Via leap-spooky |
| f/t enhancement | ✅ built-in | Via flit.nvim |
| Remote operator | ✅ built-in | Via leap-spooky |
| Active development | ✅ | ✅ |
5. nvim-window — Better Window Management
{
"anuvyklack/windows.nvim",
dependencies = {
"anuvyklack/middleclass",
"anuvyklack/animation.nvim",
},
event = "WinNew",
config = function()
vim.o.winwidth = 10
vim.o.winminwidth = 10
vim.o.equalalways = false
require("windows").setup({
autowidth = {
enable = true,
winwidth = 5,
filetype = {
help = 2,
},
},
ignore = {
buftype = { "quickfix" },
filetype = { "NvimTree", "neo-tree", "undotree", "gundo" },
},
animation = {
enable = true,
duration = 300,
fps = 30,
easing = "in_out_sine",
},
})
vim.keymap.set("n", "<C-w>z", "<cmd>WindowsMaximize<cr>", { desc = "Maximize window" })
vim.keymap.set("n", "<C-w>=", "<cmd>WindowsEqualize<cr>", { desc = "Equalize windows" })
end,
},