import re
from tkinter import messagebox
from idlelib.editor import EditorWindow
file_line_pats = [
r'file "([^"]*)", line (\d+)',
r'([^\s]+)\((\d+)\)',
r'^(\s*\S.*?):\s*(\d+):', r'([^\s]+):\s*(\d+):', r'^\s*(\S.*?):\s*(\d+):', ]
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):
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)
f.close()
break
except OSError:
continue
else:
return None
try:
return filename, int(lineno)
except TypeError:
return None
class OutputWindow(EditorWindow):
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)
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'
def write(self, s, tags=(), mark="insert"):
assert isinstance(s, str)
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):
line = self.text.get("insert linestart", "insert lineend")
result = file_line_helper(line)
if not result:
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)
class OnDemandOutputWindow:
tagdefs = {
"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)