~brian-sidebotham/wxwidgets-cmake/wxpython-2.9.4

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/plugins/codebrowser/codebrowser/gentag/pytags.py

  • Committer: Brian Sidebotham
  • Date: 2013-08-03 14:30:08 UTC
  • Revision ID: brian.sidebotham@gmail.com-20130803143008-c7806tkych1tp6fc
Initial import into Bazaar

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
###############################################################################
 
2
# Name: pytags.py                                                             #
 
3
# Purpose: Generate Python Tags                                               #
 
4
# Author: Cody Precord <cprecord@editra.org>                                  #
 
5
# Copyright: (c) 2008 Cody Precord <staff@editra.org>                         #
 
6
# License: wxWindows License                                                  #
 
7
###############################################################################
 
8
 
 
9
"""
 
10
FILE: pytags.py
 
11
AUTHOR: Cody Precord
 
12
AUTHOR: Luis Cortes
 
13
LANGUAGE: Python
 
14
SUMMARY:
 
15
  Generate a DocStruct object that captures the structure of a python document.
 
16
It supports parsing for global and class variables, class, method, and function
 
17
definitions.
 
18
 
 
19
@todo: add back support for class variables
 
20
@todo: document functions
 
21
 
 
22
"""
 
23
 
 
24
__author__ = "Cody Precord <cprecord@editra.org>"
 
25
__svnid__ = "$Id: pytags.py 69297 2011-10-03 15:53:48Z CJP $"
 
26
__revision__ = "$Revision: 69297 $"
 
27
 
 
28
#--------------------------------------------------------------------------#
 
29
# Dependencies
 
30
import taglib
 
31
import parselib
 
32
from pygments import highlight
 
33
from pygments.token import Token
 
34
from pygments.lexers import get_lexer_by_name
 
35
from pygments.formatter import Formatter
 
36
 
 
37
#--------------------------------------------------------------------------#
 
38
 
 
39
class PyFormatter(Formatter):
 
40
 
 
41
    def format(self, tokensource, outfile):
 
42
        self.rtags = taglib.DocStruct()
 
43
        self.rtags.SetElementDescription('function', "Function Definitions")
 
44
        self.rtags.SetElementDescription('class', "Class Definitions")
 
45
        self._levels = [0]
 
46
        self._toplevel = True
 
47
 
 
48
        line_count = 0
 
49
        current_line = []
 
50
        code_lines = []
 
51
 
 
52
        # Parse the file into tokens and values
 
53
        for ttype, value in tokensource:
 
54
            if '\n' in value:
 
55
                code_lines.append((line_count, current_line))
 
56
                current_line = []
 
57
                line_count += value.count('\n')
 
58
                continue
 
59
            current_line.append((ttype, value))
 
60
 
 
61
        self.getCFV(code_lines)
 
62
 
 
63
    def _getLevel(self, line):
 
64
        try:
 
65
            t, v = line[0]
 
66
            if t == Token.Text:
 
67
                return len(v)
 
68
        except:
 
69
            pass
 
70
        return 0
 
71
 
 
72
    def pushPopScope(self, level):
 
73
        """Push a scope onto the stack. If less than previous scope
 
74
        it will pop levels until it finds a matching indent level.
 
75
 
 
76
        """
 
77
        nlevels = list()
 
78
        for lvl in self._levels:
 
79
            if lvl < level:
 
80
                nlevels.append(lvl)
 
81
            else:
 
82
                break
 
83
        nlevels.append(level)
 
84
        self._levels = nlevels
 
85
 
 
86
    def insertClass(self, line, num, container_list):
 
87
        """Insert a class into the container"""
 
88
        cname = parselib.GetTokenValue(line, Token.Name.Class)
 
89
        clevel = self._getLevel(line)
 
90
 
 
91
        ctag = None
 
92
        # Top Level Class
 
93
        if clevel == 0:
 
94
            ctag = taglib.Class(cname, num)
 
95
            self.rtags.AddClass(ctag)
 
96
 
 
97
        # Somewhere else
 
98
        else:
 
99
            for l, c, ob in reversed(container_list):
 
100
                if l < clevel:
 
101
                    ctag = taglib.Class(cname, num, c)
 
102
                    ob.AddElement('class', ctag)
 
103
                    break
 
104
 
 
105
        if ctag:
 
106
            container_list.append((clevel, cname, ctag))
 
107
 
 
108
    def insertFunction(self, line, num, container_list):
 
109
        fname = parselib.GetTokenValue(line, Token.Name.Function)
 
110
        flevel = self._getLevel(line)
 
111
 
 
112
        ftag = None
 
113
        # top level function
 
114
        if flevel == 0:
 
115
            ftag = taglib.Function(fname, num)
 
116
            self.rtags.AddFunction(ftag)
 
117
 
 
118
        # Somewhere else
 
119
        else:
 
120
            for l, c, ob in reversed(container_list):
 
121
                if l < flevel:
 
122
                    if isinstance(ob, taglib.Class):
 
123
                        ftag = taglib.Method(fname, num, c)
 
124
                        ob.AddMethod(ftag)
 
125
                    else:
 
126
                        ftag = taglib.Function(fname, num, c)
 
127
                        ob.AddElement('function', ftag)
 
128
                    break
 
129
 
 
130
        if ftag:
 
131
            container_list.append((flevel, fname, ftag))
 
132
 
 
133
    def getCFV(self, code_lines):
 
134
 
 
135
        container_list = []
 
136
        vset = set()
 
137
 
 
138
        for num, line in code_lines:
 
139
            try:
 
140
                if len(line):
 
141
                    ltxt = u"".join([l[1].strip() for l in line])
 
142
                    if len(ltxt) and not ltxt.startswith(u"#"):
 
143
                        if parselib.BeginsWithAnyOf(line, Token.Keyword,
 
144
                                                    (u"def", u"class", u"if", u"else")):
 
145
                            self.pushPopScope(self._getLevel(line))
 
146
                            if len(self._levels) == 1:
 
147
                                container_list = [(0, u"", self.rtags)]
 
148
 
 
149
                # FUNCTION
 
150
                #
 
151
                if parselib.HasToken(line, Token.Keyword, "def"):
 
152
                    self.insertFunction(line, num, container_list)
 
153
 
 
154
                # CLASS
 
155
                #
 
156
                elif parselib.HasToken(line, Token.Keyword, "class"):
 
157
                    self.insertClass(line, num, container_list)
 
158
 
 
159
                # Global Variable Only
 
160
                #
 
161
                elif parselib.HasToken(line, Token.Operator, "="):
 
162
                    vname = parselib.GetTokenValue(line, Token.Name);
 
163
                    flevel = self._getLevel(line)
 
164
 
 
165
                    if flevel == 0:
 
166
                        if not vname in vset:
 
167
                            self.rtags.AddVariable(taglib.Variable(vname, num))
 
168
                            vset.add(vname)
 
169
 
 
170
            except parselib.TokenNotFound:
 
171
                pass
 
172
        return self.rtags
 
173
 
 
174
    def getTags(self):
 
175
        return self.rtags
 
176
 
 
177
#-----------------------------------------------------------------------------#
 
178
 
 
179
def GenerateTags(buff):
 
180
    """GenTag interface method
 
181
    @return: taglib.DocStruct
 
182
 
 
183
    """
 
184
    formatter = PyFormatter()
 
185
    highlight(buff.read(), get_lexer_by_name("python"), formatter)
 
186
    return formatter.getTags()
 
187
 
 
188
#-----------------------------------------------------------------------------#
 
189
# Test
 
190
if __name__ == '__main__':
 
191
    import sys
 
192
    import StringIO
 
193
    fhandle = open(sys.argv[1])
 
194
    txt = fhandle.read()
 
195
    fhandle.close()
 
196
    tags = GenerateTags(StringIO.StringIO(txt))
 
197
    print "\n\nVARIABLES:"
 
198
    for var in tags.GetVariables():
 
199
        print "%s [%d]" % (var.GetName(), var.GetLine())
 
200
    print "\n\nFUNCTIONS:"
 
201
    for fun in tags.GetFunctions():
 
202
        print "%s [%d]" % (fun.GetName(), fun.GetLine())
 
203
    print ""
 
204
    print "CLASSES:"
 
205
    for c in tags.GetClasses():
 
206
        print "* %s [%d]" % (c.GetName(), c.GetLine())
 
207
 
 
208
 
 
209
# get var and methods does not exist ( any more ?? )
 
210
#        for var in c.GetVariables():
 
211
#            print "VAR: ", var.GetName()
 
212
#        for meth in c.GetMethods():
 
213
#            print "    %s [%d]" % (meth.GetName(), meth.GetLine())
 
214
    print "END"