diff --git a/autoload/tagbar.vim b/autoload/tagbar.vim index b8b6f94..3ee4b92 100644 --- a/autoload/tagbar.vim +++ b/autoload/tagbar.vim @@ -2332,10 +2332,9 @@ function! s:IsLineVisible(line) abort endfunction " s:JumpToTag() {{{2 -function! s:JumpToTag(stay_in_tagbar) abort - let taginfo = s:GetTagInfo(line('.'), 1) - - let autoclose = w:autoclose +function! s:JumpToTag(stay_in_tagbar, ...) abort + let taginfo = a:0 > 0 ? a:1 : s:GetTagInfo(line('.'), 1) + let force_lazy_scroll = a:0 > 1 ? a:2 : 0 if empty(taginfo) || !taginfo.isNormalTag() " Cursor line not on a tag. Check if this is the start of a foldable @@ -2359,6 +2358,11 @@ function! s:JumpToTag(stay_in_tagbar) abort endif let tagbarwinnr = winnr() + if exists('w:autoclose') + let autoclose = w:autoclose + else + let autoclose = 0 + endif call s:GotoFileWindow(taginfo.fileinfo) @@ -2368,7 +2372,7 @@ function! s:JumpToTag(stay_in_tagbar) abort " Check if the tag is already visible in the window. We must do this " before jumping to the line. let noscroll = 0 - if g:tagbar_jump_lazy_scroll != 0 + if g:tagbar_jump_lazy_scroll != 0 || force_lazy_scroll let noscroll = s:IsLineVisible(taginfo.fields.line) endif @@ -3166,20 +3170,27 @@ function! s:GetNearbyTag(request, forcecurrent, ...) abort return {} endif + let curline = a:0 > 0 ? a:1 : line('.') + let direction = a:0 > 1 ? a:2 : -1 + let ignore_curline = a:0 > 2 ? a:3 : 0 + let typeinfo = fileinfo.typeinfo - if a:0 > 0 - let curline = a:1 - else - let curline = line('.') - endif let tag = {} + if direction < 0 + let endline = 1 + let increment = -1 + else + let endline = line('$') + let increment = 1 + endif + " If a tag appears in a file more than once (for example namespaces in " C++) only one of them has a 'tline' entry and can thus be highlighted. " The only way to solve this would be to go over the whole tag list again, " making everything slower. Since this should be a rare occurence and " highlighting isn't /that/ important ignore it for now. - for line in range(curline, 1, -1) + for line in range(curline, endline, increment) if has_key(fileinfo.fline, line) let curtag = fileinfo.fline[line] if a:request ==# 'nearest-stl' && typeinfo.getKind(curtag.fields.kind).stl @@ -3191,7 +3202,7 @@ function! s:GetNearbyTag(request, forcecurrent, ...) abort \ && curline <= curtag.fields.end let tag = curtag break - elseif a:request ==# 'nearest' || line == curline + elseif a:request ==# 'nearest' || (line == curline && ignore_curline == 0) let tag = curtag break endif @@ -3201,6 +3212,31 @@ function! s:GetNearbyTag(request, forcecurrent, ...) abort return tag endfunction +" s:JumpToNearbyTag() {{{2 +function! s:JumpToNearbyTag(direction, request, flags) abort + let fileinfo = tagbar#state#get_current_file(0) + if empty(fileinfo) + return {} + endif + + let lnum = a:direction > 0 ? line('.') + 1 : line('.') - 1 + let lazy_scroll = a:flags =~# 's' ? 0 : 1 + + let tag = s:GetNearbyTag(a:request, 1, lnum, a:direction, 1) + + if empty(tag) + " No next tag found + if a:direction > 0 + echo '...no next tag found' + else + echo '...no previous tag found' + endif + return + endif + + call s:JumpToTag(1, tag, lazy_scroll) +endfunction + " s:GetTagInfo() {{{2 " Return the info dictionary of the tag on the specified line. If the line " does not contain a valid tag (for example because it is empty or only @@ -4020,5 +4056,18 @@ function! tagbar#jump() abort call s:JumpToTag(1) endfun +" tagbar#jumpToNearbyTag() {{{2 +" params: +" direction = -1:backwards search 1:forward search +" [search_method] = Search method to use for GetTagNearLine() +" [flags] = list of flags (as a string) to control behavior +" 's' - use the g:tagbar_scroll_offset setting when jumping +function! tagbar#jumpToNearbyTag(direction, ...) abort + let search_method = a:0 >= 1 ? a:1 : 'nearest-stl' + let flags = a:0 >= 2 ? a:2 : '' + + call s:JumpToNearbyTag(a:direction, search_method, flags) +endfunction + " Modeline {{{1 " vim: ts=8 sw=4 sts=4 et foldenable foldmethod=marker foldcolumn=1 diff --git a/doc/tagbar.txt b/doc/tagbar.txt index d2132bf..b29d194 100644 --- a/doc/tagbar.txt +++ b/doc/tagbar.txt @@ -329,6 +329,20 @@ COMMANDS *tagbar-commands* This command will call the |tagbar#jump()| function. +:TagbarJumpPrev *:TagbarJumpPrev* + Jump to the previous tag under the cursor. This works in the file window. + This will search for the previous {'nearest-stl'} type tag starting at the + line just before the current line and do a backwards search. + + This command will call the |tagbar#jumpToNearbyTag(-1)| function. + +:TagbarJumpNext *:TagbarJumpNext* + Jump to the next tag under the cursor. This works in the file window. + This will search for the next {'nearest-stl'} type tag starting at the + line just after the current line and do a forward search. + + This command will call the |tagbar#jumpToNearbyTag(1)| function. + ------------------------------------------------------------------------------ FUNCTIONS *tagbar-functions* @@ -378,6 +392,45 @@ FUNCTIONS *tagbar-functions* This is the function called when using the |:TagbarJump| command. +*tagbar#jumpToNearbyTag()* + This function will jump to the next tag or previous tag starting a search + from the line under the cursor. This works when in the file window instead + of inside the tagbar window like the |tagbar#jump()| function. + + The direction of search must be provided. If the [direction] is greater + than 0, then it will do a forward search. If the [direction] is less + than 0, then it will do a backward search. + + Can also optionally provide a [search_method] which is used in the + |tagbar#GetTagNearLine()| function call and behaves the same way. This + will default to *'nearest-stl'* if not specified. + + Can optionally provide a flags field [flags] to control the nearby tag + jumping. The flags should be a string of characters with the following + meanings: + 's' - use the |g:tagbar_scroll_off| setting when jumping + + Full syntax: + tagbar#jumpToNearbyTag(direction [, {search-method} [, {flags}]]) + + Examples: +> + " These keymaps will jump to the next/prev tag that can be scoped. Ex: + " function calls, class definitions, etc. + nnoremap t] :call tagbar#jumpToNearbyTag(1) + nnoremap t[ :call tagbar#jumpToNearbyTag(-1) + + " These keymaps will jump to the next/prev tag regardless of type. Ex: + " function calls, class definitions, variable definitions, typedefs, etc. + nnoremap t] :call tagbar#jumpToNearbyTag(1, 'nearest') + nnoremap t[ :call tagbar#jumpToNearbyTag(-1, 'nearest') + + " These keymaps will jump to the next/prev tag regardless of type, and + " will also use the jump_offset configuration to position the cursor + nnoremap t] :call tagbar#jumpToNearbyTag(1, 'nearest', 's') + nnoremap t[ :call tagbar#jumpToNearbyTag(-1, 'nearest', 's') +< + ------------------------------------------------------------------------------ KEY MAPPINGS *tagbar-keys* diff --git a/plugin/tagbar.vim b/plugin/tagbar.vim index e6c7fc5..390434b 100644 --- a/plugin/tagbar.vim +++ b/plugin/tagbar.vim @@ -197,6 +197,8 @@ command! -nargs=0 TagbarDebugEnd call tagbar#debug#stop_debug() command! -nargs=0 TagbarTogglePause call tagbar#toggle_pause() command! -nargs=0 TagbarForceUpdate call tagbar#ForceUpdate() command! -nargs=0 TagbarJump call tagbar#jump() +command! -nargs=0 TagbarJumpPrev call tagbar#jumpToNearbyTag(-1) +command! -nargs=0 TagbarJumpNext call tagbar#jumpToNearbyTag(1) " Modeline {{{1