filtertable.py :  » IDE » PyPE » PyPE-2.9.1 » plugins » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » IDE » PyPE 
PyPE » PyPE 2.9.1 » plugins » filtertable.py

'''
This software is licensed under the GPL (GNU General Public License) version 2
as it appears here: http://www.gnu.org/copyleft/gpl.html
It is also included with this archive as `gpl.txt <gpl.txt>`_.
'''


import itertools
import math
import wx

import codetree
import exparse
from findinfiles import FoundTable
import mylistmix
import todo

import __main__

columns = (
    (0, "Lines", 50, wx.LIST_FORMAT_RIGHT),
    (1, "Definition", 20, 0),
    )

context = 'no context'
options = None


#colors
if 1:
    D = {}
    for i,j in codetree.D.items():
        k = wx.ListItemAttr()
        k.SetTextColour(j)
        D[i] = k
    
    default = D['de']
    
    del i, j, k

def lcsseq(x, y):
    #stores the full table, not necessary
    _enum = enumerate
    _max = max
    z = {}
    zg = z.get
    for i, xi in _enum(x):
        for j, yj in _enum(y):
            if xi == yj:
                k = zg((i-1,j-1), 0)+1
            else:
                k = zg((i-1,j), 0)
                l = zg((i,j-1), 0)
                if l > k:
                    k = l
            z[i,j] = k
    
    return z[i,j]

def lcsseq(x, y):
    #only stores most recent 2 lines
    #more than sufficient for our uses
    #significantly faster than the above
    #not necessary
    _enum = enumerate
    if len(y) > len(x):
        x,y = y,x
    if len(y) == 0:
        return 0
    z1 = len(y)*[0]
    z2 = z1[:]
    z1.append(0) #for == case and j==0
    for i, xi in _enum(x):
        z2[0] = z2[-1] = 0 #for != case and j==0
        for j, yj in _enum(y):
            if xi == yj:
                z2[j] = z1[j-1]+1
            else:
                k = z1[j]
                l = z2[j-1]
                if l > k:
                    k = l
                z2[j] = k
        z1[:-1] = z2[:] #for == case and j==0
    return z1[-2]

def _lcsseq(x,y):
    if len(y) > len(x):
        return 0
    ## xf = x.find
    posn = 0
    for c in y:
        posn = x.find(c, posn) + 1
        if posn == 0:
            return 0
    return len(y)

def lcsseq(x,y):
    #we really only want to know if _all_ of the characters of the shorter 
    #string are in the longer string in order
    #significantly faster than either of the above at O(n+m), compared to
    #O(n*m)
    if len(y) > len(x):
        x,y = y,x
    return _lcsseq(x,y)

def _sseq_score(x,y):
    # Only call this when you know that y is a subsequence of x.
    # Will return a "score" for the quality of the subsequence match.
    # Contiguous substring matches induce 0 score.
    ml = math.log10
    posn = x.find(y[0])
    score = 0
    for c in y:
        oposn = posn
        posn = x.find(c, posn) + 1
        try:
            score += ml(posn-oposn)
        except:
            print score, posn, oposn, c, x
            raise
    return score

class filtertable(todo.vTodo, mylistmix.ListSelect):
    def OnGetItemText(self, item, col):
        context = self.context
        if USE_NEW:
            it = self.data[item]
            if col == 1:
                if context == 'short':
                    return str(it.short)
                elif context == 'long':
                    return str(it.long)
                else:
                    return str(it.defn)
            else:
                return str(it.lines)
        elif col == 1:
            if context == 'short':
                return '%s'%(self.data[item][3],)
            elif context == 'long':
                return '%s'%(self.data[item][4],)
            else:
                return '%s'%(self.data[item][0],)
        else:
            return '%s'%(self.data[item][5],)
    def OnGetItemAttr(self, item):
        if USE_NEW:
            return D.get(self.data[item].defn[:2], default)
        return D.get(self.data[item][0][:2], default)
    def SortItems(self, *args, **kwargs):
        # Override listctrl mixin
        col=self._col
        ascending = self._colSortFlag[col]
        
        if USE_NEW:
            if self.data and col:
                try:
                    col = self.data[0].__slots__.index(context)
                except:
                    pass
            elif self.data:
                col = self.data[0].__slots__.index('lines')
        else:
            if col == 0:
                col = 5
            else:
                if context == 'short':
                    col = 3
                elif context == 'long':
                    col = 4
                else:
                    col = 0
        
        _cmp = cmp
        cmpf = lambda a,b: _cmp(a[col],b[col])
        if col != 0 and (USE_NEW and col != self.data[0].__slots__.index('lines')):
            cmpf = lambda a,b: _cmp(a[col].lower(),b[col].lower())
        
        if ascending:
            self.data.sort(cmpf)
        else:
            self.data.reverse()
        
        self.Refresh()

def partition(str, sep):
    if sep not in str:
        return str, '', ''
    x = str.find(sep)
    return str[:x], sep, str[x+len(sep):]

def rstr1(str, rch):
    if rch and str.endswith(rch):
        return str[:-len(rch)]
    return str

def get_line_counts(h, lang):
    if lang not in ('python', 'cpp') and not lang.endswith('ml'):
        return {}
    #need implementation for C/C++, but only after parser for C/C++ is done
    
    counts = {}
    stk = [h[::-1]]
    nstk = []
    lastl = 0
    lastn = ''
    while stk:
        cur = stk.pop()
        if cur is None:
            _ = nstk.pop()
            continue
        
        while cur:
            name, line_no, leading, children = cur.pop()
            
            if lang == 'python':
                pre, shortname1 = name.split(None, 1)
                shortname = partition(partition(shortname1, ':')[0], '(')[0]
                key = '%s%s%s'%('.'.join(nstk), '.'[:bool(nstk)], shortname)
            
            elif lang == 'cpp':
                key, shortname = name, line_no[2]
            
            elif lang.endswith('ml'):
                key, shortname = name, line_no[2]
            
            if lastn and not name.startswith('--'):
                counts.setdefault(lastn, []).append(line_no[1]-lastl)
            
            if not name.startswith('--'):
                lastn = key
                lastl = line_no[1]
                
            if children:
                stk.append(cur)
                nstk.append(shortname)
                stk.append(None)
                cur = children[::-1]
    
    if lastn:
        try:
            counts.setdefault(lastn, []).append(
                __main__.root.control.GetCurrentPage().GetWindow1().GetLineCount()+1-lastl)
        except:
            pass

    return counts

class DefinitionList(wx.Panel):
    def __init__(self, parent, root, stc):
        wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS)
        self.root = root
        self.parent = parent
        self.stc = stc
        self.names = []
        
        sizer = wx.BoxSizer(wx.VERTICAL)
            
        self.filter = wx.TextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER|wx.WANTS_CHARS)
        sizer.Add(self.filter, 0, wx.EXPAND|wx.ALL, 3)
        
        self.cs = wx.CheckBox(self, -1, "Case Sensitive")
        self.lcs = wx.CheckBox(self, -1, "Subsequence")
        self.sco = wx.CheckBox(self, -1, "Scored")
        
        s2 = wx.BoxSizer(wx.HORIZONTAL)
        s2.Add(self.cs, 0, wx.EXPAND|wx.ALL, 3)
        s2.Add(wx.StaticText(self, -1, ""), 1, wx.EXPAND|wx.ALL, 0)
        s2.Add(self.lcs, 0, wx.EXPAND|wx.ALL, 3)
        s2.Add(wx.StaticText(self, -1, ""), 1, wx.EXPAND|wx.ALL, 0)
        s2.Add(self.sco, 0, wx.EXPAND|wx.ALL, 3)
        
        sizer.Add(s2, 0, wx.EXPAND)
        
        s2 = wx.BoxSizer(wx.HORIZONTAL)
        self.context = wx.ComboBox(self, -1, "no context", choices=["no context", "long", "short"], style=wx.CB_READONLY)
        s2.Add(self.context, 1, wx.EXPAND|wx.ALL, 3)
        
        self.how = wx.ComboBox(self, -1, "exact", choices=["exact", "any", "all"], style=wx.CB_READONLY)
        s2.Add(self.how, 1, wx.EXPAND|wx.ALL, 3)

        sizer.Add(s2, 0, wx.EXPAND)

        self.cmdlist = filtertable(self, columns)
        mylistmix.ListSelect.__init__(self.cmdlist, self.filter)
        sizer.Add(self.cmdlist, 1, wx.EXPAND|wx.ALL, 3)
        
        self.SetSizer(sizer)
        
        self.Bind(wx.EVT_TEXT, self.OnText)
        self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnEnter)
        self.Bind(wx.EVT_CHECKBOX, self.OnText)
        self.Bind(wx.EVT_COMBOBOX, self.OnText)
        self.cmdlist.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated)
        
        self.getoptions()
        self.getting = 0
    
    def getoptions(self):
        if options:
            self.getting = 1
            try:
                self.cs.SetValue(options[0])
                self.lcs.SetValue(options[1])
                self.context.SetValue(options[2])
                self.how.SetValue(options[3])
                if len(options) >= 5:
                    self.sco.SetValue(options[4])
                wx.CallAfter(self.update)
            finally:
                self.getting = 0
    
    def setoptions(self):
        if self.getting:
            return
        global options
        options = self.cs.GetValue(), self.lcs.GetValue(), self.context.GetValue(), self.how.GetValue(), self.sco.GetValue()
    
    def new_hierarchy(self, hier):
        #parse the hierarchy, set the data
        lang = self.stc.style()
        if lang not in ('python', 'tex', 'cpp') and not lang.endswith('ml'):
            return

        if USE_NEW:
            self.names = hier
            self.update()
            return

        counts = get_line_counts(hier, lang)
        names = []
        stk = [hier[::-1]]
        nstk = []
        nstk2 = []
        
        while stk:
            cur = stk.pop()
            if cur is None:
                _ = nstk.pop()
                _ = nstk2.pop()
                continue
            
            while cur:
                name, line_no, leading, children = cur.pop()
                
                if lang == 'python':
                    pre, shortname1 = name.split(None, 1)
                    shortname = partition(partition(shortname1, ':')[0], '(')[0]
                    shortname2 = partition(partition(name, ':')[0], '(')[0]
                    key = '%s%s%s'%('.'.join(nstk), '.'[:bool(nstk)], shortname)
                    
                    names.append((name, line_no, '.'.join(nstk+[shortname]),
                                  '%s %s%s%s'%(pre, '.'.join(nstk), '.'[:bool(nstk)],shortname1),
                                  ': '.join(nstk2+[name]),
                                  (counts.get(key) or [0]).pop(0)
                                  ))
                
                elif lang == 'tex':
                    shortname2 = name
                    head, _, shortname = partition(rstr1(name, '}'), '{')
                    x = '.'.join(nstk+[shortname])
                    names.append((name, line_no, x,
                                  '%s{%s}'%(head, x),
                                  ' '.join(nstk2+[name]),
                                  0
                                  ))
                
                elif lang == 'cpp':
                    shortname = line_no[2]
                    shortname2 = name
                    x = '.'.join(nstk+[shortname])
                    y = name.find(line_no[2])
                    names.append((name, line_no, x,
                                  "%s %s%s%s"%(name[:y].strip(), '.'.join(nstk), '.'[:bool(nstk)], name[y:].strip()),
                                  ' '.join(nstk2+[name]),
                                  (counts.get(name) or [0]).pop(0)))
                elif lang.endswith('ml'):
                    names.append((name, line_no, name, name, name, 1))
                
                if children:
                    stk.append(cur)
                    nstk.append(shortname)
                    nstk2.append(shortname2)
                    stk.append(None)
                    cur = children[::-1]
        self.names = names
        self.update()
    
    def OnEnter(self, e):
        cl = self.cmdlist
        cs = cl.GetFirstSelected()
        if cs == -1:
            cl.Select(0)
        self.OnItemActivated(e)
    
    def OnText(self, e):
        if not self.getting:
            self.setoptions()
            self.update()
        if e:
            e.Skip()
    
    def update(self):
        context = self.cmdlist.context = self.context.GetValue()
        if USE_NEW:
            index = 2
            if context == 'short':
                index = 9
            elif context == 'long':
                index = 10
        else:
            index = 0
            if context == 'short':
                index = 3
            elif context == 'long':
                index = 4
        
        sseq = self.lcs.GetValue()
        _lcs = lcsseq
        txt = self.filter.GetValue()
        
        lower = not self.cs.GetValue()
        if lower:
            txt = txt.lower()
        
        if not txt.strip():
            names = [i for i in self.names if i[index]]
        else:
            names = []
            how = self.how.GetValue()
            if how != 'exact':
                txt = txt.split()
            else:
                txt = (txt,)
            
            any = how in ('any', 'exact')
            all = not any
            for i in self.names:
                it = i[index]
                if lower:
                    it = it.lower()
                for j in txt:
                    if j not in it:
                        if sseq:
                            if _lcs(j, it)!=len(j):
                                if all:
                                    break
                            elif any:
                                names.append(i)
                                break
                        elif all:
                            break
                    elif any:
                        names.append(i)
                        break
                else:
                    if all:
                        names.append(i)
            
            if sseq and self.sco.GetValue():
                def key(i, xx=txt, score=_sseq_score, prematch=(how=='any'), index=index):
                    # Average score/match works pretty well here, especially
                    # when we induce a len(input) score for mismatches.
                    matches = 0
                    sc = 0
                    iil = i[index].lower()
                    for x in xx:
                        if (not prematch) or (prematch and _lcs(x, iil) == len(x)):
                            matches += 1
                            sc += score(iil, x)
                        else:
                            sc += len(iil)
                    return sc / matches
                names.sort(key=key)
        
        self.cmdlist.setData(names, copy=0)
    
    def OnItemActivated(self, event):
        win = self.stc
        cl = self.cmdlist
        cs = cl.GetFirstSelected()
        if cs == -1:
            cl.Select(0)
            cs = 0
        if USE_NEW:
            sel = self.cmdlist.data[cs].lineno
        else:
            sel = self.cmdlist.data[cs][1][1]
        if sel < win.GetLineCount():
            sel -= 1
            win.lines.selectedlinesi = sel, sel+1
            win.EnsureVisible(sel)
            win.ScrollToColumn(0)
            win.SetFocus()
    
    def Show(self):
        self.getoptions()
        wx.Panel.Show(self)

class MultiFilter(object):
    def __init__(self, root):
        self.root = root
        self.datamap = {}
    def __iter__(self):
        order = [(i.dirname, i.filename, getattr(i, 'NEWDOCUMENT', None)) for i in self.root.control]
        for finfo in order:
            for i, d in enumerate(self.datamap.get(finfo, [])):
                if not i:
                    continue
                d.fileinfo = finfo
                yield d
    def __setitem__(self, stc, value):
        self.datamap[stc.dirname, stc.filename, getattr(stc, 'NEWDOCUMENT', None)] = value
    def __delitem__(self, stc):
        self.datamap.pop((stc.dirname, stc.filename, getattr(stc, 'NEWDOCUMENT', None)), None)

class GlobalFilter(DefinitionList):
    def __init__(self, parent, root):
        self.root = root
        DefinitionList.__init__(self, parent, root, None)
        self.names = MultiFilter(root)
        wx.CallAfter(self.getoptions)
    def new_hierarchy(self, stc, value):
        self.names[stc] = value
        self.getoptions()
    def close_hierarchy(self, stc):
        del self.names[stc]
        self.getoptions()
    def OnItemActivated(self, event):
        ## win = self.stc
        cl = self.cmdlist
        cs = cl.GetFirstSelected()
        if cs == -1:
            cl.Select(0)
            cs = 0
        finfo = self.cmdlist.data[cs].fileinfo
        sel = self.cmdlist.data[cs].lineno
        for i, win in enumerate(self.root.control):
            if (win.dirname, win.filename, getattr(win, 'NEWDOCUMENT', None)) == finfo:
                 break
        else:
            return
        self.root.control.SetSelection(i)
        if sel < win.GetLineCount():
            sel -= 1
            win.lines.selectedlinesi = sel, sel+1
            win.EnsureVisible(sel)
            win.ScrollToColumn(0)
            win.SetFocus()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.