14

I was wondering if there is a way to get vim to read .gitignore files and use them to determine options not to present when auto-completing filenames.

For example, working in python, I'd like to not see .pyc files offered for editing. I think vim has its own mechanism for this, I was wondering how to load information from .gitignore into it.

saffsd
  • 23,742
  • 18
  • 63
  • 67

4 Answers4

23

As suggested by @dwc, here's a vim script:

let filename = '.gitignore'
if filereadable(filename)
    let igstring = ''
    for oline in readfile(filename)
        let line = substitute(oline, '\s|\n|\r', '', "g")
        if line =~ '^#' | con | endif
        if line == '' | con  | endif
        if line =~ '^!' | con  | endif
        if line =~ '/$' | let igstring .= "," . line . "*" | con | endif
        let igstring .= "," . line
    endfor
    let execstring = "set wildignore=".substitute(igstring, '^,', '', "g")
    execute execstring
endif

Take that source and put it in a file in your plugin directory, such as ~/.vim/plugin/gitignore.vim. It will read your .gitignore file and parse it, transforming its format into one suitable for wildignore, and then set that option.

Limitations:

  • This will read the .gitignore file from the directory where you launch vim. No effort is made to look for other .gitignore files and parse them. Alternatively, you could specify an absolute path to a file on the first line.
  • The wildignore option in vim doesn't support the notion of negating ignores like you can in a .gitignore file. That is, you can't say :set wildignore=*.html,!foo.html to have it ignore all html files except foo.html. Therefore, .gitignore lines that start with ! are simply ignored.
Adam Bellaire
  • 108,003
  • 19
  • 148
  • 163
21

Vim will ignore file patterns specified in option wildignore , so you can set them like so:

:set wildignore=*.o,*~,*.pyc

Or place the same line (without the ":") in your ~/.vimrc file. If you need something more dynamic like adjusting to the .gitignore in the current directory then you'll need to do some scripting, but I'll leave that as an exercise for someone else.

orftz
  • 1,138
  • 13
  • 22
dwc
  • 24,196
  • 7
  • 44
  • 55
  • 3
    Great answer. Note: You can't have spaces between the \*.o \*~ and \*.pyc, so it should be: `:set wildignore=*.o,*~,*.pyc`. Cheers – Brian M. Hunt Feb 15 '10 at 15:36
3

I wrote a plugin for this: https://github.com/octref/RootIgnore

It can add .gitignore patterns to your wildignore automatically.
Some handy features:

  • When you are in a sub directory, like this:
my_proj/  
   .gitignore  
   .git/
   sub/

If you cd into sub, and open Vim there, the plugin goes recursively up to find the .gitignore and add it to wildignore.

  • You can easily add ~/.gitignore rules by let g:RootIgnoreUseHome = 1.
octref
  • 6,521
  • 7
  • 28
  • 44
0

my first vimscript, lmk how to improve.

  1. For file, add it to path. running git check-ignore is time-consuming.
  2. For directory & is ignored by git, add it to wildignore (doesn't help with :find, may be useful for completion)
function! s:git_ignore_check()
    let pathstring = ''
    let igstring = ''

    " all files in current directory, non-recursive
    for filename in split(globpath('.', '*'), '\n')
        let isdir = isdirectory(filename)
        let should_ignore = 0

        " to search file at .\DirName\SubDir\Filename.txt with :find
        " path=DirName\** works, but path=.\DirName\** won't
        let filename_better = substitute(filename, '.\\', '', 'g') 
        if isdir == 1
            " running it on Windows. For Linux/Mac, might use '/**' instead
            let filename_better .= '\\**'
        endif

        if isdir == 1
            " only run git check-ignore for directory
            let gitignore_command = "git check-ignore " . filename
            if system(gitignore_command) != ""
                let should_ignore = 1
            endif
        endif

        if should_ignore
            let igstring .= ',' . filename_better
        else
            let pathstring .= ',' . filename_better
        endif
    endfor
    execute "set wildignore+=".substitute(igstring, '^,', '', "g")
    execute  "set path=".pathstring
endfunction

" hit capital H to run on current directory
nnoremap <silent> H :call <SID>git_ignore_check()<CR>