diff --git a/doc/tagbar.txt b/doc/tagbar.txt index c5ecca1..33e85e1 100644 --- a/doc/tagbar.txt +++ b/doc/tagbar.txt @@ -11,6 +11,7 @@ Contents *tagbar* *tagbar-contents* 1. Intro ........................... |tagbar-intro| Pseudo-tags ................... |tagbar-pseudotags| Supported features ............ |tagbar-features| + Other ctags-compatible programs |tagbar-other| 2. Requirements .................... |tagbar-requirements| 3. Installation .................... |tagbar-installation| 4. Usage ........................... |tagbar-usage| @@ -102,6 +103,16 @@ The following features are supported by Tagbar: Tex, Vera, Verilog, VHDL, Vim and YACC. - Can be extended to support arbitrary new types. +------------------------------------------------------------------------------ +OTHER CTAGS-COMPATIBLE PROGRAMS *tagbar-other* + +Tagbar theoretically also supports filetype-specific programs that can output +tag information that is compatible with ctags. However due to potential +incompatibilities this may not always completely work. Tagbar has been tested +with doctorjs/jsctags and will use that if present, other programs require +some configuration (see |tagbar-extend|). If a program does not work even with +correct configuration please contact me. + ============================================================================== 2. Requirements *tagbar-requirements* @@ -119,8 +130,8 @@ The following requirements have to be met in order to be able to use tagbar: Tagbar will work on any platform that ctags runs on -- this includes UNIX derivatives, Mac OS X and Windows. Note that other versions like GNU ctags will not work. - Tagbar generates the tag information by itself and doesn't need already - existing tag files. + Tagbar generates the tag information by itself and doesn't need (or use) + already existing tag files. - File type detection must be turned on in vim. This can be done with the following command in your vimrc: > @@ -499,8 +510,8 @@ kinds: A list of the "language kinds" that should be listed in Tagbar, < would list all the function definitions in a file under the header "functions" and fold them. sro: The scope resolution operator. For example, in C++ it is "::" and - in Java it is ".". When in doubt run ctags as shown above and look - at the output. + in Java it is ".". If in doubt run ctags as shown above and check + the output. kind2scope: A dictionary describing the mapping of tag kinds (in their one-character representation) to the scopes their children will appear in, for example classes, structs etc. @@ -549,8 +560,16 @@ deffile: The path to a file with additional ctags definitions (see the < Then the "deffile" entry would look like this to allow for the plugin to be installed in an arbitray location (for example with pathogen): > + 'deffile' : expand(':p:h:h') . '/ctags/mylang.cnf' < +ctagsbin: The path to a filetype-specific ctags-compatible program like +{optional} jsctags. Set it in the same way as |g:tagbar_ctags_bin|. jsctags is + used automatically if found in your $PATH and does not have to be + set in that case. +ctagsargs: The arguments to be passed to the filetype-specific ctags program +{optional} (without the filename). Not used for the normal ctags program. + You then have to assign this dictionary to a variable with the name > diff --git a/plugin/tagbar.vim b/plugin/tagbar.vim index 1756431..a4e4dba 100644 --- a/plugin/tagbar.vim +++ b/plugin/tagbar.vim @@ -411,15 +411,33 @@ function! s:InitTypes() " JavaScript is weird -- it does have scopes, but ctags doesn't seem to " properly generate the information for them, instead it simply uses the " complete name. So ctags has to be fixed before I can do anything here. + " Alternatively jsctags/doctorjs will be used if available. let type_javascript = {} let type_javascript.ctagstype = 'javascript' - let type_javascript.kinds = [ - \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0}, - \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, - \ {'short' : 'p', 'long' : 'properties', 'fold' : 0}, - \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, - \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} - \ ] + if executable('jsctags') + let type_javascript.kinds = [ + \ {'short' : 'v', 'long' : 'variables', 'fold' : 0}, + \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} + \ ] + let type_javascript.sro = '.' + let type_javascript.kind2scope = { + \ 'v' : 'namespace', + \ 'f' : 'namespace' + \ } + let type_javascript.scope2kind = { + \ 'namespace' : 'v' + \ } + let type_javascript.ctagsbin = 'jsctags' + let type_javascript.ctagsargs = '-f -' + else + let type_javascript.kinds = [ + \ {'short' : 'v', 'long' : 'global variables', 'fold' : 0}, + \ {'short' : 'c', 'long' : 'classes', 'fold' : 0}, + \ {'short' : 'p', 'long' : 'properties', 'fold' : 0}, + \ {'short' : 'm', 'long' : 'methods', 'fold' : 0}, + \ {'short' : 'f', 'long' : 'functions', 'fold' : 0} + \ ] + endif let s:known_types.javascript = type_javascript " Lisp {{{3 let type_lisp = {} @@ -1009,12 +1027,14 @@ endfunction " s:NormalTag.str() {{{3 function! s:NormalTag.str(fileinfo, typeinfo) dict let suffix = get(self.fields, 'signature', '') - if has_key(a:typeinfo, 'kind2scope') && - \ has_key(a:typeinfo.kind2scope, self.fields.kind) + if has_key(self.fields, 'type') + let suffix .= ' : ' . self.fields.type + elseif has_key(a:typeinfo, 'kind2scope') && + \ has_key(a:typeinfo.kind2scope, self.fields.kind) let suffix .= ' : ' . a:typeinfo.kind2scope[self.fields.kind] endif - return self._getPrefix(a:fileinfo, a:typeinfo) . self.name . suffix + return self._getPrefix(a:fileinfo, a:typeinfo) . self.name . suffix . "\n" endfunction " s:NormalTag.getPrototype() {{{3 @@ -1404,32 +1424,42 @@ function! s:ProcessFile(fname, ftype) let typeinfo = s:known_types[a:ftype] - let ctags_args = ' -f - ' - let ctags_args .= ' --format=2 ' - let ctags_args .= ' --excmd=pattern ' - let ctags_args .= ' --fields=nksSaz ' - let ctags_args .= ' --extra= ' - let ctags_args .= ' --sort=yes ' + if has_key(typeinfo, 'ctagsargs') + let ctags_args = ' ' . typeinfo.ctagsargs . ' ' + else + let ctags_args = ' -f - ' + let ctags_args .= ' --format=2 ' + let ctags_args .= ' --excmd=pattern ' + let ctags_args .= ' --fields=nksSa ' + let ctags_args .= ' --extra= ' + let ctags_args .= ' --sort=yes ' - " Include extra type definitions - if has_key(typeinfo, 'deffile') - let ctags_args .= ' --options=' . typeinfo.deffile . ' ' + " Include extra type definitions + if has_key(typeinfo, 'deffile') + let ctags_args .= ' --options=' . typeinfo.deffile . ' ' + endif + + let ctags_type = typeinfo.ctagstype + + let ctags_kinds = '' + for kind in typeinfo.kinds + let ctags_kinds .= kind.short + endfor + + let ctags_args .= ' --language-force=' . ctags_type . + \ ' --' . ctags_type . '-kinds=' . ctags_kinds . ' ' endif - let ctags_type = typeinfo.ctagstype - - let ctags_kinds = '' - for kind in typeinfo.kinds - let ctags_kinds .= kind.short - endfor - - let ctags_args .= ' --language-force=' . ctags_type . - \ ' --' . ctags_type . '-kinds=' . ctags_kinds . ' ' + if has_key(typeinfo, 'ctagsbin') + let ctags_bin = expand(typeinfo.ctagsbin) + else + let ctags_bin = g:tagbar_ctags_bin + endif if has('win32') || has('win64') - let ctags_bin = fnamemodify(g:tagbar_ctags_bin, ':8') + let ctags_bin = fnamemodify(ctags_bin, ':8') else - let ctags_bin = shellescape(g:tagbar_ctags_bin) + let ctags_bin = shellescape(ctags_bin) endif let ctags_cmd = ctags_bin . ctags_args . shellescape(a:fname) let ctags_output = system(ctags_cmd) @@ -1550,6 +1580,7 @@ function! s:ParseTagline(part1, part2, typeinfo, fileinfo) let taginfo.prototype = prototype let fields = split(a:part2, '\t') + let taginfo.fields.kind = remove(fields, 0) for field in fields " can't use split() since the value can contain ':' let delimit = stridx(field, ':') @@ -1557,6 +1588,10 @@ function! s:ParseTagline(part1, part2, typeinfo, fileinfo) let val = strpart(field, delimit + 1) let taginfo.fields[key] = val endfor + " Needed for jsctags + if has_key(taginfo.fields, 'lineno') + let taginfo.fields.line = taginfo.fields.lineno + endif " Make some information easier accessible if has_key(a:typeinfo, 'scope2kind') @@ -1917,7 +1952,7 @@ endfunction " s:PrintKinds() {{{2 function! s:PrintKinds(typeinfo, fileinfo) - let first_kind = 1 + let first_tag = 1 for kind in a:typeinfo.kinds let curtags = filter(copy(a:fileinfo.tags), @@ -1931,7 +1966,7 @@ function! s:PrintKinds(typeinfo, fileinfo) \ has_key(a:typeinfo.kind2scope, kind.short) " Scoped tags for tag in curtags - if g:tagbar_compact && first_kind && s:short_help + if g:tagbar_compact && first_tag && s:short_help silent 0put =tag.str(a:fileinfo, a:typeinfo) else silent put =tag.str(a:fileinfo, a:typeinfo) @@ -1953,8 +1988,8 @@ function! s:PrintKinds(typeinfo, fileinfo) silent put _ endif + let first_tag = 0 endfor - let first_kind = 0 else " Non-scoped tags let kindtag = curtags[0].parent @@ -1965,7 +2000,7 @@ function! s:PrintKinds(typeinfo, fileinfo) let foldmarker = s:icon_open endif - if g:tagbar_compact && first_kind && s:short_help + if g:tagbar_compact && first_tag && s:short_help silent 0put =foldmarker . ' ' . kind.long else silent put =foldmarker . ' ' . kind.long @@ -1993,7 +2028,7 @@ function! s:PrintKinds(typeinfo, fileinfo) silent put _ endif - let first_kind = 0 + let first_tag = 0 endif endfor endfunction