Best IDE for Python

sjdevnull at yahoo.com sjdevnull at yahoo.com
Tue Aug 15 12:34:19 EDT 2006


Bruce Who wrote:
> Hi, sjdevnull
>
> I'm a vimmer too, and I wonder what plugins you are using. What you
> said sounds interesting. Could you tell us more about the plugins?
> "Object browser" is what I need most, but so far I've no idea what
> plugin can do this for me, :-(

It's like a 15 minute job to write something basic.

Mine's a little more complicated since I deal with ugly things like
finding the parent class in cases like:

import generic.base.klass
...
BaseKlass = generic.base.klass.someKlass
...
class newKlass(BaseKlass):

and similar constructs.  I use the following in my vimrc:

"you might need to add directories to sys.path before the following
line
"probably also wand to bracket parts of it in 'if have("gui_running")'
python import vimrc
au GUIEnter * py vimrc.tags.fakeTagsMenu()
au BufEnter *.py aunmenu Tags
au BufEnter *.py py vimrc.tags.buildMenu()
au BufLeave *.py menu disable Ta&gs
au BufEnter * py vimrc.tags.fakeTagsMenu()

And then I have a vimrc.py with, among other things:
--------------------------
import tags
import os
import vim
def cur_x():
    return vim.current.window.cursor[1]
def cur_y():
    return vim.current.window.cursor[0]
def relativePath(absolutePath):
    cwd = os.getcwd()
    if absolutePath.startswith(cwd):
        absolutePath = absolutePath[len(cwd):]
        while absolutePath[0] == '/':
            absolutePath = absolutePath[1:]
        return absolutePath
    return absolutePath
----------------------
And a tags.py:
----------------------
#!/usr/bin/python
try:
    import vim
    import vimrc
except:
    pass

def findParentClass(currLoc = None, showMenu=0, allLines=None):
    if not allLines:
        allLines = vim.current.buffer
    if currLoc == None:
        currLoc = vimrc.cur_y()
    lines = [ line for line in allLines[:currLoc] if
line.startswith("class ") ]    if len(lines) == 0:
        lines = [ line for line in allLines[currLoc:] if
line.startswith("class
") ]
    else:
        lines.reverse()
    if len(lines) == 0:
        return None

    try:
        klass = lines[0].split("(", 1)[1].split(")")[0]
    except:
        return None
    currKlass = lines[0].split(" ", 1)[1]
    currKlass = currKlass.split(":")[0]
    try:
        currKlass = currKlass.split("(")[0]
    except:
        pass

    renameLines = []
    for i in range(len(allLines)):
        line = allLines[i]
        while line.endswith("\\"):
            line = line[:-1] + allLines[i+1]
            i=i+1
        if line.endswith(" as %s" % klass) or line.startswith("%s
="%klass) or line.startswith("%s="%klass):
            renameLines.append(line)

    if len(renameLines)>0:
        parseLine = renameLines[-1]
        if parseLine.endswith("as %s"%klass):
            klass = parseLine.split(" ")[-3]
        else:
            klass = parseLine.split(".")[-1]
    if "." in klass:
        klass = klass.split(".")[-1]
    if showMenu:
            if klass == currKlass:
                generic = "generic"
            else:
                generic = "none"
            vim.command('502menu <silent> Ta&gs.Parent:%s :call
FindTag("%s", "%s")<C-M>' %(klass, klass, generic))
    try:
        klass = klass.split(".")[-1]
    except:
        pass
    return klass
def YankLine():
    try:
        word = vim.current.line
        word = word.split(" ")[-1]
    except:
        return
    try:
        vim.command("silent tag %s"%word)
    except:
        return
    stuff = vim.current.line
    vim.command("normal ^T")
    print stuff
def buildChildEntries():
    rv = 0
    for line in vim.current.buffer:
        if line.startswith("class "):
            klass = line.split(" ", 1)[1]
            try:
                klass = klass.split("(")[0]
            except:
                pass
            try:
                klass = klass.split(":")[0]
            except:
                pass
            klass = klass.strip()
            fileName = vimrc.relativePath(vim.current.buffer.name)
            lines = [ line.strip() for line in open("oobr",
"r").readlines() if
line.startswith("%s:"%klass)]
            for line in lines:
                rv = 1
                splitline = line.split(":")
                child = splitline[1]
                childBase = childFile.split("/")[-1]
                childBase = childBase.split(".")[0]
                if "_" in childBase and not
fileName.startswith(childBase) and not fileName.startswith("generic")
and not fileName.startswith("libs"):
                    continue
                vim.command('502menu <silent> Ta&gs.Child:%s :call
FindTag("%s","%s")<C-M>' % (childBase, child, childFile))
    vim.command('502menu <silent> Ta&gs.-children- :')
    return rv
def editObject():
    vim.command(":e object.py")
    vim.command(":set buftype=nowrite")
    vim.command(":set bufhidden=delete")
    vim.command(":set noswapfile")
def buildParentEntries():
    foundSome = 0
    for i in range(len(vim.current.buffer)):
        if vim.current.buffer[i].startswith("class"):
            if findParentClass(i, showMenu=1):
                foundSome = 1
    return foundSome


def fakeTagsMenu(force=0):
    ft = vim.eval("&filetype")
    if ft == "python" and force==0:
        return
    try:
        vim.command("502menu Ta&gs.-Sep- :")
        vim.command("502menu disable Ta&gs")
    except:
        pass


def showMenus(fileDict):
    files = fileDict.keys()
    files.sort()
    files = [vimrc.relativePath(vim.current.buffer.name)]
    foundSome = buildParentEntries()
    foundSome = buildChildEntries() or foundSome
    for k in files:
        kName = k.strip().split(".")[0]
        #vim.command("502menu Tags.%s :q<C-M>" % kName)
        try:
            classList = fileDict[k]["class"].keys()
        except:
            if not foundSome:
                fakeTagsMenu(1)
            return
        classList.sort()
        for c in classList:
            c = c.strip()
            tagList = fileDict[k]["class"][c].keys()
            tagList.sort()
            for t in tagList:
                vim.command("502menu <silent> Ta&gs.%s:%s :tag
%s<CR>zz" % (c, t, t))


fdList = None


def rebuildTags():
    global fdList
    tagFiles=vim.eval("&tags")
    tagFiles = tagFiles.split(",")
    fd = {}
    for t in tagFiles:
        try:
            fd = parseTagsFile(t, fd)
        except:
            pass
    fdList = fd


def buildMenu():
    global fdList
    if not fdList:
        rebuildTags()
    fd = fdList
    showMenus(fd)


def parseTagsFile(file, files = None):
    if not files:
        files = dict()
    for i in open(file).readlines():
        i = i.strip()
        try:
            (tagName, fileName, exCmd, extensions) = i.split("\t", 3)
        except:
            continue
        extensions = extensions.split("\t")
        className = ""


        if not files.has_key(fileName):
            files[fileName] = {"class":{}, "method":{}}


        hadClass=0
        for e in extensions:
            if e.startswith("class:"):
                hadClass=1
                className = e.split(":", 1)[1]
                if not files[fileName]["class"].has_key(className):
                    files[fileName]["class"][className] = {}
                files[fileName]["class"][className][tagName] = 1


        if not hadClass:
            if extensions[0] == "c":
                if not files[fileName]["class"].has_key(tagName):
                    files[fileName]["class"][tagName] = {}
            else:
                files[fileName]["method"][tagName] = tagName

        
    return files




More information about the Python-list mailing list