preservim / tagbar

Vim plugin that displays tags in a window, ordered by scope
https://preservim.github.io/tagbar
Other
6.14k stars 489 forks source link

Python - inner functions issue #846

Closed BAlmeidaS closed 1 year ago

BAlmeidaS commented 1 year ago

Honestly, I do not know with this is an issue with tagbar or ctag, so if I am wrong, I ask sorry in advance.

What is happening is, when I have a python file opened on my neovim and use tagbar to understand in which context I am in, it loses itself when there is inner functions.

This is an example:

def my_func():
    print("first layer")
    def inner_func():
        print("second layer")
        def inner_inner_func():
            print("third layer")
        print("went back to the second layer, but tag points to third layer")
    print("went back to the first layer, but tag points to third layer")

If my cursor is over the "second layer" print. It shows correctly: image

On the third print as well: image

But, as soon as I move one row down, I expect that, based on indentation, it understands that I changed the context, but this does not happen: image

I can bring more information if it is needed.

raven42 commented 1 year ago

@BAlmeidaS can you check your vim setting for g:tagbar_highlight_method? If it is set to nearest-stl (or not set, then nearest-stl is default), then you might see this behavior. Try setting this value to scoped-stl and see if this corrects the behavior. This is dependent on CTAGS outputting the scope information for each tag as well.

BAlmeidaS commented 1 year ago

@raven42 Thanks a lot for your answer. Changing the highlight method did not solve:

  1. Set on neovim after
  2. Validated inside neovim with
    :echo g:tagbar_highlight_method
    "scoped-stl"

But the behaviour was the same that I shared.

Maybe it is a cflag issue, but I am not 100% sure of how to validate if it is

raven42 commented 1 year ago

Can you share the ctags output for your file? Use the following command:

ctags --extras=+F -f - --format=2 --excmd=pattern --fields=nksSafet --sort=no --append=no -V --language-force=python --python-kinds=icfmv <file>

When I run it from my environment, I get the following output.

  Option: --language-force=python
  Option: --python-kinds=icfmv
Initialize parser: Python
Reading command line arguments
OPENING test.py as Python language file [new]
my_func test.py /^def my_func():$/;"    f   line:1  access:public   signature:()    end:10
inner_func  test.py /^    def inner_func():$/;" f   line:4  function:my_func    file:   access:private  signature:()    end:9
inner_inner_func    test.py /^        def inner_inner_func():$/;"   f   line:7  function:my_func.inner_func file:   access:private  signature:()    end:8

As you can see in my setup, this does appear to be working. image

The key bit is the last field noted as end:#. That indicates the end of the scope of that particular tag. That is how the scoped-stl works. If your installation of ctags does not have that, then you would have to upgrade to a newer version of universal ctags to ensure that it has that output.

BAlmeidaS commented 1 year ago

Thanks a lot for your answer again @raven42, super helpful!

My version does not have this end field, maybe because I am using the 5.8 (1.5y ago)

$ ctags --version                                                                                                                                                                                                                                                                                                                                                 
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Oct 25 2021, 03:50:10
  Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net
  Optional compiled features: +wildcards, +regex

$ ctags --extra=+f -f - --format=2 --excmd=pattern --fields=nksSaft --sort=no --append=no -V --language-force=python --python-kinds=icfmv inner-func.py                                                                                                                                                                                                            
  Option: --language-force=python
  Option: --python-kinds=icfmv
Reading command line arguments
OPENING inner-func.py as Python language file
inner-func.py   inner-func.py   1;" F   line:1
my_func inner-func.py   /^def my_func():$/;"    f   line:1  access:public
inner_func  inner-func.py   /^    def inner_func():$/;" f   line:3  function:my_func    access:public
inner_inner_func    inner-func.py   /^        def inner_inner_func():$/;"   f   line:5  function:my_func.inner_func access:public

I will take some time today to update the ctags. Thanks again for your support

raven42 commented 1 year ago

Ah ok. Ya that would be it. Exuberant CTAGs is very old and isn't being maintained anymore. The project was branched off to Universal CTAGS which is actively supported and has many of these new features. Try installing the universal ctags for your distro, or you can compile/install your own from the Universal CTAGS github repo.