Commit Graph
1524 Commits
Author SHA1 Message Date
Junegunn Choi 4dcedc01df Comment why floating pane requires TMUX_PANE
Blocking run-shell suspends client key processing until the command
exits, so a floating pane deadlocks; popup input bypasses the suspended
path. Fall back to display-popup when TMUX_PANE is not set.
2026-07-15 17:45:08 +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 Choi f7392a8b63 Pre-create become file with O_EXCL
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Prevents another user on a shared TMPDIR from planting a file or a
symbolic link at the predictable path while fzf is running, like the
exit status file of the floating pane. Reject an empty become command.
2026-07-05 22:00:55 +09:00
Junegunn Choi eee92b1b2a Clear border text of the floating pane when no label is given 2026-07-05 20:02:36 +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 a1fb01462d Copy input snapshot on bracketed paste begin
[]rune(t.input) is a same-type conversion that aliases t.input;
in-place query edits during the paste corrupt the snapshot and skew
the paste-end comparison.
2026-07-05 11:22:02 +09:00
Junegunn Choi 978ded5cd0 Pass bracketed paste actions through wait/track block
A pasted character firing a wait-arming binding swallowed the
subsequent bracketed-paste-end, leaving t.pasting set forever and
suppressing queryChanged for all later input. Let paste begin/end
through the block so pasting state is maintained and the search for
the edited query is dispatched.
2026-07-05 11:22:02 +09:00
Junegunn Choi 743930a38d Run bg-transform callbacks while wait/track-blocked
Background transform results are unrelated to the block; dropping them
would silently lose completed work. Applies both the dedicated
bg-transform-* setters and actions parsed from generic bg-transform
output (inBgCallback); a 'wait' in such output joins the ongoing wait.
Searches initiated by a bg result are not waited for.
2026-07-05 11:22:02 +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
Jason HanandJunegunn Choi 9e2856559d Add mouse wheel tests
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-06-28 22:15:03 +09:00
Jason HanandJunegunn Choi 9e4f8e7b7a Fix horizontal mouse wheel being treated as vertical scroll
Close #4848
2026-06-28 22:15:03 +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 f5fbfd848e Let bw theme inherit overridden colors
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
- Mark derived color slots undefined so fg/bg/list-bg propagate
- Add missing Footer slot (was rendering black)
2026-06-07 18:12:19 +09:00
Junegunn Choi dea72834ed Keep base fg/bg when resolving colors in bw theme
Trailing prompt space and other base-colored segments no longer reset to terminal default
2026-06-07 18:12:19 +09:00
Junegunn Choi ae78a5c56d Allow bare put action in transform output
transform/bg-transform now permit bare `put`, inserting the key that
triggered the action (`a:transform:echo put` puts `a`).
2026-06-02 20:21:04 +09:00
Junegunn Choi 25868a62f7 Address code scanning alerts 2026-05-25 14:31:51 +09:00
Junegunn Choi 7963a2c658 server: avoid O(n^2) body accumulation in HTTP listener
- handleHttpRequest used `body += text` per token, allocating a new
  backing array on every append (O(n^2) total copy work)
- a single ~390 KB POST monopolised the single-threaded server for
  ~8 s, blocking all other --listen clients
- switch to strings.Builder for amortised O(n)

Reported with fix by Michal Majchrowicz and Marcin Wyczechowski
(AFINE Team).
2026-05-25 14:10:52 +09:00
Junegunn Choi 4b23aa45a8 Skip FZF_CURRENT_ITEM export when item contains NUL
- exec(2) rejects env entries containing NUL, breaking preview and
  other child commands when the input has NUL bytes
- skip the export and document the limitation

Fix #2395
2026-05-25 14:06:50 +09:00
290b18d9fe shell: nushell integration scripts (#4630)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Co-authored-by: imsys <911254+imsys@users.noreply.github.com>
Co-authored-by: Grzegorz Zalewski (Greg) <12560152+zalewskigrzegorz@users.noreply.github.com>
Co-authored-by: René Jochum <rene@jochum.dev>
Co-authored-by: Junegunn Choi <junegunn.c@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-23 23:13:46 +09:00
Junegunn Choi ccedd064ca Fix integer overflow in FuzzyMatchV2 guard on 32-bit builds
On 32-bit platforms (GOARCH=386, arm), N*M overflows int when N is
large and M approaches 1000, wrapping negative. The wrapped value
slips past both `N*M > cap(slab.I16)` and `M > 1000`, so the V1
fallback is skipped and alloc16 panics on a negative slice bound.

Cast to int64 before multiplying.

Affects shipped 32-bit ARM builds (linux_armv5/6/7, windows_armv5/6/7).

Reported with fix by Michal Majchrowicz and Marcin Wyczechowski
(AFINE Team).
2026-05-23 23:09:58 +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 Choi 67319aed0b Fix rendering glitch with preview window on the left + footer
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-05-19 18:54:35 +09:00
Junegunn Choi 5819e5ff2f Fix bg-transform reload/exclude
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Async callbacks fire a later iteration than the one that scheduled
them, so newCommand/reloadSync/denylist must persist across iterations.

  fzf --bind 'space:bg-transform:echo reload:date'
2026-05-18 18:48:00 +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 e0d081906f Reward non-word match at word boundary
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
A non-word character (e.g. '.') used to receive a flat bonusNonWord
regardless of context. Now it gets bonusBoundaryWhite at the start of
input and bonusBoundaryDelimiter right after a delimiter, matching the
treatment of word characters at the same boundaries.

Without this, '.completion' matching '.completion' lost to
'bash_completion.d/completions/X' because the consecutive chunk anchor
in the long path (the 'c' after '/') received bonusBoundaryDelimiter
while the exact match's '.' was capped at bonusNonWord.

Fix #4795
2026-05-15 00:46:36 +09:00
Junegunn Choi 263eb4732f Strip UTF-8-encoded C1 control characters from rendered items
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
The display sanitizer already stripped raw 8-bit C1 bytes (0x80-0x9F)
because they decode to RuneError as standalone bytes. Their valid UTF-8
encodings (0xC2 0x80 .. 0xC2 0x9F) decode to the same code points but
were passed through, allowing a filename or input line containing CSI
(U+009B), OSC (U+009D), or DCS (U+0090) to inject terminal control
sequences when rendered.
2026-05-05 09:56: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 f783582561 Rename internal variables to match user-facing names 2026-04-26 14:47:57 +09:00
Junegunn Choi 56be41218c Redraw when change-footer changes line count
Mirror of the earlier change-header fix. The inline footer slot's row
budget depends on footer content length, but resizeIfNeeded() tolerates
a shorter-than-wanted inline window, so extra lines get clipped. Drive
a redraw on length change to re-run the layout.
2026-04-21 18:41:48 +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 1986d101e0 Redraw when change-header changes line count
The inline header slot's row budget depends on header content length,
but resizeIfNeeded() tolerates a shorter-than-wanted inline window, so
the stale slot stays. Drive a redraw on length change to re-run the
layout.
2026-04-20 00:47:16 +09:00
Junegunn Choi dd7a081b93 Let inline sections take precedence over --header-first
--header-first previously was rejected with --header-border=inline or
--header-lines-border=inline. Now, inline placement wins: an inline
section stays inside the list frame, and --header-first only affects
non-inline sections (mainly the main --header).
2026-04-20 00:47:16 +09:00
Junegunn Choi d247284bc3 Set inline separator caps per side 2026-04-20 00:47:16 +09:00
Junegunn Choi 251b08b831 Fix misleading comment on printHeader nil-window guard
The guard fires when hasHeaderWindow() returned false at resize time,
not when addInline had no budget (placeInlineStack always leaves a
non-nil 0-height placeholder).
2026-04-20 00:47:16 +09:00
Junegunn Choi 01567b4f06 Fix inline header/footer border color when falling back to line
InitTheme was called before the runtime coerced BorderInline to
BorderLine, so HeaderBorder / FooterBorder inherited from ListBorder
even when the effective shape was 'line'. Mirror the coercion so
color inheritance matches the rendered shape.
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 8b66489987 Clean up non-ascii characters 2026-04-20 00:47:16 +09:00
Tymoteusz MakowskiandJunegunn Choi 1ad7c617b1 fix: add no-modifiers fallbacks
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Close #4776
2026-04-19 14:38:36 +09:00
Junegunn Choi bd4a18d0a9 Replace sort.Sort(ByOrder(...)) with slices.SortFunc
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-12 10:43:47 +09:00
Junegunn Choi 0eb2ae9f8b Fix gutter display in --style=minimal
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
2026-04-08 23:28:10 +09:00
Junegunn Choi d1cea64a0e Allow adaptive height with negative value
Fix #4682
2026-04-04 10:13:19 +09:00
PJ EbyandGitHub fff7eda9d7 Terminate child processes on Windows (#4723)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Windows doesn't have signals, the default Kill doesn't actually kill
anything, and other forms of termination don't allow cleanup. So we
spawn preview processes in a new process group and send them a
CTRL_BREAK_EVENT to terminate.

However, we only do this for "pwsh" (PowerShell 7+) and unknown/
posix-ish shells, because cmd.exe and Windows PowerShell
("powershell.exe") don't always exit on Ctrl-Break. pwsh also needs
the -NonInteractive flag to exit on Ctrl-Break.

If the process wasn't given its own group, or if sending the console
control event fails, we fall back to the standard Kill (which likely
won't help, but doesn't hurt to try).

Fix #3134
2026-03-29 12:40:24 +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 12be5e7b83 Skip adaptive height validation when --tmux overrides --height
Fix #4742
2026-03-26 20:56:36 +09:00
Qingwei LiandGitHub 1acf980e95 enhancement: move server declaration to go func to allocate it in stack (#4739)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Fix #4735
Close #4736
2026-03-25 15:22:49 +09:00
cuiandGitHub 14e3995a06 Fix nthTransformer parts slice preallocation (#4734)
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled
Use make([]NthParts, 0, len(indexes)) so the slice starts empty with
reserved capacity. The previous length-len(indexes) allocation left
leading zero NthParts entries before appended elements.
2026-03-23 09:55:00 +09:00