Flash-style navigation for Emacs — jump to any location with search labels
Emacs Lisp
106
52 commits
updated Jul 11, 2026
* flash
[[https://melpa.org/#/flash][file:https://melpa.org/packages/flash-badge.svg]]
=flash= lets you navigate your code with search labels, enhanced character motions, and Treesitter integration.
Inspired by [[https://github.com/folke/flash.nvim][flash.nvim]] for Neovim.
[[file:demo/demo.gif]]
** Why flash?
Unlike [[https://github.com/abo-abo/avy][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=).
- *Remote Evil actions*: select a distant target, yank or delete there, then return to where you started.
** Requirements
- Emacs >= *27.1*
- Emacs >= *29.1* for Treesitter support
- Optional: [[https://github.com/emacs-evil/evil][evil-mode]] for Vim-style keybindings
** Installation
*** MELPA
=flash= is available on [[https://melpa.org/#/flash][MELPA]].
#+begin_src emacs-lisp
;; 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-action flash-action-undo
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))
#+end_src
Or install interactively: =M-x package-install RET flash RET=.
*** straight.el
#+begin_src emacs-lisp
(straight-use-package
'(flash :type git :host github :repo "Prgebish/flash"))
#+end_src
*** elpaca
#+begin_src emacs-lisp
(elpaca (flash :host github :repo "Prgebish/flash"))
#+end_src
** 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:
#+begin_src emacs-lisp
(setq flash-char-jump-labels t)
#+end_src
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
#+begin_src emacs-lisp
M-x flash-treesitter
#+end_src
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.
*** Remote Yank/Delete
Requires evil-mode. =flash-evil-setup= binds =gS= in normal state only:
1. Press =gS= and type a search pattern.
2. Press the label at the remote location.
3. Enter a normal Evil yank/delete command.
For example, =gS → price → a → yiw= copies the word at label =a=, while
=gS → debug → s → dd= deletes the line at label =s=. After the operation,
Flash restores the original window, point, mark, and Evil state.
The action starts at the first character of the selected match. The rest of
the range comes from native Evil grammar, so commands such as =yy=, =dd=,
=yiw=, =di(=, =y$=, =d2w=, =2dw=, and register prefixes such as ="ayy= work
normally. Direct =Y=, =D=, =x=, and =X= are supported too.
Only yank and delete operations are accepted. There is no =ym=/=dm= search
match object, no editing/paste actions, and no Embark integration. =gS= is not
bound in visual or operator-pending state; the existing =gs= remains the Flash
motion for compositions such as =d gs=, =y gs=, and =c gs=.
Undo history belongs to the changed buffer. Use =M-x flash-action-undo= to undo
the last remote deletion without visiting its buffer. The command refuses if
that buffer has been edited since the remote action.
** Configuration
*** Basic Options
| Variable | Default | Description |
|----------------------------+--------------------------------+----------------------------------------------------|
| ~flash-labels~ | ~"asdfjkl;ghqwertyuiopzxcvbnm"~ | Characters used for jump labels |
| ~flash-label-uppercase~ | ~nil~ | Also use uppercase labels, doubling the pool (A-Z) |
| ~flash-multi-char-labels~ | ~nil~ | Use multi-character labels (aa, as, ad...) |
| ~flash-multi-window~ | ~t~ | Search across all visible windows |
| ~flash-autojump~ | ~nil~ | Jump immediately when only one match remains |
| ~flash-backdrop~ | ~t~ | Dim non-matching text |
| ~flash-case-fold~ | ~t~ | Ignore case when searching |
| ~flash-rainbow~ | ~nil~ | Color labels with a rainbow palette |
| ~flash-rainbow-shade~ | ~2~ | Rainbow brightness 1-9 (pastel to dark) |
| ~flash-highlight-matches~ | ~t~ | Highlight matched text |
| ~flash-label-position~ | ~'overlay~ | Where to place labels: overlay, pre-overlay, after, before, eol |
| ~flash-jump-position~ | ~'start~ | Cursor position after jump: start or end of match |
| ~flash-jumplist~ | ~t~ | Push position to mark ring before jumping |
| ~flash-nohlsearch~ | ~nil~ | Clear search highlighting after jump |
| ~flash-search-history~ | ~nil~ | Add search pattern to isearch history |
| ~flash-min-pattern-length~ | ~0~ | Minimum pattern length before labels appear |
| ~flash-search-folds~ | ~nil~ | Search inside folded (invisible) regions |
| ~flash-after-jump-hook~ | ~nil~ | Hook after standalone, autojump, RET, and isearch label jumps |
**** 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
| Variable | Default | Description |
|------------------------------+---------+--------------------------------------------------------------------------------------|
| ~flash-char-jump-labels~ | ~nil~ | Show labels on all f/t/F/T matches |
| ~flash-char-multi-line~ | ~nil~ | Search beyond current line |
| ~flash-char-reserved-labels~ | ~""~ | Characters excluded from labels (e.g., ~"aisoAISO;,cCxr"~ to keep evil editing keys) |
*** Search Integration Options
| Variable | Default | Description |
|----------------------------+---------+----------------------------------------------|
| ~flash-isearch-enabled~ | ~t~ | Show labels during search |
| ~flash-isearch-toggle-key~ | ~"C-;"~ | Key to toggle labels on/off during search |
| ~flash-isearch-trigger~ | ~nil~ | Require a trigger character before label jump |
| ~flash-isearch-update-delay~ | ~0.05~ | Debounce delay for isearch updates (seconds) |
| ~flash-isearch-label-limit~ | ~'single-char~ | Max matches rendered during isearch: ~single-char~, ~full~, or integer |
*** Treesitter Options
| Variable | Default | Description |
|------------------------------+---------+------------------------------------|
| ~flash-treesitter-max-depth~ | ~10~ | Maximum depth of parent nodes shown |
*** Example Configuration
#+begin_src emacs-lisp
(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
#+end_src
** Evil Integration
*** Quick Setup
=flash-evil-setup= configures all evil keybindings in one call:
#+begin_src emacs-lisp
(require 'flash-evil)
(flash-evil-setup t) ; t = also set up f/t/F/T char motions
#+end_src
This binds =gs= to ~flash-evil-jump~ in normal, visual, motion, and operator
states, and =gS= to ~flash-action~ in normal state only. With the optional
argument, it also replaces =f=, =t=, =F=, =T= with flash-enhanced versions.
*** Manual Setup
If you prefer different keybindings:
#+begin_src emacs-lisp
(require 'flash-evil)
(evil-global-set-key 'normal (kbd "s") #'flash-evil-jump)
(evil-global-set-key 'visual (kbd "s") #'flash-evil-jump)
(evil-global-set-key 'normal (kbd "g S") #'flash-action)
;; Char motions
(flash-char-setup-evil-keys)
#+end_src
*** 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
| Face | Description |
|-----------------+------------------------|
| ~flash-label~ | Jump label |
| ~flash-match~ | Search match highlight |
| ~flash-backdrop~ | Backdrop (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~:
| Shade | Background | Foreground | Style |
|-------+------------+------------+-----------------|
| 1-2 | light | dark (900) | pastel (default) |
| 3-4 | medium | dark (900) | medium |
| 5 | saturated | dark (950) | flash.nvim default |
| 6-9 | dark | light (50) | dark / inverted |
*** Customizing Faces
#+begin_src emacs-lisp
;; 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)
#+end_src
** Alternatives
- [[https://github.com/abo-abo/avy][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.
- [[https://github.com/winterTTr/ace-jump-mode][ace-jump-mode]] --- quick cursor movement (predecessor to avy).
** Credits
Inspired by [[https://github.com/folke/flash.nvim][flash.nvim]] by folke.
** Support
If you find =flash= useful, consider giving it a [[https://github.com/Prgebish/flash][star on GitHub]] --- it helps others discover the project.
** License
MIT
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Emacs Lisp
100.0%
Flash-style navigation for Emacs — jump to any location with search labels
Emacs Lisp
106
52 commits
updated Jul 11, 2026
* flash
[[https://melpa.org/#/flash][file:https://melpa.org/packages/flash-badge.svg]]
=flash= lets you navigate your code with search labels, enhanced character motions, and Treesitter integration.
Inspired by [[https://github.com/folke/flash.nvim][flash.nvim]] for Neovim.
[[file:demo/demo.gif]]
** Why flash?
Unlike [[https://github.com/abo-abo/avy][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=).
- *Remote Evil actions*: select a distant target, yank or delete there, then return to where you started.
** Requirements
- Emacs >= *27.1*
- Emacs >= *29.1* for Treesitter support
- Optional: [[https://github.com/emacs-evil/evil][evil-mode]] for Vim-style keybindings
** Installation
*** MELPA
=flash= is available on [[https://melpa.org/#/flash][MELPA]].
#+begin_src emacs-lisp
;; 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-action flash-action-undo
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))
#+end_src
Or install interactively: =M-x package-install RET flash RET=.
*** straight.el
#+begin_src emacs-lisp
(straight-use-package
'(flash :type git :host github :repo "Prgebish/flash"))
#+end_src
*** elpaca
#+begin_src emacs-lisp
(elpaca (flash :host github :repo "Prgebish/flash"))
#+end_src
** 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:
#+begin_src emacs-lisp
(setq flash-char-jump-labels t)
#+end_src
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
#+begin_src emacs-lisp
M-x flash-treesitter
#+end_src
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.
*** Remote Yank/Delete
Requires evil-mode. =flash-evil-setup= binds =gS= in normal state only:
1. Press =gS= and type a search pattern.
2. Press the label at the remote location.
3. Enter a normal Evil yank/delete command.
For example, =gS → price → a → yiw= copies the word at label =a=, while
=gS → debug → s → dd= deletes the line at label =s=. After the operation,
Flash restores the original window, point, mark, and Evil state.
The action starts at the first character of the selected match. The rest of
the range comes from native Evil grammar, so commands such as =yy=, =dd=,
=yiw=, =di(=, =y$=, =d2w=, =2dw=, and register prefixes such as ="ayy= work
normally. Direct =Y=, =D=, =x=, and =X= are supported too.
Only yank and delete operations are accepted. There is no =ym=/=dm= search
match object, no editing/paste actions, and no Embark integration. =gS= is not
bound in visual or operator-pending state; the existing =gs= remains the Flash
motion for compositions such as =d gs=, =y gs=, and =c gs=.
Undo history belongs to the changed buffer. Use =M-x flash-action-undo= to undo
the last remote deletion without visiting its buffer. The command refuses if
that buffer has been edited since the remote action.
** Configuration
*** Basic Options
| Variable | Default | Description |
|----------------------------+--------------------------------+----------------------------------------------------|
| ~flash-labels~ | ~"asdfjkl;ghqwertyuiopzxcvbnm"~ | Characters used for jump labels |
| ~flash-label-uppercase~ | ~nil~ | Also use uppercase labels, doubling the pool (A-Z) |
| ~flash-multi-char-labels~ | ~nil~ | Use multi-character labels (aa, as, ad...) |
| ~flash-multi-window~ | ~t~ | Search across all visible windows |
| ~flash-autojump~ | ~nil~ | Jump immediately when only one match remains |
| ~flash-backdrop~ | ~t~ | Dim non-matching text |
| ~flash-case-fold~ | ~t~ | Ignore case when searching |
| ~flash-rainbow~ | ~nil~ | Color labels with a rainbow palette |
| ~flash-rainbow-shade~ | ~2~ | Rainbow brightness 1-9 (pastel to dark) |
| ~flash-highlight-matches~ | ~t~ | Highlight matched text |
| ~flash-label-position~ | ~'overlay~ | Where to place labels: overlay, pre-overlay, after, before, eol |
| ~flash-jump-position~ | ~'start~ | Cursor position after jump: start or end of match |
| ~flash-jumplist~ | ~t~ | Push position to mark ring before jumping |
| ~flash-nohlsearch~ | ~nil~ | Clear search highlighting after jump |
| ~flash-search-history~ | ~nil~ | Add search pattern to isearch history |
| ~flash-min-pattern-length~ | ~0~ | Minimum pattern length before labels appear |
| ~flash-search-folds~ | ~nil~ | Search inside folded (invisible) regions |
| ~flash-after-jump-hook~ | ~nil~ | Hook after standalone, autojump, RET, and isearch label jumps |
**** 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
| Variable | Default | Description |
|------------------------------+---------+--------------------------------------------------------------------------------------|
| ~flash-char-jump-labels~ | ~nil~ | Show labels on all f/t/F/T matches |
| ~flash-char-multi-line~ | ~nil~ | Search beyond current line |
| ~flash-char-reserved-labels~ | ~""~ | Characters excluded from labels (e.g., ~"aisoAISO;,cCxr"~ to keep evil editing keys) |
*** Search Integration Options
| Variable | Default | Description |
|----------------------------+---------+----------------------------------------------|
| ~flash-isearch-enabled~ | ~t~ | Show labels during search |
| ~flash-isearch-toggle-key~ | ~"C-;"~ | Key to toggle labels on/off during search |
| ~flash-isearch-trigger~ | ~nil~ | Require a trigger character before label jump |
| ~flash-isearch-update-delay~ | ~0.05~ | Debounce delay for isearch updates (seconds) |
| ~flash-isearch-label-limit~ | ~'single-char~ | Max matches rendered during isearch: ~single-char~, ~full~, or integer |
*** Treesitter Options
| Variable | Default | Description |
|------------------------------+---------+------------------------------------|
| ~flash-treesitter-max-depth~ | ~10~ | Maximum depth of parent nodes shown |
*** Example Configuration
#+begin_src emacs-lisp
(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
#+end_src
** Evil Integration
*** Quick Setup
=flash-evil-setup= configures all evil keybindings in one call:
#+begin_src emacs-lisp
(require 'flash-evil)
(flash-evil-setup t) ; t = also set up f/t/F/T char motions
#+end_src
This binds =gs= to ~flash-evil-jump~ in normal, visual, motion, and operator
states, and =gS= to ~flash-action~ in normal state only. With the optional
argument, it also replaces =f=, =t=, =F=, =T= with flash-enhanced versions.
*** Manual Setup
If you prefer different keybindings:
#+begin_src emacs-lisp
(require 'flash-evil)
(evil-global-set-key 'normal (kbd "s") #'flash-evil-jump)
(evil-global-set-key 'visual (kbd "s") #'flash-evil-jump)
(evil-global-set-key 'normal (kbd "g S") #'flash-action)
;; Char motions
(flash-char-setup-evil-keys)
#+end_src
*** 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
| Face | Description |
|-----------------+------------------------|
| ~flash-label~ | Jump label |
| ~flash-match~ | Search match highlight |
| ~flash-backdrop~ | Backdrop (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~:
| Shade | Background | Foreground | Style |
|-------+------------+------------+-----------------|
| 1-2 | light | dark (900) | pastel (default) |
| 3-4 | medium | dark (900) | medium |
| 5 | saturated | dark (950) | flash.nvim default |
| 6-9 | dark | light (50) | dark / inverted |
*** Customizing Faces
#+begin_src emacs-lisp
;; 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)
#+end_src
** Alternatives
- [[https://github.com/abo-abo/avy][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.
- [[https://github.com/winterTTr/ace-jump-mode][ace-jump-mode]] --- quick cursor movement (predecessor to avy).
** Credits
Inspired by [[https://github.com/folke/flash.nvim][flash.nvim]] by folke.
** Support
If you find =flash= useful, consider giving it a [[https://github.com/Prgebish/flash][star on GitHub]] --- it helps others discover the project.
** License
MIT
Not written in Markdown, so it's shown here as plain text — view it formatted on GitHub.
Emacs Lisp
100.0%