Various changes:

* New option `g:ctrlp_live_update`: enable/disable the update-as-you-type functionality.
* New option `g:ctrlp_max_depth`: the maximum directory depth to recurse into.
* New command `ResetCtrlP`: reset all options and take in new values of the option variables.
* Various other changes and bugfixes.
This commit is contained in:
Kien N 2011-09-18 18:33:37 +07:00
parent 9b188b1369
commit bfd98009ed
6 changed files with 371 additions and 298 deletions

View File

@ -13,124 +13,141 @@ if v:version < '700' "{{{
endif "}}} endif "}}}
" Option variables {{{ " Option variables {{{
if !exists('g:ctrlp_match_window_reversed') func! s:opts()
let s:mwreverse = 1 if !exists('g:ctrlp_match_window_reversed')
else let s:mwreverse = 1
let s:mwreverse = g:ctrlp_match_window_reversed else
unl g:ctrlp_match_window_reversed let s:mwreverse = g:ctrlp_match_window_reversed
endif unl g:ctrlp_match_window_reversed
endif
if !exists('g:ctrlp_persistent_input') if !exists('g:ctrlp_persistent_input')
let s:pinput = 1 let s:pinput = 1
else else
let s:pinput = g:ctrlp_persistent_input let s:pinput = g:ctrlp_persistent_input
unl g:ctrlp_persistent_input unl g:ctrlp_persistent_input
endif endif
if !exists('g:ctrlp_split_window') if !exists('g:ctrlp_split_window')
let s:splitwin = 0 let s:splitwin = 0
else else
let s:splitwin = g:ctrlp_split_window let s:splitwin = g:ctrlp_split_window
unl g:ctrlp_split_window unl g:ctrlp_split_window
endif endif
if !exists('g:ctrlp_ignore_space') if !exists('g:ctrlp_ignore_space')
let s:igspace = 0 let s:igspace = 0
else else
let s:igspace = g:ctrlp_ignore_space let s:igspace = g:ctrlp_ignore_space
unl g:ctrlp_ignore_space unl g:ctrlp_ignore_space
endif endif
if !exists('g:ctrlp_working_path_mode') if !exists('g:ctrlp_working_path_mode')
let s:pathmode = 1 let s:pathmode = 1
else else
let s:pathmode = g:ctrlp_working_path_mode let s:pathmode = g:ctrlp_working_path_mode
unl g:ctrlp_working_path_mode unl g:ctrlp_working_path_mode
endif endif
if !exists('g:ctrlp_root_markers') if !exists('g:ctrlp_root_markers')
let s:rmarkers = [] let s:rmarkers = []
else else
let s:rmarkers = g:ctrlp_root_markers let s:rmarkers = g:ctrlp_root_markers
unl g:ctrlp_root_markers unl g:ctrlp_root_markers
endif endif
if !exists('g:ctrlp_max_height') if !exists('g:ctrlp_max_height')
let s:mxheight = 10 let s:mxheight = 10
else else
let s:mxheight = g:ctrlp_max_height let s:mxheight = g:ctrlp_max_height
unl g:ctrlp_max_height unl g:ctrlp_max_height
endif endif
if !exists('g:ctrlp_regexp_search') if !exists('g:ctrlp_regexp_search')
let s:regexp = 0 let s:regexp = 0
else else
let s:regexp = g:ctrlp_regexp_search let s:regexp = g:ctrlp_regexp_search
unl g:ctrlp_regexp_search unl g:ctrlp_regexp_search
endif endif
if !exists('g:ctrlp_use_caching') if !exists('g:ctrlp_use_caching')
let s:caching = 1 let s:caching = 1
else else
let s:caching = g:ctrlp_use_caching let s:caching = g:ctrlp_use_caching
unl g:ctrlp_use_caching unl g:ctrlp_use_caching
endif endif
if !exists('g:ctrlp_clear_cache_on_exit') if !exists('g:ctrlp_clear_cache_on_exit')
let s:cconex = 1 let s:cconex = 1
else else
let s:cconex = g:ctrlp_clear_cache_on_exit let s:cconex = g:ctrlp_clear_cache_on_exit
unl g:ctrlp_clear_cache_on_exit unl g:ctrlp_clear_cache_on_exit
endif endif
if !exists('g:ctrlp_cache_dir') if !exists('g:ctrlp_cache_dir')
let s:cache_dir = $HOME let s:cache_dir = $HOME
else else
let s:cache_dir = g:ctrlp_cache_dir let s:cache_dir = g:ctrlp_cache_dir
endif endif
if !exists('g:ctrlp_newcache') if !exists('g:ctrlp_newcache')
let g:ctrlp_newcache = 0 let g:ctrlp_newcache = 0
endif endif
if !exists('g:ctrlp_by_filename') if !exists('g:ctrlp_by_filename')
let s:byfname = 0 let s:byfname = 0
else else
let s:byfname = g:ctrlp_by_filename let s:byfname = g:ctrlp_by_filename
unl g:ctrlp_by_filename unl g:ctrlp_by_filename
endif endif
if !exists('g:ctrlp_prompt_mappings') if !exists('g:ctrlp_prompt_mappings')
let s:urprtmaps = 0 let s:urprtmaps = 0
else else
let s:urprtmaps = g:ctrlp_prompt_mappings let s:urprtmaps = g:ctrlp_prompt_mappings
unl g:ctrlp_prompt_mappings unl g:ctrlp_prompt_mappings
endif endif
if !exists('g:ctrlp_dotfiles') if !exists('g:ctrlp_dotfiles')
let s:dotfiles = 1 let s:dotfiles = 1
else else
let s:dotfiles = g:ctrlp_dotfiles let s:dotfiles = g:ctrlp_dotfiles
unl g:ctrlp_dotfiles unl g:ctrlp_dotfiles
endif endif
if !exists('g:ctrlp_highlight_match') if !exists('g:ctrlp_highlight_match')
let s:mathi = [1, 'Function'] let s:mathi = [1, 'Function']
else else
let s:mathi = g:ctrlp_highlight_match let s:mathi = g:ctrlp_highlight_match
unl g:ctrlp_highlight_match unl g:ctrlp_highlight_match
endif endif
if !exists('g:ctrlp_max_files') if !exists('g:ctrlp_max_files')
let s:maxfiles = 20000 let s:maxfiles = 20000
else else
let s:maxfiles = g:ctrlp_max_files let s:maxfiles = g:ctrlp_max_files
unl g:ctrlp_max_files unl g:ctrlp_max_files
endif endif
if !exists('g:ctrlp_user_command') if !exists('g:ctrlp_max_depth')
let g:ctrlp_user_command = '' let s:maxdepth = 40
endif else
let s:maxdepth = g:ctrlp_max_depth
unl g:ctrlp_max_depth
endif
if !exists('g:ctrlp_live_update')
let s:liup = 1
else
let s:liup = g:ctrlp_live_update
unl g:ctrlp_live_update
endif
if !exists('g:ctrlp_user_command')
let g:ctrlp_user_command = ''
endif
endfunc
cal s:opts()
" Limiters " Limiters
let s:compare_lim = 3000 let s:compare_lim = 3000
@ -152,58 +169,72 @@ func! ctrlp#clearallcaches()
endif endif
cal ctrlp#clearcache() cal ctrlp#clearcache()
endfunc endfunc
func! ctrlp#reset()
cal s:opts()
cal ctrlp#utils#opts()
if g:ctrlp_mru_files | cal ctrlp#mrufiles#opts() | endif
endfunc
"}}} "}}}
" * ListAllFiles {{{ " * ListAllFiles {{{
func! s:List(dirs, allfiles) func! s:List(dirs, allfiles, depth)
" note: wildignore is ignored when using ** " note: wildignore is ignored when using **
let glob = s:dotfiles ? '.*\|*' : '*' let glob = s:dotfiles ? '.*\|*' : '*'
let entries = split(globpath(a:dirs, glob), '\n') let entries = split(globpath(a:dirs, glob), '\n')
let entries = filter(entries, 'getftype(v:val) != "link"')
let entries2 = deepcopy(entries) let entries2 = deepcopy(entries)
let alldirs = s:dotfiles ? filter(entries, 's:dirfilter(v:val)') : filter(entries, 'isdirectory(v:val)') let alldirs = s:dotfiles ? filter(entries, 's:dirfilter(v:val)') : filter(entries, 'isdirectory(v:val)')
let allfiles = filter(entries2, '!isdirectory(v:val)') let g:ctrlp_allfiles = filter(entries2, '!isdirectory(v:val)')
cal extend(allfiles, a:allfiles, 0) cal extend(g:ctrlp_allfiles, a:allfiles, 0)
if empty(alldirs) || s:maxfiles(len(allfiles)) let depth = a:depth + 1
let s:allfiles = allfiles if empty(alldirs) || s:maxfiles(len(g:ctrlp_allfiles)) || depth > s:maxdepth
retu
else else
let dirs = join(alldirs, ',') let dirs = join(alldirs, ',')
cal s:progress(len(allfiles)) sil! cal s:progress(len(g:ctrlp_allfiles))
cal s:List(dirs, allfiles) cal s:List(dirs, g:ctrlp_allfiles, depth)
endif endif
endfunc endfunc
func! s:ListAllFiles(path) func! s:ListAllFiles(path)
let cache_file = ctrlp#utils#cachefile() let cache_file = ctrlp#utils#cachefile()
if g:ctrlp_newcache || !filereadable(cache_file) || !s:caching if g:ctrlp_newcache || !filereadable(cache_file) || !s:caching
" get the files " get the list of files
if empty(g:ctrlp_user_command) if empty(g:ctrlp_user_command)
cal s:List(a:path, []) cal s:List(a:path, [], 0)
let allfiles = s:allfiles
unl s:allfiles
else else
cal s:progress(escape('Waiting...', ' ')) sil! cal s:progress(escape('Waiting...', ' '))
try try
let allfiles = split(system(printf(g:ctrlp_user_command, shellescape(a:path))), '\n') if exists('+ssl') && &ssl
let ssl = &ssl
let &ssl = 0
endif
let g:ctrlp_allfiles = split(system(printf(g:ctrlp_user_command, shellescape(a:path))), '\n')
if exists('+ssl') && exists('ssl')
let &ssl = ssl
cal map(g:ctrlp_allfiles, 'substitute(v:val, "\\", "/", "g")')
endif
catch catch
retu [] retu []
endtry endtry
endif endif
" remove base directory " remove base directory
let path = &ssl || !exists('+ssl') ? getcwd().'/' : substitute(getcwd(), '\\', '\\\\', 'g').'\\' let path = &ssl || !exists('+ssl') ? getcwd().'/' : substitute(getcwd(), '\\', '\\\\', 'g').'\\'
cal map(allfiles, 'substitute(v:val, path, "", "g")') cal map(g:ctrlp_allfiles, 'substitute(v:val, path, "", "g")')
let read_cache = 0 let read_cache = 0
else else
let allfiles = ctrlp#utils#readfile(cache_file) let g:ctrlp_allfiles = ctrlp#utils#readfile(cache_file)
let read_cache = 1 let read_cache = 1
endif endif
if len(allfiles) <= s:compare_lim | cal sort(allfiles, 's:compare') | endif if len(g:ctrlp_allfiles) <= s:compare_lim | cal sort(g:ctrlp_allfiles, 's:complen') | endif
" write cache " write cache
if !read_cache && ( ( g:ctrlp_newcache || !filereadable(cache_file) ) if !read_cache && ( ( g:ctrlp_newcache || !filereadable(cache_file) )
\ && s:caching || len(allfiles) > s:nocache_lim ) \ && s:caching || len(g:ctrlp_allfiles) > s:nocache_lim )
if len(allfiles) > s:nocache_lim | let s:caching = 1 | endif if len(g:ctrlp_allfiles) > s:nocache_lim | let s:caching = 1 | endif
cal ctrlp#utils#writecache(allfiles) cal ctrlp#utils#writecache(g:ctrlp_allfiles)
endif endif
retu allfiles retu g:ctrlp_allfiles
endfunc endfunc
"}}} "}}}
@ -221,11 +252,8 @@ func! s:ListAllBuffers() "{{{
endfunc "}}} endfunc "}}}
func! s:SplitPattern(str,...) "{{{ func! s:SplitPattern(str,...) "{{{
let str = a:str
" ignore spaces " ignore spaces
if s:igspace let str = s:igspace ? substitute(a:str, ' ', '', 'g') : a:str
let str = substitute(str, ' ', '', 'g')
endif
" clear the jumptoline var " clear the jumptoline var
if exists('s:jmpln') | unl s:jmpln | endif if exists('s:jmpln') | unl s:jmpln | endif
" If pattern contains :\d (e.g. abc:25) " If pattern contains :\d (e.g. abc:25)
@ -263,13 +291,31 @@ func! s:SplitPattern(str,...) "{{{
retu newpats retu newpats
endfunc "}}} endfunc "}}}
func! s:GetMatchedItems(items, pats, limit) "{{{ " * GetMatchedItems {{{
func! s:MatchIt(items, pat, limit)
let items = a:items
let pat = a:pat
let limit = a:limit
let newitems = []
for item in items
if s:byfname
if s:matchsubstr(item, pat) >= 0 | cal add(newitems, item) | endif
else
if match(item, pat) >= 0 | cal add(newitems, item) | endif
endif
" stop if reached the limit
if limit > 0 && len(newitems) == limit | break | endif
endfor
retu newitems
endfunc
func! s:GetMatchedItems(items, pats, limit)
let items = a:items let items = a:items
let pats = a:pats let pats = a:pats
let limit = a:limit let limit = a:limit
" if items is longer than s:mltipats_lim, use only the last pattern " if items is longer than s:mltipats_lim, use only the last pattern
if len(items) >= s:mltipats_lim if len(items) >= s:mltipats_lim
let pats = [pats[-1]] let pats = pats[-1]
endif endif
cal map(pats, 'substitute(v:val, "\\\~", "\\\\\\~", "g")') cal map(pats, 'substitute(v:val, "\\\~", "\\\\\\~", "g")')
" loop through the patterns " loop through the patterns
@ -282,43 +328,20 @@ func! s:GetMatchedItems(items, pats, limit) "{{{
if empty(items) " end here if empty(items) " end here
retu exists('newitems') ? newitems : [] retu exists('newitems') ? newitems : []
else " start here, goes back up if has 2 or more in pats else " start here, goes back up if has 2 or more in pats
let newitems = []
" loop through the items " loop through the items
for item in items let newitems = s:MatchIt(items, each, limit)
if s:byfname
if s:matchsubstr(item, each) >= 0 | cal add(newitems, item) | endif
else
if match(item, each) >= 0 | cal add(newitems, item) | endif
endif
" stop if reached the limit
if a:limit > 0 && len(newitems) == limit | break | endif
endfor
endif endif
endfor endfor
let s:nomatches = len(newitems) let s:nomatches = len(newitems)
retu newitems retu newitems
endfunc "}}} endfunc
"}}}
func! s:SetupBlank() "{{{ func! s:SetupBlank() "{{{
setl bt=nofile setl bt=nofile bh=unload noswf nobl ts=4 sw=4 sts=4 nonu
setl bh=delete \ nowrap nolist nospell cul nocuc tw=0 wfh
setl noswf
setl nobl
setl ts=4
setl sw=4
setl sts=4
setl nonu
setl nowrap
setl nolist
setl nospell
setl cul
setl nocuc
setl tw=0
setl wfh
if v:version >= '703' if v:version >= '703'
setl nornu setl nornu noudf cc=0
setl noudf
setl cc=0
endif endif
redr redr
endfunc "}}} endfunc "}}}
@ -329,29 +352,40 @@ func! s:BufOpen(...) "{{{
let bufnum = bufnr(buf) let bufnum = bufnr(buf)
" Closing " Closing
if bufnum > 0 && bufwinnr(bufnum) > 0 if bufnum > 0 && bufwinnr(bufnum) > 0
exe 'bw!' a:1 exe 'bun!'
if s:pinput != 2 && exists('g:CtrlP_cline') if s:pinput != 2 && exists('g:CtrlP_cline')
unl g:CtrlP_cline unl g:CtrlP_cline
endif endif
endif endif
if exists('a:2') if exists('a:2')
" Restore the changed global options " Restore the changed global options
exe 'let &magic=' . s:CtrlP_magic let &magic = s:CtrlP_magic
exe 'let &to=' . s:CtrlP_to let &to = s:CtrlP_to
exe 'se tm=' . s:CtrlP_tm let &tm = s:CtrlP_tm
exe 'let &sb=' . s:CtrlP_sb let &sb = s:CtrlP_sb
exe 'let &hls=' . s:CtrlP_hls let &hls = s:CtrlP_hls
exe 'let &im=' . s:CtrlP_im let &im = s:CtrlP_im
exe 'se report=' . s:CtrlP_report let &report = s:CtrlP_report
exe 'let &sc=' . s:CtrlP_sc let &sc = s:CtrlP_sc
exe 'se ss=' . s:CtrlP_ss let &ss = s:CtrlP_ss
exe 'se siso=' . s:CtrlP_siso let &siso = s:CtrlP_siso
exe 'let &ea=' . s:CtrlP_ea let &ea = s:CtrlP_ea
exe 'se gcr=' . s:CtrlP_gcr let &gcr = s:CtrlP_gcr
let &mfd = s:CtrlP_mfd
" cleaning up
if exists('s:cwd') if exists('s:cwd')
exe 'chdir' s:cwd exe 'chdir' s:cwd
unl s:cwd unl s:cwd
endif endif
if exists('s:firstinit')
unl s:firstinit
endif
if exists('g:ctrlp_lines')
let g:ctrlp_lines = []
endif
if exists('g:ctrlp_allfiles')
let g:ctrlp_allfiles = []
endif
exe s:currwin.'winc w' exe s:currwin.'winc w'
ec ec
else else
@ -371,6 +405,7 @@ func! s:BufOpen(...) "{{{
let s:CtrlP_siso = &siso let s:CtrlP_siso = &siso
let s:CtrlP_ea = &ea let s:CtrlP_ea = &ea
let s:CtrlP_gcr = &gcr let s:CtrlP_gcr = &gcr
let s:CtrlP_mfd = &mfd
if !exists('g:CtrlP_prompt') || !s:pinput if !exists('g:CtrlP_prompt') || !s:pinput
let g:CtrlP_prompt = ['', '', ''] let g:CtrlP_prompt = ['', '', '']
endif endif
@ -385,6 +420,7 @@ func! s:BufOpen(...) "{{{
se ss=0 se ss=0
se siso=0 se siso=0
se noea se noea
se mfd=200
se gcr=a:block-PmenuSel-blinkon0 se gcr=a:block-PmenuSel-blinkon0
endif endif
endfunc "}}} endfunc "}}}
@ -392,16 +428,16 @@ endfunc "}}}
func! s:Renderer(lines, pat) "{{{ func! s:Renderer(lines, pat) "{{{
let nls = [] let nls = []
for i in range(0, len(a:lines) - 1) for i in range(0, len(a:lines) - 1)
let nls = add(nls, '> '.a:lines[i]) cal add(nls, '> '.a:lines[i])
endfor endfor
" Detemine/set max height " Determine/set max height
let height = s:mxheight let height = s:mxheight
let max = len(nls) < height ? len(nls) : height let max = len(nls) < height ? len(nls) : height
exe 'res' max exe 'res' max
" Output to buffer " Output to buffer
if !empty(nls) if !empty(nls)
setl cul setl cul
" don't sort " sort if not type 2 (MRU)
if index([2], s:itemtype) < 0 if index([2], s:itemtype) < 0
let s:compat = a:pat let s:compat = a:pat
cal sort(nls, 's:mixedsort') cal sort(nls, 's:mixedsort')
@ -431,9 +467,9 @@ endfunc "}}}
func! s:UpdateMatches(pat) "{{{ func! s:UpdateMatches(pat) "{{{
" Delete the buffer's content " Delete the buffer's content
sil! %d _ sil! %d _
let pats = s:SplitPattern(a:pat) let pats = s:SplitPattern(a:pat)
let lines = s:GetMatchedItems(s:lines, pats, s:mxheight) let lines = s:GetMatchedItems(g:ctrlp_lines, pats, s:mxheight)
let pat = pats[-1] let pat = pats[-1]
cal s:Renderer(lines, pat) cal s:Renderer(lines, pat)
" highlighting " highlighting
if type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0] && exists('*clearmatches') if type(s:mathi) == 3 && len(s:mathi) == 2 && s:mathi[0] && exists('*clearmatches')
@ -451,11 +487,11 @@ func! s:BuildPrompt(...) "{{{
let prt = deepcopy(g:CtrlP_prompt) let prt = deepcopy(g:CtrlP_prompt)
cal map(prt, 'escape(v:val, estr)') cal map(prt, 'escape(v:val, estr)')
let str = prt[0] . prt[1] . prt[2] let str = prt[0] . prt[1] . prt[2]
if s:nomatches if s:nomatches && ( s:liup || s:firstinit )
" note: add sil! back after testing let s:firstinit = 0
sil! cal s:UpdateMatches(str) sil! cal s:UpdateMatches(str)
endif endif
cal s:statusline() sil! cal s:statusline()
" Toggling " Toggling
if !exists('a:1') || ( exists('a:1') && a:1 ) if !exists('a:1') || ( exists('a:1') && a:1 )
let hiactive = 'Normal' let hiactive = 'Normal'
@ -466,17 +502,25 @@ func! s:BuildPrompt(...) "{{{
let hibase = 'Comment' let hibase = 'Comment'
" Build it " Build it
redr redr
exe 'echohl' hibase '| echon "'.base.'" exe 'echoh' hibase '| echon "'.base.'"
\ | echohl' hiactive '| echon "'.prt[0].'" \ | echoh' hiactive '| echon "'.prt[0].'"
\ | echohl' hibase '| echon "'.prt[1].'" \ | echoh' hibase '| echon "'.prt[1].'"
\ | echohl' hiactive '| echon "'.prt[2].'" \ | echoh' hiactive '| echon "'.prt[2].'"
\ | echohl None' \ | echoh None'
" Append the cursor _ at the end " Append the cursor _ at the end
if empty(prt[1]) && ( !exists('a:1') || ( exists('a:1') && a:1 ) ) if empty(prt[1]) && ( !exists('a:1') || ( exists('a:1') && a:1 ) )
exe 'echohl' hibase '| echon "'.cur.'" | echohl None' exe 'echoh' hibase '| echon "'.cur.'" | echoh None'
endif endif
endfunc "}}} endfunc "}}}
func! s:ForceUpdate() "{{{
let estr = '"\'
let prt = deepcopy(g:CtrlP_prompt)
cal map(prt, 'escape(v:val, estr)')
let str = prt[0] . prt[1] . prt[2]
cal s:UpdateMatches(str)
endfunc "}}}
" * Prt Actions {{{ " * Prt Actions {{{
func! s:PrtClear() func! s:PrtClear()
let s:nomatches = 1 let s:nomatches = 1
@ -557,7 +601,7 @@ func! s:PrtDeleteWord()
endfunc endfunc
func! s:PrtSelectMove(dir) func! s:PrtSelectMove(dir)
exe 'keepj norm!' a:dir exe 'norm!' a:dir
let g:CtrlP_cline = line('.') let g:CtrlP_cline = line('.')
endfunc endfunc
@ -632,6 +676,7 @@ func! s:MapSpecs(...)
\ 'Type(0)': ['<m-1>'], \ 'Type(0)': ['<m-1>'],
\ 'Type(1)': ['<m-2>'], \ 'Type(1)': ['<m-2>'],
\ 'Type(2)': ['<m-3>'], \ 'Type(2)': ['<m-3>'],
\ 'ForceUpdate()': ['<c-o>'],
\ 'PrtCurStart()': ['<c-a>'], \ 'PrtCurStart()': ['<c-a>'],
\ 'PrtCurEnd()': ['<c-e>'], \ 'PrtCurEnd()': ['<c-e>'],
\ 'PrtCurLeft()': ['<c-h>', '<left>'], \ 'PrtCurLeft()': ['<c-h>', '<left>'],
@ -655,7 +700,7 @@ func! s:MapSpecs(...)
endfor endfor
let lcmap = 'nn <buffer> <silent>' let lcmap = 'nn <buffer> <silent>'
" correct arrow keys in terminal " correct arrow keys in terminal
if &term =~? 'xterm' || &term =~? '^vt' if &term =~? 'xterm' || &term =~? '\<k\?vt' || &term =~? 'gnome'
for each in ['\A <up>','\B <down>','\C <right>','\D <left>'] for each in ['\A <up>','\B <down>','\C <right>','\D <left>']
exe lcmap.' <esc>['.each exe lcmap.' <esc>['.each
endfor endfor
@ -690,20 +735,19 @@ endfunc
func! s:ToggleFocus() func! s:ToggleFocus()
let b:focus = !exists('b:focus') || b:focus ? 0 : 1 let b:focus = !exists('b:focus') || b:focus ? 0 : 1
cal s:MapKeys(b:focus) cal s:MapKeys(b:focus)
let s:firstinit = 1
cal s:BuildPrompt(b:focus) cal s:BuildPrompt(b:focus)
endfunc endfunc
func! s:ToggleRegex() func! s:ToggleRegex()
let s:regexp = s:regexp ? 0 : 1 let s:regexp = s:regexp ? 0 : 1
let s:nomatches = 1 cal s:PrtSwitcher()
cal s:BuildPrompt(s:Focus())
endfunc endfunc
func! s:ToggleByFname() func! s:ToggleByFname()
let s:byfname = s:byfname ? 0 : 1 let s:byfname = s:byfname ? 0 : 1
cal s:MapKeys(s:Focus(), 1) cal s:MapKeys(s:Focus(), 1)
let s:nomatches = 1 cal s:PrtSwitcher()
cal s:BuildPrompt(s:Focus())
endfunc endfunc
func! s:ToggleType(dir) func! s:ToggleType(dir)
@ -716,7 +760,12 @@ func! s:Type(type)
let s:itemtype = a:type let s:itemtype = a:type
cal s:syntax() cal s:syntax()
cal s:SetLines(s:itemtype) cal s:SetLines(s:itemtype)
cal s:PrtSwitcher()
endfunc
func! s:PrtSwitcher()
let s:nomatches = 1 let s:nomatches = 1
let s:firstinit = 1
cal s:BuildPrompt(s:Focus()) cal s:BuildPrompt(s:Focus())
endfunc endfunc
"}}} "}}}
@ -724,7 +773,7 @@ endfunc
" * SetWorkingPath {{{ " * SetWorkingPath {{{
func! s:FindRoot(curr, mark) func! s:FindRoot(curr, mark)
if !empty(globpath(a:curr, a:mark)) if !empty(globpath(a:curr, a:mark))
exe 'chdir' a:curr sil! exe 'chdir' a:curr
else else
let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '') let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '')
if parent != a:curr | cal s:FindRoot(parent, a:mark) | endif if parent != a:curr | cal s:FindRoot(parent, a:mark) | endif
@ -734,10 +783,10 @@ endfunc
func! ctrlp#SetWorkingPath(...) func! ctrlp#SetWorkingPath(...)
let l:pathmode = 2 let l:pathmode = 2
let s:cwd = getcwd() let s:cwd = getcwd()
if exists('a:1') && len(a:1) == 1 && !type('a:1') if exists('a:1') && len(a:1) == 1 && !type(a:1)
let l:pathmode = a:1 let l:pathmode = a:1
elseif exists('a:1') && len(a:1) > 1 && type('a:1') elseif exists('a:1') && len(a:1) > 1 && type(a:1)
exe 'chdir' a:1 sil! exe 'chdir' a:1
retu retu
endif endif
if match(expand('%:p'), '^\<.\+\>://.*') >= 0 if match(expand('%:p'), '^\<.\+\>://.*') >= 0
@ -745,7 +794,7 @@ func! ctrlp#SetWorkingPath(...)
retu retu
endif endif
if exists('+acd') | se noacd | endif if exists('+acd') | se noacd | endif
exe 'chdir' exists('*fnameescape') ? fnameescape(expand('%:p:h')) : expand('%:p:h') sil! exe 'chdir' exists('*fnameescape') ? fnameescape(expand('%:p:h')) : expand('%:p:h')
if s:pathmode == 1 || l:pathmode == 1 | retu | endif if s:pathmode == 1 || l:pathmode == 1 | retu | endif
let markers = [ let markers = [
\ 'root.dir', \ 'root.dir',
@ -778,8 +827,8 @@ func! s:AcceptSelection(mode,...) "{{{
retu retu
endif endif
endif endif
let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
" get the full path " get the full path
let matchstr = matchstr(getline('.'), '^> \zs.\+\ze\t*$')
let filpath = s:itemtype ? matchstr : getcwd().ctrlp#utils#lash().matchstr let filpath = s:itemtype ? matchstr : getcwd().ctrlp#utils#lash().matchstr
" If only need the full path " If only need the full path
if exists('a:1') && a:1 | retu filpath | endif if exists('a:1') && a:1 | retu filpath | endif
@ -820,30 +869,33 @@ func! s:AcceptSelection(mode,...) "{{{
endfor endfor
endif endif
endfor endfor
" switch to the buffer or open the file " switch to existing buffer or open new one
let opened = 0 let opened = 0
if s:normbuf() if s:normbuf()
exe s:normbuf().'winc w' exe s:normbuf().'winc w'
endif endif
if bufnum > 0 if bufnum > 0
if exists('buftabwinnr') if exists('buftabwinnr') " in a tab
exe 'norm!' buftabnr.'gt' exe 'norm!' buftabnr.'gt'
exe buftabwinnr.'winc w' exe buftabwinnr.'winc w'
elseif bufwinnr > 0 elseif bufwinnr > 0 " in a window
exe bufwinnr.'winc w' exe bufwinnr.'winc w'
else else
if !s:normbuf() if !s:normbuf()
exe 'bo vne' exe 'bo vne'
else
exe 'bo' cmd
endif endif
let cmd = 'b'.bufnum exe 'b'.bufnum
endif endif
else else
let pref = 'bo'
if !s:normbuf() | if md == 'e' if !s:normbuf() | if md == 'e'
exe 'bo vne' exe pref 'vne'
let pref = ''
endif | endif endif | endif
let cmd = 'bo '.cmd.' '.filpath exe 'bo '.cmd.' '.filpath
endif endif
exe cmd
" jump to line " jump to line
if exists('s:jmpln') && !empty('s:jmpln') if exists('s:jmpln') && !empty('s:jmpln')
exe s:jmpln exe s:jmpln
@ -854,7 +906,7 @@ endfunc "}}}
" * Helper functions {{{ " * Helper functions {{{
" comparing and sorting {{{ " comparing and sorting {{{
func! s:compare(s1, s2) func! s:complen(s1, s2)
" by length " by length
let len1 = strlen(a:s1) let len1 = strlen(a:s1)
let len2 = strlen(a:s2) let len2 = strlen(a:s2)
@ -863,27 +915,32 @@ endfunc
func! s:compmatlen(s1, s2) func! s:compmatlen(s1, s2)
" by match length " by match length
let lens1 = s:matchlens(a:s1, s:compat) let mln1 = s:shortest(s:matchlens(a:s1, s:compat))
let lens2 = s:matchlens(a:s2, s:compat) let mln2 = s:shortest(s:matchlens(a:s2, s:compat))
let mln1 = s:shortest(lens1) + ( s:wordonly(lens1) / 2 )
let mln2 = s:shortest(lens2) + ( s:wordonly(lens2) / 2 )
retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1 retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
endfunc endfunc
func! s:compword(s1, s2)
" by word-only (no non-word in match)
let wrd1 = s:wordonly(s:matchlens(a:s1, s:compat))
let wrd2 = s:wordonly(s:matchlens(a:s2, s:compat))
retu wrd1 == wrd2 ? 0 : wrd1 > wrd2 ? 1 : -1
endfunc
func! s:matchlens(str, pat, ...) func! s:matchlens(str, pat, ...)
if empty(a:pat) || a:pat == '$' || a:pat == '^' if empty(a:pat) || index(['^','$'], a:pat) >= 0
retu [] retu {}
endif endif
let st = exists('a:1') ? a:1 : 0 let st = exists('a:1') ? a:1 : 0
let lens = exists('a:2') ? a:2 : {} let lens = exists('a:2') ? a:2 : {}
let nr = exists('a:3') ? a:3 : 0 let nr = exists('a:3') ? a:3 : 0
if match(a:str, a:pat, st) != -1 if match(a:str, a:pat, st) != -1
let start = match(a:str, a:pat, st) let start = match(a:str, a:pat, st)
let str = matchstr(a:str, a:pat, st) let str = matchstr(a:str, a:pat, st)
let len = len(str) let len = len(str)
let end = matchend(a:str, a:pat, st) let end = matchend(a:str, a:pat, st)
let lens = extend(lens, { nr : [len, str] }) let lens = extend(lens, { nr : [len, str] })
let lens = s:matchlens(a:str, a:pat, end, lens, nr + 1) let lens = s:matchlens(a:str, a:pat, end, lens, nr + 1)
endif endif
retu lens retu lens
endfunc endfunc
@ -897,7 +954,7 @@ func! s:shortest(lens)
endfunc endfunc
func! s:wordonly(lens) func! s:wordonly(lens)
let lens = a:lens let lens = a:lens
let minln = s:shortest(lens) let minln = s:shortest(lens)
cal filter(lens, 'minln == v:val[0]') cal filter(lens, 'minln == v:val[0]')
for nr in keys(lens) for nr in keys(lens)
@ -907,7 +964,7 @@ func! s:wordonly(lens)
endfunc endfunc
func! s:mixedsort(s1, s2) func! s:mixedsort(s1, s2)
retu 3 * s:compmatlen(a:s1, a:s2) + s:compare(a:s1, a:s2) retu 3 * s:compmatlen(a:s1, a:s2) + 2 * s:complen(a:s1, a:s2) + s:compword(a:s1, a:s2)
endfunc endfunc
"}}} "}}}
@ -916,7 +973,7 @@ func! s:statusline(...)
let itemtypes = { let itemtypes = {
\ 0: ['files', 'fil'], \ 0: ['files', 'fil'],
\ 1: ['buffers', 'buf'], \ 1: ['buffers', 'buf'],
\ 2: ['recent\ files', 'mru'], \ 2: ['recent files', 'mru'],
\ } \ }
if !g:ctrlp_mru_files if !g:ctrlp_mru_files
cal remove(itemtypes, 2) cal remove(itemtypes, 2)
@ -927,19 +984,19 @@ func! s:statusline(...)
let item = itemtypes[s:itemtype][0] let item = itemtypes[s:itemtype][0]
let focus = s:Focus() ? 'prt' : 'win' let focus = s:Focus() ? 'prt' : 'win'
let byfname = s:byfname ? 'file' : 'path' let byfname = s:byfname ? 'file' : 'path'
let regex = s:regexp ? '%#LineNr#\ regex\ %*' : '' let regex = s:regexp ? '%#LineNr# regex %*' : ''
let focus = '%#LineNr#\ '.focus.'\ %*' let focus = '%#LineNr# '.focus.' %*'
let byfname = '%#Character#\ '.byfname.'\ %*' let byfname = '%#Character# '.byfname.' %*'
let item = '%#Character#\ '.item.'\ %*' let item = '%#Character# '.item.' %*'
let slider = '\ <'.prev.'>={'.item.'}=<'.next.'>' let slider = ' <'.prev.'>={'.item.'}=<'.next.'>'
let dir = '\ %=%<%#LineNr#\ '.escape(getcwd(), ' =#(){}%\').'\ %*' let dir = ' %=%<%#LineNr# '.getcwd().' %*'
exe 'setl stl='.focus.byfname.regex.slider.dir let &l:stl = focus.byfname.regex.slider.dir
endfunc endfunc
func! s:progress(len) func! s:progress(len)
let cnt = '%#Function#\ '.a:len.'\ %*' let cnt = '%#Function# '.a:len.' %*'
let dir = '\ %=%<%#LineNr#\ '.escape(getcwd(), ' =#(){}%\').'\ %*' let dir = ' %=%<%#LineNr# '.getcwd().' %*'
exe 'setl stl='.cnt.dir let &l:stl = cnt.dir
redr redr
endfunc endfunc
"}}} "}}}
@ -952,7 +1009,7 @@ endfunc
func! s:parentdir(curr) func! s:parentdir(curr)
let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '') let parent = substitute(a:curr, '[\/]\zs[^\/]\+[\/]\?$', '', '')
if parent != a:curr if parent != a:curr
exe 'chdir' parent sil! exe 'chdir' parent
endif endif
endfunc endfunc
"}}} "}}}
@ -1003,7 +1060,6 @@ func! s:maxfiles(len)
retu s:maxfiles && a:len > s:maxfiles ? 1 : 0 retu s:maxfiles && a:len > s:maxfiles ? 1 : 0
endfunc endfunc
" return the first window number with a normal buffer
func! s:normbuf() func! s:normbuf()
if &l:bl && empty(&l:bt) && &l:ma | retu winnr() | endif if &l:bl && empty(&l:bt) && &l:ma | retu winnr() | endif
for each in range(1, winnr('$')) for each in range(1, winnr('$'))
@ -1015,32 +1071,28 @@ endfunc
"}}} "}}}
"}}} "}}}
aug CtrlPAug "{{{
au!
au BufLeave,WinLeave,BufUnload ControlP cal s:BufOpen('ControlP', 'del')
au VimLeavePre * if s:cconex | cal ctrlp#clearallcaches() | endif
aug END "}}}
" * Initialization {{{ " * Initialization {{{
func! s:SetLines(type) func! s:SetLines(type)
let s:itemtype = a:type let s:itemtype = a:type
if !s:itemtype let types = [
let s:lines = s:ListAllFiles(getcwd()) \ 's:ListAllFiles(getcwd())',
elseif s:itemtype == 1 \ 's:ListAllBuffers()',
let s:lines = s:ListAllBuffers() \ 'ctrlp#mrufiles#list(-1)',
elseif s:itemtype >= 2 \ ]
let s:lines = s:hooks(s:itemtype) let g:ctrlp_lines = eval(types[a:type])
endif
endfunc
func! s:hooks(type)
let types = {
\ '2': 'ctrlp#mrufiles#list(-1)'
\ }
retu eval(types[a:type])
endfunc endfunc
func! ctrlp#init(type, ...) func! ctrlp#init(type, ...)
let s:nomatches = 1 let s:nomatches = 1
if exists('a:1') let s:firstinit = 1
cal ctrlp#SetWorkingPath(a:1) let a1 = exists('a:1') ? a:1 : ''
else cal ctrlp#SetWorkingPath(a1)
cal ctrlp#SetWorkingPath()
endif
cal s:BufOpen('ControlP') cal s:BufOpen('ControlP')
cal s:SetupBlank() cal s:SetupBlank()
cal s:MapKeys() cal s:MapKeys()
@ -1050,13 +1102,4 @@ func! ctrlp#init(type, ...)
endfunc endfunc
"}}} "}}}
aug CtrlPAug "{{{
au!
au BufLeave,WinLeave ControlP cal s:BufOpen('ControlP', 'del')
au VimLeavePre *
\ if s:cconex
\ | cal ctrlp#clearallcaches() |
\ endif
aug END "}}}
" vim:fen:fdl=0:ts=2:sw=2:sts=2 " vim:fen:fdl=0:ts=2:sw=2:sts=2

View File

@ -10,26 +10,29 @@ if v:version < '700' "{{{
endif "}}} endif "}}}
" Option variables {{{ " Option variables {{{
if !exists('g:ctrlp_mruf_max') func! ctrlp#mrufiles#opts()
let s:max = 50 if !exists('g:ctrlp_mruf_max')
else let s:max = 50
let s:max = g:ctrlp_mruf_max else
unl g:ctrlp_mruf_max let s:max = g:ctrlp_mruf_max
endif unl g:ctrlp_mruf_max
endif
if !exists('g:ctrlp_mruf_include') if !exists('g:ctrlp_mruf_include')
let s:include = '' let s:include = ''
else else
let s:include = g:ctrlp_mruf_include let s:include = g:ctrlp_mruf_include
unl g:ctrlp_mruf_include unl g:ctrlp_mruf_include
endif endif
if !exists('g:ctrlp_mruf_exclude') if !exists('g:ctrlp_mruf_exclude')
let s:exclude = '' let s:exclude = ''
else else
let s:exclude = g:ctrlp_mruf_exclude let s:exclude = g:ctrlp_mruf_exclude
unl g:ctrlp_mruf_exclude unl g:ctrlp_mruf_exclude
endif endif
endfunc
cal ctrlp#mrufiles#opts()
"}}} "}}}
func! ctrlp#mrufiles#list(bufnr) "{{{ func! ctrlp#mrufiles#list(bufnr) "{{{

View File

@ -10,11 +10,14 @@ if v:version < '700' "{{{
endif "}}} endif "}}}
" Option variables {{{ " Option variables {{{
if !exists('g:ctrlp_cache_dir') func! ctrlp#utils#opts()
let s:cache_dir = $HOME if !exists('g:ctrlp_cache_dir')
else let s:cache_dir = $HOME
let s:cache_dir = g:ctrlp_cache_dir else
endif let s:cache_dir = g:ctrlp_cache_dir
endif
endfunc
cal ctrlp#utils#opts()
"}}} "}}}
" Files and Directories functions {{{ " Files and Directories functions {{{

View File

@ -83,7 +83,7 @@ Set this to 1 to ignore whitespaces in filenames and directory names: >
*'g:ctrlp_working_path_mode'* *'g:ctrlp_working_path_mode'*
*SetWorkingPath()* *SetWorkingPath()*
When starting up the prompt, automatically sets the working directory (i.e. the When starting up the prompt, automatically set the working directory (i.e. the
|current-directory|) to: |current-directory|) to:
1 - the parent directory of the current file. 1 - the parent directory of the current file.
2 - the nearest ancestor that contains one of these directories/files: 2 - the nearest ancestor that contains one of these directories/files:
@ -150,6 +150,7 @@ only need to keep the lines that youve changed the values (inside []): >
\ 'ToggleByFname()': ['<c-d>'], \ 'ToggleByFname()': ['<c-d>'],
\ 'ToggleType(1)': ['<c-f>', '<c-up'], \ 'ToggleType(1)': ['<c-f>', '<c-up'],
\ 'ToggleType(-1)': ['<c-b>', '<c-down>'], \ 'ToggleType(-1)': ['<c-b>', '<c-down>'],
\ 'ForceUpdate()': ['<c-o>'],
\ 'PrtCurStart()': ['<c-a>'], \ 'PrtCurStart()': ['<c-a>'],
\ 'PrtCurEnd()': ['<c-e>'], \ 'PrtCurEnd()': ['<c-e>'],
\ 'PrtCurLeft()': ['<c-h>', '<left>'], \ 'PrtCurLeft()': ['<c-h>', '<left>'],
@ -212,6 +213,18 @@ The maximum number of files to scan, set to 0 for no limit: >
let g:ctrlp_max_files = 20000 let g:ctrlp_max_files = 20000
< <
*'g:ctrlp_max_depth'*
The maximum depth of a directory tree to recurse into: >
let g:ctrlp_max_depth = 40
<
Note: keep it smaller than 200. The larger the value, the more memory Vim uses.
*'g:ctrlp_live_update'*
Set to 0 to disable the update-as-you-type functionality; press <c-o> to force
an update: >
let g:ctrlp_live_update = 1
<
*'g:ctrlp_user_command'* *'g:ctrlp_user_command'*
Specify an external tool to use for indexing files instead of Vims globpath(). Specify an external tool to use for indexing files instead of Vims globpath().
Use %s in place of the target directory: > Use %s in place of the target directory: >
@ -221,7 +234,6 @@ Examples: >
let g:ctrlp_user_command = 'find %s -type f' " MacOSX/Linux let g:ctrlp_user_command = 'find %s -type f' " MacOSX/Linux
let g:ctrlp_user_command = 'dir %s /-n /b /s /a-d' " Windows let g:ctrlp_user_command = 'dir %s /-n /b /s /a-d' " Windows
< <
You can also use 'grep', 'findstr' or something else to filter the results. You can also use 'grep', 'findstr' or something else to filter the results.
Examples: > Examples: >
let g:ctrlp_user_command = 'find %s -type f | grep (?!tmp/.*)' let g:ctrlp_user_command = 'find %s -type f | grep (?!tmp/.*)'
@ -253,6 +265,10 @@ Examples: >
:ClearAllCtrlPCaches :ClearAllCtrlPCaches
Delete all the cache files saved in |ctrlp_cache_dir|. Delete all the cache files saved in |ctrlp_cache_dir|.
*:ResetCtrlP*
:ResetCtrlP
Reset all options, take in new values of the option variables (section 2).
The following commands ignore the value of |g:ctrlp_working_path_mode|: The following commands ignore the value of |g:ctrlp_working_path_mode|:
*:CtrlPCurWD* *:CtrlPCurWD*
@ -302,6 +318,10 @@ Once inside the prompt:
<tab> <tab>
Toggle the focus between the match window and the prompt. Toggle the focus between the match window and the prompt.
<c-o>
Force update the match window.
Use this if |g:ctrlp_live_update| has been set to 0.
<c-n>, <c-n>,
<c-j>, <c-j>,
<down> <down>
@ -351,7 +371,7 @@ Once inside the prompt:
<esc>, <esc>,
<c-c>, <c-c>,
<c-g> <c-g>
Exit |CtrlP|. Exit |CtrlP|. <c-c> can also be used to stop the files scan.
Chose your own mappings with |g:ctrlp_prompt_mappings|. Chose your own mappings with |g:ctrlp_prompt_mappings|.
@ -404,17 +424,20 @@ Mercurial repository: https://bitbucket.org/kien/ctrlp.vim
=============================================================================== ===============================================================================
CHANGELOG CHANGELOG
+ New option: |g:ctrlp_max_files| + New command: |ResetCtrlP|
+ New options: |g:ctrlp_max_files|,
|g:ctrlp_max_depth|,
|g:ctrlp_live_update|
Before 2011/09/12 Before 2011/09/12
+ Ability to cycle through matched lines in the match window. + Ability to cycle through matched lines in the match window.
+ Extended the behavior of |g:ctrlp_persistent_input| + Extended the behavior of |g:ctrlp_persistent_input|
+ Extended the behavior of |:CtrlP| + Extended the behavior of |:CtrlP|
+ New option: |g:ctrlp_dotfiles|, + New options: |g:ctrlp_dotfiles|,
|g:ctrlp_clear_cache_on_exit|, |g:ctrlp_clear_cache_on_exit|,
|g:ctrlp_highlight_match|, |g:ctrlp_highlight_match|,
|g:ctrlp_user_command| |g:ctrlp_user_command|
+ New input format: '..' (section 5.d) + New input format: '..' (section 5.d)
+ New mapping: <F5>. + New mapping: <F5>.
+ New commands: |:CtrlPCurWD|, + New commands: |:CtrlPCurWD|,

View File

@ -23,6 +23,11 @@ com! CtrlPCurWD cal ctrlp#init(0, 0)
com! CtrlPCurFile cal ctrlp#init(0, 1) com! CtrlPCurFile cal ctrlp#init(0, 1)
com! CtrlPRoot cal ctrlp#init(0, 2) com! CtrlPRoot cal ctrlp#init(0, 2)
com! ResetCtrlP cal ctrlp#reset()
exe 'nn <silent>' g:ctrlp_map ':<c-u>CtrlP<cr>' exe 'nn <silent>' g:ctrlp_map ':<c-u>CtrlP<cr>'
if g:ctrlp_mru_files | cal ctrlp#mrufiles#init() | endif if g:ctrlp_mru_files | cal ctrlp#mrufiles#init() | endif
let g:ctrlp_lines = []
let g:ctrlp_allfiles = []

View File

@ -17,9 +17,6 @@ Full path fuzzy __file__, __buffer__ and __MRU__ file finder for Vim.
e.g. `abc:45` to open the file matched the pattern and jump to line 45. e.g. `abc:45` to 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. * Submit two dots `..` as the input string to go backward the directory tree by 1 level.
_Screenshot: filename only mode with the match window focused._
![ctrlp filename mode, match window focused][2]
## Basic Options ## Basic Options
* Change the mapping to invoke CtrlP: * Change the mapping to invoke CtrlP:
@ -66,8 +63,7 @@ e.g. Just have something like this in your vimrc:
set wildignore+=.git\*,.hg\*,.svn\* " for Windows set wildignore+=.git\*,.hg\*,.svn\* " for Windows
``` ```
_Check [the docs][3] for more mappings, commands and options._ _Check [the docs][2] for more mappings, commands and options._
[1]: http://i.imgur.com/Gfntl.png [1]: http://i.imgur.com/iviMa.png
[2]: http://i.imgur.com/MyRIv.png [2]: https://github.com/kien/ctrlp.vim/blob/master/doc/ctrlp.txt
[3]: https://github.com/kien/ctrlp.vim/blob/master/doc/ctrlp.txt