Unrecognized Escape Sequence

An increasingly grumpy blog about software engineering

Using and meddling with fzf

What is fzf?

If you’re a linux terminal user and not familiar with fzf, I would highly recommend giving it a try. I’m not going to go to great lengths to explain the functionality here, as that information is available on the tool’s github page. But in short, fzf a search tool used for listing and browsing files,directories, command histories and other things. While this might not sound revolutionary, the clean, efficient way in which fzf makes this happen can really speed up your use of the terminal.

For example, fzf replaces the standard reverse-i-search behaviour (typically triggered by pressing Ctrl+R), with a superior alternative that shows a list of the most recent commands that match with the inputted search string, and allows for “fuzzy” text searching to further refine this list.

Listing command history

Maybe even more useful than searching the command history is fzf’s file searching. This can be invoked various ways,but the easiest to demonstrate is simply by pressing Ctrl+T. This starts the fuzzy search for files and directories under the current path.

Listing command history

Once you’ve formed the muscle memory to start using these key combinations, you begin to realise just how slow it was to constantly have to browse up and down the directory tree, essentially doing the computer’s job for it.

Usefully, fzf allows you to use your own commands to perform the actual searching, and following the recommendation of the author, I’m using fd for this, which makes things even faster. To do this I’ve added the following to my .zshrc:

# Use fd to list files for fzf
_fzf_compgen_path() {
    fd --hidden --follow --exclude ".git" . "${1}"
}

Previews

Another nice feature of fzf is the ability to show a preview pane for the file you have highlighted in the search result. The typical configuration for this will show text-based files using cat in the preview pane. While exploring the features of fzf I thought I would drill-down into the configuration of this, and try to get a bit more out of it.

So in my .zshrc I’m now telling fzf to use the fzf-preview.sh script to preview the selected search result:

# Call script to preview files
export FZF_CTRL_T_OPTS=" --preview '~/path/to/fzf-preview.sh {}'"

This script currently looks like:

#!/bin/bash

# fzf-preview.sh: fzf preview for various file types.
#
# Used in fzf config (.zshrc) as follows:
# export FZF_CTRL_T_OPTS=" --preview '~/path/to/fzf-preview.sh {}'"
#

file="$1"

if [[ -d "${file}" ]]; then
    ls -al --color "${file}"
elif [[ $(file --mime "${file}") =~ binary ]]; then
    if [[ $(file --mime "${file}") =~ "image/" ]]; then
        columns=$(tput cols)
        columns=$((${columns} / 2))
        catimg -w ${columns} "${file}"
    else
        echo "${file} is a binary file" && false
    fi
else
    bat --style=numbers --color=always "${file}" 2> /dev/null | head -100
fi

So far this handles previews for directories (shows a list the contents), binary files (shows a message), images (previews them using catimg), and text files (previews them using bat with syntax highlighting etc.)

Listing command history

There’s still a few issues with this, but I’ll expand the functionality here to do more as and when I come across other ideas for how to preview different files.

Anyway, enough said about fzf, but if you’ve not tried it already I highly recommend you give it a go.