Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
sgrepmdi.py759 linesDownload Raw Back to framework
1# SGrepMDI is by Gordon McMillan (gmcm@hypernet.com)2# It does basically what Find In Files does in MSVC with a couple enhancements.3# - It saves any directories in the app's ini file (if you want to get rid4# 	of them you'll have to edit the file)5# - "Directories" can be directories,6#  -	semicolon separated lists of "directories",7#  -	environment variables that evaluate to "directories",8#  -	registry path names that evaluate to "directories",9#  -	all of which is recursive, so you can mix them all up.10# - It is MDI, so you can 'nest' greps and return to earlier ones,11# 	(ie, have multiple results open at the same time)12# - Like FIF, double clicking a line opens an editor and takes you to the line.13# - You can highlight text, right click and start a new grep with the selected14# 	text as search pattern and same directories etc as before.15# - You can save grep parameters (so you don't lose your hardearned pattern)16# 	from File|Save17# - You can save grep results by right clicking in the result window.18# Hats off to Mark Hammond for providing an environment where I could cobble19# something like this together in a couple evenings!20 21import glob22import os23import re24 25import win32api26import win32con27import win32ui28from pywin.mfc import dialog, docview, window29 30from . import scriptutils31 32 33def getsubdirs(d):34    dlist = []35    flist = glob.glob(d + "\\*")36    for f in flist:37        if os.path.isdir(f):38            dlist.append(f)39            dlist = dlist + getsubdirs(f)40    return dlist41 42 43class dirpath:44    def __init__(self, str, recurse=0):45        dp = str.split(";")46        dirs = {}47        for d in dp:48            if os.path.isdir(d):49                d = d.lower()50                if d not in dirs:51                    dirs[d] = None52                    if recurse:53                        subdirs = getsubdirs(d)54                        for sd in subdirs:55                            sd = sd.lower()56                            if sd not in dirs:57                                dirs[sd] = None58            elif os.path.isfile(d):59                pass60            else:61                x = None62                if d in os.environ:63                    x = dirpath(os.environ[d])64                elif d[:5] == "HKEY_":65                    keystr = d.split("\\")66                    try:67                        root = eval("win32con." + keystr[0])68                    except:69                        win32ui.MessageBox(70                            "Can't interpret registry key name '%s'" % keystr[0]71                        )72                    try:73                        subkey = "\\".join(keystr[1:])74                        val = win32api.RegQueryValue(root, subkey)75                        if val:76                            x = dirpath(val)77                        else:78                            win32ui.MessageBox(79                                "Registry path '%s' did not return a path entry" % d80                            )81                    except:82                        win32ui.MessageBox(83                            "Can't interpret registry key value: %s" % keystr[1:]84                        )85                else:86                    win32ui.MessageBox("Directory '%s' not found" % d)87                if x:88                    for xd in x:89                        if xd not in dirs:90                            dirs[xd] = None91                            if recurse:92                                subdirs = getsubdirs(xd)93                                for sd in subdirs:94                                    sd = sd.lower()95                                    if sd not in dirs:96                                        dirs[sd] = None97        self.dirs = []98        for d in list(dirs.keys()):99            self.dirs.append(d)100 101    def __getitem__(self, key):102        return self.dirs[key]103 104    def __len__(self):105        return len(self.dirs)106 107    def __setitem__(self, key, value):108        self.dirs[key] = value109 110    def __delitem__(self, key):111        del self.dirs[key]112 113    def __getslice__(self, lo, hi):114        return self.dirs[lo:hi]115 116    def __setslice__(self, lo, hi, seq):117        self.dirs[lo:hi] = seq118 119    def __delslice__(self, lo, hi):120        del self.dirs[lo:hi]121 122    def __add__(self, other):123        if type(other) == type(self) or type(other) == type([]):124            return self.dirs + other.dirs125 126    def __radd__(self, other):127        if type(other) == type(self) or type(other) == type([]):128            return other.dirs + self.dirs129 130 131# Group(1) is the filename, group(2) is the lineno.132# regexGrepResult=regex.compile("^\\([a-zA-Z]:.*\\)(\\([0-9]+\\))")133 134regexGrep = re.compile(r"^([a-zA-Z]:[^(]*)\(([0-9]+)\)")135 136# these are the atom numbers defined by Windows for basic dialog controls137 138BUTTON = 0x80139EDIT = 0x81140STATIC = 0x82141LISTBOX = 0x83142SCROLLBAR = 0x84143COMBOBOX = 0x85144 145 146class GrepTemplate(docview.RichEditDocTemplate):147    def __init__(self):148        docview.RichEditDocTemplate.__init__(149            self, win32ui.IDR_TEXTTYPE, GrepDocument, GrepFrame, GrepView150        )151        self.SetDocStrings("\nGrep\nGrep\nGrep params (*.grep)\n.grep\n\n\n")152        win32ui.GetApp().AddDocTemplate(self)153        self.docparams = None154 155    def MatchDocType(self, fileName, fileType):156        doc = self.FindOpenDocument(fileName)157        if doc:158            return doc159        ext = os.path.splitext(fileName)[1].lower()160        if ext == ".grep":161            return win32ui.CDocTemplate_Confidence_yesAttemptNative162        return win32ui.CDocTemplate_Confidence_noAttempt163 164    def setParams(self, params):165        self.docparams = params166 167    def readParams(self):168        tmp = self.docparams169        self.docparams = None170        return tmp171 172 173class GrepFrame(window.MDIChildWnd):174    # The template and doc params will one day be removed.175    def __init__(self, wnd=None):176        window.MDIChildWnd.__init__(self, wnd)177 178 179class GrepDocument(docview.RichEditDoc):180    def __init__(self, template):181        docview.RichEditDoc.__init__(self, template)182        self.dirpattern = ""183        self.filpattern = ""184        self.greppattern = ""185        self.casesensitive = 1186        self.recurse = 1187        self.verbose = 0188 189    def OnOpenDocument(self, fnm):190        # this bizarre stuff with params is so right clicking in a result window191        # and starting a new grep can communicate the default parameters to the192        # new grep.193        try:194            params = open(fnm, "r").read()195        except:196            params = None197        self.setInitParams(params)198        return self.OnNewDocument()199 200    def OnCloseDocument(self):201        try:202            win32ui.GetApp().DeleteIdleHandler(self.SearchFile)203        except:204            pass205        return self._obj_.OnCloseDocument()206 207    def saveInitParams(self):208        # Only save the flags, not the text boxes.209        paramstr = "\t%s\t\t%d\t%d" % (210            self.filpattern,211            self.casesensitive,212            self.recurse,213        )214        win32ui.WriteProfileVal("Grep", "Params", paramstr)215 216    def setInitParams(self, paramstr):217        if paramstr is None:218            paramstr = win32ui.GetProfileVal("Grep", "Params", "\t\t\t1\t0\t0")219        params = paramstr.split("\t")220        if len(params) < 3:221            params = params + [""] * (3 - len(params))222        if len(params) < 6:223            params = params + [0] * (6 - len(params))224        self.dirpattern = params[0]225        self.filpattern = params[1]226        self.greppattern = params[2]227        self.casesensitive = int(params[3])228        self.recurse = int(params[4])229        self.verbose = int(params[5])230        # setup some reasonable defaults.231        if not self.dirpattern:232            try:233                editor = win32ui.GetMainFrame().MDIGetActive()[0].GetEditorView()234                self.dirpattern = os.path.abspath(235                    os.path.dirname(editor.GetDocument().GetPathName())236                )237            except (AttributeError, win32ui.error):238                self.dirpattern = os.getcwd()239        if not self.filpattern:240            self.filpattern = "*.py"241 242    def OnNewDocument(self):243        if self.dirpattern == "":244            self.setInitParams(greptemplate.readParams())245        d = GrepDialog(246            self.dirpattern,247            self.filpattern,248            self.greppattern,249            self.casesensitive,250            self.recurse,251            self.verbose,252        )253        if d.DoModal() == win32con.IDOK:254            self.dirpattern = d["dirpattern"]255            self.filpattern = d["filpattern"]256            self.greppattern = d["greppattern"]257            self.casesensitive = d["casesensitive"]258            self.recurse = d["recursive"]259            self.verbose = d["verbose"]260            self.doSearch()261            self.saveInitParams()262            return 1263        return 0  # cancelled - return zero to stop frame creation.264 265    def doSearch(self):266        self.dp = dirpath(self.dirpattern, self.recurse)267        self.SetTitle("Grep for %s in %s" % (self.greppattern, self.filpattern))268        # self.text = []269        self.GetFirstView().Append("#Search " + self.dirpattern + "\n")270        if self.verbose:271            self.GetFirstView().Append("#   =" + repr(self.dp.dirs) + "\n")272        self.GetFirstView().Append("# Files " + self.filpattern + "\n")273        self.GetFirstView().Append("#   For " + self.greppattern + "\n")274        self.fplist = self.filpattern.split(";")275        if self.casesensitive:276            self.pat = re.compile(self.greppattern)277        else:278            self.pat = re.compile(self.greppattern, re.IGNORECASE)279        win32ui.SetStatusText("Searching.  Please wait...", 0)280        self.dpndx = self.fpndx = 0281        self.fndx = -1282        if not self.dp:283            self.GetFirstView().Append(284                "# ERROR: '%s' does not resolve to any search locations"285                % self.dirpattern286            )287            self.SetModifiedFlag(0)288        else:289            self.flist = glob.glob(self.dp[0] + "\\" + self.fplist[0])290            win32ui.GetApp().AddIdleHandler(self.SearchFile)291 292    def SearchFile(self, handler, count):293        self.fndx = self.fndx + 1294        if self.fndx < len(self.flist):295            f = self.flist[self.fndx]296            if self.verbose:297                self.GetFirstView().Append("# .." + f + "\n")298            # Directories may match the file type pattern, and files may be removed299            #  while grep is running300            if os.path.isfile(f):301                win32ui.SetStatusText("Searching " + f, 0)302                lines = open(f, "r").readlines()303                for i in range(len(lines)):304                    line = lines[i]305                    if self.pat.search(line) != None:306                        self.GetFirstView().Append(f + "(" + repr(i + 1) + ") " + line)307        else:308            self.fndx = -1309            self.fpndx = self.fpndx + 1310            if self.fpndx < len(self.fplist):311                self.flist = glob.glob(312                    self.dp[self.dpndx] + "\\" + self.fplist[self.fpndx]313                )314            else:315                self.fpndx = 0316                self.dpndx = self.dpndx + 1317                if self.dpndx < len(self.dp):318                    self.flist = glob.glob(319                        self.dp[self.dpndx] + "\\" + self.fplist[self.fpndx]320                    )321                else:322                    win32ui.SetStatusText("Search complete.", 0)323                    self.SetModifiedFlag(0)  # default to not modified.324                    try:325                        win32ui.GetApp().DeleteIdleHandler(self.SearchFile)326                    except:327                        pass328                    return 0329        return 1330 331    def GetParams(self):332        return (333            self.dirpattern334            + "\t"335            + self.filpattern336            + "\t"337            + self.greppattern338            + "\t"339            + repr(self.casesensitive)340            + "\t"341            + repr(self.recurse)342            + "\t"343            + repr(self.verbose)344        )345 346    def OnSaveDocument(self, filename):347        # 		print 'OnSaveDocument() filename=',filename348        savefile = open(filename, "wb")349        txt = self.GetParams() + "\n"350        # 		print 'writing',txt351        savefile.write(txt)352        savefile.close()353        self.SetModifiedFlag(0)354        return 1355 356 357ID_OPEN_FILE = 0xE400358ID_GREP = 0xE401359ID_SAVERESULTS = 0x402360ID_TRYAGAIN = 0x403361 362 363class GrepView(docview.RichEditView):364    def __init__(self, doc):365        docview.RichEditView.__init__(self, doc)366        self.SetWordWrap(win32ui.CRichEditView_WrapNone)367        self.HookHandlers()368 369    def OnInitialUpdate(self):370        rc = self._obj_.OnInitialUpdate()371        format = (-402653169, 0, 200, 0, 0, 0, 49, "Courier New")372        self.SetDefaultCharFormat(format)373        return rc374 375    def HookHandlers(self):376        self.HookMessage(self.OnRClick, win32con.WM_RBUTTONDOWN)377        self.HookCommand(self.OnCmdOpenFile, ID_OPEN_FILE)378        self.HookCommand(self.OnCmdGrep, ID_GREP)379        self.HookCommand(self.OnCmdSave, ID_SAVERESULTS)380        self.HookCommand(self.OnTryAgain, ID_TRYAGAIN)381        self.HookMessage(self.OnLDblClick, win32con.WM_LBUTTONDBLCLK)382 383    def OnLDblClick(self, params):384        line = self.GetLine()385        regexGrepResult = regexGrep.match(line)386        if regexGrepResult:387            fname = regexGrepResult.group(1)388            line = int(regexGrepResult.group(2))389            scriptutils.JumpToDocument(fname, line)390            return 0  # dont pass on391        return 1  # pass it on by default.392 393    def OnRClick(self, params):394        menu = win32ui.CreatePopupMenu()395        flags = win32con.MF_STRING | win32con.MF_ENABLED396        lineno = self._obj_.LineFromChar(-1)  # selection or current line397        line = self._obj_.GetLine(lineno)398        regexGrepResult = regexGrep.match(line)399        if regexGrepResult:400            self.fnm = regexGrepResult.group(1)401            self.lnnum = int(regexGrepResult.group(2))402            menu.AppendMenu(flags, ID_OPEN_FILE, "&Open " + self.fnm)403            menu.AppendMenu(win32con.MF_SEPARATOR)404        menu.AppendMenu(flags, ID_TRYAGAIN, "&Try Again")405        charstart, charend = self._obj_.GetSel()406        if charstart != charend:407            linestart = self._obj_.LineIndex(lineno)408            self.sel = line[charstart - linestart : charend - linestart]409            menu.AppendMenu(flags, ID_GREP, "&Grep for " + self.sel)410            menu.AppendMenu(win32con.MF_SEPARATOR)411        menu.AppendMenu(flags, win32ui.ID_EDIT_CUT, "Cu&t")412        menu.AppendMenu(flags, win32ui.ID_EDIT_COPY, "&Copy")413        menu.AppendMenu(flags, win32ui.ID_EDIT_PASTE, "&Paste")414        menu.AppendMenu(flags, win32con.MF_SEPARATOR)415        menu.AppendMenu(flags, win32ui.ID_EDIT_SELECT_ALL, "&Select all")416        menu.AppendMenu(flags, win32con.MF_SEPARATOR)417        menu.AppendMenu(flags, ID_SAVERESULTS, "Sa&ve results")418        menu.TrackPopupMenu(params[5])419        return 0420 421    def OnCmdOpenFile(self, cmd, code):422        doc = win32ui.GetApp().OpenDocumentFile(self.fnm)423        if doc:424            vw = doc.GetFirstView()425            # hope you have an editor that implements GotoLine()!426            try:427                vw.GotoLine(int(self.lnnum))428            except:429                pass430        return 0431 432    def OnCmdGrep(self, cmd, code):433        if code != 0:434            return 1435        curparamsstr = self.GetDocument().GetParams()436        params = curparamsstr.split("\t")437        params[2] = self.sel438        greptemplate.setParams("\t".join(params))439        greptemplate.OpenDocumentFile()440        return 0441 442    def OnTryAgain(self, cmd, code):443        if code != 0:444            return 1445        greptemplate.setParams(self.GetDocument().GetParams())446        greptemplate.OpenDocumentFile()447        return 0448 449    def OnCmdSave(self, cmd, code):450        if code != 0:451            return 1452        flags = win32con.OFN_OVERWRITEPROMPT453        dlg = win32ui.CreateFileDialog(454            0, None, None, flags, "Text Files (*.txt)|*.txt||", self455        )456        dlg.SetOFNTitle("Save Results As")457        if dlg.DoModal() == win32con.IDOK:458            pn = dlg.GetPathName()459            self._obj_.SaveTextFile(pn)460        return 0461 462    def Append(self, strng):463        numlines = self.GetLineCount()464        endpos = self.LineIndex(numlines - 1) + len(self.GetLine(numlines - 1))465        self.SetSel(endpos, endpos)466        self.ReplaceSel(strng)467 468 469class GrepDialog(dialog.Dialog):470    def __init__(self, dp, fp, gp, cs, r, v):471        style = (472            win32con.DS_MODALFRAME473            | win32con.WS_POPUP474            | win32con.WS_VISIBLE475            | win32con.WS_CAPTION476            | win32con.WS_SYSMENU477            | win32con.DS_SETFONT478        )479        CS = win32con.WS_CHILD | win32con.WS_VISIBLE480        tmp = [481            ["Grep", (0, 0, 210, 90), style, None, (8, "MS Sans Serif")],482        ]483        tmp.append([STATIC, "Grep For:", -1, (7, 7, 50, 9), CS])484        tmp.append(485            [486                EDIT,487                gp,488                101,489                (52, 7, 144, 11),490                CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER,491            ]492        )493        tmp.append([STATIC, "Directories:", -1, (7, 20, 50, 9), CS])494        tmp.append(495            [496                EDIT,497                dp,498                102,499                (52, 20, 128, 11),500                CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER,501            ]502        )503        tmp.append(504            [505                BUTTON,506                "...",507                110,508                (182, 20, 16, 11),509                CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP,510            ]511        )512        tmp.append([STATIC, "File types:", -1, (7, 33, 50, 9), CS])513        tmp.append(514            [515                EDIT,516                fp,517                103,518                (52, 33, 128, 11),519                CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER,520            ]521        )522        tmp.append(523            [524                BUTTON,525                "...",526                111,527                (182, 33, 16, 11),528                CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP,529            ]530        )531        tmp.append(532            [533                BUTTON,534                "Case sensitive",535                104,536                (7, 45, 72, 9),537                CS538                | win32con.BS_AUTOCHECKBOX539                | win32con.BS_LEFTTEXT540                | win32con.WS_TABSTOP,541            ]542        )543        tmp.append(544            [545                BUTTON,546                "Subdirectories",547                105,548                (7, 56, 72, 9),549                CS550                | win32con.BS_AUTOCHECKBOX551                | win32con.BS_LEFTTEXT552                | win32con.WS_TABSTOP,553            ]554        )555        tmp.append(556            [557                BUTTON,558                "Verbose",559                106,560                (7, 67, 72, 9),561                CS562                | win32con.BS_AUTOCHECKBOX563                | win32con.BS_LEFTTEXT564                | win32con.WS_TABSTOP,565            ]566        )567        tmp.append(568            [569                BUTTON,570                "OK",571                win32con.IDOK,572                (166, 53, 32, 12),573                CS | win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP,574            ]575        )576        tmp.append(577            [578                BUTTON,579                "Cancel",580                win32con.IDCANCEL,581                (166, 67, 32, 12),582                CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP,583            ]584        )585        dialog.Dialog.__init__(self, tmp)586        self.AddDDX(101, "greppattern")587        self.AddDDX(102, "dirpattern")588        self.AddDDX(103, "filpattern")589        self.AddDDX(104, "casesensitive")590        self.AddDDX(105, "recursive")591        self.AddDDX(106, "verbose")592        self._obj_.data["greppattern"] = gp593        self._obj_.data["dirpattern"] = dp594        self._obj_.data["filpattern"] = fp595        self._obj_.data["casesensitive"] = cs596        self._obj_.data["recursive"] = r597        self._obj_.data["verbose"] = v598        self.HookCommand(self.OnMoreDirectories, 110)599        self.HookCommand(self.OnMoreFiles, 111)600 601    def OnMoreDirectories(self, cmd, code):602        if code != 0:603            return 1604        self.getMore("Grep\\Directories", "dirpattern")605 606    def OnMoreFiles(self, cmd, code):607        if code != 0:608            return 1609        self.getMore("Grep\\File Types", "filpattern")610 611    def getMore(self, section, key):612        self.UpdateData(1)613        # get the items out of the ini file614        ini = win32ui.GetProfileFileName()615        secitems = win32api.GetProfileSection(section, ini)616        items = []617        for secitem in secitems:618            items.append(secitem.split("=")[1])619        dlg = GrepParamsDialog(items)620        if dlg.DoModal() == win32con.IDOK:621            itemstr = ";".join(dlg.getItems())622            self._obj_.data[key] = itemstr623            # update the ini file with dlg.getNew()624            i = 0625            newitems = dlg.getNew()626            if newitems:627                items = items + newitems628                for item in items:629                    win32api.WriteProfileVal(section, repr(i), item, ini)630                    i = i + 1631            self.UpdateData(0)632 633    def OnOK(self):634        self.UpdateData(1)635        for id, name in (636            (101, "greppattern"),637            (102, "dirpattern"),638            (103, "filpattern"),639        ):640            if not self[name]:641                self.GetDlgItem(id).SetFocus()642                win32api.MessageBeep()643                win32ui.SetStatusText("Please enter a value")644                return645        self._obj_.OnOK()646 647 648class GrepParamsDialog(dialog.Dialog):649    def __init__(self, items):650        self.items = items651        self.newitems = []652        style = (653            win32con.DS_MODALFRAME654            | win32con.WS_POPUP655            | win32con.WS_VISIBLE656            | win32con.WS_CAPTION657            | win32con.WS_SYSMENU658            | win32con.DS_SETFONT659        )660        CS = win32con.WS_CHILD | win32con.WS_VISIBLE661        tmp = [662            ["Grep Parameters", (0, 0, 205, 100), style, None, (8, "MS Sans Serif")],663        ]664        tmp.append(665            [666                LISTBOX,667                "",668                107,669                (7, 7, 150, 72),670                CS671                | win32con.LBS_MULTIPLESEL672                | win32con.LBS_STANDARD673                | win32con.LBS_HASSTRINGS674                | win32con.WS_TABSTOP675                | win32con.LBS_NOTIFY,676            ]677        )678        tmp.append(679            [680                BUTTON,681                "OK",682                win32con.IDOK,683                (167, 7, 32, 12),684                CS | win32con.BS_DEFPUSHBUTTON | win32con.WS_TABSTOP,685            ]686        )687        tmp.append(688            [689                BUTTON,690                "Cancel",691                win32con.IDCANCEL,692                (167, 23, 32, 12),693                CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP,694            ]695        )696        tmp.append([STATIC, "New:", -1, (2, 83, 15, 12), CS])697        tmp.append(698            [699                EDIT,700                "",701                108,702                (18, 83, 139, 12),703                CS | win32con.WS_TABSTOP | win32con.ES_AUTOHSCROLL | win32con.WS_BORDER,704            ]705        )706        tmp.append(707            [708                BUTTON,709                "Add",710                109,711                (167, 83, 32, 12),712                CS | win32con.BS_PUSHBUTTON | win32con.WS_TABSTOP,713            ]714        )715        dialog.Dialog.__init__(self, tmp)716        self.HookCommand(self.OnAddItem, 109)717        self.HookCommand(self.OnListDoubleClick, 107)718 719    def OnInitDialog(self):720        lb = self.GetDlgItem(107)721        for item in self.items:722            lb.AddString(item)723        return self._obj_.OnInitDialog()724 725    def OnAddItem(self, cmd, code):726        if code != 0:727            return 1728        eb = self.GetDlgItem(108)729        item = eb.GetLine(0)730        self.newitems.append(item)731        lb = self.GetDlgItem(107)732        i = lb.AddString(item)733        lb.SetSel(i, 1)734        return 1735 736    def OnListDoubleClick(self, cmd, code):737        if code == win32con.LBN_DBLCLK:738            self.OnOK()739            return 1740 741    def OnOK(self):742        lb = self.GetDlgItem(107)743        self.selections = lb.GetSelTextItems()744        self._obj_.OnOK()745 746    def getItems(self):747        return self.selections748 749    def getNew(self):750        return self.newitems751 752 753try:754    win32ui.GetApp().RemoveDocTemplate(greptemplate)755except NameError:756    pass757 758greptemplate = GrepTemplate()759 
codekingpro/portable-devtools · Team Ai