0

Sometimes I want to just loop through all tags in a file. One use case is for help files, but it's also useful for browsing large unfamiliar source code files.

Is there a way to do this? Something like :tn/:tp but for any tag.

1
  • 1
    You can list them with :tags but I don't think there's a next/prev to cycle through them one by one. They need to be "named" (:tag {name}). Maybe try the "tagbar" plugin and navigate one by one using the side panel.
    – B Layer
    Aug 19, 2021 at 17:26

1 Answer 1

1

Do command-line auto-completion with the :tag command.

:tag <tab>

or

:tag <ctrl-d>

These will list ALL the tags. To narrow down what is included, hit <tab> or <ctrl-d> after typing a few leading characters or a wildcard pattern.

This requires :set wildmenu to be on and will subject to 'wildmenu' and 'wildoptions' settings.

Otherwise, this bit of Vimscript will do what you want: :Tnext (jump to next tag in the list) :Tprev (jump to prev tag in the list)

function! TagCycle(direction)
    if !exists('b:tag_number')
        " Initialize
        let b:max_tag_number = len(taglist('.'))-1
        if a:direction=='n'
            let b:tag_number=0
        else
            let b:tag_number = b:max_tag_number
        endif
    else
        if a:direction=='n'
            " Count up
            let b:tag_number+=1
            if b:tag_number > b:max_tag_number
                let b:tag_number = 0
            endif
        elseif a:direction=='p'
            " or count down
            let b:tag_number-=1
            if b:tag_number < 0
                let b:tag_number = b:max_tag_number
            endif
        endif
    endif

    " Jump to tag
    let b:tag_name = taglist('.')[b:tag_number]['name']
    execute 'tag '.b:tag_name
    echo "Tag jump to ".b:tag_name

endfunction

command! Tnext :call TagCycle('n')
command! Tprev :call TagCycle('p')
6
  • 1
    That's a bit too far from what I am looking for. However, is there some way to get access to the list used for completing :tag commands? Aug 19, 2021 at 21:10
  • 1
    I edited my answer with that sweet Vimscript now included. Aug 19, 2021 at 22:41
  • 1
    Wow, above and beyond! It seems like taglist('.') is what I was looking for in my previous comment, is that right? Aug 19, 2021 at 22:53
  • 1
    Yes, the taglist() function holds all the data of the tags. It's a list of dictionaries. It helps to script some helper code around taglist(), like I showed. Aug 19, 2021 at 23:51
  • 1
    I figured it out: I needed to filter so that only tags with the current filename were included. Something like: let l:taglist = filter(taglist('.'), {idx,val -> fnamemodify(val.name, 'p') == expand('%:p')}) Aug 20, 2021 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.