"""Grep dialog for Find in Files functionality.Inherits from SearchDialogBase for GUI and uses searchengineto prepare search pattern."""import fnmatchimport osimport sysfrom tkinter import StringVar, BooleanVarfrom tkinter.ttk import Checkbutton # Frame imported in ...Basefrom idlelib.searchbase import SearchDialogBasefrom idlelib import searchengine# Importing OutputWindow here fails due to import loop# EditorWindow -> GrepDialog -> OutputWindow -> EditorWindowdef grep(text, io=None, flist=None):"""Open the Find in Files dialog.Module-level function to access the singleton GrepDialoginstance and open the dialog. If text is selected, it isused as the search phrase; otherwise, the previous entryis used.Args:text: Text widget that contains the selected text fordefault search phrase.io: iomenu.IOBinding instance with default path to search.flist: filelist.FileList instance for OutputWindow parent."""root = text._root()engine = searchengine.get(root)if not hasattr(engine, "_grepdialog"):engine._grepdialog = GrepDialog(root, engine, flist)dialog = engine._grepdialogsearchphrase = text.get("sel.first", "sel.last")dialog.open(text, searchphrase, io)def walk_error(msg):"Handle os.walk error."print(msg)def findfiles(folder, pattern, recursive):"""Generate file names in dir that match pattern.Args:folder: Root directory to search.pattern: File pattern to match.recursive: True to include subdirectories."""for dirpath, _, filenames in os.walk(folder, onerror=walk_error):yield from (os.path.join(dirpath, name)for name in filenamesif fnmatch.fnmatch(name, pattern))if not recursive:breakclass GrepDialog(SearchDialogBase):"Dialog for searching multiple files."title = "Find in Files Dialog"icon = "Grep"needwrapbutton = 0def __init__(self, root, engine, flist):"""Create search dialog for searching for a phrase in the file system.Uses SearchDialogBase as the basis for the GUI and asearchengine instance to prepare the search.Attributes:flist: filelist.Filelist instance for OutputWindow parent.globvar: String value of Entry widget for path to search.globent: Entry widget for globvar. Created increate_entries().recvar: Boolean value of Checkbutton widget fortraversing through subdirectories."""super().__init__(root, engine)self.flist = flistself.globvar = StringVar(root)self.recvar = BooleanVar(root)def open(self, text, searchphrase, io=None):"""Make dialog visible on top of others and ready to use.Extend the SearchDialogBase open() to set the initial valuefor globvar.Args:text: Multicall object containing the text information.searchphrase: String phrase to search.io: iomenu.IOBinding instance containing file path."""SearchDialogBase.open(self, text, searchphrase)if io:path = io.filename or ""else:path = ""dir, base = os.path.split(path)head, tail = os.path.splitext(base)if not tail:tail = ".py"self.globvar.set(os.path.join(dir, "*" + tail))def create_entries(self):"Create base entry widgets and add widget for search path."SearchDialogBase.create_entries(self)self.globent = self.make_entry("In files:", self.globvar)[0]def create_other_buttons(self):"Add check button to recurse down subdirectories."btn = Checkbutton(self.make_frame()[0], variable=self.recvar,text="Recurse down subdirectories")btn.pack(side="top", fill="both")def create_command_buttons(self):"Create base command buttons and add button for Search Files."SearchDialogBase.create_command_buttons(self)self.make_button("Search Files", self.default_command, isdef=True)def default_command(self, event=None):"""Grep for search pattern in file path. The default command is boundto <Return>.If entry values are populated, set OutputWindow as stdoutand perform search. The search dialog is closed automaticallywhen the search begins."""prog = self.engine.getprog()if not prog:returnpath = self.globvar.get()if not path:self.top.bell()returnfrom idlelib.outwin import OutputWindow # leave here!save = sys.stdouttry:sys.stdout = OutputWindow(self.flist)self.grep_it(prog, path)finally:sys.stdout = savedef grep_it(self, prog, path):"""Search for prog within the lines of the files in path.For the each file in the path directory, open the file andsearch each line for the matching pattern. If the pattern isfound, write the file and line information to stdout (whichis an OutputWindow).Args:prog: The compiled, cooked search pattern.path: String containing the search path."""folder, filepat = os.path.split(path)if not folder:folder = os.curdirfilelist = sorted(findfiles(folder, filepat, self.recvar.get()))self.close()pat = self.engine.getpat()print(f"Searching {pat!r} in {path} ...")hits = 0try:for fn in filelist:try:with open(fn, errors='replace') as f:for lineno, line in enumerate(f, 1):if line[-1:] == '\n':line = line[:-1]if prog.search(line):sys.stdout.write(f"{fn}: {lineno}: {line}\n")hits += 1except OSError as msg:print(msg)print(f"Hits found: {hits}\n(Hint: right-click to open locations.)"if hits else "No hits.")except AttributeError:# Tk window has been closed, OutputWindow.text = None,# so in OW.write, OW.text.insert fails.passdef _grep_dialog(parent): # htest #from tkinter import Toplevel, Text, SEL, ENDfrom tkinter.ttk import Frame, Buttonfrom idlelib.pyshell import PyShellFileListtop = Toplevel(parent)top.title("Test GrepDialog")x, y = map(int, parent.geometry().split('+')[1:])top.geometry(f"+{x}+{y + 175}")flist = PyShellFileList(top)frame = Frame(top)frame.pack()text = Text(frame, height=5)text.pack()def show_grep_dialog():text.tag_add(SEL, "1.0", END)grep(text, flist=flist)text.tag_remove(SEL, "1.0", END)button = Button(frame, text="Show GrepDialog", command=show_grep_dialog)button.pack()if __name__ == "__main__":from unittest import mainmain('idlelib.idle_test.test_grep', verbosity=2, exit=False)from idlelib.idle_test.htest import runrun(_grep_dialog)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。