Focus on one thing at a time.
TunnelVision dims unrelated lines and keeps attention on the targeted symbol.

>= 0.9documentHighlight{
"leolaurindo/tunnelvision.nvim",
opts = {},
}
vim.pack.add({ "https://github.com/leolaurindo/tunnelvision.nvim" })
require("tunnelvision").setup()
vim.pack is Neovim's built-in plugin manager in newer versions, and it is still experimental upstream.
MiniDeps.add({ source = "leolaurindo/tunnelvision.nvim" })
require("tunnelvision").setup()
use({
"leolaurindo/tunnelvision.nvim",
config = function()
require("tunnelvision").setup()
end,
})
require("tunnelvision").setup() so the :TunnelVision command is registered.:TunnelVision on.:TunnelVision next and :TunnelVision prev.:TunnelVision off.:TunnelVision on|retarget|off|toggle|next|prev|refresh|status
:TunnelVision mode [static|dynamic|flow]
:TunnelVision scope [function|buffer]
:TunnelVision source [lsp_else_word|lsp|lsp_and_word|word]
:TunnelVision direction [forward|both]
Run :help tunnelvision for full command and option reference.
static (default): track the symbol selected on activation.dynamic: retarget as the cursor moves.flow: experimental mode that expands to assignment-related lines to follow value flow.scope = "function" uses Tree-sitter when available, otherwise TunnelVision falls back to the full buffer.
source = "lsp_else_word" is the default and works well as a general setting.
Use setup() to define the persistent defaults used by :TunnelVision on,
on(), and runtime commands such as :TunnelVision scope buffer.
require("tunnelvision").setup({
mode = "static",
scope = "function",
source = "lsp_else_word",
})
The default config will essentially resolve to your colorscheme Comment color. Set dim when you want to choose the color or style used for dimmed lines yourself:
require("tunnelvision").setup({
dim = { fg = "#565f89", italic = true },
})
Use one-shot overrides when you want a specific keymap or command to activate with different behavior without changing those defaults:
require("tunnelvision").on({ scope = "buffer", source = "word" })
This makes it easy to keep a stable default, such as LSP-first matching in the current function, while adding focused alternatives like plain word matching across the full buffer.
These options can be set as persistent defaults in setup(). Core behavior and
appearance options such as mode, scope, source, direction, and dim can
also be passed to on(opts) for one-shot activations.
| Option | Default | Notes |
|---|---|---|
mode |
static |
dynamic retargets as you move; flow is experimental. |
direction |
forward |
Flow mode only. Use both to include backward influence. |
scope |
function |
Uses the nearest function-like scope when Tree-sitter is available. |
source |
lsp_else_word |
LSP first, then word matching when LSP data is unavailable. |
fallback_warn |
once |
Controls fallback warnings for lsp_else_word. |
extra_keywords |
{} |
Extra identifiers to ignore in flow analysis. |
lsp_timeout_ms |
150 |
Timeout for async LSP documentHighlight requests. |
dim |
nil |
Optional color/style definition for dimmed lines. Defaults to the Comment foreground. |
dim_hl |
TunnelVisionDim |
Highlight group used for dimmed lines. |
max_dim_lines |
6000 |
Skip dimming in very large buffers. |
notify |
true |
Enable plugin notifications. |
Run :help tunnelvision-config for the full option reference.
local tv = require("tunnelvision")
vim.keymap.set("n", "<leader>v", "<cmd>TunnelVision on<CR>", { desc = "TunnelVision on" })
-- or vim.keymap.set("n", "<leader>v", "<cmd>TunnelVision toggle<CR>", { desc = "TunnelVision toggle" })
vim.keymap.set("n", "]v", "<cmd>TunnelVision next<CR>", { desc = "TunnelVision next" })
vim.keymap.set("n", "[v", "<cmd>TunnelVision prev<CR>", { desc = "TunnelVision prev" })
vim.keymap.set("n", "<Esc>", function()
if tv.is_active() then
tv.off()
return ""
end
return "<Esc>"
end, { expr = true, silent = true, desc = "TunnelVision off on Esc" })
-- as an example: a different activation as one-shot
vim.keymap.set("n", "<leader>V", function()
tv.on({ scope = "buffer", source = "word" })
end, { desc = "TunnelVision word in buffer" })
:checkhealth tunnelvisionFeel free to contribute.
Just make sure to:
CHANGELOG.md