Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigating Python modules with ctags in Vim?

I'm using Vim with ctags for Python and that works very well for classes, fields, etc, but what it doesn't seem to include are Python file names aka module names. Is this possible? I'd far prefer to type ta <module> to jump to a module, rather than navigate level-by-level with a file browser like NERDtree, and I'm very accustomed to doing this in Java, which works out since class names are file names.

like image 548
John Lehmann Avatar asked May 28 '14 15:05

John Lehmann


People also ask

Can I use Ctags with Vim?

Configuring ctags for Python and Vim. Exuberant ctags is a cool, language-agnostic tool for creating tag files for your source code. Nice editors such as Vim, could use these tag files to implement the much needed 'jump to definition' feature. Ctags is awesome, it supports Python, and is supported by Vim.

How do I create a tag in Vim?

Open the .vimrc file in vim editor with root permission and add the following set command that defines the location where tags file will be stored. Run the commands ‘ ctags -R * ’ to create tags for all the files exist in the selected project folder. Next, ‘ls’ command is executed to check the tag file is created or not.

How to set the folder path in Vim editor before using ctags?

So, you will need to set the folder path in ~/.vimrc file before using ctags. Open the ~/.vimrc file in vim editor with root privileges by using the terminal. Write the following set of commands in the .vimrc file and save it.

How to use ctags in Python?

Go to the folder where you want to apply the ctags. The following two commands are used to go to the python folder and check the file list. Ctags stores all information in tags file. It is necessary to set the folder location of tags file in .vimrc file before using this tool.


2 Answers

If you generate your tags file using exuberant ctags (Is there any other way?) then try adding the --extra=+f option. See the man page at http://ctags.sourceforge.net/ctags.html#OPTIONS for details.

like image 73
benjifisher Avatar answered Oct 02 '22 15:10

benjifisher


Exuberant tags (with --extra=+f) generates tags for python file-names (e.g. my_module.py), but not for the module name (e.g. my_module). I ended up creating a modified version of the ptags script. Save the following to a file named ptags somewhere in your path and make it executable:

#! /usr/bin/env python

# ptags
#
# Create a tags file for Python programs, usable with vi.
# Tagged are:
# - functions (even inside other defs or classes)
# - classes
# - filenames
# Warns about files it cannot open.
# No warnings about duplicate tags.

import sys, re, os
import argparse

tags = []    # Modified global variable!

def main():
    for root, folders, files in os.walk(args.folder_to_index):
        for filename in files:
            if filename.endswith('.py'):
                full_path = os.path.join(root, filename)
                treat_file(full_path)
        if not args.recursive:
            break

    if tags:
        fp = open(args.ctags_filename, 'w')
        tags.sort()
        for s in tags: fp.write(s)

expr = '^[ \t]*(def|class)[ \t]+([a-zA-Z0-9_]+)[ \t]*[:\(]'
matcher = re.compile(expr)

def treat_file(filename):
    try:
        fp = open(filename, 'r')
    except:
        sys.stderr.write('Cannot open %s\n' % filename)
        return
    base = os.path.basename(filename)
    if base[-3:] == '.py':
        base = base[:-3]
    s = base + '\t' + filename + '\t' + '1\n'
    tags.append(s)
    while 1:
        line = fp.readline()
        if not line:
            break
        m = matcher.match(line)
        if m:
            content = m.group(0)
            name = m.group(2)
            s = name + '\t' + filename + '\t/^' + content + '/\n'
            tags.append(s)

if __name__ == '__main__':
    p = argparse.ArgumentParser()
    p.add_argument('-f', '--ctags-filename', type=str, default='tags')
    p.add_argument('-R', '--recursive', action='store_true')
    p.add_argument('folder_to_index', type=str, default='.')
    args = p.parse_args()
    main()

Now run the following to generate a tags file by recursively processing the current directory:

ptags -R -f tags_file_to_create /path/to/index

like image 42
Mark Avatar answered Oct 02 '22 15:10

Mark