" vim600: set foldmethod=marker: " $Id:$ " PURPOSE: {{{ " - FindFile: Switch to an auto-completing buffer to open a file quickly. " " REQUIREMENTS: " - Vim 7.0 " " USAGE: " Put this file in your ~/.vim/plugin directory. " If you are working on a project, go to the root directory of the project, " then execute: " " :FindFileCache . " or " :FC . " " This will recursively parse the directory and create the internal cache. " " You can also put in multiple arguments in :FC: " " :FC /dir1 /dir2 /dir3 " " You can add to the cache by calling :FC again. File with the same path " will not be added to the cache twice. " " To find a file: " " :FindFile " or " :FF " " This opens a scratch buffer that you can type in the file name. Press " will quit the buffer, while will select and edit the file. " " To clear the internal cache, do: " " :FindFileCacheClear " or " :FCC " " " You can put the following lines in your ~/.vimrc in order to invoke " FindFile quickly by hitting : " " :nmap :FindFile " " By default, all the *.o, *.pyc, and */tmp/* files will be ignored, in " addition to the wildignore patterns. You can customize this by setting in " your .vimrc: " " let g:FindFileIgnore = ['*.o', '*.pyc', '*/tmp/*'] " " CREDITS: " Please mail any comment/suggestion/patch to " William Lee " " Section: Mappings {{{1 command! -nargs=* -complete=dir FindFileCache call CacheDir() command! -nargs=* -complete=dir FC call CacheDir() command! FindFileCacheClear call CacheClear() command! FCC call CacheClear() command! FindFile call FindFile() command! FF call FindFile() command! FindFileSplit call FindFileSplit() command! FS call FindFileSplit() " Global Settings {{{1 if !exists("g:FindFileIgnore") let g:FindFileIgnore = ['*.o', '*.pyc', '*/tmp/*'] endif " Section: Functions {{{1 " File cache to store the filename let s:fileCache = {} " The sorted keys for the dictionary let s:fileKeys = [] fun! CompleteFile(findstart, base) if a:findstart return 0 else " TODO: We can definitely do a binary search on the keys instead of " doing a learn match. for k in s:fileKeys let matchExpr = EscapeChars(a:base) if match(k, matchExpr) == 0 call complete_add({'word': k, 'menu': s:fileCache[k], 'icase' : 1}) endif if complete_check() break endif endfor return [] endif endfun fun! MayComplete(c) if pumvisible() return a:c else return "" . a:c . "\\" endif endfun fun! FindFileSplit() split call FindFile() endfun fun! FindFile() new FindFile setlocal buftype=nofile setlocal bufhidden=hide setlocal noswapfile " Map the keys for completion " TODO: Need to add complete list of completion keys let compKeys = [ \'a','A', \'b','B', \'c','C', \'c','C', \'d','D', \'e','E', \'f','F', \'g','G', \'h','H', \'i','I', \'j','J', \'k','K', \'l','L', \'m','M', \'n','N', \'o','O', \'p','P', \'q','Q', \'r','R', \'s','S', \'t','T', \'u','U', \'v','V', \'w','W', \'x','X', \'y','Y', \'z','Z', \'.', \',', \'_', \] for k in compKeys "let remapCmd = "inoremap " . k . " " . k . "" let remapCmd = "inoremap " . k . " MayComplete('" . k . "')" exe remapCmd endfor inoremap :silent call EditFile(getline(".")) inoremap :silent call QuitBuff() nnoremap :silent call QuitBuff() setlocal completeopt=menuone,longest,preview setlocal omnifunc=CompleteFile setlocal noignorecase startinsert endfun fun! CacheClear() let s:fileCache = {} let s:fileKeys = [] endfun fun! EscapeChars(toEscape) return escape(a:toEscape, ". \!\@\#\$\%\^\&\*\(\)\-\=\\\|\~\`\'") endfun fun! CacheDir(...) for d in a:000 "Creates the dictionary that will parse all files recursively for i in g:FindFileIgnore let s = "setlocal wildignore+=" . i exe s endfor let files = glob(d . "/**") for i in g:FindFileIgnore let s = "setlocal wildignore-=" . i exe s endfor let ctr = 0 for f in split(files, "\n") let fname = fnamemodify(f, ":t") let fpath = fnamemodify(f, ":p") " If the cache already has this entry, we'll just skip it let hasEntry = 0 while has_key(s:fileCache, fname) if s:fileCache[fname] == fpath let hasEntry = 1 break endif let fnameArr = split(fname, ":") if len(fnameArr) > 1 let fname = fnameArr[0] . ":" . (fnameArr[1] + 1) else let fname = fname . ":1" endif endwhile if !hasEntry let s:fileCache[fname] = fpath let ctr = ctr + 1 endif endfor let s:fileKeys = sort(copy(keys(s:fileCache))) echo "Found " . ctr . " new files in '" . d . "'. Cache has " . len(s:fileKeys) . " entries." endfor endfun fun! QuitBuff() silent exe "bd!" endfun fun! EditFile(f) " Closes the buffer let fileToOpen = a:f if has_key(s:fileCache, a:f) let fileToOpen = s:fileCache[a:f] else " We attempt to find the file in the list if it is not a " complete key let matchExpr = EscapeChars(a:f) for k in s:fileKeys if match(k, matchExpr) == 0 let fileToOpen = s:fileCache[k] break endif endfor endif if filereadable(fileToOpen) silent exe "bd!" silent exe "edit " . fileToOpen echo "File: " . fileToOpen else echo "File " . fileToOpen . " not found. Run ':FileFindCache .' to refresh if necessary." endif endfun