An extensible and performant Neovim minimap plugin that helps you visualize code structure, diagnostics, git changes, and more at a glance.
Lua
377
825 commits
updated Apr 12, 2026
This plugin provides a visual representation of your code structure on the side of your windows, similar to the minimap found in many modern editors.
Criticisms are welcome.
The color scheme used for these screenshots is nord
With vim.pack:
vim.pack.add({
{ src = "https://github.com/Isrothy/neominimap.nvim" },
})
-- The following options are recommended when layout == "float"
vim.opt.wrap = false
vim.opt.sidescrolloff = 36 -- Set a large value
--- Put your configuration here
---@type Neominimap.UserConfig
vim.g.neominimap = {
auto_enable = true,
}
With Lazy:
---@module "neominimap.config.meta"
{
"Isrothy/neominimap.nvim",
version = "v3.x.x",
lazy = false, -- NOTE: NO NEED to Lazy load
-- Optional. You can also set your own keybindings
keys = {
-- Global Minimap Controls
{ "<leader>nm", "<cmd>Neominimap Toggle<cr>", desc = "Toggle global minimap" },
{ "<leader>no", "<cmd>Neominimap Enable<cr>", desc = "Enable global minimap" },
{ "<leader>nc", "<cmd>Neominimap Disable<cr>", desc = "Disable global minimap" },
{ "<leader>nr", "<cmd>Neominimap Refresh<cr>", desc = "Refresh global minimap" },
-- Window-Specific Minimap Controls
{ "<leader>nwt", "<cmd>Neominimap WinToggle<cr>", desc = "Toggle minimap for current window" },
{ "<leader>nwr", "<cmd>Neominimap WinRefresh<cr>", desc = "Refresh minimap for current window" },
{ "<leader>nwo", "<cmd>Neominimap WinEnable<cr>", desc = "Enable minimap for current window" },
{ "<leader>nwc", "<cmd>Neominimap WinDisable<cr>", desc = "Disable minimap for current window" },
-- Tab-Specific Minimap Controls
{ "<leader>ntt", "<cmd>Neominimap TabToggle<cr>", desc = "Toggle minimap for current tab" },
{ "<leader>ntr", "<cmd>Neominimap TabRefresh<cr>", desc = "Refresh minimap for current tab" },
{ "<leader>nto", "<cmd>Neominimap TabEnable<cr>", desc = "Enable minimap for current tab" },
{ "<leader>ntc", "<cmd>Neominimap TabDisable<cr>", desc = "Disable minimap for current tab" },
-- Buffer-Specific Minimap Controls
{ "<leader>nbt", "<cmd>Neominimap BufToggle<cr>", desc = "Toggle minimap for current buffer" },
{ "<leader>nbr", "<cmd>Neominimap BufRefresh<cr>", desc = "Refresh minimap for current buffer" },
{ "<leader>nbo", "<cmd>Neominimap BufEnable<cr>", desc = "Enable minimap for current buffer" },
{ "<leader>nbc", "<cmd>Neominimap BufDisable<cr>", desc = "Disable minimap for current buffer" },
---Focus Controls
{ "<leader>nf", "<cmd>Neominimap Focus<cr>", desc = "Focus on minimap" },
{ "<leader>nu", "<cmd>Neominimap Unfocus<cr>", desc = "Unfocus minimap" },
{ "<leader>ns", "<cmd>Neominimap ToggleFocus<cr>", desc = "Switch focus on minimap" },
},
init = function()
-- The following options are recommended when layout == "float"
vim.opt.wrap = false
vim.opt.sidescrolloff = 36 -- Set a large value
--- Put your configuration here
---@type Neominimap.UserConfig
vim.g.neominimap = {
auto_enable = true,
}
end,
}
---@enum Neominimap.Handler.Annotation
local AnnotationMode = {
Sign = "sign", -- Show braille signs in the sign column
Icon = "icon", -- Show icons in the sign column
Line = "line", -- Highlight the background of the line on the minimap
}
vim.g.neominimap = {
-- Enable the plugin by default
auto_enable = true, ---@type boolean
-- Log level
log_level = vim.log.levels.OFF, ---@type Neominimap.Log.Levels
-- Notification level
notification_level = vim.log.levels.INFO, ---@type Neominimap.Log.Levels
-- Path to the log file
log_path = vim.fn.stdpath("data") .. "/neominimap.log", ---@type string
-- Minimaps will not be created for buffers of these filetypes
---@type string[]
exclude_filetypes = {
"help",
"bigfile", -- For Snacks.nvim
},
-- Minimaps will not be created for buffers of these buftypes
---@type string[]
exclude_buftypes = {
"nofile",
"nowrite",
"quickfix",
"terminal",
"prompt",
},
-- When this function returns false, the minimap will not be created for this buffer.
---@type fun(bufnr: integer): boolean
buf_filter = function()
return true
end,
-- When this function returns false, the minimap will not be created for this window.
---@type fun(winid: integer): boolean
win_filter = function()
return true
end,
-- When this function returns false, the minimap will not be created for this tab.
---@type fun(tabid: integer): boolean
tab_filter = function()
return true
end,
-- How many columns a dot should span
x_multiplier = 4, ---@type integer
-- How many rows a dot should span
y_multiplier = 1, ---@type integer
---@alias Neominimap.Config.CurrentLinePosition "center" | "percent"
-- How the minimap places the current line vertically.
-- `"center"` -> pins the line to the viewport middle (window-relative).
-- `"percent"` -> maps line index / total lines to minimap height (file-relative).
-- Note: here "center" means the middle of the **minimap window**, not "center of the file".
current_line_position = "center", ---@type Neominimap.Config.CurrentLinePosition
buffer = {
-- When true, the minimap will be recreated when you delete the buffer.
-- When false, the minimap will be disabled for the current buffer when you delete the minimap buffer.
persist = true, ---@type boolean
},
---@alias Neominimap.Config.LayoutType "split" | "float"
--- Either `split` or `float`
--- When layout is set to `float`, minimaps will be created in floating windows attached to all suitable windows.
--- When layout is set to `split`, the minimap will be created in one split window per tab.
layout = "float", ---@type Neominimap.Config.LayoutType
--- Used when `layout` is set to `split`
split = {
minimap_width = 20, ---@type integer
-- Always fix the width of the split window
fix_width = false, ---@type boolean
---@alias Neominimap.Config.SplitDirection "left" | "right" | "topleft" | "botright" | "aboveleft" | "rightbelow"
direction = "right", ---@type Neominimap.Config.SplitDirection
--- Automatically close the split window when it is the last window.
close_if_last_window = false, ---@type boolean
--- When true, the split window will be recreated when you close it.
--- When false, the minimap will be disabled for the current tab when you close the minimap window.
persist = true, ---@type boolean
},
--- Used when `layout` is set to `float`
float = {
minimap_width = 20, ---@type integer
--- If set to nil, there is no maximum height restriction
--- @type integer
max_minimap_height = nil,
margin = {
right = 0, ---@type integer
top = 0, ---@type integer
bottom = 0, ---@type integer
},
z_index = 1, ---@type integer
--- Border style of the floating window.
--- Accepts all usual border style options (e.g., "single", "double")
--- @type string | string[] | [string, string][]
window_border = vim.fn.has("nvim-0.11") == 1 and vim.o.winborder or "single",
-- When true, the floating window will be recreated when you close it.
-- When false, the minimap will be disabled for the current tab when you close the minimap window.
persist = true, ---@type boolean
},
-- For performance, when text changes, the minimap is refreshed after a certain delay.
-- Set the delay in milliseconds
delay = 200, ---@type integer
-- Sync the cursor position with the minimap
sync_cursor = true, ---@type boolean
click = {
-- Enable mouse click on the minimap
enabled = false, ---@type boolean
-- Automatically switch focus to the minimap when clicked
auto_switch_focus = true, ---@type boolean
},
diagnostic = {
enabled = true, ---@type boolean
-- Allowed formats for the `severity` filter:
-- 1. A single severity level:
-- eg: severity = vim.diagnostic.severity.WARN
-- 2. A table with a "min" and/or "max" key:
-- eg: severity = { min = vim.diagnostic.severity.WARN, max = vim.diagnostic.severity.ERROR }
-- 3. A list-like table of severity values:
-- eg: severity = { vim.diagnostic.severity.WARN, vim.diagnostic.severity.ERROR }
---@see vim.diagnostic.severity
severity = nil, ---@type vim.diagnostic.SeverityFilter?
mode = "line", ---@type Neominimap.Handler.Annotation.Mode
priority = {
ERROR = 100, ---@type integer
WARN = 90, ---@type integer
INFO = 80, ---@type integer
HINT = 70, ---@type integer
},
icon = {
ERROR = "σ°
", ---@type string
WARN = "σ°ͺ ", ---@type string
INFO = "σ°Ά ", ---@type string
HINT = "ο ", ---@type string
},
},
git = {
enabled = true, ---@type boolean
mode = "sign", ---@type Neominimap.Handler.Annotation.Mode
priority = 6, ---@type integer
icon = {
add = "+ ", ---@type string
change = "~ ", ---@type string
delete = "- ", ---@type string
},
},
mini_diff = {
enabled = false, ---@type boolean
mode = "sign", ---@type Neominimap.Handler.Annotation.Mode
priority = 6, ---@type integer
icon = {
add = "+ ", ---@type string
change = "~ ", ---@type string
delete = "- ", ---@type string
},
},
search = {
enabled = false, ---@type boolean
mode = "line", ---@type Neominimap.Handler.Annotation.Mode
priority = 20, ---@type integer
icon = "σ°±½ ", ---@type string
},
treesitter = {
enabled = true, ---@type boolean
priority = 200, ---@type integer
},
mark = {
enabled = false, ---@type boolean
mode = "icon", ---@type Neominimap.Handler.Annotation.Mode
priority = 10, ---@type integer
key = "m", ---@type string -- Useless for neovim >= 0.12
show_builtins = false, ---@type boolean -- shows the builtin marks like [ ] < >
},
fold = {
-- Consider folds when rendering the minimap
enabled = true, ---@type boolean
},
--- Override the default window options
---@param opt vim.wo
---@param winid integer the window id of the source window, NOT the minimap window
winopt = function(opt, winid) end,
--- Override the default buffer options
---@param opt vim.bo
---@param bufnr integer the buffer id of the source buffer, NOT the minimap buffer
bufopt = function(opt, bufnr) end,
---@type Neominimap.Map.Handler[]
handlers = {},
}
{
winhighlight = table.concat({
"Normal:NeominimapBackground",
"FloatBorder:NeominimapBorder",
"CursorLine:NeominimapCursorLine",
"CursorLineNr:NeominimapCursorLineNr",
"CursorLineSign:NeominimapCursorLineSign",
"CursorLineFold:NeominimapCursorLineFold",
}, ","),
wrap = false,
foldcolumn = "0",
signcolumn = "auto",
number = false,
relativenumber = false,
scrolloff = config.current_line_position == "center" and 99999 or 0,
sidescrolloff = 0,
winblend = 0,
cursorline = true,
spell = false,
list = false,
fillchars = "eob: ",
winfixwidth = true,
}
{
buftype = "nofile",
filetype = "neominimap",
swapfile = false,
bufhidden = "hide",
undolevels = -1,
modifiable = false,
}
Global Commands:
Neominimap Enable
Neominimap Disable
Neominimap Toggle
Neominimap Refresh
Buffer Commands:
Neominimap BufEnable [buffer_list]
Neominimap BufDisable [buffer_list]
Neominimap BufToggle [buffer_list]
Neominimap BufRefresh [buffer_list]
Tab Commands:
Neominimap TabEnable [tab_list]
Neominimap TabDisable [tab_list]
Neominimap TabToggle [tab_list]
Neominimap TabRefresh [tab_list]
Window Commands:
Neominimap WinEnable [window_list]
Neominimap WinDisable [window_list]
Neominimap WinToggle [window_list]
Neominimap WinRefresh [window_list]
Focus Commands:
Neominimap Focus
Neominimap Unfocus
Neominimap ToggleFocus
To turn on the minimap globally:
:Neominimap on
To disable the minimap for the current buffer:
:Neominimap BufOff
To refresh the minimap for windows 3 and 4:
:Neominimap WinRefresh 3 4
[!NOTE] A minimap is shown if and only if
- Neominimap is enabled globally,
- Neominimap is enabled for the current buffer,
- Neominimap is enabled for the current tabpage, and
- Neominimap is enabled for the current window.
Global API
require('neominimap.api').enable()
require('neominimap.api').disable()
require('neominimap.api').toggle()
require('neominimap.api').refresh()
require('neominimap.api').enabled()
true if the minimap is enabled, false otherwiseBuffer API
require('neominimap.api').buf.enable(<bufnr>)
require('neominimap.api').buf.disable(<bufnr>)
require('neominimap.api').buf.toggle(<bufnr>)
require('neominimap.api').buf.refresh(<bufnr>)
require('neominimap').buf.enabled(bufnr)
true if the minimap is enabled, false otherwiseTab API
require('neominimap.api').tab.enable(<tabid>)
require('neominimap.api').tab.disable(<tabid>)
require('neominimap.api').tab.toggle(<tabid>)
require('neominimap.api').tab.refresh(<tabid>)
require('neominimap').tab.enabled(tabid)
true if the minimap is enabled, false otherwiseWindow API
require('neominimap.api').win.enable(<winid>)
require('neominimap.api').win.disable(<winid>)
require('neominimap.api').win.toggle(<winid>)
require('neominimap.api').win.refresh(<winid>)
require('neominimap').win.enabled(winid)
true if the minimap is enabled, false otherwiseFocus Control
require('neominimap.api').focus.enable()
require('neominimap.api').focus.disable()
require('neominimap.api').focus.toggle()
The neominimap API has been updated to provide a more intuitive and flexible interface. The old API is now deprecated and will eventually be removed. This guide will help you transition to the new neominimap.api.
| Old Function | New Function |
|---|---|
require('neominimap').on | require('neominimap.api').enable |
require('neominimap').off | require('neominimap.api').disable |
require('neominimap').toggle | require('neominimap.api').toggle |
require('neominimap').refresh | require('neominimap.api').refresh |
require('neominimap').enabled | require('neominimap.api').enabled |
require('neominimap').bufOn | require('neominimap.api').buf.enable |
require('neominimap').bufOff | require('neominimap.api').buf.disable |
require('neominimap').bufToggle | require('neominimap.api').buf.toggle |
require('neominimap').bufRefresh | require('neominimap.api').buf.refresh |
require('neominimap').bufEnabled | require('neominimap.api').buf.enabled |
require('neominimap').tabOn | require('neominimap.api').tab.disable |
require('neominimap').tabOff | require('neominimap.api').tab.disable |
require('neominimap').tabToggle | require('neominimap.api').tab.toggle |
require('neominimap').tabRefresh | require('neominimap.api').tab.refresh |
require('neominimap').tabEnabled | require('neominimap.api').tab.enabled |
require('neominimap').winOn | require('neominimap.api').win.enable |
require('neominimap').winOff | require('neominimap.api').win.disable |
require('neominimap').winToggle | require('neominimap.api').win.toggle |
require('neominimap').winEnabled | require('neominimap.api').win.enabled |
require('neominimap').winRefresh | require('neominimap.api').win.refresh |
require('neominimap').focus | require('neominimap.api').focus.enable |
require('neominimap').unfocus | require('neominimap.api').focus.disable |
require('neominimap').toggleFocus | require('neominimap.api').focus.toggle |
| Aspect | Old API (neominimap).doSomeThing | New API (neominimap.api).do_some_thing() |
|---|---|---|
| Input Type | Expects a list of integers. | Accepts nil, a single integer, or a list of integers. An empty list does nothing. |
| Default Behavior | Automatically defaults to the current buffer/tab/window if the input list is empty. | Explicitly requires omitted input to default to the current buffer/tab/window. |
| Design Philosophy | A wrapper for Vim commands, with implicit behaviors. | Independent of Vim commands. |
{}) defaulted to the current buffer, tab, or window.nil or omit the argument.Here is an example:
-- Old API
require("neominimap").bufOn({}) -- Defaults to current buffer
-- New API
require("neominimap.api").buf.enable() -- Explicitly defaults to current buffer
require("neominimap.api").buf.enable({}) -- Does nothing
A handler is defined as a Lua table with the following fields:
name (string): A unique identifier for your handler (e.g., "my_todo_handler").mode ("sign" | "icon" | "line"): Determines how annotations are
displayed on the minimap:
"sign": Shows small braille characters in the sign column."icon": Shows a single character/icon (potentially from an icon font) in
the sign column."line": Highlights the background of the corresponding line(s) on the
minimap.namespace (integer): A Neovim namespace ID used internally by Neovim
to manage virtual text or signs. This should be created using
vim.api.nvim_create_namespace.autocmds ({event: string|string[], opts?: table}[]): A list of
autocommand specifications. Whenever one of these autocommands fires, the
handler will be triggered to update the minimap for the relevant buffer(s).
The opts table can contain standard autocommand options like pattern,
desc, and importantly, either callback or get_buffers.
opts.callback is defined (fun(apply: fun(bufnr:integer), args: any)),
it receives a function apply(bufnr) to manually trigger the handler for a
specific buffer and the autocommand arguments. You are responsible for
calling apply(bufnr) for the buffer(s) you want to update.opts.callback is not defined, you must provide opts.get_buffers
(fun(data: vim.api.keyset.create_autocmd.callback_args): integer[] | integer). This function receives the autocommand arguments and must return
the buffer number(s) that the handler should be applied to.init (fun()): A function called once when the handler is registered.get_annotations (fun(bufnr: integer): Neominimap.Map.Handler.Annotation[]):
This is the core logic of your handler. It takes a buffer number (bufnr) as
input, and returns an array of Neominimap.Map.Handler.Annotation objects.Each object returned by get_annotations must conform to the
Neominimap.Map.Handler.Annotation structure:
lnum (integer): The starting line number (1-based) in the main buffer
that this annotation refers to.end_lnum (integer): The ending line number (1-based). For single-line
annotations, this is the same as lnum.id (integer): An id for a specific kind of annotation. For example,
all git add should have the same id but git add and git change have
different ids. This is used to group annotations together like vertical
braille dots.priority (integer): Determines display order when annotations overlap.icon? (string, optional): A single character or icon string to display
if the handler's mode is "icon".highlight (string): The name of a Neovim highlight group.See the wiki page for examples.
This plugin provides statusline components that integrate with various statusline plugins like Lualine.
The plugin offers the following customizable components for your statusline:
Here's an example of how you can customize the Lualine statusline using neominimap components:
local neominimap = require("neominimap.statusline")
local minimap_extension = {
sections = {
lualine_c = {
neominimap.fullname,
},
lualine_z = {
neominimap.position,
"progress",
},
},
filetypes = { "neominimap" },
}
require("lualine").setup({ extensions = { minimap_extension } })
Alternatively, you can use the default settings provided by the plugin:
local minimap_extension = require("neominimap.statusline").lualine_default
require("lualine").setup({ extensions = { minimap_extension } })
The default Lualine extension provided by the plugin is structured as follows:
{
sections = {
winbar = {},
lualine_a = {
M.plugin_name,
},
lualine_c = {
M.shortname,
},
lualine_z = {
M.position,
"progress",
},
},
filetypes = { "neominimap" },
}
For every file opened, the plugin generates a corresponding minimap buffer.
When a buffer is displayed in a window, the minimap buffer is automatically opened side by side with the main window.
This approach minimizes unnecessary rendering when
First, the plugin retrieves all Treesitter nodes in the buffer.
For each codepoint in the minimap, the plugin calculates which highlight occurs most frequently and displays it. If multiple highlights occur the same number of times, all of them are displayed.
Note that the plugin considers which highlights are applied, rather than which highlights are shown. Specifically, when many highlights are applied to a codepoint, it is possible that only some of them are visible. However, all applied highlights are considered in the calculation. As a result, unshown highlights may be displayed in the minimap, leading to potential inconsistencies between the highlights in the minimap and those in the buffer.
When a buffer is exceptionally large, calculating and setting up the minimap can take a significant amount of time, potentially blocking the UI. To address this, the plugin employs cooperative scheduling, as Lua operates in a single-threaded environment.
Most CPU-intensive tasks are executed within coroutines, which periodically yield control back to the Neovim event loop. This allows the event loop to decide when to resume the coroutine. By releasing CPU resources intermittently, the plugin ensures that the UI remains responsive and unblocked during these operations.
Checkout the wiki page for more details. wiki
| Highlight Group | Description |
|---|---|
NeominimapBackground | Background color for the minimap. |
NeominimapBorder | Border highlight for the minimap window. |
NeominimapCursorLine | Highlight for the cursor line in minimaps. |
NeominimapCursorLineNr | To replace CursorLineNr in minimaps. |
NeominimapCursorLineSign | To replace CursorLineSign in minimaps. |
NeominimapCursorLineFold | To replace CursorLineFold in minimaps. |
| Highlight Group | Description |
|---|---|
NeominimapHintLine | |
NeominimapInfoLine | |
NeominimapWarnLine | |
NeominimapErrorLine | |
NeominimapHintSign | |
NeominimapInfoSign | |
NeominimapWarnSign | |
NeominimapErrorSign | |
NeominimapHintIcon | |
NeominimapInfoIcon | |
NeominimapWarnIcon | |
NeominimapErrorIcon |
| Highlight Group | Description |
|---|---|
NeominimapGitAddLine | |
NeominimapGitChangeLine | |
NeominimapGitDeleteLine | |
NeominimapGitAddSign | |
NeominimapGitChangeSign | |
NeominimapGitDeleteSign | |
NeominimapGitAddIcon | |
NeominimapGitChangeIcon | |
NeominimapGitDeleteIcon |
| Highlight Group | Description |
|---|---|
NeominimapMiniDiffAddLine | |
NeominimapMiniDiffChangeLine | |
NeominimapMiniDiffDeleteLine | |
NeominimapMiniDiffAddSign | |
NeominimapMiniDiffChangeSign | |
NeominimapMiniDiffDeleteSign | |
NeominimapMiniDiffAddIcon | |
NeominimapMiniDiffChangeIcon | |
NeominimapMiniDiffDeleteIcon |
| Highlight Group | Description |
|---|---|
NeominimapSearchLine | |
NeominimapSearchSign | |
NeominimapSearchIcon |
| Highlight Group | Description |
|---|---|
NeominimapMarkLine | |
NeominimapMarkSign | |
NeominimapMarkIcon |
| Namespace | Description |
|---|---|
neominimap_git | Git signs and highlights. |
neominimap_diagnostic | Diagnostic signs and highlights. |
neominimap_search | Search signs and highlights. |
neominimap_mark | Mark signs and highlights. |
neominimap_treesitter | Treesitter highlights. |
Thanks to gorbit99 for codewindow.nvim, by which this plugin was inspired. The map generation algorithm and TreeSitter integration algorithm are also learned from that project.
Special thanks to lewis6991 for creating the excellent gitsigns.nvim and satellite.nvim plugins. The Git integration in Neominimap was made possible by gitsigns.nvim, and the search and mark integrations are based on satellite.nvim's code.
292 followers Β· starred Jun 2026
751 followers Β· starred May 2026
29 followers Β· starred May 2026
33 followers Β· starred Feb 2025
An extensible and performant Neovim minimap plugin that helps you visualize code structure, diagnostics, git changes, and more at a glance.
Lua
377
825 commits
updated Apr 12, 2026
This plugin provides a visual representation of your code structure on the side of your windows, similar to the minimap found in many modern editors.
Criticisms are welcome.
The color scheme used for these screenshots is nord
With vim.pack:
vim.pack.add({
{ src = "https://github.com/Isrothy/neominimap.nvim" },
})
-- The following options are recommended when layout == "float"
vim.opt.wrap = false
vim.opt.sidescrolloff = 36 -- Set a large value
--- Put your configuration here
---@type Neominimap.UserConfig
vim.g.neominimap = {
auto_enable = true,
}
With Lazy:
---@module "neominimap.config.meta"
{
"Isrothy/neominimap.nvim",
version = "v3.x.x",
lazy = false, -- NOTE: NO NEED to Lazy load
-- Optional. You can also set your own keybindings
keys = {
-- Global Minimap Controls
{ "<leader>nm", "<cmd>Neominimap Toggle<cr>", desc = "Toggle global minimap" },
{ "<leader>no", "<cmd>Neominimap Enable<cr>", desc = "Enable global minimap" },
{ "<leader>nc", "<cmd>Neominimap Disable<cr>", desc = "Disable global minimap" },
{ "<leader>nr", "<cmd>Neominimap Refresh<cr>", desc = "Refresh global minimap" },
-- Window-Specific Minimap Controls
{ "<leader>nwt", "<cmd>Neominimap WinToggle<cr>", desc = "Toggle minimap for current window" },
{ "<leader>nwr", "<cmd>Neominimap WinRefresh<cr>", desc = "Refresh minimap for current window" },
{ "<leader>nwo", "<cmd>Neominimap WinEnable<cr>", desc = "Enable minimap for current window" },
{ "<leader>nwc", "<cmd>Neominimap WinDisable<cr>", desc = "Disable minimap for current window" },
-- Tab-Specific Minimap Controls
{ "<leader>ntt", "<cmd>Neominimap TabToggle<cr>", desc = "Toggle minimap for current tab" },
{ "<leader>ntr", "<cmd>Neominimap TabRefresh<cr>", desc = "Refresh minimap for current tab" },
{ "<leader>nto", "<cmd>Neominimap TabEnable<cr>", desc = "Enable minimap for current tab" },
{ "<leader>ntc", "<cmd>Neominimap TabDisable<cr>", desc = "Disable minimap for current tab" },
-- Buffer-Specific Minimap Controls
{ "<leader>nbt", "<cmd>Neominimap BufToggle<cr>", desc = "Toggle minimap for current buffer" },
{ "<leader>nbr", "<cmd>Neominimap BufRefresh<cr>", desc = "Refresh minimap for current buffer" },
{ "<leader>nbo", "<cmd>Neominimap BufEnable<cr>", desc = "Enable minimap for current buffer" },
{ "<leader>nbc", "<cmd>Neominimap BufDisable<cr>", desc = "Disable minimap for current buffer" },
---Focus Controls
{ "<leader>nf", "<cmd>Neominimap Focus<cr>", desc = "Focus on minimap" },
{ "<leader>nu", "<cmd>Neominimap Unfocus<cr>", desc = "Unfocus minimap" },
{ "<leader>ns", "<cmd>Neominimap ToggleFocus<cr>", desc = "Switch focus on minimap" },
},
init = function()
-- The following options are recommended when layout == "float"
vim.opt.wrap = false
vim.opt.sidescrolloff = 36 -- Set a large value
--- Put your configuration here
---@type Neominimap.UserConfig
vim.g.neominimap = {
auto_enable = true,
}
end,
}
---@enum Neominimap.Handler.Annotation
local AnnotationMode = {
Sign = "sign", -- Show braille signs in the sign column
Icon = "icon", -- Show icons in the sign column
Line = "line", -- Highlight the background of the line on the minimap
}
vim.g.neominimap = {
-- Enable the plugin by default
auto_enable = true, ---@type boolean
-- Log level
log_level = vim.log.levels.OFF, ---@type Neominimap.Log.Levels
-- Notification level
notification_level = vim.log.levels.INFO, ---@type Neominimap.Log.Levels
-- Path to the log file
log_path = vim.fn.stdpath("data") .. "/neominimap.log", ---@type string
-- Minimaps will not be created for buffers of these filetypes
---@type string[]
exclude_filetypes = {
"help",
"bigfile", -- For Snacks.nvim
},
-- Minimaps will not be created for buffers of these buftypes
---@type string[]
exclude_buftypes = {
"nofile",
"nowrite",
"quickfix",
"terminal",
"prompt",
},
-- When this function returns false, the minimap will not be created for this buffer.
---@type fun(bufnr: integer): boolean
buf_filter = function()
return true
end,
-- When this function returns false, the minimap will not be created for this window.
---@type fun(winid: integer): boolean
win_filter = function()
return true
end,
-- When this function returns false, the minimap will not be created for this tab.
---@type fun(tabid: integer): boolean
tab_filter = function()
return true
end,
-- How many columns a dot should span
x_multiplier = 4, ---@type integer
-- How many rows a dot should span
y_multiplier = 1, ---@type integer
---@alias Neominimap.Config.CurrentLinePosition "center" | "percent"
-- How the minimap places the current line vertically.
-- `"center"` -> pins the line to the viewport middle (window-relative).
-- `"percent"` -> maps line index / total lines to minimap height (file-relative).
-- Note: here "center" means the middle of the **minimap window**, not "center of the file".
current_line_position = "center", ---@type Neominimap.Config.CurrentLinePosition
buffer = {
-- When true, the minimap will be recreated when you delete the buffer.
-- When false, the minimap will be disabled for the current buffer when you delete the minimap buffer.
persist = true, ---@type boolean
},
---@alias Neominimap.Config.LayoutType "split" | "float"
--- Either `split` or `float`
--- When layout is set to `float`, minimaps will be created in floating windows attached to all suitable windows.
--- When layout is set to `split`, the minimap will be created in one split window per tab.
layout = "float", ---@type Neominimap.Config.LayoutType
--- Used when `layout` is set to `split`
split = {
minimap_width = 20, ---@type integer
-- Always fix the width of the split window
fix_width = false, ---@type boolean
---@alias Neominimap.Config.SplitDirection "left" | "right" | "topleft" | "botright" | "aboveleft" | "rightbelow"
direction = "right", ---@type Neominimap.Config.SplitDirection
--- Automatically close the split window when it is the last window.
close_if_last_window = false, ---@type boolean
--- When true, the split window will be recreated when you close it.
--- When false, the minimap will be disabled for the current tab when you close the minimap window.
persist = true, ---@type boolean
},
--- Used when `layout` is set to `float`
float = {
minimap_width = 20, ---@type integer
--- If set to nil, there is no maximum height restriction
--- @type integer
max_minimap_height = nil,
margin = {
right = 0, ---@type integer
top = 0, ---@type integer
bottom = 0, ---@type integer
},
z_index = 1, ---@type integer
--- Border style of the floating window.
--- Accepts all usual border style options (e.g., "single", "double")
--- @type string | string[] | [string, string][]
window_border = vim.fn.has("nvim-0.11") == 1 and vim.o.winborder or "single",
-- When true, the floating window will be recreated when you close it.
-- When false, the minimap will be disabled for the current tab when you close the minimap window.
persist = true, ---@type boolean
},
-- For performance, when text changes, the minimap is refreshed after a certain delay.
-- Set the delay in milliseconds
delay = 200, ---@type integer
-- Sync the cursor position with the minimap
sync_cursor = true, ---@type boolean
click = {
-- Enable mouse click on the minimap
enabled = false, ---@type boolean
-- Automatically switch focus to the minimap when clicked
auto_switch_focus = true, ---@type boolean
},
diagnostic = {
enabled = true, ---@type boolean
-- Allowed formats for the `severity` filter:
-- 1. A single severity level:
-- eg: severity = vim.diagnostic.severity.WARN
-- 2. A table with a "min" and/or "max" key:
-- eg: severity = { min = vim.diagnostic.severity.WARN, max = vim.diagnostic.severity.ERROR }
-- 3. A list-like table of severity values:
-- eg: severity = { vim.diagnostic.severity.WARN, vim.diagnostic.severity.ERROR }
---@see vim.diagnostic.severity
severity = nil, ---@type vim.diagnostic.SeverityFilter?
mode = "line", ---@type Neominimap.Handler.Annotation.Mode
priority = {
ERROR = 100, ---@type integer
WARN = 90, ---@type integer
INFO = 80, ---@type integer
HINT = 70, ---@type integer
},
icon = {
ERROR = "σ°
", ---@type string
WARN = "σ°ͺ ", ---@type string
INFO = "σ°Ά ", ---@type string
HINT = "ο ", ---@type string
},
},
git = {
enabled = true, ---@type boolean
mode = "sign", ---@type Neominimap.Handler.Annotation.Mode
priority = 6, ---@type integer
icon = {
add = "+ ", ---@type string
change = "~ ", ---@type string
delete = "- ", ---@type string
},
},
mini_diff = {
enabled = false, ---@type boolean
mode = "sign", ---@type Neominimap.Handler.Annotation.Mode
priority = 6, ---@type integer
icon = {
add = "+ ", ---@type string
change = "~ ", ---@type string
delete = "- ", ---@type string
},
},
search = {
enabled = false, ---@type boolean
mode = "line", ---@type Neominimap.Handler.Annotation.Mode
priority = 20, ---@type integer
icon = "σ°±½ ", ---@type string
},
treesitter = {
enabled = true, ---@type boolean
priority = 200, ---@type integer
},
mark = {
enabled = false, ---@type boolean
mode = "icon", ---@type Neominimap.Handler.Annotation.Mode
priority = 10, ---@type integer
key = "m", ---@type string -- Useless for neovim >= 0.12
show_builtins = false, ---@type boolean -- shows the builtin marks like [ ] < >
},
fold = {
-- Consider folds when rendering the minimap
enabled = true, ---@type boolean
},
--- Override the default window options
---@param opt vim.wo
---@param winid integer the window id of the source window, NOT the minimap window
winopt = function(opt, winid) end,
--- Override the default buffer options
---@param opt vim.bo
---@param bufnr integer the buffer id of the source buffer, NOT the minimap buffer
bufopt = function(opt, bufnr) end,
---@type Neominimap.Map.Handler[]
handlers = {},
}
{
winhighlight = table.concat({
"Normal:NeominimapBackground",
"FloatBorder:NeominimapBorder",
"CursorLine:NeominimapCursorLine",
"CursorLineNr:NeominimapCursorLineNr",
"CursorLineSign:NeominimapCursorLineSign",
"CursorLineFold:NeominimapCursorLineFold",
}, ","),
wrap = false,
foldcolumn = "0",
signcolumn = "auto",
number = false,
relativenumber = false,
scrolloff = config.current_line_position == "center" and 99999 or 0,
sidescrolloff = 0,
winblend = 0,
cursorline = true,
spell = false,
list = false,
fillchars = "eob: ",
winfixwidth = true,
}
{
buftype = "nofile",
filetype = "neominimap",
swapfile = false,
bufhidden = "hide",
undolevels = -1,
modifiable = false,
}
Global Commands:
Neominimap Enable
Neominimap Disable
Neominimap Toggle
Neominimap Refresh
Buffer Commands:
Neominimap BufEnable [buffer_list]
Neominimap BufDisable [buffer_list]
Neominimap BufToggle [buffer_list]
Neominimap BufRefresh [buffer_list]
Tab Commands:
Neominimap TabEnable [tab_list]
Neominimap TabDisable [tab_list]
Neominimap TabToggle [tab_list]
Neominimap TabRefresh [tab_list]
Window Commands:
Neominimap WinEnable [window_list]
Neominimap WinDisable [window_list]
Neominimap WinToggle [window_list]
Neominimap WinRefresh [window_list]
Focus Commands:
Neominimap Focus
Neominimap Unfocus
Neominimap ToggleFocus
To turn on the minimap globally:
:Neominimap on
To disable the minimap for the current buffer:
:Neominimap BufOff
To refresh the minimap for windows 3 and 4:
:Neominimap WinRefresh 3 4
[!NOTE] A minimap is shown if and only if
- Neominimap is enabled globally,
- Neominimap is enabled for the current buffer,
- Neominimap is enabled for the current tabpage, and
- Neominimap is enabled for the current window.
Global API
require('neominimap.api').enable()
require('neominimap.api').disable()
require('neominimap.api').toggle()
require('neominimap.api').refresh()
require('neominimap.api').enabled()
true if the minimap is enabled, false otherwiseBuffer API
require('neominimap.api').buf.enable(<bufnr>)
require('neominimap.api').buf.disable(<bufnr>)
require('neominimap.api').buf.toggle(<bufnr>)
require('neominimap.api').buf.refresh(<bufnr>)
require('neominimap').buf.enabled(bufnr)
true if the minimap is enabled, false otherwiseTab API
require('neominimap.api').tab.enable(<tabid>)
require('neominimap.api').tab.disable(<tabid>)
require('neominimap.api').tab.toggle(<tabid>)
require('neominimap.api').tab.refresh(<tabid>)
require('neominimap').tab.enabled(tabid)
true if the minimap is enabled, false otherwiseWindow API
require('neominimap.api').win.enable(<winid>)
require('neominimap.api').win.disable(<winid>)
require('neominimap.api').win.toggle(<winid>)
require('neominimap.api').win.refresh(<winid>)
require('neominimap').win.enabled(winid)
true if the minimap is enabled, false otherwiseFocus Control
require('neominimap.api').focus.enable()
require('neominimap.api').focus.disable()
require('neominimap.api').focus.toggle()
The neominimap API has been updated to provide a more intuitive and flexible interface. The old API is now deprecated and will eventually be removed. This guide will help you transition to the new neominimap.api.
| Old Function | New Function |
|---|---|
require('neominimap').on | require('neominimap.api').enable |
require('neominimap').off | require('neominimap.api').disable |
require('neominimap').toggle | require('neominimap.api').toggle |
require('neominimap').refresh | require('neominimap.api').refresh |
require('neominimap').enabled | require('neominimap.api').enabled |
require('neominimap').bufOn | require('neominimap.api').buf.enable |
require('neominimap').bufOff | require('neominimap.api').buf.disable |
require('neominimap').bufToggle | require('neominimap.api').buf.toggle |
require('neominimap').bufRefresh | require('neominimap.api').buf.refresh |
require('neominimap').bufEnabled | require('neominimap.api').buf.enabled |
require('neominimap').tabOn | require('neominimap.api').tab.disable |
require('neominimap').tabOff | require('neominimap.api').tab.disable |
require('neominimap').tabToggle | require('neominimap.api').tab.toggle |
require('neominimap').tabRefresh | require('neominimap.api').tab.refresh |
require('neominimap').tabEnabled | require('neominimap.api').tab.enabled |
require('neominimap').winOn | require('neominimap.api').win.enable |
require('neominimap').winOff | require('neominimap.api').win.disable |
require('neominimap').winToggle | require('neominimap.api').win.toggle |
require('neominimap').winEnabled | require('neominimap.api').win.enabled |
require('neominimap').winRefresh | require('neominimap.api').win.refresh |
require('neominimap').focus | require('neominimap.api').focus.enable |
require('neominimap').unfocus | require('neominimap.api').focus.disable |
require('neominimap').toggleFocus | require('neominimap.api').focus.toggle |
| Aspect | Old API (neominimap).doSomeThing | New API (neominimap.api).do_some_thing() |
|---|---|---|
| Input Type | Expects a list of integers. | Accepts nil, a single integer, or a list of integers. An empty list does nothing. |
| Default Behavior | Automatically defaults to the current buffer/tab/window if the input list is empty. | Explicitly requires omitted input to default to the current buffer/tab/window. |
| Design Philosophy | A wrapper for Vim commands, with implicit behaviors. | Independent of Vim commands. |
{}) defaulted to the current buffer, tab, or window.nil or omit the argument.Here is an example:
-- Old API
require("neominimap").bufOn({}) -- Defaults to current buffer
-- New API
require("neominimap.api").buf.enable() -- Explicitly defaults to current buffer
require("neominimap.api").buf.enable({}) -- Does nothing
A handler is defined as a Lua table with the following fields:
name (string): A unique identifier for your handler (e.g., "my_todo_handler").mode ("sign" | "icon" | "line"): Determines how annotations are
displayed on the minimap:
"sign": Shows small braille characters in the sign column."icon": Shows a single character/icon (potentially from an icon font) in
the sign column."line": Highlights the background of the corresponding line(s) on the
minimap.namespace (integer): A Neovim namespace ID used internally by Neovim
to manage virtual text or signs. This should be created using
vim.api.nvim_create_namespace.autocmds ({event: string|string[], opts?: table}[]): A list of
autocommand specifications. Whenever one of these autocommands fires, the
handler will be triggered to update the minimap for the relevant buffer(s).
The opts table can contain standard autocommand options like pattern,
desc, and importantly, either callback or get_buffers.
opts.callback is defined (fun(apply: fun(bufnr:integer), args: any)),
it receives a function apply(bufnr) to manually trigger the handler for a
specific buffer and the autocommand arguments. You are responsible for
calling apply(bufnr) for the buffer(s) you want to update.opts.callback is not defined, you must provide opts.get_buffers
(fun(data: vim.api.keyset.create_autocmd.callback_args): integer[] | integer). This function receives the autocommand arguments and must return
the buffer number(s) that the handler should be applied to.init (fun()): A function called once when the handler is registered.get_annotations (fun(bufnr: integer): Neominimap.Map.Handler.Annotation[]):
This is the core logic of your handler. It takes a buffer number (bufnr) as
input, and returns an array of Neominimap.Map.Handler.Annotation objects.Each object returned by get_annotations must conform to the
Neominimap.Map.Handler.Annotation structure:
lnum (integer): The starting line number (1-based) in the main buffer
that this annotation refers to.end_lnum (integer): The ending line number (1-based). For single-line
annotations, this is the same as lnum.id (integer): An id for a specific kind of annotation. For example,
all git add should have the same id but git add and git change have
different ids. This is used to group annotations together like vertical
braille dots.priority (integer): Determines display order when annotations overlap.icon? (string, optional): A single character or icon string to display
if the handler's mode is "icon".highlight (string): The name of a Neovim highlight group.See the wiki page for examples.
This plugin provides statusline components that integrate with various statusline plugins like Lualine.
The plugin offers the following customizable components for your statusline:
Here's an example of how you can customize the Lualine statusline using neominimap components:
local neominimap = require("neominimap.statusline")
local minimap_extension = {
sections = {
lualine_c = {
neominimap.fullname,
},
lualine_z = {
neominimap.position,
"progress",
},
},
filetypes = { "neominimap" },
}
require("lualine").setup({ extensions = { minimap_extension } })
Alternatively, you can use the default settings provided by the plugin:
local minimap_extension = require("neominimap.statusline").lualine_default
require("lualine").setup({ extensions = { minimap_extension } })
The default Lualine extension provided by the plugin is structured as follows:
{
sections = {
winbar = {},
lualine_a = {
M.plugin_name,
},
lualine_c = {
M.shortname,
},
lualine_z = {
M.position,
"progress",
},
},
filetypes = { "neominimap" },
}
For every file opened, the plugin generates a corresponding minimap buffer.
When a buffer is displayed in a window, the minimap buffer is automatically opened side by side with the main window.
This approach minimizes unnecessary rendering when
First, the plugin retrieves all Treesitter nodes in the buffer.
For each codepoint in the minimap, the plugin calculates which highlight occurs most frequently and displays it. If multiple highlights occur the same number of times, all of them are displayed.
Note that the plugin considers which highlights are applied, rather than which highlights are shown. Specifically, when many highlights are applied to a codepoint, it is possible that only some of them are visible. However, all applied highlights are considered in the calculation. As a result, unshown highlights may be displayed in the minimap, leading to potential inconsistencies between the highlights in the minimap and those in the buffer.
When a buffer is exceptionally large, calculating and setting up the minimap can take a significant amount of time, potentially blocking the UI. To address this, the plugin employs cooperative scheduling, as Lua operates in a single-threaded environment.
Most CPU-intensive tasks are executed within coroutines, which periodically yield control back to the Neovim event loop. This allows the event loop to decide when to resume the coroutine. By releasing CPU resources intermittently, the plugin ensures that the UI remains responsive and unblocked during these operations.
Checkout the wiki page for more details. wiki
| Highlight Group | Description |
|---|---|
NeominimapBackground | Background color for the minimap. |
NeominimapBorder | Border highlight for the minimap window. |
NeominimapCursorLine | Highlight for the cursor line in minimaps. |
NeominimapCursorLineNr | To replace CursorLineNr in minimaps. |
NeominimapCursorLineSign | To replace CursorLineSign in minimaps. |
NeominimapCursorLineFold | To replace CursorLineFold in minimaps. |
| Highlight Group | Description |
|---|---|
NeominimapHintLine | |
NeominimapInfoLine | |
NeominimapWarnLine | |
NeominimapErrorLine | |
NeominimapHintSign | |
NeominimapInfoSign | |
NeominimapWarnSign | |
NeominimapErrorSign | |
NeominimapHintIcon | |
NeominimapInfoIcon | |
NeominimapWarnIcon | |
NeominimapErrorIcon |
| Highlight Group | Description |
|---|---|
NeominimapGitAddLine | |
NeominimapGitChangeLine | |
NeominimapGitDeleteLine | |
NeominimapGitAddSign | |
NeominimapGitChangeSign | |
NeominimapGitDeleteSign | |
NeominimapGitAddIcon | |
NeominimapGitChangeIcon | |
NeominimapGitDeleteIcon |
| Highlight Group | Description |
|---|---|
NeominimapMiniDiffAddLine | |
NeominimapMiniDiffChangeLine | |
NeominimapMiniDiffDeleteLine | |
NeominimapMiniDiffAddSign | |
NeominimapMiniDiffChangeSign | |
NeominimapMiniDiffDeleteSign | |
NeominimapMiniDiffAddIcon | |
NeominimapMiniDiffChangeIcon | |
NeominimapMiniDiffDeleteIcon |
| Highlight Group | Description |
|---|---|
NeominimapSearchLine | |
NeominimapSearchSign | |
NeominimapSearchIcon |
| Highlight Group | Description |
|---|---|
NeominimapMarkLine | |
NeominimapMarkSign | |
NeominimapMarkIcon |
| Namespace | Description |
|---|---|
neominimap_git | Git signs and highlights. |
neominimap_diagnostic | Diagnostic signs and highlights. |
neominimap_search | Search signs and highlights. |
neominimap_mark | Mark signs and highlights. |
neominimap_treesitter | Treesitter highlights. |
Thanks to gorbit99 for codewindow.nvim, by which this plugin was inspired. The map generation algorithm and TreeSitter integration algorithm are also learned from that project.
Special thanks to lewis6991 for creating the excellent gitsigns.nvim and satellite.nvim plugins. The Git integration in Neominimap was made possible by gitsigns.nvim, and the search and mark integrations are based on satellite.nvim's code.
292 followers Β· starred Jun 2026
751 followers Β· starred May 2026
29 followers Β· starred May 2026
33 followers Β· starred Feb 2025