|
1 from Tkinter import * |
|
2 from EditorWindow import EditorWindow |
|
3 import re |
|
4 import tkMessageBox |
|
5 import IOBinding |
|
6 |
|
7 class OutputWindow(EditorWindow): |
|
8 |
|
9 """An editor window that can serve as an output file. |
|
10 |
|
11 Also the future base class for the Python shell window. |
|
12 This class has no input facilities. |
|
13 """ |
|
14 |
|
15 def __init__(self, *args): |
|
16 EditorWindow.__init__(self, *args) |
|
17 self.text.bind("<<goto-file-line>>", self.goto_file_line) |
|
18 |
|
19 # Customize EditorWindow |
|
20 |
|
21 def ispythonsource(self, filename): |
|
22 # No colorization needed |
|
23 return 0 |
|
24 |
|
25 def short_title(self): |
|
26 return "Output" |
|
27 |
|
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" |
|
34 |
|
35 # Act as output file |
|
36 |
|
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() |
|
49 |
|
50 def writelines(self, l): |
|
51 map(self.write, l) |
|
52 |
|
53 def flush(self): |
|
54 pass |
|
55 |
|
56 # Our own right-button menu |
|
57 |
|
58 rmenu_specs = [ |
|
59 ("Go to file/line", "<<goto-file-line>>"), |
|
60 ] |
|
61 |
|
62 file_line_pats = [ |
|
63 r'file "([^"]*)", line (\d+)', |
|
64 r'([^\s]+)\((\d+)\)', |
|
65 r'([^\s]+):\s*(\d+):', |
|
66 ] |
|
67 |
|
68 file_line_progs = None |
|
69 |
|
70 def goto_file_line(self, event=None): |
|
71 if self.file_line_progs is None: |
|
72 l = [] |
|
73 for pat in self.file_line_pats: |
|
74 l.append(re.compile(pat, re.IGNORECASE)) |
|
75 self.file_line_progs = l |
|
76 # x, y = self.event.x, self.event.y |
|
77 # self.text.mark_set("insert", "@%d,%d" % (x, y)) |
|
78 line = self.text.get("insert linestart", "insert lineend") |
|
79 result = self._file_line_helper(line) |
|
80 if not result: |
|
81 # Try the previous line. This is handy e.g. in tracebacks, |
|
82 # where you tend to right-click on the displayed source line |
|
83 line = self.text.get("insert -1line linestart", |
|
84 "insert -1line lineend") |
|
85 result = self._file_line_helper(line) |
|
86 if not result: |
|
87 tkMessageBox.showerror( |
|
88 "No special line", |
|
89 "The line you point at doesn't look like " |
|
90 "a valid file name followed by a line number.", |
|
91 master=self.text) |
|
92 return |
|
93 filename, lineno = result |
|
94 edit = self.flist.open(filename) |
|
95 edit.gotoline(lineno) |
|
96 |
|
97 def _file_line_helper(self, line): |
|
98 for prog in self.file_line_progs: |
|
99 m = prog.search(line) |
|
100 if m: |
|
101 break |
|
102 else: |
|
103 return None |
|
104 filename, lineno = m.group(1, 2) |
|
105 try: |
|
106 f = open(filename, "r") |
|
107 f.close() |
|
108 except IOError: |
|
109 return None |
|
110 try: |
|
111 return filename, int(lineno) |
|
112 except TypeError: |
|
113 return None |
|
114 |
|
115 # These classes are currently not used but might come in handy |
|
116 |
|
117 class OnDemandOutputWindow: |
|
118 |
|
119 tagdefs = { |
|
120 # XXX Should use IdlePrefs.ColorPrefs |
|
121 "stdout": {"foreground": "blue"}, |
|
122 "stderr": {"foreground": "#007700"}, |
|
123 } |
|
124 |
|
125 def __init__(self, flist): |
|
126 self.flist = flist |
|
127 self.owin = None |
|
128 |
|
129 def write(self, s, tags, mark): |
|
130 if not self.owin: |
|
131 self.setup() |
|
132 self.owin.write(s, tags, mark) |
|
133 |
|
134 def setup(self): |
|
135 self.owin = owin = OutputWindow(self.flist) |
|
136 text = owin.text |
|
137 for tag, cnf in self.tagdefs.items(): |
|
138 if cnf: |
|
139 text.tag_configure(tag, **cnf) |
|
140 text.tag_raise('sel') |
|
141 self.write = self.owin.write |
|
142 |
|
143 #class PseudoFile: |
|
144 # |
|
145 # def __init__(self, owin, tags, mark="end"): |
|
146 # self.owin = owin |
|
147 # self.tags = tags |
|
148 # self.mark = mark |
|
149 |
|
150 # def write(self, s): |
|
151 # self.owin.write(s, self.tags, self.mark) |
|
152 |
|
153 # def writelines(self, l): |
|
154 # map(self.write, l) |
|
155 |
|
156 # def flush(self): |
|
157 # pass |