Can I get the Vim Ctrlp plugin to ignore a specific folder in one project?
The Vim Ctrlp plugin has a way to globally ignore certain folder names. Eg:
let g:ctrlp_custom_ignore = '\v[\/]\.(git|hg|svn)$'
However, I have an ignore rule that's specific to one project. I would like something more like a .gitignore
file.
Is there a way to ignore a specific folder in a specific project without modifying my global configuration?
Solution 1:
Use a custom listing command
Ctrlp lets you tell it what command to use to get a list of files in the folder. So if you wanted to exclude anything named beets.txt
, you could do:
let g:ctrlp_user_command = 'find %s -type f | grep -v "beets.txt"'
That's global, but it starts to point toward the answer: supply your own shell command.
Even better, Ctrlp lets you supply multiple shell commands with markers, meaning "if you see this marker in the root directory, use this command."
I found this in :help ctrlp
, and modified slightly based on the author's comment on an issue.
let g:ctrlp_user_command = {
\ 'types': {
\ 1: ['.git', 'cd %s && git ls-files --cached --exclude-standard --others'],
\ 2: ['.hg', 'hg --cwd %s locate -I .'],
\ },
\ 'fallback': 'find %s -type f'
\ }
This means: "If you see .git
in the folder, use git ls-files...
. Otherwise, if you see .hg
, use hg --cwd...
, otherwise use a regular find
."
So, to ignore a specific folder in one project, devise a command that will ignore that folder, then place a unique marker in that project to let Ctrlp that you want to use your special command here.
(In my case, I actually wanted to ignore files that were in .gitignore
, so the git ls-files
command above works for me.)
Solution 2:
If you are using the Silver Searcher backend for CtrlP (which is far faster), just add an .agignore
file to your project directory in the same format as a .gitignore
:
.git/
.hg/
.svn/
Alternatively, keep a global ~/.agignore
file.
Add the Silver Searcher as the backend with this in your .vimrc
let g:ctrlp_user_command = 'ag %s -l --nocolor --hidden -g ""'
Solution 3:
Specifies intentionally untracked files in a file
To solve this with a file like .gitignore
(based in the Nathan grep solution), I created a file named .ctrlpignore
and put the patterns that should be ignored, separated by lines:
node_modules/
\.log$
...
And my ctrlp configuration:
let g:ctrlp_user_command = 'find %s -type f | grep -v "`cat .ctrlpignore`"'
Maybe the .gitignore
itself can be used to ignore the files in ctrlp, not needing to create a new file to do almost the same thing.
Solution 4:
As Wagner Andrade said, using a seperate .ctrlpignore
would be a good idea.
A more robust and convenient vim setting is like this:
let g:ctrlp_user_command = 'cd %s;
\ commonfilter="\.(jpg|bmp|png|jar|7z|zip|tar|gz|tgz|bz)$";
\ if [ ! -r ".ctrlpignore" ]; then
\ find . -type f | grep -Evi "$commonfilter";
\ else
\ find . -type f | grep -vF "$(cat .ctrlpignore)" | grep -Evi "$commonfilter";
\ fi'
.ctrlpignore
can be put in any dir that would be recognized as a root dir by ctrlp. Here is an example, every line is starting with ./
vim ~/.ctrlpignore
./Desktop
./R
./.vim
./.local/lib
.....
Note:
grep -F
will interpret pattern, ex. './.tmp', as a fixed string if you don't want your './ptmp' be filtered out. There are still some trivial bugs: './.tmp' will also filter out './.tmp2'. Forget it, I don't like\.
g:ctrlp_custom_ignore
will be ignored ifg:ctrlp_user_command
is set. Those could be done in a more complexg:ctrlp_user_command
white-list instead of black-list is also possible. More convenient if implemented in a seperate script