707
|
1 " =============================================================================
|
|
2 " File: autoload/ctrlp/autoignore.vim
|
|
3 " Description: Auto-ignore Extension
|
|
4 " Author: Ludovic Chabant <github.com/ludovicchabant>
|
|
5 " =============================================================================
|
|
6
|
|
7
|
|
8 " Global Settings {{{
|
|
9
|
|
10 if exists('g:ctrlp_autoignore_loaded') && g:ctrlp_autoignore_loaded
|
|
11 \ && !g:ctrlp_autoignore_debug
|
|
12 finish
|
|
13 endif
|
|
14 let g:ctrlp_autoignore_loaded = 1
|
|
15
|
|
16 if !exists('g:ctrlp_autoignore_debug')
|
|
17 let g:ctrlp_autoignore_debug = 0
|
|
18 endif
|
|
19
|
|
20 if !exists('g:ctrlp_autoignore_trace')
|
|
21 let g:ctrlp_autoignore_trace = 0
|
|
22 endif
|
|
23
|
|
24 " }}}
|
|
25
|
|
26 " Initialization {{{
|
|
27
|
|
28 if !exists('g:ctrlp_custom_ignore')
|
|
29 let g:ctrlp_custom_ignore = {}
|
|
30 endif
|
|
31 let g:ctrlp_custom_ignore['func'] = 'ctrlp#autoignore#ignore'
|
|
32 let g:ctrlp_custom_ignore['func-init'] = 'ctrlp#autoignore#ignore_init'
|
|
33 let g:ctrlp_custom_ignore['func-close'] = 'ctrlp#autoignore#ignore_close'
|
|
34
|
|
35 if !exists('g:ctrlp_root_markers')
|
|
36 let g:ctrlp_root_markers = []
|
|
37 endif
|
|
38 call add(g:ctrlp_root_markers, '.ctrlpignore')
|
|
39
|
|
40 " }}}
|
|
41
|
|
42 " Internals {{{
|
|
43
|
|
44 function! s:trace(message) abort
|
|
45 if g:ctrlp_autoignore_trace
|
|
46 echom "ctrlp_autoignore: " . a:message
|
|
47 endif
|
|
48 endfunction
|
|
49
|
|
50 let s:proj_cache = {}
|
|
51 let s:active_cwd = ''
|
|
52 let s:active_cwd_len = 0
|
|
53 let s:active_patterns = []
|
|
54 let s:changed_wildignore = 0
|
|
55 let s:prev_wildignore = ''
|
|
56
|
|
57 function! s:load_project_patterns(root_dir) abort
|
|
58 let l:ign_path = a:root_dir . '/.ctrlpignore'
|
|
59 if !filereadable(l:ign_path)
|
|
60 call s:trace("No pattern file at: " . l:ign_path)
|
|
61 return []
|
|
62 endif
|
|
63 let l:cursyntax = 'regexp'
|
|
64 let l:knownsyntaxes = ['regexp', 'wildignore']
|
|
65 let l:patterns = []
|
|
66 let l:lines = readfile(l:ign_path)
|
|
67 for line in l:lines
|
|
68 " Comment line?
|
|
69 if match(line, '\v^\s*$') >= 0 || match(line, '\v^\s*#') >= 0
|
|
70 continue
|
|
71 endif
|
|
72 " Syntax change?
|
|
73 let l:matches = matchlist(line, '\v^syntax:\s?(\w+)\s*$')
|
|
74 if len(l:matches) > 0
|
|
75 let l:cursyntax = l:matches[1]
|
|
76 if index(l:knownsyntaxes, l:cursyntax) < 0
|
|
77 echoerr "ctrlp_autoignore: Unknown syntax '".l:cursyntax."' in: ".l:ign_path
|
|
78 endif
|
|
79 continue
|
|
80 endif
|
|
81 " Patterns!
|
|
82 let l:matches = matchlist(line, '\v^((dir|file|link)\:)?(.*)')
|
|
83 let l:mtype = l:matches[2]
|
|
84 let l:mpat = l:matches[3]
|
|
85 call add(l:patterns, {'syn': l:cursyntax, 'type': l:mtype, 'pat': l:mpat})
|
|
86 endfor
|
|
87 call s:trace("Loaded " . len(l:patterns) . " patterns from: " . l:ign_path)
|
|
88 return l:patterns
|
|
89 endfunction
|
|
90
|
|
91 function! s:get_project_patterns(root_dir) abort
|
|
92 let l:ign_path = a:root_dir . '/.ctrlpignore'
|
|
93 let l:ign_mtime = getftime(l:ign_path)
|
|
94 let l:patterns = get(s:proj_cache, a:root_dir)
|
|
95 if type(l:patterns) == type({})
|
|
96 " Check that these patterns are still valid.
|
|
97 if l:ign_mtime < 0
|
|
98 " File got deleted! :(
|
|
99 let l:patterns['pats'] = []
|
|
100 return l:patterns['pats']
|
|
101 elseif l:ign_mtime <= l:patterns['mtime']
|
|
102 " File hasn't changed! :)
|
|
103 return l:patterns['pats']
|
|
104 endif
|
|
105 endif
|
|
106
|
|
107 call s:trace("Loading patterns for project: " . a:root_dir)
|
|
108 let l:loaded = s:load_project_patterns(a:root_dir)
|
|
109 let s:proj_cache[a:root_dir] = {
|
|
110 \'mtime': localtime(),
|
|
111 \'pats': l:loaded}
|
|
112 return l:loaded
|
|
113 endfunction
|
|
114
|
|
115 " The custom ignore function that CtrlP will be using in addition to
|
|
116 " normal pattern-based matching.
|
|
117 function! ctrlp#autoignore#ignore(item, type) abort
|
|
118 let l:cnv_item = tr(strpart(a:item, s:active_cwd_len), "\\", "/")
|
|
119 for pat in s:active_patterns
|
|
120 if pat['syn'] != 'regexp'
|
|
121 continue
|
|
122 endif
|
|
123 if pat['type'] == '' || pat['type'] == a:type
|
|
124 if match(l:cnv_item, pat['pat']) >= 0
|
|
125 call s:trace("Ignoring ".l:cnv_item." because of ".pat['pat'])
|
|
126 return 1
|
|
127 endif
|
|
128 endif
|
|
129 endfor
|
|
130 return 0
|
|
131 endfunction
|
|
132
|
|
133 function! ctrlp#autoignore#ignore_init() abort
|
|
134 let l:root = getcwd()
|
|
135 let s:active_cwd = l:root
|
|
136 " len+1 is for including the next separator after the root.
|
|
137 let s:active_cwd_len = len(l:root) + 1
|
|
138 let s:active_patterns = s:get_project_patterns(l:root)
|
|
139 call s:trace("Got ".len(s:active_patterns)." patterns for ".l:root)
|
|
140
|
|
141 let s:changed_wildignore = 0
|
|
142 let s:prev_wildignore = &wildignore
|
|
143 for pat in s:active_patterns
|
|
144 if pat['syn'] == 'wildignore'
|
|
145 execute 'set wildignore+='.pat['pat']
|
|
146 let s:changed_wildignore = 1
|
|
147 endif
|
|
148 endfor
|
|
149 if s:changed_wildignore
|
|
150 call s:trace("Set wildignore to ".&wildignore)
|
|
151 endif
|
|
152 endfunction
|
|
153
|
|
154 function! ctrlp#autoignore#ignore_close() abort
|
|
155 if s:changed_wildignore
|
|
156 execute 'set wildignore='.s:prev_wildignore
|
|
157 let s:prev_wildignore = ''
|
|
158 call s:trace("Set wildignore back to ".&wildignore)
|
|
159 endif
|
|
160 endfunction
|
|
161
|
|
162 " List patterns for a given project's root.
|
|
163 function! ctrlp#autoignore#get_patterns(root_dir) abort
|
|
164 let l:patterns = s:get_project_patterns(a:root_dir)
|
|
165 for pat in l:patterns
|
|
166 let l:prefix = pat['type'] == '' ? '(all)' : pat['type']
|
|
167 echom l:prefix . ':' . pat['pat']
|
|
168 endfor
|
|
169 endfunction
|
|
170
|
|
171 " }}}
|
|
172
|
|
173 " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|