fzf: 0.60.0

0.60.0 #

(February 2025)

Choosing output fields #

This release introduces --accept-nth option for choosing fields to print on exit.

It can be used to replace cut, sed, or awk in the post-processing step.

# Use 'awk' to print the second field
ps -ef | fzf --multi --header-lines 1 | awk '{print $2}'
# Now you can do this with fzf
ps -ef | fzf --multi --header-lines 1 --accept-nth 2

# Use 'cut' to remove the first two characters ('* ')
git branch | fzf | cut -c3-
# Tell fzf to only print the last field
git branch | fzf --accept-nth -1

This may not be a very “Unix-y” approach, so I’ve always felt that fzf shouldn’t have such an option, but I’ve finally changed my mind for the following reasons:

  • When using a custom --delimiter (fixed string or regular expression), you don’t want to repeat yourself in the post-processing step. e.g. fzf -d: ... | awk -F: ...
  • Also, tools like awk or sed may interpret a regular expression differently, leading to unexpected results.
  • The field index expression TM of fzf is a very compact and expressive way of specifying fields, and it’s not always easy to replicate in awk or sed.

Previously, users could achieve similar functionality using the become action:

ps -ef | fzf --multi --header-lines 1 --bind 'enter:become(echo {+2})'

However, this approach has some drawbacks:

  • Intimidating for new users, as it requires understanding --bind and become.
  • Less portable (e.g. different shell)
  • Doesn’t work very well with multiple selections.
    • To print each selection on a separate line, you need a different command than echo.
    • This breaks when the number of selections is extremely large.

So overall, I believe this is a nice quality-of-life improvement, though it might anger the ancient Unix gods (or a past me).

Hold on, we’re not done yet.

Advanced transformation using templates #

--accept-nth #

The new --accept-nth not only accepts a single field index expression, but a template that includes multiple field index expressions in curly braces.

# Single expression
echo foo bar baz | fzf --accept-nth 2
  # bar

# Template
echo foo bar baz | fzf --accept-nth '1st: {1}, 2nd: {2}, 3rd: {3}'
  # 1st: foo, 2nd: bar, 3rd: baz

--with-nth #

--with-nth has been a great option to hide a field or two from the input, but for more complex transformations, it would yield unintuitive results.

echo foo,bar,baz | fzf --delimiter , --with-nth 1,3,..2
  # foo,bazfoo,bar,
  • 1 -> foo,
  • 3 -> baz
  • ..2 -> foo,bar,

While it was working as intended, it was not very useful or intuitive.

But if you use a template, the trailing delimiter for each placeholder is removed, and you have precise control over the transformation.

echo foo,bar,baz | fzf --delimiter , --with-nth '{1},{3},{..2}'
  # foo,baz,foo,bar

Info

The template only supports field index expressions in curly braces. It doesn’t support other placeholders like {q}, {+}, or {n}.

Dynamically excluding items #

The new exclude action allows users to mark the current item as “excluded”, removing it from subsequent results.

seq 100 | fzf --bind 'ctrl-x:exclude'

Previously, you would have to reload the entire list to exclude certain items.

You’ll notice that when items are excluded, the total item count doesn’t change. This was a deliberate design choice to indicate that some items are “excluded”, not that the list has been fully “reloaded” and replaced.

To exclude multiple items at once, you can use exclude-multi action.

# 'exclude-multi' will exclude the selected items or the current item
seq 100 | fzf --multi --bind 'ctrl-x:exclude-multi'

Bug fixes and improvements #

As always, there are several bug fixes and improvements in this release. So please go ahead and upgrade. The latest fzf is the best fzf.

  • Improved scrolling performance when using --wrap option (#4221)
  • Improved preview window to print wrap indicator when wrapping is enabled (#4233)
  • Fixed nth highlighting bug (#4222)
  • Fixed edge case where header label is not initially visible (#4227)
  • [fish] Fixed CTRL-T binding to properly handle prefix with special characters (#4230, #4236)
  • Fixed suffix match on --nth element when a custom --delimiter is used (#3983)
Last modified: Feb 9, 2025
Copyright © 2024 Junegunn Choi