CTRLP
[my-vim-dotfolder.git] / bundle / ctrlp / autoload / ctrlp / buffertag.vim
blob0a24eef8e6a0953f49fd3d416f46bdba75c76f7d
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 " =============================================================================
10 " Init {{{1
11 if exists('g:loaded_ctrlp_buftag') && g:loaded_ctrlp_buftag
12         fini
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',
20         \ 'sname': 'bft',
21         \ 'exit': 'ctrlp#buffertag#exit()',
22         \ 'type': 'tabs',
23         \ 'opts': 'ctrlp#buffertag#opts()',
24         \ })
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', {}],
32         \ }]
34 let s:bins = [
35         \ 'ctags-exuberant',
36         \ 'exuberant-ctags',
37         \ 'exctags',
38         \ '/usr/local/bin/ctags',
39         \ '/opt/local/bin/ctags',
40         \ 'ctags',
41         \ 'ctags.exe',
42         \ 'tags',
43         \ ]
45 let s:types = {
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',
83         \ }
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]
94         endfo
95         " Ctags bin
96         if empty(s:bin)
97                 for bin in s:bins | if executable(bin)
98                         let s:bin = bin
99                         brea
100                 en | endfo
101         el
102                 let s:bin = expand(s:bin, 1)
103         en
104         " Types
105         cal extend(s:types, s:usr_types)
106 endf
107 " Utilities {{{1
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
111         retu 0
112 endf
114 fu! s:exectags(cmd)
115         if exists('+ssl')
116                 let [ssl, &ssl] = [&ssl, 0]
117         en
118         if &sh =~ 'cmd\.exe'
119                 let [sxq, &sxq, shcf, &shcf] = [&sxq, '"', &shcf, '/s /c']
120         en
121         let output = system(a:cmd)
122         if &sh =~ 'cmd\.exe'
123                 let [&sxq, &shcf] = [sxq, shcf]
124         en
125         if exists('+ssl')
126                 let &ssl = ssl
127         en
128         retu output
129 endf
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]
135                 let bin = s:bin
136         elsei type(s:types[ft]) == 4
137                 let ags = s:types[ft]['args']
138                 let bin = expand(s:types[ft]['bin'], 1)
139         en
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
145         retu output
146 endf
148 fu! s:esctagscmd(bin, args, ...)
149         if exists('+ssl')
150                 let [ssl, &ssl] = [&ssl, 0]
151         en
152         let fname = a:0 ? shellescape(a:1) : ''
153         let cmd = shellescape(a:bin).' '.a:args.' '.fname
154         if &sh =~ 'cmd\.exe'
155                 let cmd = substitute(cmd, '[&()@^<>|]', '^\0', 'g')
156         en
157         if exists('+ssl')
158                 let &ssl = ssl
159         en
160         if has('iconv')
161                 let last = s:enc != &enc ? s:enc : !empty($LANG) ? $LANG : &enc
162                 let cmd = iconv(cmd, &enc, last)
163         en
164         retu cmd
165 endf
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']
173         el
174                 let data = s:exectagsonfile(a:fname, a:ftype)
175                 let [raw, lines] = [split(data, '\n\+'), []]
176                 for line in raw
177                         if line !~# '^!_TAG_' && len(split(line, ';"')) == 2
178                                 let parsed_line = s:parseline(line)
179                                 if parsed_line != ''
180                                         cal add(lines, parsed_line)
181                                 en
182                         en
183                 endfo
184                 let cache = { a:fname : { 'time': ftime, 'lines': lines } }
185                 cal extend(g:ctrlp_buftags, cache)
186         en
187         retu lines
188 endf
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]
196 endf
198 fu! s:syntax()
199         if !ctrlp#nosy()
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
206         en
207 endf
209 fu! s:chknearby(pat)
210         if match(getline('.'), a:pat) < 0
211                 let [int, forw, maxl] = [1, 1, line('$')]
212                 wh !search(a:pat, 'W'.( forw ? '' : 'b' ))
213                         if !forw
214                                 if int > maxl | brea | en
215                                 let int += int
216                         en
217                         let forw = !forw
218                 endw
219         en
220 endf
221 " Public {{{1
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]
226         let lines = []
227         for each in bufs
228                 let bname = fnamemodify(each, ':p')
229                 let tftype = get(split(getbufvar('^'.bname.'$', '&ft'), '\.'), 0, '')
230                 cal extend(lines, s:process(bname, tftype))
231         endfo
232         cal s:syntax()
233         retu lines
234 endf
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))
240         if bufnr
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, ''))
244                 sil! norm! zvzz
245         en
246 endf
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')
252         en
253         retu s:id
254 endf
256 fu! ctrlp#buffertag#exit()
257         unl! s:btmode s:bufname
258 endf
259 "}}}
261 " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2