From 0af1cdc7917813bbe846be7faa9dfbc55156c030 Mon Sep 17 00:00:00 2001 From: Kien N Date: Sat, 12 Nov 2011 22:00:50 +0700 Subject: [PATCH] Find root with '/' and '\' * Submit '/' or '\' to find the project's root. Close #30. * Add wig flag to glob() and globpath() in addition to expand(). * Make handling working directory less intrusive. --- autoload/ctrlp.vim | 304 +++++++++++++++++++----------------- autoload/ctrlp/mrufiles.vim | 18 ++- autoload/ctrlp/utils.vim | 9 +- doc/ctrlp.txt | 169 ++++++++++---------- plugin/ctrlp.vim | 26 ++- readme.md | 17 +- 6 files changed, 281 insertions(+), 262 deletions(-) diff --git a/autoload/ctrlp.vim b/autoload/ctrlp.vim index 4a725a7..7bd1ef8 100644 --- a/autoload/ctrlp.vim +++ b/autoload/ctrlp.vim @@ -1,15 +1,15 @@ " ============================================================================= " File: autoload/ctrlp.vim -" Description: Full path fuzzy file, buffer and MRU file finder for Vim +" Description: Fuzzy file, buffer and MRU file finder. " Author: Kien Nguyen -" Version: 1.5.9 +" Version: 1.6.0 " ============================================================================= " Static variables {{{ fu! s:opts() let opts = { \ 'g:ctrlp_by_filename': ['s:byfname', 0], - \ 'g:ctrlp_clear_cache_on_exit': ['s:cconex', 1], + \ 'g:ctrlp_clear_cache_on_exit': ['s:clrex', 1], \ 'g:ctrlp_dont_split': ['s:nosplit', ''], \ 'g:ctrlp_dotfiles': ['s:dotfiles', 1], \ 'g:ctrlp_extensions': ['s:extensions', []], @@ -20,7 +20,7 @@ fu! s:opts() \ 'g:ctrlp_max_depth': ['s:maxdepth', 40], \ 'g:ctrlp_max_files': ['s:maxfiles', 20000], \ 'g:ctrlp_max_height': ['s:mxheight', 10], - \ 'g:ctrlp_open_multi': ['s:opmul', 1], + \ 'g:ctrlp_open_multi': ['s:opmul', '1v'], \ 'g:ctrlp_open_new_file': ['s:newfop', 3], \ 'g:ctrlp_prompt_mappings': ['s:urprtmaps', 0], \ 'g:ctrlp_regexp_search': ['s:regexp', 0], @@ -42,8 +42,7 @@ fu! s:opts() let s:glob = s:dotfiles ? '.*\|*' : '*' let s:cache_dir = exists('g:ctrlp_cache_dir') ? g:ctrlp_cache_dir : $HOME let s:maxdepth = min([s:maxdepth, 100]) - let s:mru = g:ctrlp_mru_files - let g:ctrlp_builtins = s:mru + 1 + let g:ctrlp_builtins = 2 if !empty(s:extensions) | for each in s:extensions exe 'ru autoload/ctrlp/'.each.'.vim' endfo | en @@ -53,19 +52,20 @@ cal s:opts() let s:lash = ctrlp#utils#lash() " Global options -let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, - \ 'im': 0, 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, - \ 'mfd': 200, 'gcr': 'a:block-PmenuSel-blinkon0', 'mouse': 'n' } +let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0, + \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'mouse': 'n', + \ 'gcr': 'a:block-PmenuSel-blinkon0' } " Limiters let [s:compare_lim, s:nocache_lim, s:mltipats_lim] = [3000, 4000, 2000] "}}} " * Open & Close {{{ fu! s:Open() - let s:winres = winrestcmd() + let [s:cwd, s:winres] = [getcwd(), winrestcmd()] + let [s:crfile, s:crfpath] = [expand('%:p', 1), expand('%:p:h', 1)] sil! exe s:mwbottom ? 'bo' : 'to' '1new ControlP' let s:currwin = s:mwbottom ? winnr('#') : winnr('#') + 1 - let [s:winnr, s:bufnr, s:prompt] = [bufwinnr('%'), bufnr('%'), ['', '', '']] + let [s:bufnr, s:prompt] = [bufnr('%'), ['', '', '']] abc if !exists('s:hstry') let hst = filereadable(s:gethistloc()[1]) ? s:gethistdata() : [''] @@ -88,40 +88,43 @@ fu! s:Close() endfo if exists('s:glb_acd') | let &acd = s:glb_acd | en let [g:ctrlp_lines, g:ctrlp_allfiles] = [[], []] - sil! exe 'chd!' s:cwd exe s:winres - unl! s:focus s:hisidx s:hstgot s:marked s:winnr s:statypes s:cline s:cwd - \ s:init s:savestr s:winres + unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:cline s:init s:savestr + \ s:crfile s:crfpath cal s:recordhist(join(s:prompt, '')) ec endf "}}} " * Clear caches {{{ -fu! ctrlp#clearcache() +fu! ctrlp#clr() let g:ctrlp_newcache = 1 endf -fu! ctrlp#clearallcaches() +fu! ctrlp#clra(...) + if !exists('a:1') && ( has('dialog_gui') || has('dialog_con') ) && + \ confirm("Delete all cache files?", "&OK\n&Cancel") != 1 | retu | en let cache_dir = ctrlp#utils#cachedir() - if isdirectory(cache_dir) && match(cache_dir, '.ctrlp_cache') >= 0 - let cache_files = split(globpath(cache_dir, '*.txt'), '\n') + if isdirectory(cache_dir) + let cache_files = split(s:glbpath(cache_dir, '*.txt', 1), "\n") cal filter(cache_files, '!isdirectory(v:val)') sil! cal map(cache_files, 'delete(v:val)') en - cal ctrlp#clearcache() + cal ctrlp#clr() endf fu! ctrlp#reset() + if ( has('dialog_gui') || has('dialog_con') ) && + \ confirm("Reset and apply new options?", "&OK\n&Cancel") != 1 | retu | en cal s:opts() cal ctrlp#utils#opts() - if s:mru | cal ctrlp#mrufiles#opts() | en + cal ctrlp#mrufiles#opts() let s:prompt = ['', '', ''] unl! s:cline endf "}}} " * Files() {{{ fu! s:GlobPath(dirs, allfiles, depth) - let entries = split(globpath(a:dirs, s:glob), '\n') + let entries = split(globpath(a:dirs, s:glob), "\n") let entries = filter(entries, 'getftype(v:val) != "link"') let g:ctrlp_allfiles = filter(copy(entries), '!isdirectory(v:val)') let ftrfunc = s:dotfiles ? 's:dirfilter(v:val)' : 'isdirectory(v:val)' @@ -140,7 +143,7 @@ fu! s:UserCommand(path, lscmd) let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')] en let path = exists('*shellescape') ? shellescape(path) : path - let g:ctrlp_allfiles = split(system(printf(a:lscmd, path)), '\n') + let g:ctrlp_allfiles = split(system(printf(a:lscmd, path)), "\n") if exists('+ssl') && exists('ssl') let &ssl = ssl cal map(g:ctrlp_allfiles, 'tr(v:val, "\\", "/")') @@ -223,7 +226,7 @@ fu! s:MatchedItems(items, pats, limit) retu newitems endf "}}} -fu! s:SplitPattern(str,...) "{{{ +fu! s:SplitPattern(str, ...) "{{{ let str = s:sanstail(a:str) let s:savestr = str if s:regexp || match(str, '\\\(zs\|ze\|<\|>\)\|[*|]') >= 0 @@ -255,39 +258,39 @@ endf "}}} fu! s:Render(lines, pat) let lines = a:lines " Setup the match window - sil! exe '%d _ | res' min([len(lines), s:mxheight]) + let s:height = min([len(lines), s:mxheight]) + sil! exe '%d _ | res' s:height " Print the new items if empty(lines) setl nocul cal setline(1, ' == NO MATCHES ==') cal s:unmarksigns() - el - setl cul - " Sort if not MRU - if ( s:mru && s:itemtype != 2 ) || !s:mru - let s:compat = a:pat - cal sort(lines, 's:mixedsort') - unl s:compat - en - if s:mwreverse | cal reverse(lines) | en - let s:matched = copy(lines) - cal map(lines, 'substitute(v:val, "^", "> ", "")') - cal setline(1, lines) - exe 'keepj norm!' s:mwreverse ? 'G' : 'gg' - keepj norm! 1| - cal s:unmarksigns() - cal s:remarksigns() + retu en + setl cul + " Sort if not MRU + if s:itemtype != 2 || !empty(join(s:prompt, '')) + let s:compat = a:pat + cal sort(lines, 's:mixedsort') + unl s:compat + en + if s:mwreverse | cal reverse(lines) | en + let s:matched = copy(lines) + cal map(lines, 'substitute(v:val, "^", "> ", "")') + cal setline(1, lines) + exe 'keepj norm!' s:mwreverse ? 'G' : 'gg' + keepj norm! 1| + cal s:unmarksigns() + cal s:remarksigns() if exists('s:cline') | cal cursor(s:cline, 1) | en " Highlighting if type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0] - \ && exists('*clearmatches') && !empty(lines) - let grp = empty(s:mathi[1]) ? 'Identifier' : s:mathi[1] - cal s:highlight(a:pat, grp) + \ && exists('*clearmatches') + cal s:highlight(a:pat, empty(s:mathi[1]) ? 'Identifier' : s:mathi[1]) en endf -fu! s:Update(pat,...) +fu! s:Update(pat, ...) let pat = a:pat " Get the previous string if existed let oldstr = exists('s:savestr') ? s:savestr : '' @@ -299,11 +302,10 @@ fu! s:Update(pat,...) retu en let lines = s:MatchedItems(g:ctrlp_lines, pats, s:mxheight) - let pat = pats[-1] - cal s:Render(lines, pat) + cal s:Render(lines, pats[-1]) endf -fu! s:BuildPrompt(upd,...) +fu! s:BuildPrompt(upd, ...) let base = ( s:regexp ? 'r' : '>' ).( s:byfname ? 'd' : '>' ).'> ' let [estr, prt] = ['"\', copy(s:prompt)] cal map(prt, 'escape(v:val, estr)') @@ -365,8 +367,8 @@ fu! s:PrtDeleteWord() let str = matchstr(str, '^.\+\W\ze\w\+$') elsei match(str, '\w\W\+$') >= 0 let str = matchstr(str, '^.\+\w\ze\W\+$') - elsei match(str, '[ ]\+$') >= 0 - let str = matchstr(str, '^.*[^ ]\+\ze[ ]\+$') + elsei match(str, '\s\+$') >= 0 + let str = matchstr(str, '^.*[^ \t]\+\ze\s\+$') elsei match(str, ' ') <= 0 let str = '' en @@ -412,7 +414,7 @@ fu! s:PrtSelectMove(dir) let s:cline = line('.') endf -fu! s:PrtSelectJump(char,...) +fu! s:PrtSelectJump(char, ...) let lines = copy(s:matched) if exists('a:1') cal map(lines, 'split(v:val, ''[\/]\ze[^\/]\+$'')[-1]') @@ -438,17 +440,26 @@ endf " Hooks {{{ fu! s:PrtClearCache() let s:force = 1 - if s:itemtype == 0 - cal ctrlp#clearcache() + if !s:itemtype + cal ctrlp#clr() cal s:SetLines(s:itemtype) cal s:BuildPrompt(1) - elsei s:mru && s:itemtype == 2 + elsei s:itemtype == 2 let g:ctrlp_lines = ctrlp#mrufiles#list(-1, 1) cal s:BuildPrompt(1) en unl s:force endf +fu! s:PrtDeleteMRU() + if s:itemtype == 2 + let s:force = 1 + let g:ctrlp_lines = ctrlp#mrufiles#list(-1, 2) + cal s:BuildPrompt(1) + unl s:force + en +endf + fu! s:PrtExit() if !has('autocmd') | cal s:Close() | en exe s:currwin.'winc w' @@ -473,7 +484,7 @@ fu! s:MapKeys(...) " Normal keys let pfunc = exists('a:1') && !a:1 ? 'PrtSelectJump' : 'PrtAdd' let dojmp = s:byfname && pfunc == 'PrtSelectJump' ? ', 1' : '' - for each in range(32,126) + for each in range(32, 126) let cmd = "nn \ \ \ :\cal \%s(\"%s\"%s)\" exe printf(cmd, each, pfunc, escape(nr2char(each), '"|\'), dojmp) endfo @@ -506,12 +517,13 @@ fu! s:MapSpecs(...) \ 'PrtCurLeft()': ['', ''], \ 'PrtCurRight()': ['', ''], \ 'PrtClearCache()': [''], + \ 'PrtDeleteMRU()': [''], \ 'CreateNewFile()': [''], \ 'MarkToOpen()': [''], \ 'OpenMulti()': [''], \ 'PrtExit()': ['', '', ''], \ }] - if type(s:urprtmaps) == 4 && !empty(s:urprtmaps) + if type(s:urprtmaps) == 4 cal extend(prtmaps, s:urprtmaps) en " Correct arrow keys in terminal @@ -584,30 +596,28 @@ fu! s:PrtSwitcher() cal s:BuildPrompt(1, s:Focus(), 1) endf "}}} -fu! ctrlp#SetWorkingPath(...) "{{{ - let [pathmode, s:cwd] = [s:pathmode, getcwd()] +fu! s:SetWD(...) "{{{ + let pathmode = s:pathmode if exists('a:1') && len(a:1) == 1 && !type(a:1) let pathmode = a:1 elsei exists('a:1') && len(a:1) > 1 && type(a:1) - sil! exe 'chd!' a:1 - retu + cal s:setdir(a:1) | retu en - if match(expand('%:p', 1), '^\<.\+\>://.*') >= 0 || !pathmode - retu + if !exists('a:2') + if match(s:crfile, '^\<.\+\>://.*') >= 0 || !pathmode | retu | en + if exists('+acd') | let [s:glb_acd, &acd] = [&acd, 0] | en + cal s:setdir(s:crfpath) en - if exists('+acd') | let [s:glb_acd, &acd] = [&acd, 0] | en - let path = expand('%:p:h', 1) - let path = exists('*fnameescape') ? fnameescape(path) : escape(path, '%#') - sil! exe 'chd!' path if pathmode == 1 | retu | en let markers = ['root.dir','.git/','.hg/','.vimprojects','_darcs/','.bzr/'] if type(s:rmarkers) == 3 && !empty(s:rmarkers) cal extend(markers, s:rmarkers, 0) en for marker in markers - let found = s:findroot(getcwd(), marker, 0, 0) - if getcwd() != expand('%:p:h', 1) || found | brea | en + cal s:findroot(getcwd(), marker, 0, 0) + if exists('s:foundroot') | brea | en endfo + unl! s:foundroot endf "}}} " * AcceptSelection() {{{ fu! ctrlp#acceptfile(mode, matchstr) @@ -644,29 +654,14 @@ fu! ctrlp#acceptfile(mode, matchstr) endf fu! s:AcceptSelection(mode) - if a:mode == 'e' - let str = join(s:prompt, '') - if str == '..' && !s:itemtype - cal s:parentdir(getcwd()) - cal s:SetLines(s:itemtype) - cal s:PrtClear() - retu - elsei str == '?' - cal s:PrtExit() - let hlpwin = &columns > 159 ? '| vert res 80' : '' - sil! exe 'bo vert h ctrlp-mappings' hlpwin '| norm! 0' - retu - en - en + if a:mode == 'e' | if s:specinputs() | retu | en | en " Get the selected line let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$') if empty(matchstr) | retu | en " Do something with it - let rhs = s:mru ? '0\|1\|2' : '0\|1' - let actfunc = s:itemtype =~ rhs ? 'ctrlp#acceptfile' + let actfunc = s:itemtype =~ '0\|1\|2' ? 'ctrlp#acceptfile' \ : g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][1] cal call(actfunc, [a:mode, matchstr]) - ec endf "}}} fu! s:CreateNewFile() "{{{ @@ -747,14 +742,15 @@ fu! s:OpenMulti() en if ntab | tabnew | en let [ic, wnr] = [1, exists('wnr') ? wnr : 1] + let cmds = { 'v': 'vne', 'h': 'new', 't': 'tabe' } + let spt = len(s:opmul) > 1 ? cmds[s:opmul[1]] : 'vne' exe wnr.'winc w' for key in keys(mkd) - let cmd = ic == 1 ? 'e' : 'vne' + let cmd = ic == 1 ? 'e' : spt cal s:openfile(cmd, mkd[key]) - if s:opmul > 1 && s:opmul < ic | clo! + if s:opmul[0] > 1 && s:opmul[0] < ic | clo! el | let ic += 1 | en endfo - ec endf "}}} " ** Helper functions {{{ @@ -791,9 +787,9 @@ fu! s:matchlens(str, pat, ...) let lens = exists('a:2') ? a:2 : {} let nr = exists('a:3') ? a:3 : 0 if match(a:str, a:pat, st) != -1 - let [str, mend] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)] - let lens = extend(lens, { nr : [len(str), str] }) - let lens = s:matchlens(a:str, a:pat, mend, lens, nr + 1) + let [mst, mnd] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)] + let lens = extend(lens, { nr : [len(mst), mst] }) + let lens = s:matchlens(a:str, a:pat, mnd, lens, nr + 1) en retu lens endf @@ -814,14 +810,12 @@ fu! s:wordonly(lens) endf fu! s:mixedsort(s1, s2) - let [cmatlen, clen] = [s:compmatlen(a:s1, a:s2), s:complen(a:s1, a:s2)] - let rhs = s:mru ? '0\|1\|2' : '0\|1' - if s:itemtype =~ rhs - let [ctime, cword] = [s:comptime(a:s1, a:s2), s:compword(a:s1, a:s2)] - retu 6 * cmatlen + 3 * ctime + 2 * clen + cword - el - retu 2 * cmatlen + clen + let [cml, cln] = [s:compmatlen(a:s1, a:s2), s:complen(a:s1, a:s2)] + if s:itemtype =~ '0\|1\|2' && s:height < 21 + let [ctm, wrd] = [s:comptime(a:s1, a:s2), s:compword(a:s1, a:s2)] + retu 6 * cml + 3 * ctm + 2 * cln + wrd en + retu 2 * cml + cln endf "}}} " Statusline {{{ @@ -832,7 +826,6 @@ fu! s:statusline(...) \ ['buffers', 'buf'], \ ['mru files', 'mru'], \ ] - if !s:mru | cal remove(s:statypes, 2) | en if exists('g:ctrlp_ext_vars') | for each in g:ctrlp_ext_vars cal add(s:statypes, [ each[2], each[3] ]) endfo | en @@ -872,9 +865,7 @@ endf fu! s:parentdir(curr) let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '') - if parent != a:curr - sil! exe 'lc!' parent - en + if parent != a:curr | cal s:setdir(parent) | en endf fu! s:createparentdirs(arr) @@ -885,15 +876,15 @@ fu! s:createparentdirs(arr) retu curr endf -fu! s:listdirs(path,parent) - let str = '' - for entry in filter(split(globpath(a:path, '*'), '\n'), 'isdirectory(v:val)') +fu! s:listdirs(path, parent) + let [str, dirs] = [split(s:glbpath(a:path, '*', 1), "\n"), ''] + for entry in filter(dirs, 'isdirectory(v:val)') let str .= a:parent . split(entry, '[\/]')[-1] . "\n" endfo retu str endf -fu! ctrlp#compl(A,L,P) +fu! ctrlp#cpl(A, L, P) let haslash = match(a:A, '[\/]') let parent = substitute(a:A, '[^\/]*$', '', 'g') let path = !haslash ? parent : haslash > 0 ? getcwd().s:lash.parent : getcwd() @@ -901,25 +892,36 @@ fu! ctrlp#compl(A,L,P) endf fu! s:findroot(curr, mark, depth, type) - let [depth, notfound] = [a:depth + 1, empty(globpath(a:curr, a:mark))] + let [depth, notfound] = [a:depth + 1, empty(s:glbpath(a:curr, a:mark, 1))] if !notfound || depth > s:maxdepth - if notfound - if exists('s:cwd') - sil! exe 'chd!' s:cwd - en - retu 0 - en + if notfound | cal s:setdir(s:cwd) | en if a:type let s:vcsroot = depth <= s:maxdepth ? a:curr : '' el - sil! exe 'chd!' a:curr - retu 1 + cal s:setdir(a:curr) + let s:foundroot = 1 en el - let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '') + let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/:]\?$', '', '') if parent != a:curr | cal s:findroot(parent, a:mark, depth, a:type) | en en endf + +fu! s:glbpath(...) + retu call('globpath', v:version > 701 ? [a:1, a:2, a:3] : [a:1, a:2]) +endf + +fu! s:fnesc(path) + retu exists('*fnameescape') ? fnameescape(a:path) : escape(a:path, " %#*?|<\"\n") +endf + +fu! s:setdir(path) + try + exe 'lc!' s:fnesc(a:path) + cat + cal s:msg("Can't change working dir. Directory not exists.") + endt +endf "}}} " Highlighting {{{ fu! s:syntax() @@ -1031,33 +1033,31 @@ fu! s:normbuf() endf fu! s:normcmd(cmd) - if !empty(s:nosplit) && match([bufname('%'), &l:ft], s:nosplit) >=0 + if !empty(s:nosplit) && match([bufname('%'), &l:ft], s:nosplit) >= 0 retu a:cmd en " Find a regular buffer let norwins = s:normbuf() let norwin = empty(norwins) ? 0 : norwins[0] - " If there's at least 1 if norwin - " But not the current if index(norwins, winnr()) < 0 exe norwin.'winc w' en retu a:cmd - el - retu 'bo vne' en + retu 'bo vne' endf fu! s:setupblank() - setl noswf nobl nonu nowrap nolist nospell cul nocuc wfh fdc=0 tw=0 bt=nofile bh=unload + setl noswf nobl nonu nowrap nolist nospell nocuc wfh + setl fdc=0 fdl=99 tw=0 bt=nofile bh=unload if v:version >= 703 setl nornu noudf cc=0 en endf fu! s:leavepre() - if s:cconex | cal ctrlp#clearallcaches() | en + if s:clrex | cal ctrlp#clra(1) | en cal ctrlp#utils#writecache(s:hstry, s:gethistloc()[0], s:gethistloc()[1]) endf @@ -1084,20 +1084,38 @@ fu! s:sanstail(str) if match(str, ':\([^:]\|\\:\)*$') >= 0 let s:optail = matchstr(str, ':\zs\([^:]\|\\:\)*$') retu substitute(str, ':\([^:]\|\\:\)*$', '', 'g') - el - retu str en + retu str endf "}}} " Misc {{{ +fu! s:specinputs() + let str = join(s:prompt, '') + if str == '..' && !s:itemtype + cal s:parentdir(getcwd()) + cal s:SetLines(0) + cal s:PrtClear() + retu 1 + elsei ( str == '/' || str == '\' ) && !s:itemtype + cal s:SetWD(2, 0) + cal s:SetLines(0) + cal s:PrtClear() + retu 1 + elsei str == '?' + cal s:PrtExit() + let hlpwin = &columns > 159 ? '| vert res 80' : '' + sil! exe 'bo vert h ctrlp-mappings' hlpwin '| norm! 0' + retu 1 + en + retu 0 +endf + fu! s:openfile(cmd, filpath) - let cmd = a:cmd == 'e' && &modified ? 'new' : a:cmd + let cmd = a:cmd == 'e' && &modified ? 'hid e' : a:cmd try - exe cmd.s:tail().' '.escape(a:filpath, '%# ') + exe cmd.s:tail().' '.s:fnesc(a:filpath) cat - echoh Identifier - echon "CtrlP: Operation can't be completed. Make sure filename is valid." - echoh None + cal s:msg("Operation can't be completed. Make sure filename is valid.") fina if !empty(s:tail()) sil! norm! zOzz @@ -1105,6 +1123,10 @@ fu! s:openfile(cmd, filpath) endt endf +fu! s:msg(msg) + echoh Identifier | echon "CtrlP: ".a:msg | echoh None +endf + fu! s:writecache(read_cache, cache_file) if !a:read_cache && ( ( g:ctrlp_newcache || !filereadable(a:cache_file) ) \ && s:caching || len(g:ctrlp_allfiles) > s:nocache_lim ) @@ -1144,7 +1166,6 @@ fu! s:maxfiles(len) endf fu! s:insertcache(str) - if match(a:str, '|\|?\|:\|"\|\*\|<\|>') >= 0 | retu | en let [data, g:ctrlp_newcache, str] = [g:ctrlp_allfiles, 1, a:str] if strlen(str) <= strlen(data[0]) let pos = 0 @@ -1162,21 +1183,19 @@ fu! s:insertcache(str) endf fu! s:lscommand() - let usercmd = g:ctrlp_user_command - if type(usercmd) == 1 - retu usercmd - elsei type(usercmd) == 3 && len(usercmd) >= 2 - \ && !empty(usercmd[0]) && !empty(usercmd[1]) - let rmarker = usercmd[0] + let cmd = g:ctrlp_user_command + if type(cmd) == 1 + retu cmd + elsei type(cmd) == 3 && len(cmd) >= 2 && !empty(cmd[0]) && !empty(cmd[1]) + let rmarker = cmd[0] " Find a repo root cal s:findroot(getcwd(), rmarker, 0, 1) if !exists('s:vcsroot') || ( exists('s:vcsroot') && empty(s:vcsroot) ) " Try the secondary_command - retu len(usercmd) == 3 ? usercmd[2] : '' - el - let s:vcscmd = s:lash == '\' ? 1 : 0 - retu usercmd[1] + retu len(cmd) == 3 ? cmd[2] : '' en + let s:vcscmd = s:lash == '\' ? 1 : 0 + retu cmd[1] en endf "}}} @@ -1189,7 +1208,6 @@ fu! s:SetLines(type) \ 's:Buffers()', \ 'ctrlp#mrufiles#list(-1)', \ ] - if !s:mru | cal remove(types, 2) | en if exists('g:ctrlp_ext_vars') | for each in g:ctrlp_ext_vars cal add(types, each[0]) endfo | en @@ -1199,9 +1217,9 @@ endf fu! ctrlp#init(type, ...) if exists('s:init') | retu | en let [s:matches, s:init] = [1, 1] - let path = exists('a:1') ? a:1 : '' - cal ctrlp#SetWorkingPath(path) + let input = exists('a:1') ? a:1 : '' cal s:Open() + cal s:SetWD(input) cal s:MapKeys() cal s:SetLines(a:type) cal s:BuildPrompt(1) diff --git a/autoload/ctrlp/mrufiles.vim b/autoload/ctrlp/mrufiles.vim index 239e71c..b0bc4a4 100644 --- a/autoload/ctrlp/mrufiles.vim +++ b/autoload/ctrlp/mrufiles.vim @@ -7,9 +7,10 @@ " Static variables {{{ fu! ctrlp#mrufiles#opts() let opts = { - \ 'g:ctrlp_mruf_max': ['s:max', 150], + \ 'g:ctrlp_mruf_max': ['s:max', 150], \ 'g:ctrlp_mruf_include': ['s:include', ''], \ 'g:ctrlp_mruf_exclude': ['s:exclude', ''], + \ 'g:ctrlp_mruf_case_sensitive': ['s:csen', 1], \ } for key in keys(opts) let def = string(exists(key) ? eval(key) : opts[key][1]) @@ -18,15 +19,18 @@ fu! ctrlp#mrufiles#opts() endf cal ctrlp#mrufiles#opts() "}}} -fu! ctrlp#mrufiles#list(bufnr,...) "{{{ +fu! ctrlp#mrufiles#list(bufnr, ...) "{{{ if s:locked | retu | en " Get the list let cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().'mru' let cafile = cadir.ctrlp#utils#lash().'cache.txt' let mrufs = ctrlp#utils#readfile(cafile) " Remove non-existent files - if exists('a:1') + if exists('a:1') && a:1 == 1 let mrufs = s:rmdeleted(mrufs, cadir, cafile) + elsei exists('a:1') && a:1 == 2 + cal ctrlp#utils#writecache([], cadir, cafile) + retu [] en " Return the list if a:bufnr == -1 | retu mrufs | en @@ -39,18 +43,16 @@ fu! ctrlp#mrufiles#list(bufnr,...) "{{{ retu en " Remove old matched entry - cal filter(mrufs, 'v:val !=# filename') + cal filter(mrufs, 'v:val !='.( s:csen ? "#" : "?" ).' filename') " Insert new one cal insert(mrufs, filename) " Remove oldest entry - if len(mrufs) > s:max - cal remove(mrufs, s:max, -1) - en + if len(mrufs) > s:max | cal remove(mrufs, s:max, -1) | en cal ctrlp#utils#writecache(mrufs, cadir, cafile) endf "}}} fu! s:rmdeleted(mrufs, cadir, cafile) "{{{ for each in range(len(a:mrufs) - 1, 0, -1) - if empty(glob(a:mrufs[each])) + if empty(ctrlp#utils#glob(a:mrufs[each], 1)) cal remove(a:mrufs, each) en endfo diff --git a/autoload/ctrlp/utils.vim b/autoload/ctrlp/utils.vim index ed8565f..3017a59 100644 --- a/autoload/ctrlp/utils.vim +++ b/autoload/ctrlp/utils.vim @@ -27,9 +27,8 @@ fu! ctrlp#utils#readfile(file) unl data | let data = [] en retu data - el - retu [] en + retu [] endf fu! ctrlp#utils#mkdir(dir) @@ -38,7 +37,7 @@ fu! ctrlp#utils#mkdir(dir) en endf -fu! ctrlp#utils#writecache(lines,...) +fu! ctrlp#utils#writecache(lines, ...) let cache_dir = exists('a:1') ? a:1 : ctrlp#utils#cachedir() cal ctrlp#utils#mkdir(cache_dir) " write cache @@ -53,6 +52,10 @@ endf fu! ctrlp#utils#lash() retu &ssl || !exists('+ssl') ? '/' : '\' endf + +fu! ctrlp#utils#glob(...) + retu call('glob', v:version > 701 ? [a:1, a:2] : [a:1]) +endf "}}} " vim:fen:fdl=0:fdc=1:ts=2:sw=2:sts=2 diff --git a/doc/ctrlp.txt b/doc/ctrlp.txt index ff87744..63400b5 100644 --- a/doc/ctrlp.txt +++ b/doc/ctrlp.txt @@ -1,4 +1,4 @@ -*ctrlp.txt* Full path fuzzy file, buffer and MRU file finder. v1.5.9 +*ctrlp.txt* Fuzzy file, buffer and MRU file finder. v1.6.0 *CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'* =============================================================================== # # @@ -30,7 +30,7 @@ finder, and more. =============================================================================== 2. Options *ctrlp-options* -Below are the available options and their default values. +Below are the available options and their default values:~ *'g:ctrlp_map'* Use this option to change the mapping to invoke |CtrlP| in |Normal| mode: > @@ -48,7 +48,7 @@ Set this to 1 to set search by filename (not full path) as the default: > < *'g:ctrlp_regexp_search'* -Set this to 1 to set |regexp| search as the default mode: > +Set this to 1 to set |regexp| search as the default: > let g:ctrlp_regexp_search = 0 < @@ -75,7 +75,6 @@ tab if the selected buffer’s opened in another tab: > < *'g:ctrlp_working_path_mode'* - *SetWorkingPath()* When starting up the prompt, temporarily set the working directory (i.e. the |current-directory|) to: 1 - the parent directory of the current file. @@ -90,16 +89,14 @@ When starting up the prompt, temporarily set the working directory (i.e. the > let g:ctrlp_working_path_mode = 2 < -You can use this functionality outside of |CtrlP| by adding the following line -to your |.vimrc|; the parameter is the same (1, 2 or 0): > - au BufEnter * cal ctrlp#SetWorkingPath(2) -< *'g:ctrlp_root_markers'* -Use this to set your own root markers for the |SetWorkingPath()| function, in -addition to the default ones. Your markers will take precedence: > +Use this to set your own root markers in addition to the default ones. Your +markers will take precedence: > let g:ctrlp_root_markers = [''] < +These markers (builtins and yours) will serve as identifier for the '/' and '\' +special inputs (section 5.e) *'g:ctrlp_use_caching'* Set this to 0 to disable per-session caching. When disabled, caching will still @@ -130,10 +127,10 @@ only need to keep the lines that you’ve changed the values (inside []): > \ 'PrtSelectMove("k")': ['', ''], \ 'PrtHistory(-1)': [''], \ 'PrtHistory(1)': [''], - \ 'AcceptSelection("e")': [''], + \ 'AcceptSelection("e")': ['', '<2-LeftMouse>'], \ 'AcceptSelection("h")': ['', '', ''], - \ 'AcceptSelection("t")': [''], - \ 'AcceptSelection("v")': ['', ''], + \ 'AcceptSelection("t")': ['', ''], + \ 'AcceptSelection("v")': ['', '', ''], \ 'ToggleFocus()': [''], \ 'ToggleRegex()': [''], \ 'ToggleByFname()': [''], @@ -144,6 +141,7 @@ only need to keep the lines that you’ve changed the values (inside []): > \ 'PrtCurLeft()': ['', ''], \ 'PrtCurRight()': ['', ''], \ 'PrtClearCache()': [''], + \ 'PrtDeleteMRU()': [''], \ 'CreateNewFile()': [''], \ 'MarkToOpen()': [''], \ 'OpenMulti()': [''], @@ -151,11 +149,6 @@ only need to keep the lines that you’ve changed the values (inside []): > \ } < - *'g:ctrlp_mru_files'* -Set this to 0 to completely disable the Most Recently Used files feature: > - let g:ctrlp_mru_files = 1 -< - *'g:ctrlp_mruf_max'* Specify the number of recently opened files you want |CtrlP| to remember: > let g:ctrlp_mruf_max = 150 @@ -179,6 +172,12 @@ Example: > let g:ctrlp_mruf_include = '\.py$\|\.rb$' < + *'g:ctrlp_mruf_case_sensitive'* +Match this with your file system case-sensitivity setting to avoid duplicate +MRU entries: > + let g:ctrlp_mruf_case_sensitive = 1 +< + *'g:ctrlp_dotfiles'* Set this to 0 if you don’t want |CtrlP| to search for dotfiles and dotdirs: > let g:ctrlp_dotfiles = 1 @@ -229,11 +228,12 @@ Examples: > let g:ctrlp_user_command = 'find %s -type f | grep (?!tmp/.*)' let g:ctrlp_user_command = 'dir %s /-n /b /s /a-d | findstr .*\.py$' < -Use a version control listing command when inside a repository: > - let g:ctrlp_user_command = [marker, command, secondary_command] +Use a version control listing command when inside a repository, this is a lot +faster when working with large projects: > + let g:ctrlp_user_command = [repo_marker, vcs_ls_command, fallback_command] < -If the secondary_command is empty or not defined, globpath() will be used when -outside a repo. Examples: > +If the fallback_command is empty or not defined, globpath() will then be used +when outside a repo. Examples: > let g:ctrlp_user_command = ['.git/', 'cd %s && git ls-files'] let g:ctrlp_user_command = ['.hg/', 'hg --cwd %s locate --fullpath -I .'] < @@ -257,25 +257,28 @@ value mirrors Vim’s global |'history'| option. E.g. `set history=50`: > Set to 0 to disable prompt’s history. *'g:ctrlp_open_multi'* -If non-zero this will enable opening multiple files with and : > - let g:ctrlp_open_multi = 1 +If non-zero, this will enable opening multiple files with and : > + let g:ctrlp_open_multi = '1v' < -If bigger than 1, it’ll be used as the maximum number of windows to create when -opening the files (the rest will be hidden buffers). If is 1, will open -all files, each in a vertical split. +For the number: + If bigger than 1, it’ll be used as the maximum number of windows or tabs to + create when opening the files (the rest will be hidden buffers). If is 1, + will open all files, each in a new window or new tab. +For the letter: + t - each in a tab + h - each in a horizontal split + v - each in a vertical split *'g:ctrlp_dont_split'* When opening a file with , |CtrlP| avoids opening it in windows created by -plugins. Use this to setup some exceptions: > +plugins, help and quickfix. Use this to setup some exceptions: > let g:ctrlp_dont_split = '' < -Acceptable values are partial names or filetypes of the special buffers. -Use |regexp| to specify the pattern. -Example: > - let g:ctrlp_dont_split = 'netrw\|myplugin' +Acceptable values are partial names or filetypes of the special buffers. Use +|regexp| to specify the pattern. Example: > + let g:ctrlp_dont_split = 'netrw\|help' < - =============================================================================== 3. Commands *ctrlp-commands* @@ -290,13 +293,13 @@ Example: > :CtrlPBuffer Open the |CtrlP| prompt in find buffer mode. - *:CtrlPMRUFiles* -:CtrlPMRUFiles + *:CtrlPMRU* +:CtrlPMRU Open the |CtrlP| prompt in find Most-Recently-Used file mode. *:ClearCtrlPCache* :ClearCtrlPCache - Flush the cache for the current working directory. Same as pressing + Flush the cache for the current working directory. The same as pressing inside |CtrlP|. *:ClearAllCtrlPCaches* @@ -305,26 +308,19 @@ Example: > *:ResetCtrlP* :ResetCtrlP - Reset all options, take in new values of the option variables (section 2). + Reset all options, take in new values of the option variables in section 2. -The following commands ignore the value of |g:ctrlp_working_path_mode|: +------------------------------------------------------------------------------- +The following commands ignore the current value of |g:ctrlp_working_path_mode|: - *:CtrlPCurWD* -:CtrlPCurWD +:CtrlPCurWD *:CtrlPCurWD* This acts like |:CtrlP| with |path_mode| = 0 - Find files in the |current-directory|. - *:CtrlPCurFile* -:CtrlPCurFile +:CtrlPCurFile *:CtrlPCurFile* This acts like |:CtrlP| with |path_mode| = 1 - Find files in the same directory as the active buffer, regardless of what - the |current-directory| is. - *:CtrlPRoot* -:CtrlPRoot +:CtrlPRoot *:CtrlPRoot* This acts like |:CtrlP| with |path_mode| = 2 - Find files in the project’s root directory. - Check |working_path_mode| to see how |CtrlP| finds a root. =============================================================================== 4. Mappings *ctrlp-mappings* @@ -333,7 +329,7 @@ The following commands ignore the value of |g:ctrlp_working_path_mode|: Default |Normal| mode mapping to open the |CtrlP| prompt. -Once inside the prompt: +Once inside the prompt:~ *'ctrlp-fullregexp'* Toggle between the string mode (section 5.a & b) and full |regexp| mode. @@ -418,6 +414,9 @@ Once inside the prompt: Refresh the match window and purge the cache for the current directory. Or remove deleted files from MRU list. + + Clear the MRU list. + , , @@ -425,7 +424,7 @@ Once inside the prompt: Chose your own mappings with |g:ctrlp_prompt_mappings|. -When inside the match window (press to switch): +When inside the match window (press to switch):~ a-z 0-9 @@ -436,8 +435,7 @@ When inside the match window (press to switch): =============================================================================== 5. Input Formats *ctrlp-input-formats* - *ctrlp-prompt-input-formats* -Formats for inputting in the prompt: +Formats for inputting in the prompt:~ a) Simple string. e.g. 'abc' is understood internally as 'a[^a]\{-}b[^b]\{-}c' @@ -459,37 +457,41 @@ c) End the string with a colon ':' followed by a Vim command to execute that See also Vim’s |++opt| and |+cmd|. -d) Type exactly two dots (..) at the start of the line and press enter to go +d) Type exactly two dots '..' at the start of the prompt and press enter to go backward in the directory tree by 1 level. If the parent directory is large, this might be slow. -e) Type the name of a non-existent file and press to create it. - e.g. 'parentdir/file.txt' will create a directory named 'parentdir' as well - as 'file.txt'. Use '\' in place of '/' on Windows (if |'ssl'| is not set). +e) Similarly submit '/' or '\' to find and go to the project’s root. If the + project is large, using a VCS listing command to look for files might help + speeding up the intial scan (see |g:ctrlp_user_command| for more details). -f) Submit ? to open this help file. +f) Type the name of a non-existent file and press to create it. + e.g. 'parentdir/file.txt' will create a directory named 'parentdir' as well + as 'file.txt'. + Use '\' in place of '/' on Windows (if |'ssl'| is not set). + +g) Submit ? to open this help file. =============================================================================== EXTENDING *ctrlp-extending* -Extending |CtrlP| is made to be incredibly simple. Just create a .vim file -following a short guidelines, place the file in the right spot and add a line -to your .vimrc. +Extending |CtrlP| is very simple. Simply create a .vim file following a short +guidelines, place it in autoload/ctrlp/ and add its name to your .vimrc. To see how it all works, get the sample.vim from the 'extensions' branch on the -git repository (https://github.com/kien/ctrlp.vim/tree/extensions), and place -it (along with the parent directories) somewhere in your runtimepath. Then put -this into your .vimrc: > +main git repository (https://github.com/kien/ctrlp.vim/tree/extensions), and +place it (along with the parent directories) somewhere in your runtimepath. +Then put this into your .vimrc: > let g:ctrlp_extensions = ['sample'] < A 4th search type will show up the next time you open |CtrlP|. -For more details, check out the comments inside sample.vim. +For more details, check out the comments inside sample.vim.~ =============================================================================== CREDITS *ctrlp-credits* -Developed by Kien Nguyen (github.com/kien), primarily based on the Command-T +Developed by Kien Nguyen (github.com/kien), initially based on the Command-T and the LustyExplorer plugins. No code was taken from these plugins, but I did clone the majority of their (awesome) interfaces and the way they work. @@ -509,7 +511,7 @@ THANKS *ctrlp-thanks* Thanks to everyone that has submitted ideas, bug reports or helped debugging on gibhub, bitbucket, and through email. -Special thanks: +Special thanks:~ * Woojong Koh Forked and suggested the support for VCS listing commands. @@ -517,25 +519,34 @@ Special thanks: =============================================================================== CHANGELOG *ctrlp-changelog* - + New option: |g:ctrlp_dont_split| +Before 2011/11/13~ -Before 2011/10/30 + + New special input: '/' and '\' find root (section 5.e) + + New mapping: clear MRU. + + Remove ctrlp#SetWorkingPath(). + + Remove |g:ctrlp_mru_files|, make MRU permanent. + + Extend |g:ctrlp_open_multi|, add new ways to open files. + + New option: |g:ctrlp_dont_split|, + |g:ctrlp_mruf_case_sensitive| + +Before 2011/10/30~ + New feature: Support for custom extensions. - now removes non-existent files from MRU list. + also removes non-existent files from MRU list. + New option: |g:ctrlp_jump_to_buffer| -Before 2011/10/12 +Before 2011/10/12~ + New features: Open multiple files. - Pass Vim’s ++opt and +cmd to the opening file (section 5.c) + Pass Vim’s |++opt| and |+cmd| to the opening file + (section 5.c) Auto-complete each dir for |:CtrlP| [starting-directory] + New mappings: mark/unmark a file to be opened with . open all marked files. + New option: |g:ctrlp_open_multi| + Remove |g:ctrlp_persistent_input|, |g:ctrlp_live_update| and . -Before 2011/09/29 +Before 2011/09/29~ + New mappings: , next/prev string in the input history. create a new file and its parent dirs. @@ -543,7 +554,7 @@ Before 2011/09/29 |g:ctrlp_max_history| + Added a new open-in-horizontal-split mapping: -Before 2011/09/19 +Before 2011/09/19~ + New command: |ResetCtrlP| + New options: |g:ctrlp_max_files|, @@ -551,16 +562,16 @@ Before 2011/09/19 |g:ctrlp_live_update| + New mapping: -Before 2011/09/12 +Before 2011/09/12~ + Ability to cycle through matched lines in the match window. - + Extended the behavior of |g:ctrlp_persistent_input| - + Extended the behavior of |:CtrlP| + + Extend the behavior of |g:ctrlp_persistent_input| + + Extend the behavior of |:CtrlP| + New options: |g:ctrlp_dotfiles|, |g:ctrlp_clear_cache_on_exit|, |g:ctrlp_highlight_match|, |g:ctrlp_user_command| - + New input format: '..' (section 5.d) + + New special input: '..' (section 5.d) + New mapping: . + New commands: |:CtrlPCurWD|, |:CtrlPCurFile|, @@ -575,7 +586,7 @@ Before 2011/09/12 |g:ctrlp_mruf_include| + New command: |:CtrlPMRUFiles| -First public release: 2011/09/06 +First public release: 2011/09/06~ =============================================================================== vim:et:ts=2:sw=2:sts=2 diff --git a/plugin/ctrlp.vim b/plugin/ctrlp.vim index 504ecd8..f91aa36 100644 --- a/plugin/ctrlp.vim +++ b/plugin/ctrlp.vim @@ -1,34 +1,32 @@ " ============================================================================= " File: plugin/ctrlp.vim -" Description: Full path fuzzy file, buffer and MRU file finder for Vim. +" Description: Fuzzy file, buffer and MRU file finder. " Author: Kien Nguyen -" License: MIT " ============================================================================= " GetLatestVimScripts: 3736 1 :AutoInstall: ctrlp.zip -if ( exists('g:loaded_ctrlp') && g:loaded_ctrlp ) || v:version < '700' || &cp +if ( exists('g:loaded_ctrlp') && g:loaded_ctrlp ) || v:version < 700 || &cp fini -endif +en let g:loaded_ctrlp = 1 -if !exists('g:ctrlp_map') | let g:ctrlp_map = '' | endif -if !exists('g:ctrlp_mru_files') | let g:ctrlp_mru_files = 1 | endif +if !exists('g:ctrlp_map') | let g:ctrlp_map = '' | en -com! -nargs=? -complete=custom,ctrlp#compl CtrlP cal ctrlp#init(0, ) +com! -na=? -comp=custom,ctrlp#cpl CtrlP cal ctrlp#init(0, ) -com! CtrlPBuffer cal ctrlp#init(1) -com! CtrlPMRUFiles cal ctrlp#init(2) -com! ClearCtrlPCache cal ctrlp#clearcache() -com! ClearAllCtrlPCaches cal ctrlp#clearallcaches() +com! CtrlPBuffer cal ctrlp#init(1) +com! CtrlPMRUFiles cal ctrlp#init(2) + +com! ClearCtrlPCache cal ctrlp#clr() +com! ClearAllCtrlPCaches cal ctrlp#clra() +com! ResetCtrlP cal ctrlp#reset() com! CtrlPCurWD cal ctrlp#init(0, 0) com! CtrlPCurFile cal ctrlp#init(0, 1) com! CtrlPRoot cal ctrlp#init(0, 2) -com! ResetCtrlP cal ctrlp#reset() - exe 'nn ' g:ctrlp_map ':CtrlP' -if g:ctrlp_mru_files | cal ctrlp#mrufiles#init() | endif +cal ctrlp#mrufiles#init() let [g:ctrlp_lines, g:ctrlp_allfiles] = [[], []] diff --git a/readme.md b/readme.md index c042ac9..fc9caf6 100644 --- a/readme.md +++ b/readme.md @@ -5,6 +5,7 @@ Full path fuzzy __file__, __buffer__ and __MRU__ file finder for Vim. * Full support for Vim’s regexp as search pattern. * Built-in Most Recently Used (MRU) files monitoring. * Built-in project’s root finder. +* Open Multiple Files. * [Extensible][3]. ![ctrlp][1] @@ -18,7 +19,7 @@ Once CtrlP is open: * Press `` and `` to switch between find file, buffer, and MRU file modes. * Press `` to switch to filename only search instead of full path. * Use `*` or `|` in the prompt to submit the string as a Vim’s regexp pattern. -* Or press `` to switch to full regexp search mode. +* Or press `` to switch to regexp mode. * End the input string with a colon `:` followed by a command to execute after opening the file. e.g. `abc:45` will open the file matched the pattern and jump to line 45. * Submit two dots `..` as the input string to go backward the directory tree by 1 level. @@ -49,20 +50,6 @@ e.g. `abc:45` will open the file matched the pattern and jump to line 45. root.dir .vimprojects -* You can also use the set-working-directory functionality above outside of CtrlP -by adding the following line to your vimrc. -The parameter is the same (0, 1 or 2): - - ```vim - au BufEnter * cal ctrlp#SetWorkingPath(2) - ``` - -* Enable/Disable Most Recently Used files monitoring and its functionalities: - - ```vim - let g:ctrlp_mru_files = 1 - ``` - * If you want to exclude directories or files from the search, you can use the Vim’s option `wildignore`. Examples: