mirror of
https://github.com/preservim/tagbar.git
synced 2025-01-31 15:54:00 +08:00
Scoped kinds (#696)
* Add support for scope Closes #508, #516 Add --fields=e (end) to the ctags field types to look for the end of the scope. Update the `s:GetNearbyTag()` routine to use this scope to look for the correct tag. * Update comment to call out exuberant ctags not supporting the -e option * Update autoload/tagbar.vim Co-authored-by: Caleb Maclennan <caleb@alerque.com> * Optimize nearesttag search, add option for scoped-stl search method Co-authored-by: Caleb Maclennan <caleb@alerque.com>
This commit is contained in:
parent
601b5c0073
commit
55b8ffa85c
|
@ -1342,7 +1342,7 @@ function! s:ExecuteCtagsOnFile(fname, realfname, typeinfo) abort
|
|||
\ '-',
|
||||
\ '--format=2',
|
||||
\ '--excmd=pattern',
|
||||
\ '--fields=nksSaft',
|
||||
\ '--fields=nksSafet',
|
||||
\ '--sort=no',
|
||||
\ '--append=no'
|
||||
\ ]
|
||||
|
@ -1463,7 +1463,7 @@ function! s:ParseTagline(part1, part2, typeinfo, fileinfo) abort
|
|||
let fielddict[key] = 'yes'
|
||||
endif
|
||||
if len(val) > 0
|
||||
if key ==# 'line' || key ==# 'column'
|
||||
if key ==# 'line' || key ==# 'column' || key ==# 'end'
|
||||
let fielddict[key] = str2nr(val)
|
||||
else
|
||||
let fielddict[key] = val
|
||||
|
@ -1525,6 +1525,22 @@ function! s:ProcessTag(name, filename, pattern, fields, is_split, typeinfo, file
|
|||
let taginfo.fields.line = 0
|
||||
endif
|
||||
|
||||
" Make sure our 'end' is valid
|
||||
if taginfo.fields.end < taginfo.fields.line
|
||||
if a:typeinfo.getKind(taginfo.fields.kind).stl
|
||||
" the config indicates this is a scoped kind due to 'stl', but we
|
||||
" don't have scope vars, assume scope goes to end of file. This
|
||||
" can also be the case for exhuberant ctags which doesn't support
|
||||
" the --fields=e option.
|
||||
" When we call the GetNearbyTag(), it will look up for the nearest
|
||||
" tag, so if we have multiples that have scope to the end of the
|
||||
" file it will still only grab the first one above the current line
|
||||
let taginfo.fields.end = line('$')
|
||||
else
|
||||
let taginfo.fields.end = taginfo.fields.line
|
||||
endif
|
||||
endif
|
||||
|
||||
if !has_key(taginfo.fields, 'kind')
|
||||
call tagbar#debug#log(
|
||||
\ "Warning: No 'kind' field found for tag " . a:name[0] . '!')
|
||||
|
@ -2153,9 +2169,9 @@ function! s:HighlightTag(openfolds, ...) abort
|
|||
let force = a:0 > 0 ? a:1 : 0
|
||||
|
||||
if a:0 > 1
|
||||
let tag = s:GetNearbyTag('highlight', 0, a:2)
|
||||
let tag = s:GetNearbyTag('nearest-stl', 0, a:2)
|
||||
else
|
||||
let tag = s:GetNearbyTag('highlight', 0)
|
||||
let tag = s:GetNearbyTag('nearest-stl', 0)
|
||||
endif
|
||||
if !empty(tag)
|
||||
let tagline = tag.tline
|
||||
|
@ -2615,7 +2631,7 @@ function! s:OpenParents(...) abort
|
|||
if a:0 == 1
|
||||
let tag = a:1
|
||||
else
|
||||
let tag = s:GetNearbyTag('parent', 0)
|
||||
let tag = s:GetNearbyTag('nearest', 0)
|
||||
endif
|
||||
|
||||
if !empty(tag)
|
||||
|
@ -3058,19 +3074,17 @@ function! s:GetNearbyTag(request, forcecurrent, ...) abort
|
|||
for line in range(curline, 1, -1)
|
||||
if has_key(fileinfo.fline, line)
|
||||
let curtag = fileinfo.fline[line]
|
||||
if a:request ==# 'highlight' && typeinfo.getKind(curtag.fields.kind).stl
|
||||
if a:request ==# 'nearest-stl'
|
||||
\ && typeinfo.getKind(curtag.fields.kind).stl || line == curline
|
||||
let tag = curtag
|
||||
break
|
||||
endif
|
||||
if a:request ==# 'highlight' && line == curline
|
||||
elseif a:request ==# 'scoped-stl'
|
||||
\ && typeinfo.getKind(curtag.fields.kind).stl
|
||||
\ && curtag.fields.line <= curline
|
||||
\ && curline <= curtag.fields.end
|
||||
let tag = curtag
|
||||
break
|
||||
endif
|
||||
if a:request ==# 'statusline' && typeinfo.getKind(curtag.fields.kind).stl
|
||||
let tag = curtag
|
||||
break
|
||||
endif
|
||||
if a:request ==# 'parent'
|
||||
elseif a:request ==# 'nearest'
|
||||
let tag = curtag
|
||||
break
|
||||
endif
|
||||
|
@ -3586,31 +3600,6 @@ endfunction
|
|||
" Autoload functions {{{1
|
||||
|
||||
" Wrappers {{{2
|
||||
function! tagbar#GetTagNearLine(lnum, ...) abort
|
||||
if a:0 > 0
|
||||
let fmt = a:1
|
||||
let longsig = a:2 =~# 's'
|
||||
let fullpath = a:2 =~# 'f'
|
||||
let prototype = a:2 =~# 'p'
|
||||
else
|
||||
let fmt = '%s'
|
||||
let longsig = 0
|
||||
let fullpath = 0
|
||||
let prototype = 0
|
||||
endif
|
||||
|
||||
let taginfo = s:GetNearbyTag('statusline', 1, a:lnum)
|
||||
|
||||
if empty(taginfo)
|
||||
return ''
|
||||
endif
|
||||
|
||||
if prototype
|
||||
return taginfo.getPrototype(1)
|
||||
else
|
||||
return printf(fmt, taginfo.str(longsig, fullpath))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! tagbar#ToggleWindow(...) abort
|
||||
let flags = a:0 > 0 ? a:1 : ''
|
||||
|
@ -3719,28 +3708,67 @@ function! tagbar#autoopen(...) abort
|
|||
call tagbar#debug#log('tagbar#autoopen finished without finding valid file')
|
||||
endfunction
|
||||
|
||||
" tagbar#GetTagNearLine() {{{2
|
||||
function! tagbar#GetTagNearLine(lnum, ...) abort
|
||||
if a:0 >= 2
|
||||
let fmt = a:1
|
||||
let longsig = a:2 =~# 's'
|
||||
let fullpath = a:2 =~# 'f'
|
||||
let prototype = a:2 =~# 'p'
|
||||
if a:0 >= 3
|
||||
let search_method = a:3
|
||||
else
|
||||
let search_method = 'nearest-stl'
|
||||
endif
|
||||
else
|
||||
let fmt = '%s'
|
||||
let longsig = 0
|
||||
let fullpath = 0
|
||||
let prototype = 0
|
||||
let search_method = 'nearest-stl'
|
||||
endif
|
||||
|
||||
let taginfo = s:GetNearbyTag(search_method, 1, a:lnum)
|
||||
|
||||
if empty(taginfo)
|
||||
return ''
|
||||
endif
|
||||
|
||||
if prototype
|
||||
return taginfo.getPrototype(1)
|
||||
else
|
||||
return printf(fmt, taginfo.str(longsig, fullpath))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" tagbar#currenttag() {{{2
|
||||
function! tagbar#currenttag(fmt, default, ...) abort
|
||||
" Indicate that the statusline functionality is being used. This prevents
|
||||
" the CloseWindow() function from removing the autocommands.
|
||||
let s:statusline_in_use = 1
|
||||
|
||||
if a:0 > 0
|
||||
if a:0 >= 1
|
||||
" also test for non-zero value for backwards compatibility
|
||||
let longsig = a:1 =~# 's' || (type(a:1) == type(0) && a:1 != 0)
|
||||
let fullpath = a:1 =~# 'f'
|
||||
let prototype = a:1 =~# 'p'
|
||||
if a:0 >= 2
|
||||
let search_method = a:2
|
||||
else
|
||||
let search_method = 'nearest-stl'
|
||||
endif
|
||||
else
|
||||
let longsig = 0
|
||||
let fullpath = 0
|
||||
let prototype = 0
|
||||
let search_method = 'nearest-stl'
|
||||
endif
|
||||
|
||||
if !s:Init(1)
|
||||
return a:default
|
||||
endif
|
||||
|
||||
let tag = s:GetNearbyTag('statusline', 1)
|
||||
let tag = s:GetNearbyTag(search_method, 1)
|
||||
|
||||
if !empty(tag)
|
||||
if prototype
|
||||
|
@ -3812,7 +3840,7 @@ function! tagbar#currenttagtype(fmt, default) abort
|
|||
" the CloseWindow() function from removing the autocommands.
|
||||
let s:statusline_in_use = 1
|
||||
let kind = ''
|
||||
let tag = s:GetNearbyTag('statusline', 1)
|
||||
let tag = s:GetNearbyTag('scoped-stl', 1)
|
||||
|
||||
if empty(tag)
|
||||
return a:default
|
||||
|
|
|
@ -14,6 +14,7 @@ function! tagbar#prototypes#basetag#new(name) abort
|
|||
let newobj.fields = {}
|
||||
let newobj.fields.line = 0
|
||||
let newobj.fields.column = 0
|
||||
let newobj.fields.end = 0
|
||||
let newobj.prototype = ''
|
||||
let newobj.data_type = ''
|
||||
let newobj.path = ''
|
||||
|
|
|
@ -334,14 +334,17 @@ FUNCTIONS *tagbar-functions*
|
|||
This could be used in a custom foldtext function to show the current tag
|
||||
the fold current fold is located in.
|
||||
|
||||
Example:
|
||||
>
|
||||
set foldtext=MyFoldFunc()
|
||||
function! MyFoldFunc()
|
||||
let tag = tagbar#GetTagNearLine(v:foldend, '%s', 'p')
|
||||
let lines = v:foldend - v:foldstart + 1
|
||||
return tag . ' --- ' . lines . ' lines'
|
||||
endfunction
|
||||
This function can also take in a search method similar to the
|
||||
|tagbar#currenttag()| function. Full syntax is as follows:
|
||||
tagbar#GetTagNearLine(lnum [, {fmt}, {flags} [, {search-method}]])
|
||||
|
||||
Example: >
|
||||
set foldtext=MyFoldFunc()
|
||||
function! MyFoldFunc()
|
||||
let tag = tagbar#GetTagNearLine(v:foldend, '%s', 'p')
|
||||
let lines = v:foldend - v:foldstart + 1
|
||||
return tag . ' --- ' . lines . ' lines'
|
||||
endfunction
|
||||
<
|
||||
*tagbar#ForceUpdate()*
|
||||
Forcefully update a file even if it exceeds the |g:tagbar_file_size_limit|
|
||||
|
@ -1182,7 +1185,7 @@ read |tagbar-extend| (especially the "kinds" entry) on how to do that.
|
|||
|
||||
The function has the following signature:
|
||||
|
||||
tagbar#currenttag({format}, {default} [, {flags}])
|
||||
tagbar#currenttag({format}, {default} [, {flags} [, {search-method}]])
|
||||
{format} is a |printf()|-compatible format string where "%s" will be
|
||||
replaced by the name of the tag. {default} will be displayed instead of
|
||||
the format string if no tag can be found.
|
||||
|
@ -1197,10 +1200,33 @@ tagbar#currenttag({format}, {default} [, {flags}])
|
|||
useful in cases where ctags doesn't report some information, like
|
||||
the signature. Note that this can get quite long.
|
||||
|
||||
The optional {search-method} argument specified how to search for the
|
||||
nearest tag. Valid options are:
|
||||
'nearest' This will look for the closest tag above the current line
|
||||
regardless of type. This will match even one line tags or
|
||||
other tags not defined with the {stl} flag in their kind
|
||||
definition. This is the quickest option, but least
|
||||
accurate.
|
||||
'nearest-stl' This will look for the closest tag above the current line
|
||||
which is defined with the {stl} flag in its kind
|
||||
definition. This is a little slower, but provides a little
|
||||
more context and accuracy.
|
||||
'scoped-stl' This will look for the closest tag above the current line
|
||||
taking scope into account as well as the {stl} flag. The
|
||||
scope is determined by the ctags 'end' field. This is the
|
||||
slowest of the options as when outside of a function
|
||||
scope, it could end up searching all the way to the top of
|
||||
the file for the nearest scoped tag (or possibly none if
|
||||
not in any scope at all).
|
||||
For example, if you put the following into your statusline: >
|
||||
%{tagbar#currenttag('[%s] ','')}
|
||||
< then the function "myfunc" will be shown as "[myfunc()] ".
|
||||
|
||||
< then the function "myfunc" will be shown as "[myfunc()] ".
|
||||
As another example, we can use the following in our status line to find
|
||||
the current scoped tag and also print the full path when found: >
|
||||
%{tagbar#currenttag('%s', '', 'f', 'scoped-stl')}
|
||||
< then the function "myfunc" within class "myclass" will be shown as
|
||||
"myclass::myfunc()". But when outside of the function, it will be shown as
|
||||
"myclass"
|
||||
Additionally you can show the kind (type) of the current tag, using following
|
||||
function:
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user