From 7ccb62b28b02d63feb37b763e0c25e915b0dd10d Mon Sep 17 00:00:00 2001 From: Kien N Date: Wed, 21 Dec 2011 18:58:08 +0700 Subject: [PATCH] Add BufferTag extension First version of buffertag.vim extension. * Enable: `let g:ctrlp_extensions = ['buffertag']` * Command: ':CtrlPBufTag' * Options: + g:ctrlp_buftag_ctags_bin + g:ctrlp_buftag_systemenc + g:ctrlp_buftag_types --- autoload/ctrlp.vim | 28 +++-- autoload/ctrlp/buffertag.vim | 215 +++++++++++++++++++++++++++++++++++ autoload/ctrlp/quickfix.vim | 2 +- doc/ctrlp.txt | 41 ++++++- plugin/ctrlp.vim | 5 + 5 files changed, 276 insertions(+), 15 deletions(-) create mode 100644 autoload/ctrlp/buffertag.vim diff --git a/autoload/ctrlp.vim b/autoload/ctrlp.vim index 678cdae..1244190 100644 --- a/autoload/ctrlp.vim +++ b/autoload/ctrlp.vim @@ -2,7 +2,7 @@ " File: autoload/ctrlp.vim " Description: Fuzzy file, buffer, mru and tag finder. " Author: Kien Nguyen -" Version: 1.6.4 +" Version: 1.6.5 " ============================================================================= " Static variables {{{1 @@ -327,7 +327,7 @@ fu! s:Update(str) let oldstr = exists('s:savestr') ? s:savestr : '' let pats = s:SplitPattern(a:str) " Get the new string sans tail - let notail = substitute(a:str, ':\([^:]\|\\:\)*$', '', 'g') + let notail = substitute(a:str, '\\\@= 0 ) && !lazy + if a:upd && !lazy && ( s:matches || s:regexp + \ || match(str, '[*|]') >= 0 || match(str, '\\\:\([^:]\|\\:\)*$') >= 0 ) sil! cal s:Update(str) en sil! cal ctrlp#statusline() @@ -692,11 +693,11 @@ fu! ctrlp#acceptfile(mode, matchstr, ...) " Switch to existing buffer or open new one if exists('jmpb') && bufwinnr > 0 && md != 't' exe bufwinnr.'winc w' - if j2l | cal s:j2l(j2l) | en + if j2l | cal ctrlp#j2l(j2l) | en elsei exists('jmpb') && buftab[0] exe 'tabn' buftab[0] exe buftab[1].'winc w' - if j2l | cal s:j2l(j2l) | en + if j2l | cal ctrlp#j2l(j2l) | en el " Determine the command to use let cmd = md == 't' || s:splitwin == 1 ? 'tabe' @@ -1195,11 +1196,14 @@ endf fu! s:sanstail(str) " Restore the number of backslashes - let str = substitute(a:str, '\\\\', '\', 'g') + let [str, pat] = [substitute(a:str, '\\\\', '\', 'g'), '\([^:]\|\\:\)*$'] unl! s:optail - if match(str, ':\([^:]\|\\:\)*$') >= 0 - let s:optail = matchstr(str, ':\zs\([^:]\|\\:\)*$') - retu substitute(str, ':\([^:]\|\\:\)*$', '', 'g') + if match(str, '\\\@= 0 + let s:optail = matchstr(str, ':\zs'.pat) + retu substitute(str, ':'.pat, '', '') + en + if match(str, '\\\=:'.pat) >= 0 + let str = substitute(str, '\\\=\ze:'.pat, '', '') en retu str endf @@ -1229,7 +1233,7 @@ fu! s:openfile(cmd, filpath, ...) cal ctrlp#msg("Operation can't be completed. Make sure filename is valid.") fina if !empty(tail) - sil! norm! zOzz + sil! norm! zvzz en endt endf @@ -1242,9 +1246,9 @@ fu! s:writecache(read_cache, cache_file) en endf -fu! s:j2l(nr) +fu! ctrlp#j2l(nr) exe a:nr - sil! norm! zOzz + sil! norm! zvzz endf fu! s:regexfilter(str) diff --git a/autoload/ctrlp/buffertag.vim b/autoload/ctrlp/buffertag.vim new file mode 100644 index 0000000..c85e351 --- /dev/null +++ b/autoload/ctrlp/buffertag.vim @@ -0,0 +1,215 @@ +" ============================================================================= +" File: autoload/ctrlp/buffertag.vim +" Description: Buffer Tag extension +" Maintainer: Kien Nguyen +" ============================================================================= + +" Init {{{1 +if exists('g:loaded_ctrlp_buftag') && g:loaded_ctrlp_buftag + fini +en +let g:loaded_ctrlp_buftag = 1 + +let s:buftag_var = ['ctrlp#buffertag#init(s:crfile, s:crbufnr)', + \ 'ctrlp#buffertag#accept', 'buffer tags', 'bft'] + +let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars) + \ ? add(g:ctrlp_ext_vars, s:buftag_var) : [s:buftag_var] + +let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) + +fu! s:opts() + let opts = { + \ 'g:ctrlp_buftag_systemenc': ['s:enc', &enc], + \ 'g:ctrlp_buftag_ctags_bin': ['s:bin', ''], + \ 'g:ctrlp_buftag_types': ['s:usr_types', ''], + \ } + for [ke, va] in items(opts) + exe 'let' va[0] '=' string(exists(ke) ? eval(ke) : va[1]) + endfo +endf +cal s:opts() + +fu! s:bins() + let bins = [ + \ 'ctags-exuberant', + \ 'exuberant-ctags', + \ 'exctags', + \ '/usr/local/bin/ctags', + \ '/opt/local/bin/ctags', + \ 'ctags', + \ 'ctags.exe', + \ 'tags', + \ ] + if empty(s:bin) + for bin in bins + if executable(bin) + let s:bin = bin + brea + en + endfo + el + let s:bin = expand(s:bin, 1) + en +endf +cal s:bins() + +" Arguments {{{2 +let s:types = { + \ 'asm' : '--language-force=asm --asm-types=dlmt', + \ 'aspperl' : '--language-force=asp --asp-types=fsv', + \ 'aspvbs' : '--language-force=asp --asp-types=fsv', + \ 'awk' : '--language-force=awk --awk-types=f', + \ 'beta' : '--language-force=beta --beta-types=fsv', + \ 'c' : '--language-force=c --c-types=dgsutvf', + \ 'cpp' : '--language-force=c++ --c++-types=nvdtcgsuf', + \ 'cs' : '--language-force=c# --c#-types=dtncEgsipm', + \ 'cobol' : '--language-force=cobol --cobol-types=dfgpPs', + \ 'eiffel' : '--language-force=eiffel --eiffel-types=cf', + \ 'erlang' : '--language-force=erlang --erlang-types=drmf', + \ 'expect' : '--language-force=tcl --tcl-types=cfp', + \ 'fortran' : '--language-force=fortran --fortran-types=pbceiklmntvfs', + \ 'html' : '--language-force=html --html-types=af', + \ 'java' : '--language-force=java --java-types=pcifm', + \ 'javascript': '--language-force=javascript --javascript-types=f', + \ 'lisp' : '--language-force=lisp --lisp-types=f', + \ 'lua' : '--language-force=lua --lua-types=f', + \ 'make' : '--language-force=make --make-types=m', + \ 'pascal' : '--language-force=pascal --pascal-types=fp', + \ 'perl' : '--language-force=perl --perl-types=clps', + \ 'php' : '--language-force=php --php-types=cdvf', + \ 'python' : '--language-force=python --python-types=cmf', + \ 'rexx' : '--language-force=rexx --rexx-types=s', + \ 'ruby' : '--language-force=ruby --ruby-types=cfFm', + \ 'scheme' : '--language-force=scheme --scheme-types=sf', + \ 'sh' : '--language-force=sh --sh-types=f', + \ 'csh' : '--language-force=sh --sh-types=f', + \ 'zsh' : '--language-force=sh --sh-types=f', + \ 'slang' : '--language-force=slang --slang-types=nf', + \ 'sml' : '--language-force=sml --sml-types=ecsrtvf', + \ 'sql' : '--language-force=sql --sql-types=cFPrstTvfp', + \ 'tcl' : '--language-force=tcl --tcl-types=cfmp', + \ 'vera' : '--language-force=vera --vera-types=cdefgmpPtTvx', + \ 'verilog' : '--language-force=verilog --verilog-types=mcPertwpvf', + \ 'vim' : '--language-force=vim --vim-types=avf', + \ 'yacc' : '--language-force=yacc --yacc-types=l', + \ } + +if executable('jsctags') + cal extend(s:types, { 'javascript': { 'args': '-f -', 'bin': 'jsctags' } }) +en + +if type(s:usr_types) == 4 + cal extend(s:types, s:usr_types) +en +" Utilities {{{1 +fu! s:validfile(fname, ftype) + if ( !empty(a:fname) || !empty(a:ftype) ) && filereadable(a:fname) + \ && index(keys(s:types), a:ftype) >= 0 | retu 1 | en + retu 0 +endf + +fu! s:exectags(cmd) + if exists('+ssl') + let [ssl, &ssl] = [&ssl, 0] + en + if &sh =~ 'cmd\.exe' + let [sxq, &sxq, shcf, &shcf] = [&sxq, '"', &shcf, '/s /c'] + en + let output = system(a:cmd) + if &sh =~ 'cmd\.exe' + let [&sxq, &shcf] = [sxq, shcf] + en + if exists('+ssl') + let &ssl = ssl + en + retu output +endf + +fu! s:exectagsonfile(fname, ftype) + let args = '-f - --sort=no --excmd=pattern --fields=nKs ' + if type(s:types[a:ftype]) == 1 + let args .= s:types[a:ftype] + let bin = s:bin + elsei type(s:types[a:ftype]) == 4 + let args = s:types[a:ftype]['args'] + let bin = expand(s:types[a:ftype]['bin'], 1) + en + if empty(bin) | retu '' | en + let cmd = s:esctagscmd(bin, args, a:fname) + if empty(cmd) | retu '' | en + let output = s:exectags(cmd) + if v:shell_error || output =~ 'Warning: cannot open' | retu '' | en + retu output +endf + +fu! s:esctagscmd(bin, args, ...) + if exists('+ssl') + let [ssl, &ssl] = [&ssl, 0] + en + let fname = a:0 == 1 ? shellescape(a:1) : '' + let cmd = shellescape(a:bin).' '.a:args.' '.fname + if exists('+ssl') + let &ssl = ssl + en + if has('iconv') + let last = s:enc != &enc ? s:enc : !empty($LANG) ? $LANG : &enc + let cmd = call('iconv', [cmd, &encoding, last]) + en + if empty(cmd) + cal ctrlp#msg('Encoding conversion failed!') + en + retu cmd +endf + +fu! s:process(fname, ftype) + if !s:validfile(a:fname, a:ftype) | retu [] | endif + let ftime = getftime(a:fname) + if has_key(g:ctrlp_buftags, a:fname) + \ && g:ctrlp_buftags[a:fname]['time'] >= ftime + let data = g:ctrlp_buftags[a:fname]['data'] + el + let data = s:exectagsonfile(a:fname, a:ftype) + let cache = { a:fname : { 'time': ftime, 'data': data } } + cal extend(g:ctrlp_buftags, cache) + en + let [raw, lines] = [split(data, '\n\+'), []] + for line in raw | if len(split(line, ';"')) == 2 + cal add(lines, s:parseline(line)) + en | endfo + retu lines +endf + +fu! s:parseline(line) + let eval = '\v^([^\t]+)\t(.+)\t\/\^(.+)\$\/\;\"\t(.+)\tline(no)?\:(\d+)' + let vals = matchlist(a:line, eval) + if empty(vals) | retu '' | en + retu vals[1].' '.vals[4].'|'.vals[6].'| '.vals[3] +endf +" Public {{{1 +fu! ctrlp#buffertag#init(fname, bufnr) + let s:fname = a:fname + let ftype = get(split(getbufvar(a:bufnr, '&filetype'), '\.'), 0, '') + sy match CtrlPTabExtra '\zs\t.*\ze$' + hi link CtrlPTabExtra Comment + retu s:process(a:fname, ftype) +endf + +fu! ctrlp#buffertag#accept(mode, str) + cal ctrlp#exit() + if a:mode == 't' + exe 'tabe' ctrlp#fnesc(s:fname) + elsei a:mode == 'h' + sp + elsei a:mode == 'v' + vs + en + cal ctrlp#j2l(str2nr(matchstr(a:str, '^[^\t]\+\t\+[^\t|]\+|\zs\d\+\ze|'))) +endf + +fu! ctrlp#buffertag#id() + retu s:id +endf +"}}} + +" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2 diff --git a/autoload/ctrlp/quickfix.vim b/autoload/ctrlp/quickfix.vim index 0013481..92e15e1 100644 --- a/autoload/ctrlp/quickfix.vim +++ b/autoload/ctrlp/quickfix.vim @@ -43,7 +43,7 @@ fu! ctrlp#quickfix#accept(mode, str) cat cal ctrlp#msg("Invalid command or argument.") fina - cal cursor(items[2], items[3]) | sil! norm! zOzz + cal cursor(items[2], items[3]) | sil! norm! zvzz endt endf diff --git a/doc/ctrlp.txt b/doc/ctrlp.txt index 169eb67..ed1dfd4 100644 --- a/doc/ctrlp.txt +++ b/doc/ctrlp.txt @@ -1,4 +1,4 @@ -*ctrlp.txt* Fuzzy file, buffer, mru and tag finder. v1.6.4 +*ctrlp.txt* Fuzzy file, buffer, mru and tag finder. v1.6.5 *CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'* =============================================================================== # # @@ -516,7 +516,7 @@ g) Submit ? to open this help file. Extensions are optional. To enable an extension, add its name to the variable g:ctrlp_extensions: > - let g:ctrlp_extensions = ['tag', 'quickfix', 'dir'] + let g:ctrlp_extensions = ['tag', 'buffertag', 'quickfix', 'dir'] < The order of the items will be the order they appear on the statusline and when using , . @@ -531,6 +531,13 @@ Available extensions:~ definition. Use the Vim’s option |'tags'| to specify the names and the locations of the tags file(s). Example: `set tags+=tags/help,doc/tags` + *:CtrlPBufTag* + * Buffer Tag mode:~ + - Name: 'buffertag' + - Command: ':CtrlPBufTag' + - Search for a tag within the current buffer and jump to the definition. + Requires |exuberant_ctags|. + *:CtrlPQuickfix* * Quickfix mode:~ - Name: 'quickfix' @@ -549,6 +556,34 @@ Available extensions:~ + change the global working directory to |CtrlP|’s current local working directory (exit). +------------------------------------------------------------------------------- +Buffer Tag mode options:~ + + *'g:ctrlp_buftag_ctags_bin'* +If ctags isn’t in your $PATH, use this to set its location: > + let g:ctrlp_buftag_ctags_bin = '' +< + + *'g:ctrlp_buftag_systemenc'* +Match this with your OS’s encoding (not Vim’s). The default value mirrors Vim’s +global |'encoding'| option: > + let g:ctrlp_buftag_systemenc = &encoding +< + + *'g:ctrlp_buftag_types'* +Use this to set the arguments for ctags, jsctags... for a given filetype: > + let g:ctrlp_buftag_types = '' +< +Examples: > + let g:ctrlp_buftag_types = { + \ 'erlang' : '--language-force=erlang --erlang-types=drmf', + \ 'javascript' : { + \ 'bin': 'jsctags', + \ 'args': '-f -', + \ }, + \ } +< + =============================================================================== EXTENDING *ctrlp-extending* @@ -599,6 +634,8 @@ Special thanks:~ =============================================================================== CHANGELOG *ctrlp-changelog* + + New feature: Buffer Tag extension. + + New command: |:CtrlPBufTag|. + New options: |g:ctrlp_cmd|, |g:ctrlp_custom_ignore| diff --git a/plugin/ctrlp.vim b/plugin/ctrlp.vim index e3b354d..d99d558 100644 --- a/plugin/ctrlp.vim +++ b/plugin/ctrlp.vim @@ -43,3 +43,8 @@ en if index(g:ctrlp_extensions, 'dir') >= 0 let g:ctrlp_alldirs = [] | com! CtrlPDir cal ctrlp#init(ctrlp#dir#id()) en + +if index(g:ctrlp_extensions, 'buffertag') >= 0 + let g:ctrlp_buftags = {} + com! CtrlPBufTag cal ctrlp#init(ctrlp#buffertag#id()) +en