fzf can boost your workflow
Abstract
There are many things that a command line user can do, and also there are bunch of graphical application that can help user to boos their productivity.
But of course the beauty of CLI software is that they can be chained together in a logical order to drastically improve workflow and reduce potential mistakes.
In this post I am going to share some of these quick scripts that I personally use. All these use fzf
as the title also suggests.
Main
There are few CLI tools that one can use in combination to classic gnu utils and etc. to have a more modern, safe, and fast experience. In this article I'm showing a subset of those that I'm using in daily basis. These tools are:
fzf
: fuzzy finderbat
: improvedcat
Quick file preview
The fzf
already previews the file contents, but we can add color coding automatically to the preview window of fzf
:
fzf --layout=reverse-list \
--preview 'bat --style=numbers \
--wrap=auto \
--color=always \
--paging=never \
--line-range :500 "{}" '
Of course you can add more flags to the fzf
based on your use-case. For instance the --exact
and --multi
are popular one by users.
Better history
Many people know about the history
command, and a subset of them know about the Ctrlr to search through your history, but the look of it is a bit ancient and kind hurts my eyes.
But as you can imaging, we can make our life much easier and smoother.
In the following:
- the
print -z
is responsible inserting the selected command in your terminal prompt. - the
sed
removed the line number. - the
fzf
is the fuzzy finder which is the main point of this article - the
cut
would remove the date. This is because I have configured myhistory
to store the date and time of each record in history.
print -z "$(history \
| sed -E "s/^ +[0-9]+ +//g" \
| fzf --tac \
--no-sort \
--height=10 \
--layout="reverse" \
--border="rounded" \
| cut --delimiter=" " \
--field="4-")"
This is a preliminary command here. I have a much better implementation that I will have a dedicated blog post about it.
Going through git commits
It is common that one goes through the git log and see previous commits. The problem is that with git log
you can see the commit messages and commit hashes. You can even beautify it by adding --oneline
and --graph
to get a better view of the commits and branches and merging events, but you still have to use the commit hash and use it in git show
to see the code changes of that commit. This is very suboptimal for me. I would like to see them side-by-side and have it interactive.
So this is what I put together in couple of minutes to make my experience smoother:
git log --oneline \
--graph \
--color=always \
| nl \
| fzf --ansi \
--track \
--no-sort \
--layout=reverse-list \
--preview 'echo -n {} \
| head -n 1 \
| grep --only-matching \
--perl-regexp \
--regexp="[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]" \
| head -n 1 \
| xargs -I _ git show _ \
| bat --language=diff \
--color=always \
--style=numbers \
--wrap=auto \
--paging=never \
--line-range :500'
Just make sure you have installed git
, fzf
, bat
on your computer.
Also, I should add that the regex here looks repetitive, but here is the issue, the better approach is /[0-9a-f]{7}/
but having the {7}
in this regex will be replaced with the --preview
of fzf
. In fzf
terms it means the 7th element if the selected string with space delimiter.
Of course there is a way in fzf
to change the {}
with something else, but that needs setting an environmental variable, which is not an easy thing to do when using this as an alias.
Summary
As you can see (and you can test for yourself in your terminal), these can drastically improve your workflow and save you time and effort.
It worth to mention that these are not exactly what I use on my machine and I have done some more tweaks that fits better my workflow.
I encourage you to read the manpages of fzf
, bat
, and other tools and familiarize yourself with the flags and start tweaking this to your liking. :)
One last [obvious] note: perhaps the best way to use these codes is by turning them into aliases:
hash fzf 2> /dev/null \
&& alias fhist='print -z "$(history \
| \sed -E "s/^ +[0-9]+ +//g" \
| \fzf --tac \
--no-sort \
--height=10 \
--layout="reverse" \
--border="rounded" \
| \cut --delimiter=" " \
--field="4-")"'
hash fzf 2> /dev/null \
&& alias fzfp="fzf --layout=reverse-list \
--preview 'bat --style=numbers \
--wrap=auto \
--color=always \
--paging=never \
--line-range :500 "{}" '"
hash git fzf bat 2> /dev/null \
&& alias fzfgl="git log \
--oneline \
--graph \
--color=always \
| nl \
| fzf --ansi \
--track \
--no-sort \
--layout=reverse-list \
--preview 'echo -n {} \
| head -n 1 \
| grep --only-matching \
--perl-regexp \
--regexp=\"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\" \
| head -n 1 \
| xargs -I _ git show _ \
| bat --language=diff \
--color=always \
--style=numbers \
--wrap=auto \
--paging=never \
--line-range :500'"
Note that in the code section above, I am using hash
to make sure the tools I have used in these aliases are already installed.
If they are not already installed, the alias will not be created.