-3

I want to make an alias that uses fzf to find a file in my directory, preview it, and then open it in neovim. If I don't select a file and exit the fzf interface, do not open neovim, but exit back to the shell. I'm using bat instead of cat (for syntax highlighting).

SO far, I've got this in my .bash_aliases:

alias fe='nvim $(fzf -m --preview="batcat --color=always {}")')

This alias opens fzf and uses bat for the preview with syntax highlighting. when I select a file I want to edit, it then opens the file in neovim. If I press escape, it opens a new, empty file in neovim. I'm not so sure how to make it so that if I press escape without selecting a file, then don't open neovim and go back to the shell.

3
  • What is batcat? Commented Oct 30, 2024 at 8:26
  • 1
    @Jetchisel For some reason, Debian (and in consequence Ubuntu) renamed bat's executable to batcat. On other distributions it's still bat. Commented Oct 30, 2024 at 8:36
  • @pmf, oh ok, could have been batrat :-) but, yeah thanks for the info. Commented Oct 30, 2024 at 10:39

1 Answer 1

4

Generally speaking, don't use aliases. Instead, use functions as they are more versatile when the code they cover becomes more complex.

Using nvim $(fzf …), you unconditionally start nvim with whatever fzf outputs. One way would be to capture fzf's output, and based on its return code (which is greater than zero if you cancel it), do one thing or another, e.g. using &&:

f="$(fzf --preview='batcat --color=always {}')" && nvim -- "$f"

Here, I just ignored that you have used fzf's -m option to select multiple files, because this creates some issues. You could leave out the quotes to make spaces become separators but this will fail if you select files containing spaces themselves. Mitigating this is possible, but makes the code even more complex.

Another way would be to use fzf's built-in functions execute or become. The difference is whether fzf should be kept running in the background or not, i.e. whether after exiting nvim you want to return to fzf or not.

fzf --preview='batcat --color=always {}' --bind enter:'become(nvim {})'

In this case, introducing multiple selections is easy, as fzf provides with {+} a way to insert a space-separated list of arguments:

fzf -m --preview='batcat --color=always {}' --bind 'enter:become(nvim {+})'

To wrap it up, here are the alias and function implementations of the final snippet, with my recommendation to use the latter:

alias fe='fzf -m --preview="batcat --color=always {}" --bind "enter:become(nvim {+})"'

fe() { fzf -m --preview='batcat --color=always {}' --bind 'enter:become(nvim {+})'; }
Sign up to request clarification or add additional context in comments.

1 Comment

Well done! --bind 'enter:become(... is clearly intended for this! And I agree: Prefer functions to aliases! @importedgallo: Please Read The Fzf Man page!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.