blob: cba9013997660dc161521816ba01bbe5dceb9e46 [file] [log] [blame]
Georg Brandl14fc4272008-05-17 18:39:55 +00001from tkinter import *
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00002from idlelib.EditorWindow import EditorWindow
David Scherer7aced172000-08-15 01:13:23 +00003import re
Georg Brandl14fc4272008-05-17 18:39:55 +00004import tkinter.messagebox as tkMessageBox
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00005from idlelib import IOBinding
David Scherer7aced172000-08-15 01:13:23 +00006
David Scherer7aced172000-08-15 01:13:23 +00007class OutputWindow(EditorWindow):
Kurt B. Kaiser969de452002-06-12 03:28:57 +00008
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.
David Scherer7aced172000-08-15 01:13:23 +000013 """
14
Kurt B. Kaiser969de452002-06-12 03:28:57 +000015 def __init__(self, *args):
Raymond Hettinger931237e2003-07-09 18:48:24 +000016 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +000017 self.text.bind("<<goto-file-line>>", self.goto_file_line)
David Scherer7aced172000-08-15 01:13:23 +000018
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
David Scherer7aced172000-08-15 01:13:23 +000028 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
David Scherer7aced172000-08-15 01:13:23 +000035 # Act as output file
36
Kurt B. Kaiser969de452002-06-12 03:28:57 +000037 def write(self, s, tags=(), mark="insert"):
Guido van Rossum98297ee2007-11-06 21:34:58 +000038 if isinstance(s, (bytes, bytes)):
Martin v. Löwis0f98d8f2007-08-13 06:26:48 +000039 s = s.decode(IOBinding.encoding, "replace")
Kurt B. Kaiserd0116362002-09-02 21:29:40 +000040 self.text.insert(mark, s, tags)
David Scherer7aced172000-08-15 01:13:23 +000041 self.text.see(mark)
42 self.text.update()
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +020043 return len(s)
David Scherer7aced172000-08-15 01:13:23 +000044
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +000045 def writelines(self, lines):
46 for line in lines:
47 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +000048
49 def flush(self):
50 pass
51
52 # Our own right-button menu
53
54 rmenu_specs = [
55 ("Go to file/line", "<<goto-file-line>>"),
56 ]
57
58 file_line_pats = [
Kurt B. Kaisercef4b812009-05-06 03:23:37 +000059 # order of patterns matters
David Scherer7aced172000-08-15 01:13:23 +000060 r'file "([^"]*)", line (\d+)',
61 r'([^\s]+)\((\d+)\)',
Kurt B. Kaisercef4b812009-05-06 03:23:37 +000062 r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces
63 r'([^\s]+):\s*(\d+):', # filename or path, ltrim
64 r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim
David Scherer7aced172000-08-15 01:13:23 +000065 ]
66
67 file_line_progs = None
68
69 def goto_file_line(self, event=None):
70 if self.file_line_progs is None:
71 l = []
72 for pat in self.file_line_pats:
73 l.append(re.compile(pat, re.IGNORECASE))
74 self.file_line_progs = l
75 # x, y = self.event.x, self.event.y
76 # self.text.mark_set("insert", "@%d,%d" % (x, y))
77 line = self.text.get("insert linestart", "insert lineend")
78 result = self._file_line_helper(line)
79 if not result:
80 # Try the previous line. This is handy e.g. in tracebacks,
81 # where you tend to right-click on the displayed source line
82 line = self.text.get("insert -1line linestart",
83 "insert -1line lineend")
84 result = self._file_line_helper(line)
85 if not result:
86 tkMessageBox.showerror(
87 "No special line",
88 "The line you point at doesn't look like "
89 "a valid file name followed by a line number.",
90 master=self.text)
91 return
92 filename, lineno = result
Kurt B. Kaiser969de452002-06-12 03:28:57 +000093 edit = self.flist.open(filename)
David Scherer7aced172000-08-15 01:13:23 +000094 edit.gotoline(lineno)
David Scherer7aced172000-08-15 01:13:23 +000095
96 def _file_line_helper(self, line):
97 for prog in self.file_line_progs:
Georg Brandl7b2669b2009-04-27 16:58:05 +000098 match = prog.search(line)
99 if match:
100 filename, lineno = match.group(1, 2)
101 try:
102 f = open(filename, "r")
103 f.close()
104 break
105 except IOError:
106 continue
David Scherer7aced172000-08-15 01:13:23 +0000107 else:
108 return None
David Scherer7aced172000-08-15 01:13:23 +0000109 try:
110 return filename, int(lineno)
111 except TypeError:
112 return None
113
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000114# These classes are currently not used but might come in handy
David Scherer7aced172000-08-15 01:13:23 +0000115
116class OnDemandOutputWindow:
David Scherer7aced172000-08-15 01:13:23 +0000117
118 tagdefs = {
119 # XXX Should use IdlePrefs.ColorPrefs
David Scherer7aced172000-08-15 01:13:23 +0000120 "stdout": {"foreground": "blue"},
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000121 "stderr": {"foreground": "#007700"},
122 }
123
David Scherer7aced172000-08-15 01:13:23 +0000124 def __init__(self, flist):
125 self.flist = flist
126 self.owin = None
David Scherer7aced172000-08-15 01:13:23 +0000127
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000128 def write(self, s, tags, mark):
129 if not self.owin:
David Scherer7aced172000-08-15 01:13:23 +0000130 self.setup()
131 self.owin.write(s, tags, mark)
132
David Scherer7aced172000-08-15 01:13:23 +0000133 def setup(self):
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000134 self.owin = owin = OutputWindow(self.flist)
David Scherer7aced172000-08-15 01:13:23 +0000135 text = owin.text
David Scherer7aced172000-08-15 01:13:23 +0000136 for tag, cnf in self.tagdefs.items():
137 if cnf:
Raymond Hettinger931237e2003-07-09 18:48:24 +0000138 text.tag_configure(tag, **cnf)
David Scherer7aced172000-08-15 01:13:23 +0000139 text.tag_raise('sel')
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000140 self.write = self.owin.write