Flash.nvim
Navigate your code with search labels, enhanced character motions and Treesitter integration
Install / Use
/learn @folke/Flash.nvimREADME
⚡flash.nvim
flash.nvim lets you navigate your code with search labels,
enhanced character motions, and Treesitter integration.
✨ Features
- 🔍 Search Integration: integrate flash.nvim with your regular
search using
/or?. Labels appear next to the matches, allowing you to quickly jump to any location. Labels are guaranteed not to exist as a continuation of the search pattern. - ⌨️ type as many characters as you want before using a jump label.
- ⚡ Enhanced
f,t,F,Tmotions - 🌳 Treesitter Integration: all parents of the Treesitter node under your cursor are highlighted with a label for quick selection of a specific Treesitter node.
- 🎯 Jump Mode: a standalone jumping mode similar to search
- 🔎 Search Modes:
exact,search(regex), andfuzzysearch modes - 🪟 Multi Window jumping
- 🌐 Remote Actions: perform motions in remote locations
- ⚫ dot-repeatable jumps
- 📡 highly extensible: check the examples
📋 Requirements
- Neovim >= 0.8.0 (needs to be built with LuaJIT)
📦 Installation
Install the plugin with your preferred package manager:
<!-- setup:start -->{
"folke/flash.nvim",
event = "VeryLazy",
---@type Flash.Config
opts = {},
keys = {
{ "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" },
{ "S", mode = { "n", "x", "o" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" },
{ "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" },
{ "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" },
{ "<c-s>", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" },
},
}
<!-- setup:end -->
⚠️ When creating the keymaps manually either use a lua function like
function() require("flash").jump() endas the rhs, or a string like<cmd>lua require("flash").jump()<cr>. DO NOT use:lua, since that will break dot-repeat
⚙️ Configuration
flash.nvim is highly configurable. Please refer to the default settings below.
<details><summary>Default Settings</summary> <!-- config:start -->{
-- labels = "abcdefghijklmnopqrstuvwxyz",
labels = "asdfghjklqwertyuiopzxcvbnm",
search = {
-- search/jump in all windows
multi_window = true,
-- search direction
forward = true,
-- when `false`, find only matches in the given direction
wrap = true,
---@type Flash.Pattern.Mode
-- Each mode will take ignorecase and smartcase into account.
-- * exact: exact match
-- * search: regular search
-- * fuzzy: fuzzy search
-- * fun(str): custom function that returns a pattern
-- For example, to only match at the beginning of a word:
-- mode = function(str)
-- return "\\<" .. str
-- end,
mode = "exact",
-- behave like `incsearch`
incremental = false,
-- Excluded filetypes and custom window filters
---@type (string|fun(win:window))[]
exclude = {
"notify",
"cmp_menu",
"noice",
"flash_prompt",
function(win)
-- exclude non-focusable windows
return not vim.api.nvim_win_get_config(win).focusable
end,
},
-- Optional trigger character that needs to be typed before
-- a jump label can be used. It's NOT recommended to set this,
-- unless you know what you're doing
trigger = "",
-- max pattern length. If the pattern length is equal to this
-- labels will no longer be skipped. When it exceeds this length
-- it will either end in a jump or terminate the search
max_length = false, ---@type number|false
},
jump = {
-- save location in the jumplist
jumplist = true,
-- jump position
pos = "start", ---@type "start" | "end" | "range"
-- add pattern to search history
history = false,
-- add pattern to search register
register = false,
-- clear highlight after jump
nohlsearch = false,
-- automatically jump when there is only one match
autojump = false,
-- You can force inclusive/exclusive jumps by setting the
-- `inclusive` option. By default it will be automatically
-- set based on the mode.
inclusive = nil, ---@type boolean?
-- jump position offset. Not used for range jumps.
-- 0: default
-- 1: when pos == "end" and pos < current position
offset = nil, ---@type number
},
label = {
-- allow uppercase labels
uppercase = true,
-- add any labels with the correct case here, that you want to exclude
exclude = "",
-- add a label for the first match in the current window.
-- you can always jump to the first match with `<CR>`
current = true,
-- show the label after the match
after = true, ---@type boolean|number[]
-- show the label before the match
before = false, ---@type boolean|number[]
-- position of the label extmark
style = "overlay", ---@type "eol" | "overlay" | "right_align" | "inline"
-- flash tries to re-use labels that were already assigned to a position,
-- when typing more characters. By default only lower-case labels are re-used.
reuse = "lowercase", ---@type "lowercase" | "all" | "none"
-- for the current window, label targets closer to the cursor first
distance = true,
-- minimum pattern length to show labels
-- Ignored for custom labelers.
min_pattern_length = 0,
-- Enable this to use rainbow colors to highlight labels
-- Can be useful for visualizing Treesitter ranges.
rainbow = {
enabled = false,
-- number between 1 and 9
shade = 5,
},
-- With `format`, you can change how the label is rendered.
-- Should return a list of `[text, highlight]` tuples.
---@class Flash.Format
---@field state Flash.State
---@field match Flash.Match
---@field hl_group string
---@field after boolean
---@type fun(opts:Flash.Format): string[][]
format = function(opts)
return { { opts.match.label, opts.hl_group } }
end,
},
highlight = {
-- show a backdrop with hl FlashBackdrop
backdrop = true,
-- Highlight the search matches
matches = true,
-- extmark priority
priority = 5000,
groups = {
match = "FlashMatch",
current = "FlashCurrent",
backdrop = "FlashBackdrop",
label = "FlashLabel",
},
},
-- action to perform when picking a label.
-- defaults to the jumping logic depending on the mode.
---@type fun(match:Flash.Match, state:Flash.State)|nil
action = nil,
-- initial pattern to use when opening flash
pattern = "",
-- When `true`, flash will try to continue the last search
continue = false,
-- Set config to a function to dynamically change the config
config = nil, ---@type fun(opts:Flash.Config)|nil
-- You can override the default options for a specific mode.
-- Use it with `require("flash").jump({mode = "forward"})`
---@type table<string, Flash.Config>
modes = {
-- options used when flash is activated through
-- a regular search with `/` or `?`
search = {
-- when `true`, flash will be activated during regular search by default.
-- You can always toggle when searching with `require("flash").toggle()`
enabled = false,
highlight = { backdrop = false },
jump = { history = true, register = true, nohlsearch = true },
search = {
-- `forward` will be automatically set to the search direction
-- `mode` is always set to `search`
-- `incremental` is set to `true` when `incsearch` is enabled
},
},
-- options used when flash is activated through
-- `f`, `F`, `t`, `T`, `;` and `,` motions
char = {
enabled = true,
-- dynamic configuration for ftFT motions
config = function(opts)
-- autohide flash when in operator-pending mode
opts.autohide = opts.autohide or (vim.fn.mode(true):find("no") and vim.v.operator == "y")
-- disable jump labels when not enabled, when using a count,
-- or when recording/executing registers
opts.jump_labels = opts.jump_labels
and vim.v.count == 0
and vim.fn.reg_executing() == ""
and vim.fn.reg_recording() == ""
-- Show jump labels only in operator-pending mode
-- opts.jump_labels = vim.v.count == 0 and vim.fn.mode(true):find("o")
end,
-- hide after jump when not using jump labels
autohide = false,
-- show jump labels
jump_labels = false,
-- set to `false` to use the current line only
multi_line = true,
-- When using jump labels, don't use these keys
-- This allows using those keys directly after the motion
label = { exclude = "hjkliardc" },
-- by default all keymaps are enabled, but you can disable some of them,
-- by removing them from the list.
-- If you rather use another key, you can map them
-- to something else, e.g., { [";"] = "L", [","] = H }
keys = { "f", "F", "t", "T", ";", "," },
Related Skills
node-connect
339.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
339.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.9kCommit, push, and open a PR
