Skip to content

emacsmirror/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, 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

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

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Emacs Lisp 100.0%