Mercurial > repos > rliterman > csp2
diff CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/outwin.py @ 68:5028fdace37b
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 16:23:26 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/outwin.py Tue Mar 18 16:23:26 2025 -0400 @@ -0,0 +1,189 @@ +"""Editor window that can serve as an output file. +""" + +import re + +from tkinter import messagebox + +from idlelib.editor import EditorWindow +from idlelib import iomenu + + +file_line_pats = [ + # order of patterns matters + r'file "([^"]*)", line (\d+)', + r'([^\s]+)\((\d+)\)', + r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces + r'([^\s]+):\s*(\d+):', # filename or path, ltrim + r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim +] + +file_line_progs = None + + +def compile_progs(): + "Compile the patterns for matching to file name and line number." + global file_line_progs + file_line_progs = [re.compile(pat, re.IGNORECASE) + for pat in file_line_pats] + + +def file_line_helper(line): + """Extract file name and line number from line of text. + + Check if line of text contains one of the file/line patterns. + If it does and if the file and line are valid, return + a tuple of the file name and line number. If it doesn't match + or if the file or line is invalid, return None. + """ + if not file_line_progs: + compile_progs() + for prog in file_line_progs: + match = prog.search(line) + if match: + filename, lineno = match.group(1, 2) + try: + f = open(filename, "r") + f.close() + break + except OSError: + continue + else: + return None + try: + return filename, int(lineno) + except TypeError: + return None + + +class OutputWindow(EditorWindow): + """An editor window that can serve as an output file. + + Also the future base class for the Python shell window. + This class has no input facilities. + + Adds binding to open a file at a line to the text widget. + """ + + # Our own right-button menu + rmenu_specs = [ + ("Cut", "<<cut>>", "rmenu_check_cut"), + ("Copy", "<<copy>>", "rmenu_check_copy"), + ("Paste", "<<paste>>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<<goto-file-line>>", None), + ] + + allow_code_context = False + + def __init__(self, *args): + EditorWindow.__init__(self, *args) + self.text.bind("<<goto-file-line>>", self.goto_file_line) + + # Customize EditorWindow + def ispythonsource(self, filename): + "Python source is only part of output: do not colorize." + return False + + def short_title(self): + "Customize EditorWindow title." + return "Output" + + def maybesave(self): + "Customize EditorWindow to not display save file messagebox." + return 'yes' if self.get_saved() else 'no' + + # Act as output file + def write(self, s, tags=(), mark="insert"): + """Write text to text widget. + + The text is inserted at the given index with the provided + tags. The text widget is then scrolled to make it visible + and updated to display it, giving the effect of seeing each + line as it is added. + + Args: + s: Text to insert into text widget. + tags: Tuple of tag strings to apply on the insert. + mark: Index for the insert. + + Return: + Length of text inserted. + """ + if isinstance(s, bytes): + s = s.decode(iomenu.encoding, "replace") + self.text.insert(mark, s, tags) + self.text.see(mark) + self.text.update() + return len(s) + + def writelines(self, lines): + "Write each item in lines iterable." + for line in lines: + self.write(line) + + def flush(self): + "No flushing needed as write() directly writes to widget." + pass + + def showerror(self, *args, **kwargs): + messagebox.showerror(*args, **kwargs) + + def goto_file_line(self, event=None): + """Handle request to open file/line. + + If the selected or previous line in the output window + contains a file name and line number, then open that file + name in a new window and position on the line number. + + Otherwise, display an error messagebox. + """ + line = self.text.get("insert linestart", "insert lineend") + result = file_line_helper(line) + if not result: + # Try the previous line. This is handy e.g. in tracebacks, + # where you tend to right-click on the displayed source line + line = self.text.get("insert -1line linestart", + "insert -1line lineend") + result = file_line_helper(line) + if not result: + self.showerror( + "No special line", + "The line you point at doesn't look like " + "a valid file name followed by a line number.", + parent=self.text) + return + filename, lineno = result + self.flist.gotofileline(filename, lineno) + + +# These classes are currently not used but might come in handy +class OnDemandOutputWindow: + + tagdefs = { + # XXX Should use IdlePrefs.ColorPrefs + "stdout": {"foreground": "blue"}, + "stderr": {"foreground": "#007700"}, + } + + def __init__(self, flist): + self.flist = flist + self.owin = None + + def write(self, s, tags, mark): + if not self.owin: + self.setup() + self.owin.write(s, tags, mark) + + def setup(self): + self.owin = owin = OutputWindow(self.flist) + text = owin.text + for tag, cnf in self.tagdefs.items(): + if cnf: + text.tag_configure(tag, **cnf) + text.tag_raise('sel') + self.write = self.owin.write + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_outwin', verbosity=2, exit=False)