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 bytrueby default, at least I think so, but it’s no big deal, simply call the file picker like this:1require('telescope.builtin').find_files(hidden=true)no-ignore: this one either respects or disrespects ignore files, i.e.,no-ignore=trueshows 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!