From 03f1d920da66d54a855b90780d01c94b958cbac1 Mon Sep 17 00:00:00 2001 From: Kien N Date: Wed, 30 Nov 2011 16:42:19 +0700 Subject: [PATCH] Directory extension * Add directory extension. * Merge fix for Migemo support, pull #42. --- autoload/ctrlp.vim | 86 ++++++++++++++++++++----------------- autoload/ctrlp/dir.vim | 97 ++++++++++++++++++++++++++++++++++++++++++ autoload/ctrlp/tag.vim | 16 ++++++- doc/ctrlp.txt | 11 +++-- plugin/ctrlp.vim | 4 ++ 5 files changed, 170 insertions(+), 44 deletions(-) create mode 100644 autoload/ctrlp/dir.vim diff --git a/autoload/ctrlp.vim b/autoload/ctrlp.vim index 3255fd6..48c4cb3 100644 --- a/autoload/ctrlp.vim +++ b/autoload/ctrlp.vim @@ -99,7 +99,7 @@ fu! s:Close() unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:cline s:init s:savestr \ s:crfile s:crfpath s:crword s:crvisual s:tagfiles s:crline s:crcursor \ g:ctrlp_nolimit - cal s:recordhist(join(s:prompt, '')) + cal ctrlp#recordhist() ec endf "}}} @@ -136,12 +136,12 @@ fu! s:GlobPath(dirs, allfiles, depth) let entries = filter(entries, 'getftype(v:val) != "link"') en let g:ctrlp_allfiles = filter(copy(entries), '!isdirectory(v:val)') - let ftrfunc = s:dotfiles ? 's:dirfilter(v:val)' : 'isdirectory(v:val)' + let ftrfunc = s:dotfiles ? 'ctrlp#dirfilter(v:val)' : 'isdirectory(v:val)' let alldirs = filter(entries, ftrfunc) cal extend(g:ctrlp_allfiles, a:allfiles, 0) let depth = a:depth + 1 if !empty(alldirs) && !s:maxfiles(len(g:ctrlp_allfiles)) && depth <= s:maxdepth - sil! cal s:progress(len(g:ctrlp_allfiles)) + sil! cal ctrlp#progress(len(g:ctrlp_allfiles)) cal s:GlobPath(join(alldirs, ','), g:ctrlp_allfiles, depth) en endf @@ -162,16 +162,16 @@ fu! s:UserCommand(path, lscmd) en endf -fu! s:Files(path) - let cache_file = ctrlp#utils#cachefile() +fu! s:Files() + let [cwd, cache_file] = [getcwd(), ctrlp#utils#cachefile()] if g:ctrlp_newcache || !filereadable(cache_file) || !s:caching let lscmd = s:lscommand() " Get the list of files if empty(lscmd) - cal s:GlobPath(a:path, [], 0) + cal s:GlobPath(cwd, [], 0) el - sil! cal s:progress('Waiting...') - try | cal s:UserCommand(a:path, lscmd) | cat | retu [] | endt + sil! cal ctrlp#progress('Waiting...') + try | cal s:UserCommand(cwd, lscmd) | cat | retu [] | endt en " Remove base directory let path = &ssl || !exists('+ssl') ? getcwd().'/' : @@ -183,7 +183,7 @@ fu! s:Files(path) let read_cache = 1 en if len(g:ctrlp_allfiles) <= s:compare_lim - cal sort(g:ctrlp_allfiles, 's:complen') + cal sort(g:ctrlp_allfiles, 'ctrlp#complen') en cal s:writecache(read_cache, cache_file) retu g:ctrlp_allfiles @@ -245,15 +245,10 @@ fu! s:SplitPattern(str, ...) "{{{ en if len(dict) let tokens = split(str, '\s') - let str = '' - let cmd = 'cmigemo -v -w %s -d %s' + let [str, cmd] = ['cmigemo -v -w %s -d %s', ''] for token in tokens let rtn = system(printf(cmd, shellescape(token), shellescape(dict))) - if !v:shell_error && len(rtn) > 0 - let str .= len(str) > 0 ? '.*'.rtn : rtn - else - let str .= token - en + let str .= !v:shell_error && len(rtn) > 0 ? '.*'.rtn : token endfo en en @@ -350,7 +345,7 @@ fu! s:BuildPrompt(upd, ...) if a:upd && ( s:matches || s:regexp || match(str, '[*|]') >= 0 ) && !lazy sil! cal s:Update(str) en - sil! cal s:statusline() + sil! cal ctrlp#statusline() " Toggling let [hiactive, hicursor, base] = exists('a:1') && !a:1 \ ? ['Comment', 'Comment', tr(base, '>', '-')] @@ -765,7 +760,7 @@ fu! s:MarkToOpen() exe 'sign place' key 'line='.line('.').' name=ctrlpmark buffer='.s:bufnr en en - sil! cal s:statusline() + sil! cal ctrlp#statusline() endf fu! s:OpenMulti() @@ -802,7 +797,7 @@ endf "}}} " ** Helper functions {{{ " Sorting {{{ -fu! s:complen(s1, s2) +fu! ctrlp#complen(s1, s2) " By length let [len1, len2] = [strlen(a:s1), strlen(a:s2)] retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1 @@ -851,7 +846,7 @@ fu! s:shortest(lens) endf fu! s:mixedsort(s1, s2) - let [cml, cln] = [s:compmatlen(a:s1, a:s2), s:complen(a:s1, a:s2)] + let [cml, cln] = [s:compmatlen(a:s1, a:s2), ctrlp#complen(a:s1, a:s2)] if s:itemtype < 3 && s:height < 51 let par = s:comparent(a:s1, a:s2) if s:height < 21 @@ -863,7 +858,7 @@ fu! s:mixedsort(s1, s2) endf "}}} " Statusline {{{ -fu! s:statusline(...) +fu! ctrlp#statusline(...) if !exists('s:statypes') let s:statypes = [ \ ['files', 'fil'], @@ -896,14 +891,14 @@ fu! s:dismrk() \ '%<'.join(values(map(copy(s:marked), 'split(v:val, "[\\/]")[-1]')), ', ') endf -fu! s:progress(len) +fu! ctrlp#progress(len) if has('macunix') || has('mac') | sl 1m | en let &l:stl = '%#Function# '.a:len.' %* %=%<%#LineNr# '.getcwd().' %*' redr endf "}}} " Paths {{{ -fu! s:dirfilter(val) +fu! ctrlp#dirfilter(val) retu isdirectory(a:val) && match(a:val, '[\/]\.\{,2}$') < 0 ? 1 : 0 endf @@ -1013,11 +1008,12 @@ fu! s:gethistdata() retu ctrlp#utils#readfile(s:gethistloc()[1]) endf -fu! s:recordhist(str) - if empty(a:str) || !s:maxhst | retu | en +fu! ctrlp#recordhist() + let str = join(s:prompt, '') + if empty(str) || !s:maxhst | retu | en let hst = s:hstry - if len(hst) > 1 && hst[1] == a:str | retu | en - cal extend(hst, [a:str], 1) + if len(hst) > 1 && hst[1] == str | retu | en + cal extend(hst, [str], 1) if len(hst) > s:maxhst | cal remove(hst, s:maxhst, -1) | en endf "}}} @@ -1144,14 +1140,16 @@ endf " Misc {{{ fu! s:specinputs() let str = join(s:prompt, '') - if str == '..' && !s:itemtype + let type = s:itemtype > 2 ? + \ g:ctrlp_ext_vars[s:itemtype - ( g:ctrlp_builtins + 1 )][3] : s:itemtype + if str == '..' && type =~ '0\|dir' cal s:parentdir(getcwd()) - cal s:SetLines(0) + cal s:SetLines(s:itemtype) cal s:PrtClear() retu 1 - elsei ( str == '/' || str == '\' ) && !s:itemtype + elsei ( str == '/' || str == '\' ) && type =~ '0\|dir' cal s:SetWD(2, 0) - cal s:SetLines(0) + cal s:SetLines(s:itemtype) cal s:PrtClear() retu 1 elsei str == '?' @@ -1172,6 +1170,10 @@ fu! s:lastvisual() retu selected endf +fu! ctrlp#msg(msg) + echoh Identifier | echon "CtrlP: ".a:msg | echoh None +endf + fu! s:openfile(cmd, filpath) let cmd = a:cmd == 'e' && &modified ? 'hid e' : a:cmd let tail = s:tail() @@ -1186,10 +1188,6 @@ fu! s:openfile(cmd, filpath) endt endf -fu! ctrlp#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 ) @@ -1212,10 +1210,6 @@ fu! s:regexfilter(str) retu str endf -fu! ctrlp#exit() - cal s:PrtExit() -endf - fu! s:walker(max, pos, dir) retu a:dir > 0 ? a:pos < a:max ? a:pos + 1 : 0 : a:pos > 0 ? a:pos - 1 : a:max endf @@ -1265,6 +1259,18 @@ fu! s:lscommand() retu cmd[1] en endf + +fu! ctrlp#exit() + cal s:PrtExit() +endf + +fu! ctrlp#prtclear() + cal s:PrtClear() +endf + +fu! ctrlp#setlines(type) + cal s:SetLines(a:type) +endf "}}} " Extensions {{{ fu! s:tagfiles() @@ -1276,7 +1282,7 @@ endf fu! s:SetLines(type) let s:itemtype = a:type let types = [ - \ 's:Files(getcwd())', + \ 's:Files()', \ 's:Buffers()', \ 'ctrlp#mrufiles#list(-1)', \ ] diff --git a/autoload/ctrlp/dir.vim b/autoload/ctrlp/dir.vim new file mode 100644 index 0000000..9f026b1 --- /dev/null +++ b/autoload/ctrlp/dir.vim @@ -0,0 +1,97 @@ +" ============================================================================= +" File: autoload/ctrlp/dir.vim +" Description: Directory switcher extension +" Author: Kien Nguyen +" ============================================================================= + +" Init {{{ +if exists('g:loaded_ctrlp_dir') && g:loaded_ctrlp_dir + fini +en +let [g:loaded_ctrlp_dir, g:ctrlp_newdir] = [1, 0] + +let s:ars = [ + \ 's:folsym', + \ 's:dotfiles', + \ 's:maxdepth', + \ 's:maxfiles', + \ 's:compare_lim', + \ 's:glob', + \ ] + +let s:dir_var = ['ctrlp#dir#init('.join(s:ars, ', ').')', 'ctrlp#dir#accept', + \ 'dirs', 'dir'] + +let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars) + \ ? add(g:ctrlp_ext_vars, s:dir_var) : [s:dir_var] + +let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) +"}}} +" Utilities {{{ +fu! s:globdirs(dirs, depth) + let entries = split(globpath(a:dirs, s:glob), "\n") + if !s:folsym + let entries = filter(entries, 'getftype(v:val) != "link"') + en + let ftrfunc = s:dotfiles ? 'ctrlp#dirfilter(v:val)' : 'isdirectory(v:val)' + let alldirs = filter(entries, ftrfunc) + cal extend(g:ctrlp_alldirs, alldirs) + let depth = a:depth + 1 + if !empty(g:ctrlp_alldirs) && !s:max(len(g:ctrlp_alldirs), s:maxfiles) + \ && depth <= s:maxdepth + sil! cal ctrlp#progress(len(g:ctrlp_alldirs)) + cal s:globdirs(join(alldirs, ','), depth) + en +endf + +fu! s:max(len, max) + retu a:max && a:len > a:max ? 1 : 0 +endf +"}}} +" Public {{{ +fu! ctrlp#dir#init(...) + let s:cwd = getcwd() + for each in range(len(s:ars)) + exe 'let' s:ars[each] '=' string(eval('a:'.(each + 1))) + endfo + let cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().s:dir_var[3] + let cafile = cadir.ctrlp#utils#lash().ctrlp#utils#cachefile(s:dir_var[3]) + if g:ctrlp_newdir || !filereadable(cafile) + let g:ctrlp_alldirs = [] + cal s:globdirs(s:cwd, 0) + let path = &ssl || !exists('+ssl') ? getcwd().'/' : + \ substitute(getcwd(), '\\', '\\\\', 'g').'\\' + cal map(g:ctrlp_alldirs, 'substitute(v:val, path, "", "g")') + let read_cache = 0 + el + let g:ctrlp_alldirs = ctrlp#utils#readfile(cafile) + let read_cache = 1 + en + if len(g:ctrlp_alldirs) <= s:compare_lim + cal sort(g:ctrlp_alldirs, 'ctrlp#complen') + en + if !read_cache + cal ctrlp#utils#writecache(g:ctrlp_alldirs, cadir, cafile) + let g:ctrlp_newdir = 0 + en + retu g:ctrlp_alldirs +endf + +fu! ctrlp#dir#accept(mode, str) + try + cal ctrlp#setdir(s:cwd.ctrlp#utils#lash().a:str) + sil! cal ctrlp#statusline() + cal ctrlp#setlines(s:id) + cal ctrlp#recordhist() + cal ctrlp#prtclear() + cat + cal ctrlp#msg("Directory not exists.") + endt +endf + +fu! ctrlp#dir#id() + retu s:id +endf +"}}} + +" vim:fen:fdl=0:ts=2:sw=2:sts=2 diff --git a/autoload/ctrlp/tag.vim b/autoload/ctrlp/tag.vim index 8510ddd..e884d7c 100644 --- a/autoload/ctrlp/tag.vim +++ b/autoload/ctrlp/tag.vim @@ -39,6 +39,17 @@ fu! s:hash224(str) endfo retu join(map(hashes, 'printf("%08x", v:val)'), '') endf + +fu! s:expand(path, fname) + let fname = expand(a:fname, 1) + retu fname == a:fname ? a:path.ctrlp#utils#lash().fname : fname +endf + +fu! s:append(path, atag) + let parts = split(a:atag, '\t\+') + let fname = s:expand(a:path, parts[1]) + retu parts[0].' '.fname +endf "}}} " Public {{{ fu! ctrlp#tag#init(tagfiles) @@ -56,7 +67,10 @@ fu! ctrlp#tag#init(tagfiles) let g:ctrlp_alltags = { key : [] } let eval = 'matchstr(v:val, ''^[^!\t][^\t]*\t\+[^\t]\+\ze\t\+'')' for each in tagfiles - let alltags = filter(map(readfile(each), eval), 'v:val =~# ''\S''') + "let path = substitute(each, '[\/][^\/]\+$', '', '') + let alltags = map(ctrlp#utils#readfile(each), eval) + let alltags = filter(alltags, 'v:val =~# ''\S''') + "let alltags = map(alltags, 's:append(path, v:val)') cal extend(g:ctrlp_alltags[key], alltags) endfo let read_cache = 0 diff --git a/doc/ctrlp.txt b/doc/ctrlp.txt index 37d330e..4c70342 100644 --- a/doc/ctrlp.txt +++ b/doc/ctrlp.txt @@ -28,7 +28,7 @@ Written in pure Vimscript for MacVim and Vim version 7.0+. Has full support for Vim’s |regexp| as search pattern, built-in MRU monitoring, project’s root finder, and more. -To enable optional extensions (tag, quickfix ...), see |ctrlp-extensions|. +To enable optional extensions (tag, quickfix, dir...), see |ctrlp-extensions|. =============================================================================== 2. Options *ctrlp-options* @@ -515,7 +515,12 @@ Available extensions:~ * Quickfix mode:~ - Shortname: 'qfx' - Command: ':CtrlPQuickfix' - - Search for an entry in the current quickfix errors and jump to it. If the + - Search for an entry in the current quickfix errors and jump to it. + + * Directory mode:~ + - Shortname: 'dir' + - Command: ':CtrlPDir' + - Search for a directory and change the local working directory to it. =============================================================================== EXTENDING *ctrlp-extending* @@ -567,7 +572,7 @@ Special thanks:~ =============================================================================== CHANGELOG *ctrlp-changelog* - + New features: Tag and Quickfix extensions. + + New features: Tag, Quickfix and Directory extensions. + New options: |g:ctrlp_use_migemo|, |g:ctrlp_lazy_update|, |g:ctrlp_follow_symlinks| diff --git a/plugin/ctrlp.vim b/plugin/ctrlp.vim index b2967ab..21dabc2 100644 --- a/plugin/ctrlp.vim +++ b/plugin/ctrlp.vim @@ -38,3 +38,7 @@ en if index(g:ctrlp_extensions, 'quickfix') >= 0 com! CtrlPQuickfix cal ctrlp#init(ctrlp#quickfix#id()) en + +if index(g:ctrlp_extensions, 'dir') >= 0 + let g:ctrlp_alldirs = [] | com! CtrlPDir cal ctrlp#init(ctrlp#dir#id()) +en