Skip to content
/ flash Public

Flash-style navigation for Emacs — jump to any location with search labels

License

Notifications You must be signed in to change notification settings

Prgebish/flash

Repository files navigation

flash

https://melpa.org/packages/flash-badge.svg

flash lets you navigate your code with search labels, enhanced character motions, and Treesitter integration.

Inspired by flash.nvim for Neovim.

demo/demo.gif

Why flash?

Unlike avy, flash uses incremental search: you type as many characters as you want to narrow down matches, and labels appear alongside the results. Labels are assigned intelligently — characters that would continue the search pattern are never used as labels, so there is no ambiguity between searching and jumping.

Features

  • Search Integration: labels appear during regular C-s, /, ? search. Press a label character to jump instantly.
  • Incremental input: type as many characters as you need before using a label. No fixed-length input.
  • Enhanced f, t, F, T motions with multi-match labels.
  • Treesitter Integration: select any parent node of the syntax tree at point with a single keystroke.
  • Standalone Jump Mode (core feature): type a character, then press a label to jump where you need.
  • Multi-window jumping across all visible windows.
  • Evil integration: works as a proper evil motion (composable with operators like d, y, c).

Requirements

  • Emacs >= 27.1
  • Emacs >= 29.1 for Treesitter support
  • Optional: evil-mode for Vim-style keybindings

Installation

MELPA

flash is available on MELPA.

;; Add MELPA to package-archives if you haven't already:
;; (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

(use-package flash
  :commands (flash-jump flash-jump-continue
             flash-treesitter)
  :bind ("s-j" . flash-jump)
  :custom
  (flash-multi-window t)
  :init
  ;; Evil integration (simple setup)
  (with-eval-after-load 'evil
    (require 'flash-evil)
    (flash-evil-setup t))  ; t = also set up f/t/F/T char motions
  :config
  ;; Search integration (labels during C-s, /, ?)
  (require 'flash-isearch)
  (flash-isearch-mode 1))

Or install interactively: M-x package-install RET flash RET.

straight.el

(straight-use-package
 '(flash :type git :host github :repo "Prgebish/flash"))

elpaca

(elpaca (flash :host github :repo "Prgebish/flash"))

Usage

Standalone Jump

M-x flash-jump starts an interactive search. Type characters to narrow matches, then press a label to jump.

With evil-mode: press gs (or s if you bind it manually). I personally find C-/ convenient — it is easy to reach and does not shadow any useful evil bindings.

M-x flash-jump-continue resumes the previous search with the same pattern. Useful when you want to jump again to another match of the same text.

Search Integration

flash-isearch-mode adds labels to your regular incremental search. It works with C-s (Emacs isearch), /, ? (evil-ex-search).

When enabled:

  • Start a search as usual (C-s or /).
  • As you type, labels appear next to each match.
  • Press a label character to jump directly to that match.
  • Press C-; to toggle labels on or off during a search.

Character Motions (f/t/F/T)

Requires evil-mode. Set up keybindings with flash-evil-setup (pass t for char motions) or flash-char-setup-evil-keys manually. Then enable labels:

(setq flash-char-jump-labels t)

Without flash-char-jump-labels, f / t just jump to the first match (like normal evil motions). With it enabled, all matches get labels, so you can reach any match with a single keystroke instead of repeating ;.

  • f{char} / F{char} — jump to character forward / backward.
  • t{char} / T{char} — jump to just before character forward / backward.
  • ; — repeat last motion.
  • , — repeat last motion in reverse (if , is your localleader, rebind to e.g. \).

Treesitter

M-x flash-treesitter

Shows labels for all parent nodes of the Treesitter syntax tree at point, from the innermost to the outermost. Each label corresponds to a progressively larger region of code (e.g., identifier, expression, statement, function body, function definition). Press a label to select that entire node. With evil-mode, the selection enters visual state automatically.

This is useful for quickly selecting or operating on a surrounding code structure — for example, selecting an entire function, an if-block, or an argument list.

Configuration

Basic Options

VariableDefaultDescription
flash-labels"asdfjkl;ghqwertyuiopzxcvbnm"Characters used for jump labels
flash-label-uppercasenilAlso use uppercase labels, doubling the pool (A-Z)
flash-multi-char-labelsnilUse multi-character labels (aa, as, ad…)
flash-multi-windowtSearch across all visible windows
flash-autojumpnilJump immediately when only one match remains
flash-backdroptDim non-matching text
flash-case-foldtIgnore case when searching
flash-rainbownilColor labels with a rainbow palette
flash-rainbow-shade2Rainbow brightness 1-9 (pastel to dark)
flash-highlight-matchestHighlight matched text
flash-label-position'overlayWhere to place labels: overlay, pre-overlay, after, before, eol
flash-jump-position'startCursor position after jump: start or end of match
flash-jumplisttPush position to mark ring before jumping
flash-nohlsearchnilClear search highlighting after jump
flash-search-historynilAdd search pattern to isearch history
flash-min-pattern-length0Minimum pattern length before labels appear

Label Positions

  • overlay (default) — label replaces the first character of the match.
  • pre-overlay — label replaces the character before the match. The match text stays fully readable and there is no text shift. Falls back to overlay when the match is at the beginning of a line or buffer.
  • after — label is inserted after the match (flash.nvim default).
  • before — label is inserted before the match.
  • eol — label appears at the end of the line.

Char Motion Options

VariableDefaultDescription
flash-char-jump-labelsnilShow labels on all f/t/F/T matches
flash-char-multi-linenilSearch beyond current line
flash-char-reserved-labels""Characters excluded from labels (e.g., "aisoAISO;,cCxr" to keep evil editing keys)

Search Integration Options

VariableDefaultDescription
flash-isearch-enabledtShow labels during search
flash-isearch-toggle-key"C-;"Key to toggle labels on/off during search
flash-isearch-triggernilRequire a trigger character before label jump

Treesitter Options

VariableDefaultDescription
flash-treesitter-max-depth10Maximum depth of parent nodes shown

Example Configuration

(use-package flash
  :custom
  (flash-labels "asdfjkl;ghqwertyuiopzxcvbnm")
  (flash-label-uppercase t)     ; double available labels (a-z + A-Z)
  (flash-multi-window t)
  (flash-autojump t)            ; auto-jump when single match
  (flash-backdrop nil)          ; no dimming
  (flash-rainbow t)             ; colorful labels
  (flash-rainbow-shade 2)       ; 1-9: pastel to dark
  (flash-highlight-matches t)
  (flash-label-position 'overlay)
  (flash-char-jump-labels t)    ; labels on f/t/F/T matches
  (flash-nohlsearch t)          ; clear highlight after jump
  (flash-search-history t))     ; save patterns to isearch history

Evil Integration

Quick Setup

flash-evil-setup configures all evil keybindings in one call:

(require 'flash-evil)
(flash-evil-setup t)  ; t = also set up f/t/F/T char motions

This binds gs to flash-evil-jump in normal, visual, motion, and operator states. With the optional argument, it also replaces f, t, F, T with flash-enhanced versions.

Manual Setup

If you prefer different keybindings:

(require 'flash-evil)
(evil-global-set-key 'normal (kbd "s") #'flash-evil-jump)
(evil-global-set-key 'visual (kbd "s") #'flash-evil-jump)
;; Char motions
(flash-char-setup-evil-keys)

Operator Support

flash-evil-jump is a proper evil motion, so it composes with operators:

  • d gs {label} — delete to target
  • y gs {label} — yank to target
  • v gs {label} — extend visual selection to target

Faces

FaceDescription
flash-labelJump label
flash-matchSearch match highlight
flash-backdropBackdrop (dimmed text)

Rainbow labels use dynamic colors from the Tailwind CSS palette (10 colors: red, amber, lime, green, teal, cyan, blue, violet, fuchsia, rose). The brightness is controlled by flash-rainbow-shade:

ShadeBackgroundForegroundStyle
1-2lightdark (900)pastel (default)
3-4mediumdark (900)medium
5saturateddark (950)flash.nvim default
6-9darklight (50)dark / inverted

Customizing Faces

;; Change label appearance
(set-face-attribute 'flash-label nil
                    :background "#ff0000"
                    :foreground "#ffffff"
                    :weight 'bold)

;; Change match highlight
(set-face-attribute 'flash-match nil
                    :underline nil
                    :background "#ffff00"
                    :foreground "#000000")

;; Rainbow: pastel labels
(setq flash-rainbow t
      flash-rainbow-shade 2)

;; Rainbow: dark labels with light text
(setq flash-rainbow-shade 7)

Alternatives

  • avy — jump to visible text using a char-based decision tree. Unlike flash, avy uses fixed-length input: you choose a target type (word, line, character), then press label keys. Flash lets you type an arbitrary search pattern first.
  • ace-jump-mode — quick cursor movement (predecessor to avy).

Credits

Inspired by flash.nvim by folke.

Support

If you find flash useful, consider giving it a star on GitHub — it helps others discover the project.

License

MIT

About

Flash-style navigation for Emacs — jump to any location with search labels

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published