Credit Nir Aides for r77288
[python.git] / Lib / idlelib / OutputWindow.py
blobf6b379b9a6a69154c898b80c7be237a979a363da
1 from Tkinter import *
2 from EditorWindow import EditorWindow
3 import re
4 import tkMessageBox
5 import IOBinding
7 class OutputWindow(EditorWindow):
9 """An editor window that can serve as an output file.
11 Also the future base class for the Python shell window.
12 This class has no input facilities.
13 """
15 def __init__(self, *args):
16 EditorWindow.__init__(self, *args)
17 self.text.bind("<<goto-file-line>>", self.goto_file_line)
19 # Customize EditorWindow
21 def ispythonsource(self, filename):
22 # No colorization needed
23 return 0
25 def short_title(self):
26 return "Output"
28 def maybesave(self):
29 # Override base class method -- don't ask any questions
30 if self.get_saved():
31 return "yes"
32 else:
33 return "no"
35 # Act as output file
37 def write(self, s, tags=(), mark="insert"):
38 # Tk assumes that byte strings are Latin-1;
39 # we assume that they are in the locale's encoding
40 if isinstance(s, str):
41 try:
42 s = unicode(s, IOBinding.encoding)
43 except UnicodeError:
44 # some other encoding; let Tcl deal with it
45 pass
46 self.text.insert(mark, s, tags)
47 self.text.see(mark)
48 self.text.update()
50 def writelines(self, l):
51 map(self.write, l)
53 def flush(self):
54 pass
56 # Our own right-button menu
58 rmenu_specs = [
59 ("Go to file/line", "<<goto-file-line>>"),
62 file_line_pats = [
63 # order of patterns matters
64 r'file "([^"]*)", line (\d+)',
65 r'([^\s]+)\((\d+)\)',
66 r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces
67 r'([^\s]+):\s*(\d+):', # filename or path, ltrim
68 r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim
71 file_line_progs = None
73 def goto_file_line(self, event=None):
74 if self.file_line_progs is None:
75 l = []
76 for pat in self.file_line_pats:
77 l.append(re.compile(pat, re.IGNORECASE))
78 self.file_line_progs = l
79 # x, y = self.event.x, self.event.y
80 # self.text.mark_set("insert", "@%d,%d" % (x, y))
81 line = self.text.get("insert linestart", "insert lineend")
82 result = self._file_line_helper(line)
83 if not result:
84 # Try the previous line. This is handy e.g. in tracebacks,
85 # where you tend to right-click on the displayed source line
86 line = self.text.get("insert -1line linestart",
87 "insert -1line lineend")
88 result = self._file_line_helper(line)
89 if not result:
90 tkMessageBox.showerror(
91 "No special line",
92 "The line you point at doesn't look like "
93 "a valid file name followed by a line number.",
94 master=self.text)
95 return
96 filename, lineno = result
97 edit = self.flist.open(filename)
98 edit.gotoline(lineno)
100 def _file_line_helper(self, line):
101 for prog in self.file_line_progs:
102 match = prog.search(line)
103 if match:
104 filename, lineno = match.group(1, 2)
105 try:
106 f = open(filename, "r")
107 f.close()
108 break
109 except IOError:
110 continue
111 else:
112 return None
113 try:
114 return filename, int(lineno)
115 except TypeError:
116 return None
118 # These classes are currently not used but might come in handy
120 class OnDemandOutputWindow:
122 tagdefs = {
123 # XXX Should use IdlePrefs.ColorPrefs
124 "stdout": {"foreground": "blue"},
125 "stderr": {"foreground": "#007700"},
128 def __init__(self, flist):
129 self.flist = flist
130 self.owin = None
132 def write(self, s, tags, mark):
133 if not self.owin:
134 self.setup()
135 self.owin.write(s, tags, mark)
137 def setup(self):
138 self.owin = owin = OutputWindow(self.flist)
139 text = owin.text
140 for tag, cnf in self.tagdefs.items():
141 if cnf:
142 text.tag_configure(tag, **cnf)
143 text.tag_raise('sel')
144 self.write = self.owin.write