1 " =============================================================================
2 " File: autoload/ctrlp/buffertag.vim
3 " Description: Buffer Tag extension
4 " Maintainer: Kien Nguyen <github.com/kien>
5 " Credits: Much of the code was taken from tagbar.vim by Jan Larres, plus
6 " a few lines from taglist.vim by Yegappan Lakshmanan and from
7 " buffertag.vim by Takeshi Nishida.
8 " =============================================================================
11 if exists('g:loaded_ctrlp_buftag') && g:loaded_ctrlp_buftag
14 let g:loaded_ctrlp_buftag = 1
16 cal add(g:ctrlp_ext_vars, {
17 \ 'init': 'ctrlp#buffertag#init(s:crfile)',
18 \ 'accept': 'ctrlp#buffertag#accept',
19 \ 'lname': 'buffer tags',
21 \ 'exit': 'ctrlp#buffertag#exit()',
23 \ 'opts': 'ctrlp#buffertag#opts()',
26 let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
28 let [s:pref, s:opts] = ['g:ctrlp_buftag_', {
29 \ 'systemenc': ['s:enc', &enc],
30 \ 'ctags_bin': ['s:bin', ''],
31 \ 'types': ['s:usr_types', {}],
38 \ '/usr/local/bin/ctags',
39 \ '/opt/local/bin/ctags',
46 \ 'asm' : '%sasm%sasm%sdlmt',
47 \ 'aspperl': '%sasp%sasp%sfsv',
48 \ 'aspvbs' : '%sasp%sasp%sfsv',
49 \ 'awk' : '%sawk%sawk%sf',
50 \ 'beta' : '%sbeta%sbeta%sfsv',
51 \ 'c' : '%sc%sc%sdgsutvf',
52 \ 'cpp' : '%sc++%sc++%snvdtcgsuf',
53 \ 'cs' : '%sc#%sc#%sdtncEgsipm',
54 \ 'cobol' : '%scobol%scobol%sdfgpPs',
55 \ 'eiffel' : '%seiffel%seiffel%scf',
56 \ 'erlang' : '%serlang%serlang%sdrmf',
57 \ 'expect' : '%stcl%stcl%scfp',
58 \ 'fortran': '%sfortran%sfortran%spbceiklmntvfs',
59 \ 'html' : '%shtml%shtml%saf',
60 \ 'java' : '%sjava%sjava%spcifm',
61 \ 'javascript': '%sjavascript%sjavascript%sf',
62 \ 'lisp' : '%slisp%slisp%sf',
63 \ 'lua' : '%slua%slua%sf',
64 \ 'make' : '%smake%smake%sm',
65 \ 'pascal' : '%spascal%spascal%sfp',
66 \ 'perl' : '%sperl%sperl%sclps',
67 \ 'php' : '%sphp%sphp%scdvf',
68 \ 'python' : '%spython%spython%scmf',
69 \ 'rexx' : '%srexx%srexx%ss',
70 \ 'ruby' : '%sruby%sruby%scfFm',
71 \ 'scheme' : '%sscheme%sscheme%ssf',
72 \ 'sh' : '%ssh%ssh%sf',
73 \ 'csh' : '%ssh%ssh%sf',
74 \ 'zsh' : '%ssh%ssh%sf',
75 \ 'slang' : '%sslang%sslang%snf',
76 \ 'sml' : '%ssml%ssml%secsrtvf',
77 \ 'sql' : '%ssql%ssql%scFPrstTvfp',
78 \ 'tcl' : '%stcl%stcl%scfmp',
79 \ 'vera' : '%svera%svera%scdefgmpPtTvx',
80 \ 'verilog': '%sverilog%sverilog%smcPertwpvf',
81 \ 'vim' : '%svim%svim%savf',
82 \ 'yacc' : '%syacc%syacc%sl',
85 cal map(s:types, 'printf(v:val, "--language-force=", " --", "-types=")')
87 if executable('jsctags')
88 cal extend(s:types, { 'javascript': { 'args': '-f -', 'bin': 'jsctags' } })
91 fu! ctrlp#buffertag#opts()
92 for [ke, va] in items(s:opts)
93 let {va[0]} = exists(s:pref.ke) ? {s:pref.ke} : va[1]
97 for bin in s:bins | if executable(bin)
102 let s:bin = expand(s:bin, 1)
105 cal extend(s:types, s:usr_types)
108 fu! s:validfile(fname, ftype)
109 if ( !empty(a:fname) || !empty(a:ftype) ) && filereadable(a:fname)
110 \ && index(keys(s:types), a:ftype) >= 0 | retu 1 | en
116 let [ssl, &ssl] = [&ssl, 0]
119 let [sxq, &sxq, shcf, &shcf] = [&sxq, '"', &shcf, '/s /c']
121 let output = system(a:cmd)
123 let [&sxq, &shcf] = [sxq, shcf]
131 fu! s:exectagsonfile(fname, ftype)
132 let [ags, ft] = ['-f - --sort=no --excmd=pattern --fields=nKs ', a:ftype]
133 if type(s:types[ft]) == 1
134 let ags .= s:types[ft]
136 elsei type(s:types[ft]) == 4
137 let ags = s:types[ft]['args']
138 let bin = expand(s:types[ft]['bin'], 1)
140 if empty(bin) | retu '' | en
141 let cmd = s:esctagscmd(bin, ags, a:fname)
142 if empty(cmd) | retu '' | en
143 let output = s:exectags(cmd)
144 if v:shell_error || output =~ 'Warning: cannot open' | retu '' | en
148 fu! s:esctagscmd(bin, args, ...)
150 let [ssl, &ssl] = [&ssl, 0]
152 let fname = a:0 ? shellescape(a:1) : ''
153 let cmd = shellescape(a:bin).' '.a:args.' '.fname
155 let cmd = substitute(cmd, '[&()@^<>|]', '^\0', 'g')
161 let last = s:enc != &enc ? s:enc : !empty($LANG) ? $LANG : &enc
162 let cmd = iconv(cmd, &enc, last)
167 fu! s:process(fname, ftype)
168 if !s:validfile(a:fname, a:ftype) | retu [] | endif
169 let ftime = getftime(a:fname)
170 if has_key(g:ctrlp_buftags, a:fname)
171 \ && g:ctrlp_buftags[a:fname]['time'] >= ftime
172 let lines = g:ctrlp_buftags[a:fname]['lines']
174 let data = s:exectagsonfile(a:fname, a:ftype)
175 let [raw, lines] = [split(data, '\n\+'), []]
177 if line !~# '^!_TAG_' && len(split(line, ';"')) == 2
178 let parsed_line = s:parseline(line)
180 cal add(lines, parsed_line)
184 let cache = { a:fname : { 'time': ftime, 'lines': lines } }
185 cal extend(g:ctrlp_buftags, cache)
190 fu! s:parseline(line)
191 let vals = matchlist(a:line,
192 \ '\v^([^\t]+)\t(.+)\t[?/]\^?(.{-1,})\$?[?/]\;\"\t(.+)\tline(no)?\:(\d+)')
193 if vals == [] | retu '' | en
194 let [bufnr, bufname] = [bufnr('^'.vals[2].'$'), fnamemodify(vals[2], ':p:t')]
195 retu vals[1].' '.vals[4].'|'.bufnr.':'.bufname.'|'.vals[6].'| '.vals[3]
200 cal ctrlp#hicheck('CtrlPTagKind', 'Title')
201 cal ctrlp#hicheck('CtrlPBufName', 'Directory')
202 cal ctrlp#hicheck('CtrlPTabExtra', 'Comment')
203 sy match CtrlPTagKind '\zs[^\t|]\+\ze|\d\+:[^|]\+|\d\+|'
204 sy match CtrlPBufName '|\d\+:\zs[^|]\+\ze|\d\+|'
205 sy match CtrlPTabExtra '\zs\t.*\ze$' contains=CtrlPBufName,CtrlPTagKind
210 if match(getline('.'), a:pat) < 0
211 let [int, forw, maxl] = [1, 1, line('$')]
212 wh !search(a:pat, 'W'.( forw ? '' : 'b' ))
214 if int > maxl | brea | en
222 fu! ctrlp#buffertag#init(fname)
223 let bufs = exists('s:btmode') && s:btmode
224 \ ? filter(ctrlp#buffers(), 'filereadable(v:val)')
225 \ : [exists('s:bufname') ? s:bufname : a:fname]
228 let bname = fnamemodify(each, ':p')
229 let tftype = get(split(getbufvar('^'.bname.'$', '&ft'), '\.'), 0, '')
230 cal extend(lines, s:process(bname, tftype))
236 fu! ctrlp#buffertag#accept(mode, str)
237 let vals = matchlist(a:str,
238 \ '\v^[^\t]+\t+[^\t|]+\|(\d+)\:[^\t|]+\|(\d+)\|\s(.+)$')
239 let bufnr = str2nr(get(vals, 1))
241 cal ctrlp#acceptfile(a:mode, bufname(bufnr))
242 exe 'norm!' str2nr(get(vals, 2, line('.'))).'G'
243 cal s:chknearby('\V\C'.get(vals, 3, ''))
248 fu! ctrlp#buffertag#cmd(mode, ...)
249 let s:btmode = a:mode
250 if a:0 && !empty(a:1)
251 let s:bufname = fnamemodify(a:1, ':p')
256 fu! ctrlp#buffertag#exit()
257 unl! s:btmode s:bufname
261 " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2