Commit Graph
519 Commits
Author SHA1 Message Date
Junegunn Choi 3337be9d45 0.74.2
CodeQL / Analyze (go) (push) Canceled after 0s
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
2026-08-01 09:07:37 +09:00
Junegunn Choi b66153825f Update CHANGELOG
CodeQL / Analyze (go) (push) Canceled after 0s
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
2026-07-30 00:53:50 +09:00
Junegunn Choi 50e6c026ec Separate floating pane border label from pane title
--border-label of a tmux floating pane was stored in the pane title and
read back by pane-border-format as '#{pane_title}', so any program in the
pane could replace the border text by setting the title. On Zellij the
name was only set when the pane was created. Either way the built-in
label actions could not touch it, as fzf draws no border of its own
there.

- tmux: hold the label in pane-scoped @fzf-border-label. Set the option
  even without a label, so a later change-border-label has somewhere to
  write. Drop select-pane -T; the pane title is left to the user
- Zellij: run 'zellij action rename-pane' on label change. 'zellij run'
  has no option to set the environment of the new pane, so the command
  exports the target itself
- change-border-label and transform-border-label now update the native
  border, through the setter nativeLabelSetter picks by multiplexer
- The pane is named in a __FZF_INTERNAL_ variable that runProxy withholds
  from the environment replay, so the same name in the outer environment
  cannot redirect the update to another pane
2026-07-29 20:59:52 +09:00
Junegunn Choi f779e6a4df Add fast path for two-character patterns in FuzzyMatchV2
For two ASCII characters, rows 0 and 1 of the score matrix collapse to
scalar running state, so Phase 2 and Phase 3 fuse into one pass with no
score arrays. withPos stores the two rows for the backtrace. Up to 1.4x
on two-char queries, the most common multi-char length.

Verify both fast paths against the general algorithm with exhaustive
(every short string over a class-complete alphabet) and fuzz tests,
runnable via the new make fuzz target.
2026-07-27 21:19:37 +09:00
Junegunn Choi 0efef298d2 Skip all-zero passes in radix sort of results
CodeQL / Analyze (go) (push) Canceled after 0s
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
Precompute OR of all sort keys; a byte position that is zero across every
key contributes a no-op pass. Default two-criteria setup leaves the low 32
bits zero, so 4 of 8 passes are skipped without a histogram scan. 2x on the
sort, 3-8% on high-match queries. No regression when all bytes are used.
2026-07-24 21:38:18 +09:00
Junegunn Choi 2209a94e13 Update CHANGELOG
CodeQL / Analyze (go) (push) Waiting to run
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
2026-07-23 21:30:47 +09:00
Junegunn Choi e58c5e6bd8 Hide separator next to preview window at 'next' position when decidable
Decision must not depend on threshold chain resolution
(computePreviewSize consults noSeparatorLine); separator is hidden only
when every spec in the chain displays a 'next' preview window with a
border line facing the input section. Otherwise err on the side of
showing it.

- Without active previewer, preview position is resolved from first spec
  alone, so 'next' in a threshold alternative does not create input
  window and cannot hide the separator
- Empty preview command is undecidable; preview(...) action can display
  ad-hoc window at 'next' position at any time
- change-preview-window relayouts or repaints when separator visibility
  changes even if the active spec is unchanged, without dropping preview
  window forced by preview(...) action
2026-07-18 16:43:23 +09:00
Junegunn Choi 7fe4831be6 Apply facing-line rule to input border as well
Visible input border suppressed separator even when it draws no line
toward list section (bottom in default layout, top in reverse, vertical).
Suppress only when input border has a line on the list side; otherwise
fall through to adjacent section check.

- Requires header window to have content before treating it as facing
  section; hasHeaderWindow returns true with empty header when input
  border is visible
- Extract inputBorderFacesList and resolveInputBorderShape shared by
  options and terminal
- Add tests for separator suppression rules
2026-07-18 16:43:23 +09:00
Junegunn Choi 6030226835 Hide default separator when a border separates input from list
- Applies when adjacent section (header, header lines, or list) draws
  border line facing input section

    # No separator below header border
    fzf --style full --input-border none --header foo

    # Separator shown; nothing separates input from list
    fzf --style full --input-border none --header foo --no-header-border

- Evaluated dynamically so change-header/toggle-header update it
- Inline header is drawn inside list border and not adjacent to input;
  decide from section actually next to it
- Separator is kept when a preview window can be at 'next' position,
  right next to the input section
2026-07-18 16:43:23 +09:00
Junegunn Choi e877b6f846 Update CHANGELOG
CodeQL / Analyze (go) (push) Canceled after 0s
build / build (push) Canceled after 0s
Test fzf on macOS / build (push) Canceled after 0s
2026-07-17 14:44:20 +09:00
Junegunn Choi 7e134f0a78 Update CHANGELOG 2026-07-17 10:47:56 +09:00
Junegunn Choi 6765f464a6 0.74.0
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-07-06 22:21:21 +09:00
Junegunn Choi c110aec3c4 Update CHANGELOG 2026-07-06 21:06:27 +09:00
Junegunn ChoiandGitHub e54f11c64e Default to native border for Zellij floating pane (#4854)
The native border is the handle for moving and resizing the pane with
the mouse, so use it by default, consistent with tmux. fzf draws its
own border only when a border style is explicitly specified with
--border. Extract the shared native-border decision into a helper.
2026-07-06 21:04:35 +09:00
Junegunn ChoiandGitHub 77e6394f50 Set --border-label as the title of the tmux floating pane (#4853)
The pane sets the options itself before running fzf, so that they are
in place no matter how quickly the command exits, targeted at
$TMUX_PANE; the default target would resolve to the active pane of
the session's current window.

- pane-border-format is set to '#{pane_title}' so that the label is
  displayed on the border when pane-border-status is enabled;
  pane-border-status itself is a window option in released tmux
  versions and is left alone
- When a border style is explicitly specified with --border, a popup
  is used instead of a floating pane so that the fzf-drawn border is
  the only border shown; give 'border-native' to force a floating pane
- 'none' and 'line' are treated as no border; fzf draws no box for
  either, so the label is displayed on the native border
- Remove 'border-fzf' which is now redundant; it was never released
- The title is escaped for select-pane -T which expands format
  expressions; a lone ';' is escaped as tmux would treat it as a
  command separator
- The label is skipped when ANSI stripping leaves an empty string
- --border-label-pos is ignored
- Fix remain-on-exit set on the original pane instead of the floating
  pane
2026-07-05 19:35:34 +09:00
Junegunn ChoiandGitHub 1e31e5dfbe Use floating pane instead of popup on tmux 3.7 or above (#4850) (#4852)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Unlike a popup, a floating pane is not modal; you can switch to other
panes and windows while fzf is running, move and resize the pane with
the mouse, zoom it to fullscreen, and use copy-mode in it.

- Floating pane always has a native border, so 'border-native' is
  implied; give new 'border-fzf' option to fall back to a popup where
  fzf draws its own border
- Popup is also used on tmux versions below 3.7, or when the window is
  too small to fit a floating pane
- new-pane does not block until the command finishes and does not
  propagate the exit status; block on a wait-for channel signaled by
  the pane and pass the exit status through a temporary file
- Watchdog process signals the channel when the pane is closed
  abnormally (e.g. kill-pane)
- Kill the pane when the proxy process is interrupted, like a popup
  dying with its client
- Unzoom the window before creating the floating pane; doing so over a
  zoomed window crashes the tmux server on 3.7b, and newer versions of
  tmux unzoom the window anyway
- Floating pane size excludes the border and the position is that of
  the content area; treat the requested size as the total footprint
  including the border for consistency with popups
- Close the pane on exit even when remain-on-exit is on
- Pre-create the exit status file with O_EXCL to prevent tampering on
  a shared TMPDIR
2026-07-05 14:15:11 +09:00
Junegunn Choi 8ec443ba40 Add 'wait' action to block until search completion (#4825)
Blocks execution of subsequent actions until the current search
completes, so motion actions operate on the complete result set.

  # Move to the best match only after the search is done
  fzf --bind 'start:change-query(foo)+wait+best'

- Blocks when a search is in progress, will be triggered by preceding
  actions, or the query was edited in the same binding; no-op otherwise
- Initial input load counts as a search in progress, so 'start:wait'
  blocks until the input is fully loaded and searched
- User input ignored while blocked, including --expect keys; keys bound
  to abort/cancel cancel the wait and discard pending actions instead
- Actions deferred by the wait survive across nested lists (trigger
  chords) and cancel/re-arm chains
- Debounced feedback after 200ms: dimmed prompt, hidden cursor, and
  (..) on the info line
2026-07-05 11:22:02 +09:00
Junegunn Choi f2e451596c Skip FZF_CURRENT_ITEM export for items larger than 64 KB
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
A huge item can overflow ARG_MAX and break exec with E2BIG, failing
preview and other child commands. (#4806)
2026-06-23 20:50:12 +09:00
Junegunn Choi 3951df8537 Bind alt-left/alt-right to backward-word/forward-word by default
Fix #4833
2026-06-14 21:55:48 +09:00
Junegunn Choi 5dd698b869 Add result-final event
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
- Fires like result, but only after the input stream closes
- Use for one-shot per-query actions that would otherwise re-fire on
  every intermediate snapshot during loading

Close #4835
2026-06-14 19:37:22 +09:00
Junegunn Choi 07c5cd4185 Fix typo in CHANGELOG
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-05-25 14:39:05 +09:00
Junegunn Choi ce4bef7595 0.73.1 2026-05-25 14:35:03 +09:00
Junegunn Choi a24deef77b 0.73.0 2026-05-24 00:15:16 +09:00
Junegunn ChoiandGitHub de1fca99d5 Export FZF_CURRENT_ITEM to child processes (#4803)
Close #4802
2026-05-23 22:28:03 +09:00
Junegunn ChoiandGitHub 677e854850 Add --preview-window=next position (#4801)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Places preview adjacent to input on the list side: above input in the
default layout, below it in --layout=reverse.

  fzf --preview 'cat {}' --preview-window=next

Close #4798
2026-05-23 10:32:19 +09:00
Junegunn ChoiandGitHub fcc3c6acce Add every(N) bind event and FZF_IDLE_TIME env var (#4797)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
- every(N) fires every N seconds (fractional, floored to 0.01s)
- Encoded as tui.Every with duration in Char as milliseconds, so
  every(1) and every(2) coexist as distinct keymap entries
- FZF_IDLE_TIME exposes whole seconds since the last user activity
  (keystroke or mouse event); pair with every() for idle-based
  patterns like auto-accept/auto-quit

Close #1211
2026-05-17 23:54:59 +09:00
Junegunn Choi b4a86a9c8a Preserve wrap state across change-preview-window
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
toggle-preview-wrap (and -wrap-word) modifies t.activePreviewOpts.wrap,
but change-preview-window resets t.previewOpts to t.initialPreviewOpts,
discarding the user's toggle. Carry wrap and wrapWord over so toggles
survive a layout change. Explicit wrap / nowrap tokens in the new spec
still win, so cycling and the empty-token reset are unaffected.

Close #4791
2026-05-02 15:40:41 +09:00
Junegunn Choi 6fefe02546 0.72.0
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-26 18:04:37 +09:00
Junegunn Choi 27dab2422e Change the example command in the 0.72.0 changelog
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-21 18:48:00 +09:00
Junegunn Choi 7782da6c00 Add dashed border style
New --border=dashed / --list-border=dashed / --header-border=dashed etc.
Uses U+2576 (╶) for horizontal edges and U+2506 (┆) for verticals, with
rounded corners (╭╮╰╯) and sharp T-junction mids (├┤). Terminal cells
are taller than wide (~2:1), so horizontals use a sparse stub per cell
while verticals need more dashes per cell to look evenly dashed.
Works with inline sections.
2026-04-20 22:23:41 +09:00
Junegunn Choi 43f0508dd2 Update CHANGELOG (0.72.0)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-20 00:55:43 +09:00
Junegunn Choi 0142fe9d04 Update CHANGELOG: clarify inline list-border shape requirements 2026-04-20 00:47:16 +09:00
Junegunn Choi d754cfab87 Add --{header,header-lines,footer}-border=inline
New BorderShape that embeds the section inside the --list-border
frame, joined to the list content by a horizontal separator with
T-junctions where the list shape has side borders. Requires a list
border with both top and bottom segments; falls back to 'line'
otherwise. Stacks when multiple sections are inline.

Sections inherit --color list-border by default and are colored as a
uniform block via their own --color *-border and *-bg.

Incompatible with --header-first. --header-border=inline requires
--header-lines-border to be inline or unset.
2026-04-20 00:47:16 +09:00
Junegunn Choi 62899fd74e 0.71.0
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Generate Sponsors README / deploy (push) Has been cancelled
2026-04-04 14:04:34 +09:00
bitraidandJunegunn Choi d7a132b8bf Update changelog 2026-04-04 09:48:00 +09:00
Junegunn ChoiandGitHub 6f17d49dbb Support zellij floating pane via --popup (new name for --tmux) (#4145) 2026-03-26 21:32:56 +09:00
Junegunn Choi a00df93e13 bash: CTRL-R now supports multi-select and batch deletion
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Generate Sponsors README / deploy (push) Has been cancelled
- Changed +m to --multi to enable multi-select in CTRL-R
- Changed exclude to exclude-multi and {1} to {+1} so
  shift-delete removes all selected entries at once
2026-03-21 21:41:22 +09:00
Junegunn Choi 76efddd718 bash: shift-delete to delete history entries during CTRL-R
Close #4715
2026-03-21 21:10:43 +09:00
Junegunn Choi b638ff46fb Include match positions in GET / HTTP response
Close #4726
2026-03-20 23:06:16 +09:00
Junegunn Choi f0a2f5ef14 Skip symlinks targeting ancestors of walker root to prevent resource exhaustion
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
When --walker=follow is used, symlinks like Wine's z: -> / cause fzf to
traverse the entire root filesystem. fastwalk's built-in loop detection
only catches this on the second pass, but a single pass through / already
causes severe CPU and memory exhaustion.

This fix resolves each symlink-to-directory target to its absolute real
path and skips it if it is an ancestor of (or equal to) the walker root.

Close #4710
2026-03-18 20:43:00 +09:00
Junegunn Choi 2ae7367e8a Revert "Use IgnoreDuplicateDirs to prevent duplicate directory traversal"
This reverts commit 6f33df755e.
2026-03-18 18:57:40 +09:00
Junegunn Choi 6f33df755e Use IgnoreDuplicateDirs to prevent duplicate directory traversal
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
When --walker=follow is used, symlink following is now handled by
fastwalk's IgnoreDuplicateDirs adapter which tracks visited directories
by device+inode. This prevents the same directory from being entered
more than once, avoiding effectively infinite traversal when a symlink
points outside the walker root.

Close #4710
2026-03-18 10:17:49 +09:00
Eman ResuandGitHub 2aec7d5201 Fix typo in 0.71 changelog entry (#4721)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Thanks!
2026-03-17 11:45:00 +09:00
Junegunn Choi b5f7221580 Replace --track=NTH with --id-nth for cross-reload item identity
Separate item identity from cursor tracking:
- Add --id-nth=NTH to define item identity fields for cross-reload ops
- --track reverts to a simple boolean flag
- track-current action no longer accepts nth argument
- With --multi, selections are preserved across reload-sync by matching
  identity keys in the reloaded list

Close #4718
Close #4701
Close #4483
Close #4409
Close #3460
Close #2441
2026-03-14 21:49:16 +09:00
Junegunn Choi 9f422851fe Add field-based tracking across reloads (--track=NTH)
Allow --track to accept an optional nth expression for cross-reload
tracking. When a reload is triggered, fzf extracts a tracking key from
the current item using the nth expression, blocks the UI, and searches
for a matching item in the reloaded list.

- --track=.. tracks by entire line, --track=1 by first field, etc.
- --track without NTH retains existing index-based behavior
- UI is blocked during search (dimmed query, hidden cursor, +T*/+t*)
- reload unblocks eagerly on match; reload-sync waits for stream end
- Escape/Ctrl-C cancels blocked state without quitting
- track-current action accepts optional nth: track-current(1)
- Validate nth expression at parse time for both --track and track()
- Cache trackKeyFor results per item to avoid redundant computation
- Rename executeRegexp to argActionRegexp

Close #4701
Close #3460
2026-03-14 20:52:04 +09:00
Junegunn Choi b59f27ef5a Fix --with-shell not handling quoted arguments correctly
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Fix #4709

Use go-shellwords instead of strings.Fields to parse --with-shell,
so paths with spaces can be properly quoted.

  ln -s /bin/bash "/tmp/ba sh"

  fzf --with-shell='/tmp/ba\ sh -c' --preview 'echo hello world'

  fzf --with-shell='"/tmp/ba sh" -c' --preview 'echo hello world'
2026-03-09 22:09:36 +09:00
Junegunn Choi f3ca0b1365 Fix OSC8 hyperlinks mangled when URL contains unicode
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Fix #4707
2026-03-08 13:55:14 +09:00
Junegunn Choi a8e1ef0989 Add CHANGELOG.md entry for 0.70.1 2026-03-08 11:54:56 +09:00
Junegunn Choi eacef5ea6e 0.70.0
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-03-02 16:56:13 +09:00
Junegunn ChoiandGitHub 3cfee281b4 Add change-with-nth action to dynamically change --with-nth (#4691) 2026-03-01 16:09:54 +09:00