comparison vim/vimfiles/autoload/ctrlp.vim @ 3:92af3257a261

Update to latest ctrlp.vim.
author Brian Neal <bgneal@gmail.com>
date Wed, 04 Jan 2012 19:37:22 -0600
parents 48859d9c82c5
children
comparison
equal deleted inserted replaced
2:611e13daeafb 3:92af3257a261
1 " ============================================================================= 1 " =============================================================================
2 " File: autoload/ctrlp.vim 2 " File: autoload/ctrlp.vim
3 " Description: Fuzzy file, buffer, mru and tag finder. 3 " Description: Fuzzy file, buffer, mru and tag finder.
4 " Author: Kien Nguyen <github.com/kien> 4 " Author: Kien Nguyen <github.com/kien>
5 " Version: 1.6.4 5 " Version: 1.6.5
6 " ============================================================================= 6 " =============================================================================
7 7
8 " Static variables {{{1 8 " Static variables {{{1
9 fu! s:opts() 9 fu! s:opts()
10 let hst = exists('+hi') ? &hi : 20 10 let hst = exists('+hi') ? &hi : 20
11 let opts = { 11 let opts = {
12 \ 'g:ctrlp_by_filename': ['s:byfname', 0], 12 \ 'g:ctrlp_by_filename': ['s:byfname', 0],
13 \ 'g:ctrlp_clear_cache_on_exit': ['s:clrex', 1], 13 \ 'g:ctrlp_clear_cache_on_exit': ['s:clrex', 1],
14 \ 'g:ctrlp_custom_ignore': ['s:usrign', ''],
14 \ 'g:ctrlp_dont_split': ['s:nosplit', ''], 15 \ 'g:ctrlp_dont_split': ['s:nosplit', ''],
15 \ 'g:ctrlp_dotfiles': ['s:dotfiles', 1], 16 \ 'g:ctrlp_dotfiles': ['s:dotfiles', 1],
16 \ 'g:ctrlp_extensions': ['s:extensions', []], 17 \ 'g:ctrlp_extensions': ['s:extensions', []],
17 \ 'g:ctrlp_follow_symlinks': ['s:folsym', 0], 18 \ 'g:ctrlp_follow_symlinks': ['s:folsym', 0],
18 \ 'g:ctrlp_highlight_match': ['s:mathi', [1, 'Identifier']], 19 \ 'g:ctrlp_highlight_match': ['s:mathi', [1, 'Identifier']],
19 \ 'g:ctrlp_lazy_update': ['s:lazy', 0], 20 \ 'g:ctrlp_lazy_update': ['s:lazy', 0],
20 \ 'g:ctrlp_jump_to_buffer': ['s:jmptobuf', 1], 21 \ 'g:ctrlp_jump_to_buffer': ['s:jmptobuf', 2],
21 \ 'g:ctrlp_match_window_bottom': ['s:mwbottom', 1], 22 \ 'g:ctrlp_match_window_bottom': ['s:mwbottom', 1],
22 \ 'g:ctrlp_match_window_reversed': ['s:mwreverse', 1], 23 \ 'g:ctrlp_match_window_reversed': ['s:mwreverse', 1],
23 \ 'g:ctrlp_max_depth': ['s:maxdepth', 40], 24 \ 'g:ctrlp_max_depth': ['s:maxdepth', 40],
24 \ 'g:ctrlp_max_files': ['s:maxfiles', 20000], 25 \ 'g:ctrlp_max_files': ['s:maxfiles', 20000],
25 \ 'g:ctrlp_max_height': ['s:mxheight', 10], 26 \ 'g:ctrlp_max_height': ['s:mxheight', 10],
51 let s:lash = ctrlp#utils#lash() 52 let s:lash = ctrlp#utils#lash()
52 53
53 " Global options 54 " Global options
54 let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0, 55 let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0,
55 \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'mouse': 'n', 56 \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'mouse': 'n',
56 \ 'gcr': 'a:block-PmenuSel-blinkon0' } 57 \ 'gcr': 'a:blinkon0' }
57 58
58 if s:lazy 59 if s:lazy
59 cal extend(s:glbs, { 'ut': ( s:lazy > 1 ? s:lazy : 250 ) }) 60 cal extend(s:glbs, { 'ut': ( s:lazy > 1 ? s:lazy : 250 ) })
60 en 61 en
61 62
62 " Limiters 63 " Limiters
63 let [s:compare_lim, s:nocache_lim, s:mltipats_lim] = [3000, 4000, 2000] 64 let [s:compare_lim, s:nocache_lim, s:mltipats_lim] = [3000, 4000, 2000]
64 " * Open & Close {{{1 65 " * Open & Close {{{1
65 fu! s:Open() 66 fu! s:Open()
67 if exists('g:ctrlp_log') && g:ctrlp_log
68 sil! exe 'redi >>' ctrlp#utils#cachedir().s:lash.'ctrlp.log'
69 en
66 let [s:cwd, s:winres] = [getcwd(), winrestcmd()] 70 let [s:cwd, s:winres] = [getcwd(), winrestcmd()]
67 let [s:crfile, s:crfpath] = [expand('%:p', 1), expand('%:p:h', 1)] 71 let [s:crfile, s:crfpath] = [expand('%:p', 1), expand('%:p:h', 1)]
68 let [s:crword, s:crline] = [expand('<cword>'), getline('.')] 72 let [s:crword, s:crline] = [expand('<cword>'), getline('.')]
69 let [s:tagfiles, s:crcursor] = [s:tagfiles(), getpos('.')] 73 let [s:tagfiles, s:crcursor] = [s:tagfiles(), getpos('.')]
70 let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()] 74 let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()]
93 endfo 97 endfo
94 if exists('s:glb_acd') | let &acd = s:glb_acd | en 98 if exists('s:glb_acd') | let &acd = s:glb_acd | en
95 let [g:ctrlp_lines, g:ctrlp_allfiles] = [[], []] 99 let [g:ctrlp_lines, g:ctrlp_allfiles] = [[], []]
96 exe s:winres 100 exe s:winres
97 unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:cline s:init s:savestr 101 unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:cline s:init s:savestr
98 \ s:crfile s:crfpath s:crword s:crvisual s:tagfiles s:crline s:crcursor 102 \ g:ctrlp_nolimit
99 \ g:ctrlp_nolimit s:crbufnr
100 cal ctrlp#recordhist() 103 cal ctrlp#recordhist()
104 if exists('g:ctrlp_log') && g:ctrlp_log
105 sil! redi END
106 en
101 ec 107 ec
102 endf 108 endf
103 " * Clear caches {{{1 109 " * Clear caches {{{1
104 fu! ctrlp#clr(...) 110 fu! ctrlp#clr(...)
105 exe 'let g:ctrlp_new'.( exists('a:1') ? a:1 : 'cache' ).' = 1' 111 exe 'let g:ctrlp_new'.( exists('a:1') ? a:1 : 'cache' ).' = 1'
124 cal ctrlp#utils#opts() 130 cal ctrlp#utils#opts()
125 cal ctrlp#mrufiles#opts() 131 cal ctrlp#mrufiles#opts()
126 unl! s:cline 132 unl! s:cline
127 endf 133 endf
128 " * Files() {{{1 134 " * Files() {{{1
129 fu! s:GlobPath(dirs, allfiles, depth) 135 fu! s:Files()
136 let [cwd, cafile, g:ctrlp_allfiles] = [getcwd(), ctrlp#utils#cachefile(), []]
137 if g:ctrlp_newcache || !filereadable(cafile) || !s:caching
138 let lscmd = s:lsCmd()
139 " Get the list of files
140 if empty(lscmd)
141 cal s:GlobPath(cwd, 0)
142 el
143 sil! cal ctrlp#progress('Indexing...')
144 try | cal s:UserCmd(cwd, lscmd) | cat | retu [] | endt
145 en
146 " Remove base directory
147 cal ctrlp#rmbasedir(g:ctrlp_allfiles)
148 let read_cache = 0
149 el
150 let g:ctrlp_allfiles = ctrlp#utils#readfile(cafile)
151 let read_cache = 1
152 en
153 if len(g:ctrlp_allfiles) <= s:compare_lim
154 cal sort(g:ctrlp_allfiles, 'ctrlp#complen')
155 en
156 cal s:writecache(read_cache, cafile)
157 retu g:ctrlp_allfiles
158 endf
159
160 fu! s:GlobPath(dirs, depth)
130 let entries = split(globpath(a:dirs, s:glob), "\n") 161 let entries = split(globpath(a:dirs, s:glob), "\n")
131 if !s:folsym 162 if s:usrign != ''
132 let entries = filter(entries, 'getftype(v:val) != "link"') 163 cal filter(entries, 'v:val !~ s:usrign')
133 en 164 en
134 let g:ctrlp_allfiles = filter(copy(entries), '!isdirectory(v:val)') 165 let [dnf, depth] = [ctrlp#dirnfile(entries), a:depth + 1]
135 let ftrfunc = s:dotfiles ? 'ctrlp#dirfilter(v:val)' : 'isdirectory(v:val)' 166 cal extend(g:ctrlp_allfiles, dnf[1])
136 let alldirs = filter(entries, ftrfunc) 167 if !empty(dnf[0]) && !s:maxf(len(g:ctrlp_allfiles)) && depth <= s:maxdepth
137 cal extend(g:ctrlp_allfiles, a:allfiles, 0)
138 let depth = a:depth + 1
139 if !empty(alldirs) && !s:maxfiles(len(g:ctrlp_allfiles)) && depth <= s:maxdepth
140 sil! cal ctrlp#progress(len(g:ctrlp_allfiles)) 168 sil! cal ctrlp#progress(len(g:ctrlp_allfiles))
141 cal s:GlobPath(join(alldirs, ','), g:ctrlp_allfiles, depth) 169 cal s:GlobPath(join(dnf[0], ','), depth)
142 en 170 en
143 endf 171 endf
144 172
145 fu! s:UserCommand(path, lscmd) 173 fu! s:UserCmd(path, lscmd)
146 let path = a:path 174 let path = a:path
147 if exists('+ssl') && &ssl 175 if exists('+ssl') && &ssl
148 let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')] 176 let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')]
149 en 177 en
150 let path = exists('*shellescape') ? shellescape(path) : path 178 let path = exists('*shellescape') ? shellescape(path) : path
156 if exists('s:vcscmd') && s:vcscmd 184 if exists('s:vcscmd') && s:vcscmd
157 cal map(g:ctrlp_allfiles, 'tr(v:val, "/", "\\")') 185 cal map(g:ctrlp_allfiles, 'tr(v:val, "/", "\\")')
158 en 186 en
159 endf 187 endf
160 188
161 fu! s:Files() 189 fu! s:lsCmd()
162 let [cwd, cache_file] = [getcwd(), ctrlp#utils#cachefile()] 190 let cmd = s:usrcmd
163 if g:ctrlp_newcache || !filereadable(cache_file) || !s:caching 191 if type(cmd) == 1
164 let lscmd = s:lscommand() 192 retu cmd
165 " Get the list of files 193 elsei type(cmd) == 3 && len(cmd) >= 2 && !empty(cmd[0]) && !empty(cmd[1])
166 if empty(lscmd) 194 let rmarker = cmd[0]
167 cal s:GlobPath(cwd, [], 0) 195 " Find a repo root
168 el 196 cal s:findroot(getcwd(), rmarker, 0, 1)
169 sil! cal ctrlp#progress('Waiting...') 197 if !exists('s:vcsroot') || ( exists('s:vcsroot') && empty(s:vcsroot) )
170 try | cal s:UserCommand(cwd, lscmd) | cat | retu [] | endt 198 " Try the secondary_command
171 en 199 retu len(cmd) == 3 ? cmd[2] : ''
172 " Remove base directory 200 en
173 cal ctrlp#rmbasedir(g:ctrlp_allfiles) 201 let s:vcscmd = s:lash == '\' ? 1 : 0
174 let read_cache = 0 202 retu cmd[1]
175 el 203 en
176 let g:ctrlp_allfiles = ctrlp#utils#readfile(cache_file)
177 let read_cache = 1
178 en
179 if len(g:ctrlp_allfiles) <= s:compare_lim
180 cal sort(g:ctrlp_allfiles, 'ctrlp#complen')
181 en
182 cal s:writecache(read_cache, cache_file)
183 retu g:ctrlp_allfiles
184 endf 204 endf
185 fu! s:Buffers() "{{{1 205 fu! s:Buffers() "{{{1
186 let allbufs = [] 206 let allbufs = []
187 for each in range(1, bufnr('$')) 207 for each in range(1, bufnr('$'))
188 if getbufvar(each, '&bl') && each != bufnr('#') 208 if getbufvar(each, '&bl') && each != s:crbufnr
189 let bufname = bufname(each) 209 let bufname = bufname(each)
190 if strlen(bufname) && getbufvar(each, '&ma') && bufname != 'ControlP' 210 if strlen(bufname) && getbufvar(each, '&ma') && bufname != 'ControlP'
191 cal add(allbufs, fnamemodify(bufname, ':p')) 211 cal add(allbufs, fnamemodify(bufname, ':p'))
192 en 212 en
193 en 213 en
194 endfo 214 endfo
195 retu allbufs 215 retu allbufs
196 endf 216 endf
197 " * MatchedItems() {{{1 217 " * MatchedItems() {{{1
198 fu! s:MatchIt(items, pat, limit, ispathitem) 218 fu! s:MatchIt(items, pat, limit, ispathitem, mfunc)
199 let [items, pat, limit, newitems] = [a:items, a:pat, a:limit, []] 219 let newitems = []
200 let mfunc = s:byfname && a:ispathitem ? 's:matchfname' 220 for item in a:items
201 \ : s:itemtype > 2 && len(items) < 30000 && !a:ispathitem ? 's:matchtab' 221 if call(a:mfunc, [item, a:pat]) >= 0 | cal add(newitems, item) | en
202 \ : 'match' 222 if a:limit > 0 && len(newitems) >= a:limit | brea | en
203 for item in items
204 if call(mfunc, [item, pat]) >= 0 | cal add(newitems, item) | en
205 if limit > 0 && len(newitems) >= limit | brea | en
206 endfo 223 endfo
207 retu newitems 224 retu newitems
208 endf 225 endf
209 226
210 fu! s:MatchedItems(items, pats, limit) 227 fu! s:MatchedItems(items, pats, limit)
211 let [items, pats, limit, ipt] = [a:items, a:pats, a:limit, s:ispathitem()] 228 let [items, pats, limit, ipt] = [a:items, a:pats, a:limit, s:ispathitem()]
212 " If items is longer than s:mltipats_lim, use only the last pattern 229 " If items is longer than s:mltipats_lim, use only the last pattern
213 if len(items) >= s:mltipats_lim | let pats = [pats[-1]] | en 230 if len(items) >= s:mltipats_lim | let pats = [pats[-1]] | en
214 cal map(pats, 'substitute(v:val, "\\\~", "\\\\\\~", "g")') 231 cal map(pats, 'substitute(v:val, "\\\~", "\\\\\\~", "g")')
215 if !s:regexp | cal map(pats, 'escape(v:val, ".")') | en 232 if !s:regexp | cal map(pats, 'escape(v:val, ".")') | en
233 let mfunc = s:byfname && ipt ? 's:matchfname'
234 \ : s:itemtype > 2 && len(items) < 30000 && !ipt ? 's:matchtab'
235 \ : 'match'
216 " Loop through the patterns 236 " Loop through the patterns
217 for each in pats 237 for pat in pats
218 " If newitems is small, set it as items to search in 238 " If newitems is small, set it as items to search in
219 if exists('newitems') && len(newitems) < limit 239 if exists('newitems') && len(newitems) < limit
220 let items = copy(newitems) 240 let items = copy(newitems)
221 en 241 en
222 if empty(items) " End here 242 if empty(items) " End here
223 retu exists('newitems') ? newitems : [] 243 retu exists('newitems') ? newitems : []
224 el " Start here, go back up if have 2 or more in pats 244 el " Start here, go back up if have 2 or more in pats
225 " Loop through the items 245 " Loop through the items
226 let newitems = s:MatchIt(items, each, limit, ipt) 246 let newitems = s:MatchIt(items, pat, limit, ipt, mfunc)
227 en 247 en
228 endfo 248 endfo
229 let s:matches = len(newitems) 249 let s:matches = len(newitems)
230 retu newitems 250 retu newitems
231 endf 251 endf
261 let nitem = !empty(array) ? array[0] : '' 281 let nitem = !empty(array) ? array[0] : ''
262 let newpats = [nitem] 282 let newpats = [nitem]
263 if len(array) > 1 283 if len(array) > 1
264 for item in range(1, len(array) - 1) 284 for item in range(1, len(array) - 1)
265 " Separator 285 " Separator
266 let sep = exists('a:1') ? a:1 : '[^'.array[item-1].']\{-}' 286 let sep = a:0 ? a:1 : '[^'.array[item-1].']\{-}'
267 let nitem .= sep.array[item] 287 let nitem .= sep.array[item]
268 cal add(newpats, nitem) 288 cal add(newpats, nitem)
269 endfo 289 endfo
270 en 290 en
271 retu newpats 291 retu newpats
292 cal sort(lines, 's:mixedsort') 312 cal sort(lines, 's:mixedsort')
293 unl s:compat 313 unl s:compat
294 en 314 en
295 if s:mwreverse | cal reverse(lines) | en 315 if s:mwreverse | cal reverse(lines) | en
296 let s:matched = copy(lines) 316 let s:matched = copy(lines)
297 cal map(lines, 'substitute(v:val, "^", "> ", "")') 317 cal map(lines, '"> ".v:val')
298 cal setline(1, lines) 318 cal setline(1, lines)
299 exe 'keepj norm!' s:mwreverse ? 'G' : 'gg' 319 exe 'keepj norm!' s:mwreverse ? 'G' : 'gg'
300 keepj norm! 1| 320 keepj norm! 1|
301 cal s:unmarksigns() 321 cal s:unmarksigns()
302 cal s:remarksigns() 322 cal s:remarksigns()
310 fu! s:Update(str) 330 fu! s:Update(str)
311 " Get the previous string if existed 331 " Get the previous string if existed
312 let oldstr = exists('s:savestr') ? s:savestr : '' 332 let oldstr = exists('s:savestr') ? s:savestr : ''
313 let pats = s:SplitPattern(a:str) 333 let pats = s:SplitPattern(a:str)
314 " Get the new string sans tail 334 " Get the new string sans tail
315 let notail = substitute(a:str, ':\([^:]\|\\:\)*$', '', 'g') 335 let notail = substitute(a:str, '\\\\', '\', 'g')
336 let notail = substitute(notail, '\\\@<!:\([^:]\|\\:\)*$', '', '')
337 let notail = substitute(notail, '\\\ze:', '', 'g')
316 " Stop if the string's unchanged 338 " Stop if the string's unchanged
317 if notail == oldstr && !empty(notail) && !exists('s:force') 339 if notail == oldstr && !empty(notail) && !exists('s:force')
318 retu 340 retu
319 en 341 en
320 let lines = exists('g:ctrlp_nolimit') && empty(notail) ? copy(g:ctrlp_lines) 342 let lines = exists('g:ctrlp_nolimit') && empty(notail) ? copy(g:ctrlp_lines)
321 \ : s:MatchedItems(g:ctrlp_lines, pats, s:mxheight) 343 \ : s:MatchedItems(g:ctrlp_lines, copy(pats), s:mxheight)
322 cal s:Render(lines, pats[-1]) 344 cal s:Render(lines, pats[-1])
323 endf 345 endf
324 346
325 fu! s:ForceUpdate() 347 fu! s:ForceUpdate()
326 let [estr, prt] = ['"\', copy(s:prompt)] 348 let [estr, prt] = ['"\', copy(s:prompt)]
332 let base = ( s:regexp ? 'r' : '>' ).( s:byfname ? 'd' : '>' ).'> ' 354 let base = ( s:regexp ? 'r' : '>' ).( s:byfname ? 'd' : '>' ).'> '
333 let [estr, prt] = ['"\', copy(s:prompt)] 355 let [estr, prt] = ['"\', copy(s:prompt)]
334 cal map(prt, 'escape(v:val, estr)') 356 cal map(prt, 'escape(v:val, estr)')
335 let str = join(prt, '') 357 let str = join(prt, '')
336 let lazy = empty(str) || exists('s:force') || !has('autocmd') ? 0 : s:lazy 358 let lazy = empty(str) || exists('s:force') || !has('autocmd') ? 0 : s:lazy
337 if a:upd && ( s:matches || s:regexp || match(str, '[*|]') >= 0 ) && !lazy 359 if a:upd && !lazy && ( s:matches || s:regexp
360 \ || match(str, '[*|]') >= 0 || match(str, '\\\:\([^:]\|\\:\)*$') >= 0 )
338 sil! cal s:Update(str) 361 sil! cal s:Update(str)
339 en 362 en
340 sil! cal ctrlp#statusline() 363 sil! cal ctrlp#statusline()
341 " Toggling 364 " Toggling
342 let [hiactive, hicursor, base] = exists('a:1') && !a:1 365 let [hiactive, hicursor, base] = exists('a:1') && !a:1
539 \ 'AcceptSelection("t")': ['<c-t>', '<MiddleMouse>'], 562 \ 'AcceptSelection("t")': ['<c-t>', '<MiddleMouse>'],
540 \ 'AcceptSelection("v")': ['<c-v>', '<c-q>', '<RightMouse>'], 563 \ 'AcceptSelection("v")': ['<c-v>', '<c-q>', '<RightMouse>'],
541 \ 'ToggleFocus()': ['<tab>'], 564 \ 'ToggleFocus()': ['<tab>'],
542 \ 'ToggleRegex()': ['<c-r>'], 565 \ 'ToggleRegex()': ['<c-r>'],
543 \ 'ToggleByFname()': ['<c-d>'], 566 \ 'ToggleByFname()': ['<c-d>'],
544 \ 'ToggleType(1)': ['<c-f>', '<c-up'], 567 \ 'ToggleType(1)': ['<c-f>', '<c-up>'],
545 \ 'ToggleType(-1)': ['<c-b>', '<c-down>'], 568 \ 'ToggleType(-1)': ['<c-b>', '<c-down>'],
546 \ 'PrtInsert("w")': ['<F2>'], 569 \ 'PrtInsert("w")': ['<F2>'],
547 \ 'PrtInsert("s")': ['<F3>'], 570 \ 'PrtInsert("s")': ['<F3>'],
548 \ 'PrtInsert("v")': ['<F4>'], 571 \ 'PrtInsert("v")': ['<F4>'],
549 \ 'PrtInsert("+")': ['<F6>'], 572 \ 'PrtInsert("+")': ['<F6>'],
561 if type(s:urprtmaps) == 4 584 if type(s:urprtmaps) == 4
562 cal extend(prtmaps, s:urprtmaps) 585 cal extend(prtmaps, s:urprtmaps)
563 en 586 en
564 " Correct arrow keys in terminal 587 " Correct arrow keys in terminal
565 if ( has('termresponse') && !empty(v:termresponse) ) 588 if ( has('termresponse') && !empty(v:termresponse) )
566 \ || &term =~? 'xterm\|\<k\?vt\|gnome\|screen' 589 \ || &term =~? 'xterm\|\<k\?vt\|gnome\|screen\|linux'
567 for each in ['\A <up>','\B <down>','\C <right>','\D <left>'] 590 for each in ['\A <up>','\B <down>','\C <right>','\D <left>']
568 exe lcmap.' <esc>['.each 591 exe lcmap.' <esc>['.each
569 endfo 592 endfo
570 en 593 en
571 if exists('a:1') 594 if exists('a:1')
667 let [md, matchstr] = [a:mode, a:matchstr] 690 let [md, matchstr] = [a:mode, a:matchstr]
668 " Get the full path 691 " Get the full path
669 let filpath = s:itemtype ? matchstr : getcwd().s:lash.matchstr 692 let filpath = s:itemtype ? matchstr : getcwd().s:lash.matchstr
670 cal s:PrtExit() 693 cal s:PrtExit()
671 let bufnum = bufnr(filpath) 694 let bufnum = bufnr(filpath)
672 if s:jmptobuf && bufnum > 0 && md == 'e' 695 if s:jmptobuf && bufnum > 0 && md =~ 'e\|t'
673 let [jmpb, bufwinnr] = [1, bufwinnr(bufnum)] 696 let [jmpb, bufwinnr] = [1, bufwinnr(bufnum)]
674 let buftab = s:jmptobuf > 1 ? s:buftab(bufnum) : [0, 0] 697 let buftab = s:jmptobuf > 1 ? s:buftab(bufnum, md) : [0, 0]
675 let j2l = a:0 ? a:1 : str2nr(matchstr(s:tail(), '^ +\zs\d\+$')) 698 let j2l = a:0 ? a:1 : str2nr(matchstr(s:tail(), '^ +\zs\d\+$'))
676 en 699 en
677 " Switch to existing buffer or open new one 700 " Switch to existing buffer or open new one
678 if exists('jmpb') && buftab[0] 701 if exists('jmpb') && bufwinnr > 0 && md != 't'
679 exe 'tabn' buftab[1]
680 exe buftab[0].'winc w'
681 if j2l | cal s:j2l(j2l) | en
682 elsei exists('jmpb') && bufwinnr > 0
683 exe bufwinnr.'winc w' 702 exe bufwinnr.'winc w'
684 if j2l | cal s:j2l(j2l) | en 703 if j2l | cal ctrlp#j2l(j2l) | en
704 elsei exists('jmpb') && buftab[0]
705 exe 'tabn' buftab[0]
706 exe buftab[1].'winc w'
707 if j2l | cal ctrlp#j2l(j2l) | en
685 el 708 el
686 " Determine the command to use 709 " Determine the command to use
687 let cmd = md == 't' || s:splitwin == 1 ? 'tabe' 710 let cmd = md == 't' || s:splitwin == 1 ? 'tabe'
688 \ : md == 'h' || s:splitwin == 2 ? 'new' 711 \ : md == 'h' || s:splitwin == 2 ? 'new'
689 \ : md == 'v' || s:splitwin == 3 ? 'vne' : ctrlp#normcmd('e') 712 \ : md == 'v' || s:splitwin == 3 ? 'vne' : ctrlp#normcmd('e')
690 " Open new window/buffer 713 " Open new window/buffer
691 cal call('s:openfile', a:0 ? [cmd, filpath, ' +'.a:1] : [cmd, filpath]) 714 cal call('s:openfile', a:0 ? [cmd, filpath, ' +'.a:1] : [cmd, filpath])
692 en 715 en
693 endf 716 endf
694 717
695 fu! s:AcceptSelection(mode) 718 fu! s:SpecInputs()
696 if a:mode == 'e' | if s:specinputs() | retu | en | en
697 " Get the selected line
698 let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
699 if empty(matchstr) | retu | en
700 " Do something with it
701 let actfunc = s:itemtype =~ '0\|1\|2' ? 'ctrlp#acceptfile'
702 \ : g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][1]
703 cal call(actfunc, [a:mode, matchstr])
704 endf
705 fu! s:CreateNewFile() "{{{1
706 let str = join(s:prompt, '')
707 if empty(str) | retu | en
708 let str = s:sanstail(str)
709 let arr = split(str, '[\/]')
710 let fname = remove(arr, -1)
711 if len(arr) | if isdirectory(s:createparentdirs(arr))
712 let optyp = str
713 en | el
714 let optyp = fname
715 en
716 if exists('optyp')
717 let filpath = getcwd().s:lash.optyp
718 cal s:insertcache(str)
719 cal s:PrtExit()
720 let cmd = s:newfop == 1 ? 'tabe'
721 \ : s:newfop == 2 ? 'new'
722 \ : s:newfop == 3 ? 'vne' : ctrlp#normcmd('e')
723 cal s:openfile(cmd, filpath)
724 en
725 endf
726 " * OpenMulti() {{{1
727 fu! s:MarkToOpen()
728 if s:bufnr <= 0 || !s:opmul || s:itemtype > g:ctrlp_builtins | retu | en
729 let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
730 if empty(matchstr) | retu | en
731 let filpath = s:itemtype ? matchstr : getcwd().s:lash.matchstr
732 if exists('s:marked') && s:dictindex(s:marked, filpath) > 0
733 " Unmark and remove the file from s:marked
734 let key = s:dictindex(s:marked, filpath)
735 cal remove(s:marked, key)
736 if empty(s:marked) | unl! s:marked | en
737 if has('signs')
738 exe 'sign unplace' key 'buffer='.s:bufnr
739 en
740 el
741 " Add to s:marked and place a new sign
742 if exists('s:marked')
743 let vac = s:vacantdict(s:marked)
744 let key = empty(vac) ? len(s:marked) + 1 : vac[0]
745 let s:marked = extend(s:marked, { key : filpath })
746 el
747 let [key, s:marked] = [1, { 1 : filpath }]
748 en
749 if has('signs')
750 exe 'sign place' key 'line='.line('.').' name=ctrlpmark buffer='.s:bufnr
751 en
752 en
753 sil! cal ctrlp#statusline()
754 endf
755
756 fu! s:OpenMulti()
757 if !exists('s:marked') || !s:opmul
758 cal s:AcceptSelection('e')
759 retu
760 en
761 let mkd = s:marked
762 cal s:PrtExit()
763 " Try not to open a new tab
764 let [ntab, norwins] = [0, s:normbuf()]
765 if empty(norwins) | let ntab = 1 | el
766 for each in norwins
767 let bufnr = winbufnr(each)
768 if !empty(bufname(bufnr)) && !empty(getbufvar(bufnr, '&ft'))
769 \ && bufname(bufnr) != 'ControlP'
770 let ntab = 1
771 en
772 endfo
773 if !ntab | let wnr = min(norwins) | en
774 en
775 if ntab | tabnew | en
776 let [ic, wnr] = [1, exists('wnr') ? wnr : 1]
777 let cmds = { 'v': 'vne', 'h': 'new', 't': 'tabe' }
778 let spt = len(s:opmul) > 1 ? cmds[matchstr(s:opmul, '\w$')] : 'vne'
779 let nr = matchstr(s:opmul, '^\d\+')
780 exe wnr.'winc w'
781 for [ke, va] in items(mkd)
782 let cmd = ic == 1 ? 'e' : spt
783 cal s:openfile(cmd, va)
784 if nr > 1 && nr < ic | clo! | el | let ic += 1 | en
785 endfo
786 endf
787 " ** Helper functions {{{1
788 " Sorting {{{2
789 fu! ctrlp#complen(s1, s2)
790 " By length
791 let [len1, len2] = [strlen(a:s1), strlen(a:s2)]
792 retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
793 endf
794
795 fu! s:compmatlen(s1, s2)
796 " By match length
797 let mln1 = s:shortest(s:matchlens(a:s1, s:compat))
798 let mln2 = s:shortest(s:matchlens(a:s2, s:compat))
799 retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
800 endf
801
802 fu! s:comptime(s1, s2)
803 " By last modified time
804 let [time1, time2] = [getftime(a:s1), getftime(a:s2)]
805 retu time1 == time2 ? 0 : time1 < time2 ? 1 : -1
806 endf
807
808 fu! s:comparent(s1, s2)
809 " By same parent dir
810 if match(s:crfpath, escape(getcwd(), '.^$*\')) >= 0
811 let [as1, as2] = [getcwd().s:lash.a:s1, getcwd().s:lash.a:s2]
812 let [loc1, loc2] = [s:getparent(as1), s:getparent(as2)]
813 if loc1 == s:crfpath && loc2 != s:crfpath | retu -1 | en
814 if loc2 == s:crfpath && loc1 != s:crfpath | retu 1 | en
815 retu 0
816 en
817 retu 0
818 endf
819
820 fu! s:matchlens(str, pat, ...)
821 if empty(a:pat) || index(['^','$'], a:pat) >= 0 | retu {} | en
822 let st = exists('a:1') ? a:1 : 0
823 let lens = exists('a:2') ? a:2 : {}
824 let nr = exists('a:3') ? a:3 : 0
825 if match(a:str, a:pat, st) != -1
826 let [mst, mnd] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)]
827 let lens = extend(lens, { nr : [len(mst), mst] })
828 let lens = s:matchlens(a:str, a:pat, mnd, lens, nr + 1)
829 en
830 retu lens
831 endf
832
833 fu! s:shortest(lens)
834 retu min(map(values(a:lens), 'v:val[0]'))
835 endf
836
837 fu! s:mixedsort(s1, s2)
838 let [cml, cln] = [s:compmatlen(a:s1, a:s2), ctrlp#complen(a:s1, a:s2)]
839 if s:itemtype < 3 && s:height < 51
840 let par = s:comparent(a:s1, a:s2)
841 if s:height < 21
842 retu 6 * cml + 3 * par + 2 * s:comptime(a:s1, a:s2) + cln
843 en
844 retu 3 * cml + 2 * par + cln
845 en
846 retu 2 * cml + cln
847 endf
848 " Statusline {{{2
849 fu! ctrlp#statusline(...)
850 if !exists('s:statypes')
851 let s:statypes = [
852 \ ['files', 'fil'],
853 \ ['buffers', 'buf'],
854 \ ['mru files', 'mru'],
855 \ ]
856 if exists('g:ctrlp_ext_vars')
857 cal map(copy(g:ctrlp_ext_vars), 'add(s:statypes, [ v:val[2], v:val[3] ])')
858 en
859 en
860 let tps = s:statypes
861 let max = len(tps) - 1
862 let nxt = tps[s:walker(max, s:itemtype, 1)][1]
863 let prv = tps[s:walker(max, s:itemtype, -1)][1]
864 let item = tps[s:itemtype][0]
865 let focus = s:Focus() ? 'prt' : 'win'
866 let byfname = s:byfname ? 'file' : 'path'
867 let regex = s:regexp ? '%#LineNr# regex %*' : ''
868 let focus = '%#LineNr# '.focus.' %*'
869 let byfname = '%#Character# '.byfname.' %*'
870 let item = '%#Character# '.item.' %*'
871 let slider = ' <'.prv.'>={'.item.'}=<'.nxt.'>'
872 let dir = ' %=%<%#LineNr# '.getcwd().' %*'
873 let marked = s:opmul ? exists('s:marked') ? ' <'.s:dismrk().'>' : ' <+>' : ''
874 let &l:stl = focus.byfname.regex.slider.marked.dir
875 endf
876
877 fu! s:dismrk()
878 retu has('signs') ? '+'.len(s:marked) :
879 \ '%<'.join(values(map(copy(s:marked), 'split(v:val, "[\\/]")[-1]')), ', ')
880 endf
881
882 fu! ctrlp#progress(len)
883 if has('macunix') || has('mac') | sl 1m | en
884 let &l:stl = '%#Function# '.a:len.' %* %=%<%#LineNr# '.getcwd().' %*'
885 redr
886 endf
887 " Paths {{{2
888 fu! ctrlp#dirfilter(val)
889 retu isdirectory(a:val) && match(a:val, '[\/]\.\{,2}$') < 0 ? 1 : 0
890 endf
891
892 fu! s:ispathitem()
893 let ext = s:itemtype - ( g:ctrlp_builtins + 1 )
894 if s:itemtype < 3 || ( s:itemtype > 2 && g:ctrlp_ext_vars[ext][3] == 'dir' )
895 retu 1
896 en
897 retu 0
898 endf
899
900 fu! ctrlp#rmbasedir(items)
901 let path = &ssl || !exists('+ssl') ? getcwd().'/' :
902 \ substitute(getcwd(), '\\', '\\\\', 'g').'\\'
903 retu map(a:items, 'substitute(v:val, path, "", "g")')
904 endf
905
906 fu! s:parentdir(curr)
907 let parent = s:getparent(a:curr)
908 if parent != a:curr | cal ctrlp#setdir(parent) | en
909 endf
910
911 fu! s:getparent(item)
912 retu split(a:item, '[\/]\ze[^\/]\+[\/:]\?$')[0]
913 endf
914
915 fu! s:getgrand(item)
916 retu split(a:item, '[\/]\ze[^\/]\+[\/][^\/]\+[\/:]\?$')[0]
917 endf
918
919 fu! s:createparentdirs(arr)
920 for each in a:arr
921 let curr = exists('curr') ? curr.s:lash.each : each
922 cal ctrlp#utils#mkdir(curr)
923 endfo
924 retu curr
925 endf
926
927 fu! s:listdirs(path, parent)
928 let [str, dirs] = ['', split(s:glbpath(a:path, '*', 1), "\n")]
929 for entry in filter(dirs, 'isdirectory(v:val)')
930 let str .= a:parent . split(entry, '[\/]')[-1] . "\n"
931 endfo
932 retu str
933 endf
934
935 fu! ctrlp#cpl(A, L, P)
936 let haslash = match(a:A, '[\/]')
937 let parent = substitute(a:A, '[^\/]*$', '', 'g')
938 let path = !haslash ? parent : haslash > 0 ? getcwd().s:lash.parent : getcwd()
939 retu s:listdirs(path, parent)
940 endf
941
942 fu! s:findroot(curr, mark, depth, type)
943 let [depth, notfound] = [a:depth + 1, empty(s:glbpath(a:curr, a:mark, 1))]
944 if !notfound || depth > s:maxdepth
945 if notfound | cal ctrlp#setdir(s:cwd) | en
946 if a:type
947 let s:vcsroot = depth <= s:maxdepth ? a:curr : ''
948 el
949 cal ctrlp#setdir(a:curr)
950 let s:foundroot = 1
951 en
952 el
953 let parent = s:getparent(a:curr)
954 if parent != a:curr | cal s:findroot(parent, a:mark, depth, a:type) | en
955 en
956 endf
957
958 fu! s:glbpath(...)
959 retu call('globpath', v:version > 701 ? a:000 : a:000[:1])
960 endf
961
962 fu! ctrlp#fnesc(path)
963 retu exists('*fnameescape') ? fnameescape(a:path) : escape(a:path, " %#*?|<\"\n")
964 endf
965
966 fu! ctrlp#setdir(path, ...)
967 let cmd = exists('a:1') ? a:1 : 'lc!'
968 try
969 exe cmd.' '.ctrlp#fnesc(a:path)
970 cat
971 cal ctrlp#msg("Can't change working dir. Directory not exists.")
972 endt
973 endf
974 " Highlighting {{{2
975 fu! s:syntax()
976 sy match CtrlPNoEntries '^ == NO ENTRIES ==$'
977 sy match CtrlPLineMarker '^>'
978 hi link CtrlPNoEntries Error
979 hi CtrlPLineMarker guifg=bg
980 endf
981
982 fu! s:highlight(pat, grp)
983 cal clearmatches()
984 if !empty(a:pat) && a:pat != '..' && s:itemtype < 3
985 let pat = substitute(a:pat, '\~', '\\~', 'g')
986 if !s:regexp | let pat = escape(pat, '.') | en
987 " Match only filename
988 if s:byfname
989 let pat = substitute(pat, '\[\^\(.\{-}\)\]\\{-}', '[^\\/\1]\\{-}', 'g')
990 let pat = substitute(pat, '$', '\\ze[^\\/]*$', 'g')
991 en
992 cal matchadd(a:grp, '\c'.pat)
993 cal matchadd('CtrlPLineMarker', '^>')
994 en
995 endf
996
997 fu! s:dohighlight()
998 retu type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0]
999 \ && exists('*clearmatches')
1000 endf
1001 " Prompt history {{{2
1002 fu! s:gethistloc()
1003 let cache_dir = ctrlp#utils#cachedir().s:lash.'hist'
1004 retu [cache_dir, cache_dir.s:lash.'cache.txt']
1005 endf
1006
1007 fu! s:gethistdata()
1008 retu ctrlp#utils#readfile(s:gethistloc()[1])
1009 endf
1010
1011 fu! ctrlp#recordhist()
1012 let str = join(s:prompt, '')
1013 if empty(str) || !s:maxhst | retu | en
1014 let hst = s:hstry
1015 if len(hst) > 1 && hst[1] == str | retu | en
1016 cal extend(hst, [str], 1)
1017 if len(hst) > s:maxhst | cal remove(hst, s:maxhst, -1) | en
1018 endf
1019 " Signs {{{2
1020 fu! s:unmarksigns()
1021 if !s:dosigns() | retu | en
1022 for key in keys(s:marked)
1023 exe 'sign unplace' key 'buffer='.s:bufnr
1024 endfo
1025 endf
1026
1027 fu! s:remarksigns()
1028 if !s:dosigns() | retu | en
1029 let nls = s:matched
1030 for ic in range(1, len(nls))
1031 let filpath = s:itemtype ? nls[ic - 1] : getcwd().s:lash.nls[ic - 1]
1032 let key = s:dictindex(s:marked, filpath)
1033 if key > 0
1034 exe 'sign place' key 'line='.ic.' name=ctrlpmark buffer='.s:bufnr
1035 en
1036 endfo
1037 endf
1038
1039 fu! s:dosigns()
1040 retu exists('s:marked') && s:bufnr > 0 && s:opmul && has('signs')
1041 endf
1042 " Dictionaries {{{2
1043 fu! s:dictindex(dict, expr)
1044 for key in keys(a:dict)
1045 if a:dict[key] == a:expr | retu key | en
1046 endfo
1047 retu -1
1048 endf
1049
1050 fu! s:vacantdict(dict)
1051 retu filter(range(1, max(keys(a:dict))), '!has_key(a:dict, v:val)')
1052 endf
1053 " Buffers {{{2
1054 fu! s:buftab(bufnum)
1055 for nr in range(1, tabpagenr('$'))
1056 let buflist = tabpagebuflist(nr)
1057 if match(buflist, a:bufnum) >= 0
1058 let [buftabnr, tabwinnrs] = [nr, tabpagewinnr(nr, '$')]
1059 for ewin in range(1, tabwinnrs)
1060 if buflist[ewin - 1] == a:bufnum
1061 retu [ewin, buftabnr]
1062 en
1063 endfo
1064 en
1065 endfo
1066 retu [0, 0]
1067 endf
1068
1069 fu! s:normbuf()
1070 let winnrs = []
1071 for each in range(1, winnr('$'))
1072 let bufnr = winbufnr(each)
1073 if getbufvar(bufnr, '&bl') && empty(getbufvar(bufnr, '&bt'))
1074 \ && getbufvar(bufnr, '&ma')
1075 cal add(winnrs, each)
1076 en
1077 endfo
1078 retu winnrs
1079 endf
1080
1081 fu! ctrlp#normcmd(cmd)
1082 if !empty(s:nosplit) && match([bufname('%'), &l:ft], s:nosplit) >= 0
1083 retu a:cmd
1084 en
1085 " Find a regular buffer
1086 let norwins = s:normbuf()
1087 let norwin = empty(norwins) ? 0 : norwins[0]
1088 if norwin
1089 if index(norwins, winnr()) < 0
1090 exe norwin.'winc w'
1091 en
1092 retu a:cmd
1093 en
1094 retu 'bo vne'
1095 endf
1096
1097 fu! s:setupblank()
1098 setl noswf nobl nonu nowrap nolist nospell nocuc wfh
1099 setl fdc=0 fdl=99 tw=0 bt=nofile bh=unload
1100 if v:version >= 703
1101 setl nornu noudf cc=0
1102 en
1103 endf
1104
1105 fu! s:leavepre()
1106 if s:clrex && ( !has('clientserver') ||
1107 \ ( has('clientserver') && len(split(serverlist(), "\n")) == 1 ) )
1108 cal ctrlp#clra(1)
1109 en
1110 cal ctrlp#utils#writecache(s:hstry, s:gethistloc()[0], s:gethistloc()[1])
1111 endf
1112
1113 fu! s:checkbuf()
1114 if exists('s:init') | retu | en
1115 if exists('s:bufnr') && s:bufnr > 0
1116 exe s:bufnr.'bw!'
1117 en
1118 endf
1119 " Arguments {{{2
1120 fu! s:tail()
1121 if exists('s:optail') && !empty('s:optail')
1122 let tailpref = match(s:optail, '^\s*+') < 0 ? ' +' : ' '
1123 retu tailpref.s:optail
1124 en
1125 retu ''
1126 endf
1127
1128 fu! s:sanstail(str)
1129 " Restore the number of backslashes
1130 let str = substitute(a:str, '\\\\', '\', 'g')
1131 unl! s:optail
1132 if match(str, ':\([^:]\|\\:\)*$') >= 0
1133 let s:optail = matchstr(str, ':\zs\([^:]\|\\:\)*$')
1134 retu substitute(str, ':\([^:]\|\\:\)*$', '', 'g')
1135 en
1136 retu str
1137 endf
1138 " Misc {{{2
1139 fu! s:specinputs()
1140 let str = join(s:prompt, '') 719 let str = join(s:prompt, '')
1141 let type = s:itemtype > 2 ? 720 let type = s:itemtype > 2 ?
1142 \ g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][3] : s:itemtype 721 \ g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][3] : s:itemtype
1143 if str == '..' && type =~ '0\|dir' 722 if str == '..' && type =~ '0\|dir'
1144 cal s:parentdir(getcwd()) 723 cal s:parentdir(getcwd())
1157 retu 1 736 retu 1
1158 en 737 en
1159 retu 0 738 retu 0
1160 endf 739 endf
1161 740
741 fu! s:AcceptSelection(mode)
742 if a:mode == 'e' | if s:SpecInputs() | retu | en | en
743 " Get the selected line
744 let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
745 if empty(matchstr) | retu | en
746 " Do something with it
747 let actfunc = s:itemtype =~ '0\|1\|2' ? 'ctrlp#acceptfile'
748 \ : g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][1]
749 cal call(actfunc, [a:mode, matchstr])
750 endf
751 fu! s:CreateNewFile() "{{{1
752 let str = join(s:prompt, '')
753 if empty(str) | retu | en
754 let str = s:sanstail(str)
755 let arr = split(str, '[\/]')
756 let fname = remove(arr, -1)
757 if len(arr) | if isdirectory(s:createparentdirs(arr))
758 let optyp = str
759 en | el
760 let optyp = fname
761 en
762 if exists('optyp')
763 let filpath = getcwd().s:lash.optyp
764 cal s:insertcache(str)
765 cal s:PrtExit()
766 let cmd = s:newfop == 1 ? 'tabe'
767 \ : s:newfop == 2 ? 'new'
768 \ : s:newfop == 3 ? 'vne' : ctrlp#normcmd('e')
769 cal s:openfile(cmd, filpath)
770 en
771 endf
772 " * OpenMulti() {{{1
773 fu! s:MarkToOpen()
774 if s:bufnr <= 0 || !s:opmul || s:itemtype > g:ctrlp_builtins | retu | en
775 let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
776 if empty(matchstr) | retu | en
777 let filpath = s:itemtype ? matchstr : getcwd().s:lash.matchstr
778 if exists('s:marked') && s:dictindex(s:marked, filpath) > 0
779 " Unmark and remove the file from s:marked
780 let key = s:dictindex(s:marked, filpath)
781 cal remove(s:marked, key)
782 if empty(s:marked) | unl! s:marked | en
783 if has('signs')
784 exe 'sign unplace' key 'buffer='.s:bufnr
785 en
786 el
787 " Add to s:marked and place a new sign
788 if exists('s:marked')
789 let vac = s:vacantdict(s:marked)
790 let key = empty(vac) ? len(s:marked) + 1 : vac[0]
791 let s:marked = extend(s:marked, { key : filpath })
792 el
793 let [key, s:marked] = [1, { 1 : filpath }]
794 en
795 if has('signs')
796 exe 'sign place' key 'line='.line('.').' name=ctrlpmark buffer='.s:bufnr
797 en
798 en
799 sil! cal ctrlp#statusline()
800 endf
801
802 fu! s:OpenMulti()
803 if !exists('s:marked') || !s:opmul
804 cal s:AcceptSelection('e')
805 retu
806 en
807 let mkd = s:marked
808 cal s:PrtExit()
809 " Try not to open a new tab
810 let [ntab, norwins] = [0, s:normbuf()]
811 if empty(norwins) | let ntab = 1 | el
812 for each in norwins
813 let bufnr = winbufnr(each)
814 if !empty(bufname(bufnr)) && !empty(getbufvar(bufnr, '&ft'))
815 \ && bufname(bufnr) != 'ControlP'
816 let ntab = 1
817 en
818 endfo
819 if !ntab | let wnr = min(norwins) | en
820 en
821 if ntab | tabnew | en
822 let [ic, wnr] = [1, exists('wnr') ? wnr : 1]
823 let cmds = { 'v': 'vne', 'h': 'new', 't': 'tabe' }
824 let spt = len(s:opmul) > 1 ? cmds[matchstr(s:opmul, '\w$')] : 'vne'
825 let nr = matchstr(s:opmul, '^\d\+')
826 exe wnr.'winc w'
827 for va in values(mkd)
828 let cmd = ic == 1 ? 'e' : spt
829 cal s:openfile(cmd, va)
830 if nr > 1 && nr < ic | clo! | el | let ic += 1 | en
831 endfo
832 endf
833 " ** Helper functions {{{1
834 " Sorting {{{2
835 fu! ctrlp#complen(s1, s2)
836 " By length
837 let [len1, len2] = [strlen(a:s1), strlen(a:s2)]
838 retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
839 endf
840
841 fu! s:compmatlen(s1, s2)
842 " By match length
843 let mln1 = s:shortest(s:matchlens(a:s1, s:compat))
844 let mln2 = s:shortest(s:matchlens(a:s2, s:compat))
845 retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
846 endf
847
848 fu! s:comptime(s1, s2)
849 " By last modified time
850 let [time1, time2] = [getftime(a:s1), getftime(a:s2)]
851 retu time1 == time2 ? 0 : time1 < time2 ? 1 : -1
852 endf
853
854 fu! s:comparent(s1, s2)
855 " By same parent dir
856 if match(s:crfpath, escape(getcwd(), '.^$*\')) >= 0
857 let [as1, as2] = [getcwd().s:lash.a:s1, getcwd().s:lash.a:s2]
858 let [loc1, loc2] = [s:getparent(as1), s:getparent(as2)]
859 if loc1 == s:crfpath && loc2 != s:crfpath | retu -1 | en
860 if loc2 == s:crfpath && loc1 != s:crfpath | retu 1 | en
861 retu 0
862 en
863 retu 0
864 endf
865
866 fu! s:matchlens(str, pat, ...)
867 if empty(a:pat) || index(['^','$'], a:pat) >= 0 | retu {} | en
868 let st = exists('a:1') ? a:1 : 0
869 let lens = exists('a:2') ? a:2 : {}
870 let nr = exists('a:3') ? a:3 : 0
871 if match(a:str, a:pat, st) != -1
872 let [mst, mnd] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)]
873 let lens = extend(lens, { nr : [len(mst), mst] })
874 let lens = s:matchlens(a:str, a:pat, mnd, lens, nr + 1)
875 en
876 retu lens
877 endf
878
879 fu! s:shortest(lens)
880 retu min(map(values(a:lens), 'v:val[0]'))
881 endf
882
883 fu! s:mixedsort(s1, s2)
884 let [cml, cln] = [s:compmatlen(a:s1, a:s2), ctrlp#complen(a:s1, a:s2)]
885 if s:itemtype < 3 && s:height < 51
886 let par = s:comparent(a:s1, a:s2)
887 if s:height < 21
888 retu 6 * cml + 3 * par + 2 * s:comptime(a:s1, a:s2) + cln
889 en
890 retu 3 * cml + 2 * par + cln
891 en
892 retu 2 * cml + cln
893 endf
894 " Statusline {{{2
895 fu! ctrlp#statusline(...)
896 if !exists('s:statypes')
897 let s:statypes = [
898 \ ['files', 'fil'],
899 \ ['buffers', 'buf'],
900 \ ['mru files', 'mru'],
901 \ ]
902 if exists('g:ctrlp_ext_vars')
903 cal map(copy(g:ctrlp_ext_vars), 'add(s:statypes, [ v:val[2], v:val[3] ])')
904 en
905 en
906 let tps = s:statypes
907 let max = len(tps) - 1
908 let nxt = tps[s:walker(max, s:itemtype, 1)][1]
909 let prv = tps[s:walker(max, s:itemtype, -1)][1]
910 let item = tps[s:itemtype][0]
911 let focus = s:Focus() ? 'prt' : 'win'
912 let byfname = s:byfname ? 'file' : 'path'
913 let regex = s:regexp ? '%#LineNr# regex %*' : ''
914 let focus = '%#LineNr# '.focus.' %*'
915 let byfname = '%#Character# '.byfname.' %*'
916 let item = '%#Character# '.item.' %*'
917 let slider = ' <'.prv.'>={'.item.'}=<'.nxt.'>'
918 let dir = ' %=%<%#LineNr# '.getcwd().' %*'
919 let marked = s:opmul ? exists('s:marked') ? ' <'.s:dismrk().'>' : ' <+>' : ''
920 let &l:stl = focus.byfname.regex.slider.marked.dir
921 endf
922
923 fu! s:dismrk()
924 retu has('signs') ? '+'.len(s:marked) :
925 \ '%<'.join(values(map(copy(s:marked), 'split(v:val, "[\\/]")[-1]')), ', ')
926 endf
927
928 fu! ctrlp#progress(len)
929 if has('macunix') || has('mac') | sl 1m | en
930 let &l:stl = '%#Function# '.a:len.' %* %=%<%#LineNr# '.getcwd().' %*'
931 redr
932 endf
933 " Paths {{{2
934 fu! s:ispathitem()
935 let ext = s:itemtype - ( g:ctrlp_builtins + 1 )
936 retu s:itemtype < 3 || ( s:itemtype > 2 && g:ctrlp_ext_vars[ext][3] == 'dir' )
937 endf
938
939 fu! ctrlp#dirnfile(entries)
940 let [items, cwd] = [[[], []], getcwd().s:lash]
941 for each in a:entries
942 let etype = getftype(each)
943 if etype == 'dir'
944 if s:dotfiles | if match(each, '[\/]\.\{,2}$') < 0
945 cal add(items[0], each)
946 en | el
947 cal add(items[0], each)
948 en
949 elsei etype == 'link'
950 if s:folsym
951 let isfile = !isdirectory(each)
952 if !s:samerootsyml(each, isfile, cwd)
953 cal add(items[isfile], each)
954 en
955 en
956 elsei etype == 'file'
957 cal add(items[1], each)
958 en
959 endfo
960 retu items
961 endf
962
963 fu! s:samerootsyml(each, isfile, cwd)
964 let resolve = resolve(a:each)
965 let resolve = ( a:isfile ? fnamemodify(resolve, ':p:h') : resolve ).s:lash
966 retu !( stridx(resolve, a:cwd) && ( stridx(a:cwd, resolve) || a:isfile ) )
967 endf
968
969 fu! ctrlp#rmbasedir(items)
970 let idx = strlen(getcwd()) + 1
971 retu map(a:items, 'strpart(v:val, idx)')
972 endf
973
974 fu! s:parentdir(curr)
975 let parent = s:getparent(a:curr)
976 if parent != a:curr | cal ctrlp#setdir(parent) | en
977 endf
978
979 fu! s:getparent(item)
980 retu split(a:item, '[\/]\ze[^\/]\+[\/:]\?$')[0]
981 endf
982
983 fu! s:getgrand(item)
984 retu split(a:item, '[\/]\ze[^\/]\+[\/][^\/]\+[\/:]\?$')[0]
985 endf
986
987 fu! s:createparentdirs(arr)
988 for each in a:arr
989 let curr = exists('curr') ? curr.s:lash.each : each
990 cal ctrlp#utils#mkdir(curr)
991 endfo
992 retu curr
993 endf
994
995 fu! s:listdirs(path, parent)
996 let [str, dirs] = ['', split(s:glbpath(a:path, '*', 1), "\n")]
997 for entry in filter(dirs, 'isdirectory(v:val)')
998 let str .= a:parent . split(entry, '[\/]')[-1] . "\n"
999 endfo
1000 retu str
1001 endf
1002
1003 fu! ctrlp#cpl(A, L, P)
1004 let haslash = match(a:A, '[\/]')
1005 let parent = substitute(a:A, '[^\/]*$', '', 'g')
1006 let path = !haslash ? parent : haslash > 0 ? getcwd().s:lash.parent : getcwd()
1007 retu s:listdirs(path, parent)
1008 endf
1009
1010 fu! s:findroot(curr, mark, depth, type)
1011 let [depth, notfound] = [a:depth + 1, empty(s:glbpath(a:curr, a:mark, 1))]
1012 if !notfound || depth > s:maxdepth
1013 if notfound | cal ctrlp#setdir(s:cwd) | en
1014 if a:type
1015 let s:vcsroot = depth <= s:maxdepth ? a:curr : ''
1016 el
1017 cal ctrlp#setdir(a:curr)
1018 let s:foundroot = 1
1019 en
1020 el
1021 let parent = s:getparent(a:curr)
1022 if parent != a:curr | cal s:findroot(parent, a:mark, depth, a:type) | en
1023 en
1024 endf
1025
1026 fu! s:glbpath(...)
1027 retu call('globpath', v:version > 701 ? a:000 : a:000[:1])
1028 endf
1029
1030 fu! ctrlp#fnesc(path)
1031 retu exists('*fnameescape') ? fnameescape(a:path) : escape(a:path, " %#*?|<\"\n")
1032 endf
1033
1034 fu! ctrlp#setdir(path, ...)
1035 let cmd = exists('a:1') ? a:1 : 'lc!'
1036 try
1037 exe cmd.' '.ctrlp#fnesc(a:path)
1038 cat
1039 cal ctrlp#msg("Can't change working dir. Directory not exists.")
1040 endt
1041 endf
1042 " Highlighting {{{2
1043 fu! s:syntax()
1044 sy match CtrlPNoEntries '^ == NO ENTRIES ==$'
1045 sy match CtrlPLineMarker '^>'
1046 hi link CtrlPNoEntries Error
1047 hi CtrlPLineMarker guifg=bg
1048 endf
1049
1050 fu! s:highlight(pat, grp)
1051 cal clearmatches()
1052 if !empty(a:pat) && s:itemtype < 3
1053 let pat = substitute(a:pat, '\~', '\\~', 'g')
1054 if !s:regexp | let pat = escape(pat, '.') | en
1055 " Match only filename
1056 if s:byfname
1057 let pat = substitute(pat, '\[\^\(.\{-}\)\]\\{-}', '[^\\/\1]\\{-}', 'g')
1058 let pat = substitute(pat, '$', '\\ze[^\\/]*$', 'g')
1059 en
1060 cal matchadd(a:grp, '\c'.pat)
1061 cal matchadd('CtrlPLineMarker', '^>')
1062 en
1063 endf
1064
1065 fu! s:dohighlight()
1066 retu type(s:mathi) == 3 && len(s:mathi) > 1 && s:mathi[0]
1067 \ && exists('*clearmatches')
1068 endf
1069 " Prompt history {{{2
1070 fu! s:gethistloc()
1071 let cache_dir = ctrlp#utils#cachedir().s:lash.'hist'
1072 retu [cache_dir, cache_dir.s:lash.'cache.txt']
1073 endf
1074
1075 fu! s:gethistdata()
1076 retu ctrlp#utils#readfile(s:gethistloc()[1])
1077 endf
1078
1079 fu! ctrlp#recordhist()
1080 let str = join(s:prompt, '')
1081 if empty(str) || !s:maxhst | retu | en
1082 let hst = s:hstry
1083 if len(hst) > 1 && hst[1] == str | retu | en
1084 cal extend(hst, [str], 1)
1085 if len(hst) > s:maxhst | cal remove(hst, s:maxhst, -1) | en
1086 endf
1087 " Signs {{{2
1088 fu! s:unmarksigns()
1089 if !s:dosigns() | retu | en
1090 for key in keys(s:marked)
1091 exe 'sign unplace' key 'buffer='.s:bufnr
1092 endfo
1093 endf
1094
1095 fu! s:remarksigns()
1096 if !s:dosigns() | retu | en
1097 let [nls, head] = [s:matched, s:itemtype ? '' : getcwd().s:lash]
1098 for ic in range(1, len(nls))
1099 let filpath = head.nls[ic - 1]
1100 let key = s:dictindex(s:marked, filpath)
1101 if key > 0
1102 exe 'sign place' key 'line='.ic.' name=ctrlpmark buffer='.s:bufnr
1103 en
1104 endfo
1105 endf
1106
1107 fu! s:dosigns()
1108 retu exists('s:marked') && s:bufnr > 0 && s:opmul && has('signs')
1109 endf
1110 " Dictionaries {{{2
1111 fu! s:dictindex(dict, expr)
1112 for key in keys(a:dict)
1113 if a:dict[key] == a:expr | retu key | en
1114 endfo
1115 retu -1
1116 endf
1117
1118 fu! s:vacantdict(dict)
1119 retu filter(range(1, max(keys(a:dict))), '!has_key(a:dict, v:val)')
1120 endf
1121 " Buffers {{{2
1122 fu! s:buftab(bufnum, md)
1123 for tabnr in range(1, tabpagenr('$'))
1124 if tabpagenr() == tabnr && a:md == 't' | con | en
1125 let buflist = tabpagebuflist(tabnr)
1126 if index(buflist, a:bufnum) >= 0
1127 for winnr in range(1, tabpagewinnr(tabnr, '$'))
1128 if buflist[winnr - 1] == a:bufnum
1129 retu [tabnr, winnr]
1130 en
1131 endfo
1132 en
1133 endfo
1134 retu [0, 0]
1135 endf
1136
1137 fu! s:normbuf()
1138 let winnrs = []
1139 for each in range(1, winnr('$'))
1140 let bufnr = winbufnr(each)
1141 if getbufvar(bufnr, '&bl') && empty(getbufvar(bufnr, '&bt'))
1142 \ && getbufvar(bufnr, '&ma')
1143 cal add(winnrs, each)
1144 en
1145 endfo
1146 retu winnrs
1147 endf
1148
1149 fu! ctrlp#normcmd(cmd)
1150 if !empty(s:nosplit) && match([bufname('%'), &l:ft], s:nosplit) >= 0
1151 retu a:cmd
1152 en
1153 " Find a regular buffer
1154 let norwins = s:normbuf()
1155 let norwin = empty(norwins) ? 0 : norwins[0]
1156 if norwin
1157 if index(norwins, winnr()) < 0
1158 exe norwin.'winc w'
1159 en
1160 retu a:cmd
1161 en
1162 retu 'bo vne'
1163 endf
1164
1165 fu! s:setupblank()
1166 setl noswf nobl nonu nowrap nolist nospell nocuc wfh
1167 setl fdc=0 fdl=99 tw=0 bt=nofile bh=unload
1168 if v:version > 702
1169 setl nornu noudf cc=0
1170 en
1171 endf
1172
1173 fu! s:leavepre()
1174 if s:clrex && ( !has('clientserver') ||
1175 \ ( has('clientserver') && len(split(serverlist(), "\n")) == 1 ) )
1176 cal ctrlp#clra(1)
1177 en
1178 cal ctrlp#utils#writecache(s:hstry, s:gethistloc()[0], s:gethistloc()[1])
1179 endf
1180
1181 fu! s:checkbuf()
1182 if exists('s:init') | retu | en
1183 if exists('s:bufnr') && s:bufnr > 0
1184 exe s:bufnr.'bw!'
1185 en
1186 endf
1187 " Arguments {{{2
1188 fu! s:tail()
1189 if exists('s:optail') && !empty('s:optail')
1190 let tailpref = match(s:optail, '^\s*+') < 0 ? ' +' : ' '
1191 retu tailpref.s:optail
1192 en
1193 retu ''
1194 endf
1195
1196 fu! s:sanstail(str)
1197 let [str, pat] = [substitute(a:str, '\\\\', '\', 'g'), '\([^:]\|\\:\)*$']
1198 unl! s:optail
1199 if match(str, '\\\@<!:'.pat) >= 0
1200 let s:optail = matchstr(str, '\\\@<!:\zs'.pat)
1201 let str = substitute(str, '\\\@<!:'.pat, '', '')
1202 en
1203 retu substitute(str, '\\\ze:', '', 'g')
1204 endf
1205 " Misc {{{2
1162 fu! s:lastvisual() 1206 fu! s:lastvisual()
1163 let cview = winsaveview() 1207 let cview = winsaveview()
1164 let [ovreg, ovtype] = [getreg('v'), getregtype('v')] 1208 let [ovreg, ovtype] = [getreg('v'), getregtype('v')]
1165 let [oureg, outype] = [getreg('"'), getregtype('"')] 1209 let [oureg, outype] = [getreg('"'), getregtype('"')]
1166 sil! norm! gv"vy 1210 sil! norm! gv"vy
1170 cal winrestview(cview) 1214 cal winrestview(cview)
1171 retu selected 1215 retu selected
1172 endf 1216 endf
1173 1217
1174 fu! ctrlp#msg(msg) 1218 fu! ctrlp#msg(msg)
1175 echoh Identifier | echon "CtrlP: ".a:msg | echoh None 1219 redr | echoh Identifier | echon "CtrlP: ".a:msg | echoh None
1176 endf 1220 endf
1177 1221
1178 fu! s:openfile(cmd, filpath, ...) 1222 fu! s:openfile(cmd, filpath, ...)
1179 let cmd = a:cmd == 'e' && &modified ? 'hid e' : a:cmd 1223 let cmd = a:cmd == 'e' && &modified ? 'hid e' : a:cmd
1180 let tail = a:0 ? a:1 : s:tail() 1224 let tail = a:0 ? a:1 : s:tail()
1181 try 1225 try
1182 exe cmd.tail.' '.ctrlp#fnesc(a:filpath) 1226 exe cmd.tail.' '.ctrlp#fnesc(a:filpath)
1183 cat 1227 cat
1184 cal ctrlp#msg("Operation can't be completed. Make sure filename is valid.")
1185 fina 1228 fina
1186 if !empty(tail) 1229 if !empty(tail)
1187 sil! norm! zOzz 1230 sil! norm! zvzz
1188 en 1231 en
1189 endt 1232 endt
1190 endf 1233 endf
1191 1234
1192 fu! s:writecache(read_cache, cache_file) 1235 fu! s:writecache(read_cache, cache_file)
1195 if len(g:ctrlp_allfiles) > s:nocache_lim | let s:caching = 1 | en 1238 if len(g:ctrlp_allfiles) > s:nocache_lim | let s:caching = 1 | en
1196 cal ctrlp#utils#writecache(g:ctrlp_allfiles) 1239 cal ctrlp#utils#writecache(g:ctrlp_allfiles)
1197 en 1240 en
1198 endf 1241 endf
1199 1242
1200 fu! s:j2l(nr) 1243 fu! ctrlp#j2l(nr)
1201 exe a:nr 1244 exe a:nr
1202 sil! norm! zOzz 1245 sil! norm! zvzz
1203 endf 1246 endf
1204 1247
1205 fu! s:regexfilter(str) 1248 fu! s:regexfilter(str)
1206 let str = a:str 1249 let str = a:str
1207 let pats = { 1250 let pats = {
1226 1269
1227 fu! s:matchtab(item, pat) 1270 fu! s:matchtab(item, pat)
1228 retu match(split(a:item, '\t\+[^\t]\+$')[0], a:pat) 1271 retu match(split(a:item, '\t\+[^\t]\+$')[0], a:pat)
1229 endf 1272 endf
1230 1273
1231 fu! s:maxfiles(len) 1274 fu! s:maxf(len)
1232 retu s:maxfiles && a:len > s:maxfiles ? 1 : 0 1275 retu s:maxfiles && a:len > s:maxfiles ? 1 : 0
1233 endf 1276 endf
1234 1277
1235 fu! s:insertcache(str) 1278 fu! s:insertcache(str)
1236 let [data, g:ctrlp_newcache, str] = [g:ctrlp_allfiles, 1, a:str] 1279 let [data, g:ctrlp_newcache, str] = [g:ctrlp_allfiles, 1, a:str]
1246 endfo 1289 endfo
1247 en 1290 en
1248 cal insert(data, str, pos) 1291 cal insert(data, str, pos)
1249 cal s:writecache(0, ctrlp#utils#cachefile()) 1292 cal s:writecache(0, ctrlp#utils#cachefile())
1250 endf 1293 endf
1251
1252 fu! s:lscommand()
1253 let cmd = s:usrcmd
1254 if type(cmd) == 1
1255 retu cmd
1256 elsei type(cmd) == 3 && len(cmd) >= 2 && !empty(cmd[0]) && !empty(cmd[1])
1257 let rmarker = cmd[0]
1258 " Find a repo root
1259 cal s:findroot(getcwd(), rmarker, 0, 1)
1260 if !exists('s:vcsroot') || ( exists('s:vcsroot') && empty(s:vcsroot) )
1261 " Try the secondary_command
1262 retu len(cmd) == 3 ? cmd[2] : ''
1263 en
1264 let s:vcscmd = s:lash == '\' ? 1 : 0
1265 retu cmd[1]
1266 en
1267 endf
1268 " Extensions {{{2 1294 " Extensions {{{2
1269 fu! s:tagfiles() 1295 fu! s:tagfiles()
1270 retu filter(map(tagfiles(), 'fnamemodify(v:val, ":p")'), 'filereadable(v:val)') 1296 retu filter(map(tagfiles(), 'fnamemodify(v:val, ":p")'), 'filereadable(v:val)')
1271 endf 1297 endf
1272 1298
1298 1324
1299 fu! ctrlp#init(type, ...) 1325 fu! ctrlp#init(type, ...)
1300 if exists('s:init') | retu | en 1326 if exists('s:init') | retu | en
1301 let [s:matches, s:init] = [1, 1] 1327 let [s:matches, s:init] = [1, 1]
1302 cal s:Open() 1328 cal s:Open()
1303 cal s:SetWD(exists('a:1') ? a:1 : '') 1329 cal s:SetWD(a:0 ? a:1 : '')
1304 cal s:MapKeys() 1330 cal s:MapKeys()
1305 cal s:SetLines(a:type) 1331 cal s:SetLines(a:type)
1306 cal s:BuildPrompt(1) 1332 cal s:BuildPrompt(1)
1307 if has('syntax') && exists('g:syntax_on') 1333 if has('syntax') && exists('g:syntax_on') | cal s:syntax() | en
1308 cal s:syntax()
1309 en
1310 endf 1334 endf
1311 if has('autocmd') "{{{1 1335 if has('autocmd') "{{{1
1312 aug CtrlPAug 1336 aug CtrlPAug
1313 au! 1337 au!
1314 au BufEnter ControlP cal s:checkbuf() 1338 au BufEnter ControlP cal s:checkbuf()