Intro
Recently, I hit a very specific issue. I wanted to edit a file that is reasonably put into .gitignore
like .env
. neovim’s great file explorer, Telescope, respects ignore files such as .gitignore
and .ignore
, when searching for files, which makes sense most of the time. I do not need to find a file in .git
, a Python virtual environment folder like venv
, or in node_modules
, or at least not often enough that I could not go about it some other way. But files like .env
or the .ignore
file itself that I am ignoring from my git repository I absolutely must be seeing in my file picker.
So, I checked the Telescope documentation and code to find a solution. This is the journey and the result!
Hidden and ignored files
By default, require('telescope.builtin').find_files()
finds all files that are not hidden (i.e. starting with a dot) or are in one of the usual ignore files (.gitignore
and .ignore
, maybe even more). The reason for this behavior is that Telescope uses ripgrep
(and friends) internally, which are operating just like that. There are two optional parameters that can be used to control, which files are found:
hidden
: obviously, it either shows (hidden=true
) or hides (hidden=false
) hidden files. This should bytrue
by default, at least I think so, but it’s no big deal, simply call the file picker like this:1
require('telescope.builtin').find_files(hidden=true)
no-ignore
: this one either respects or disrespects ignore files, i.e.,no-ignore=true
shows me all files, because it tells the search tool to not care about ignore files.
Note: The parameter values are a bit couter-intutive, at least to me, but that is the issue with boolean flags in general. hidden=true
means hidden files are shown, no_ignore=true
means the ignore files are not used.
And this is where my problems begin. When I am developing on my own, I simply create an .ignore
file, run the filepicker with hidden=true, no_ignore=false
and can edit the files that I need, while dumping all other files into .ignore
. However, when I am in a git repository with a well behaved .gitignore
file, my file picker will not show the files listed in .gitignore
, even though they are not listed in .ignore
. Most of the time, this is not an issue, but sometimes it is and then it becomes tedious to type out :e .env
instead of just running the file picker, which is deeply ingrained in my muscle memory.
The root cause is simply that Telescope has only one setting for ignore files. Based on this setting, the underlying search tool like ripgrep
or find
is then configured, when the file picker is started.
The default behavior
As is often the case, it helps to simply take a look at the source code. Here is the implementation of the Telescope file picker from nvim-telescope/telescope.nvim:
|
|
I picked out the parts that are dealing with the actual ignoring of files, the rest of the code is pretty straightforward, the length is mostly a result from handling the different search tools that can be used behind the scenes. For the parameter no_ignore
, the flag --no-ignore
is passed to the find tool. In the case of ripgrep
there are actually several options to handle ignore files. From its man page:
|
|
There it is, we actually need --no-ignore-vcs
but NOT --no-ignore-dot
, but the global setting --no-ignore
overrides this. So the solution is simple, pass in --no-ignore-vcs
instead of --no-ignore
. However, I do not want to make changes to the Telescope code directly, but luckily we can easily extend it with our own code.
The solution
I am defining my own file picker function that essentially just primes the find_command
argument that the find_files
method will use. From the find_files
code:
|
|
So, by passing in a function to the find_command
parameter, we can easily set our own custom settings for the build tool that we want to use:
|
|
In my case, I am using ripgrep
and passing the newly discovered --no-ignore-vcs
flag. The default behavior will honor the .ignore
file, which is almost always the behavior that I want, so that is all there is to do. Finally, I am calling my new custom picker:
|
|
Conclusion
While the solution is very easy, I let myself be bothered by this for way too long. Actually solving it was done in a few minutes and now I am happy every time I bring up my file picker and see .env
and .ignore
in the list.
Hope this is useful to anyone else!