blob: f6d2915c62443ed03d62863b96c33e258f0e51c6 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001import re
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -04002
3from tkinter import *
Georg Brandl14fc4272008-05-17 18:39:55 +00004import tkinter.messagebox as tkMessageBox
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -04005
6from idlelib.editor import EditorWindow
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -04007from idlelib import iomenu
David Scherer7aced172000-08-15 01:13:23 +00008
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -04009
David Scherer7aced172000-08-15 01:13:23 +000010class OutputWindow(EditorWindow):
Kurt B. Kaiser969de452002-06-12 03:28:57 +000011
12 """An editor window that can serve as an output file.
13
14 Also the future base class for the Python shell window.
15 This class has no input facilities.
David Scherer7aced172000-08-15 01:13:23 +000016 """
17
Kurt B. Kaiser969de452002-06-12 03:28:57 +000018 def __init__(self, *args):
Raymond Hettinger931237e2003-07-09 18:48:24 +000019 EditorWindow.__init__(self, *args)
David Scherer7aced172000-08-15 01:13:23 +000020 self.text.bind("<<goto-file-line>>", self.goto_file_line)
David Scherer7aced172000-08-15 01:13:23 +000021
22 # Customize EditorWindow
23
24 def ispythonsource(self, filename):
25 # No colorization needed
26 return 0
27
28 def short_title(self):
29 return "Output"
30
David Scherer7aced172000-08-15 01:13:23 +000031 def maybesave(self):
32 # Override base class method -- don't ask any questions
33 if self.get_saved():
34 return "yes"
35 else:
36 return "no"
37
David Scherer7aced172000-08-15 01:13:23 +000038 # Act as output file
39
Kurt B. Kaiser969de452002-06-12 03:28:57 +000040 def write(self, s, tags=(), mark="insert"):
Guido van Rossum98297ee2007-11-06 21:34:58 +000041 if isinstance(s, (bytes, bytes)):
Terry Jan Reedy6fa5bdc2016-05-28 13:22:31 -040042 s = s.decode(iomenu.encoding, "replace")
Kurt B. Kaiserd0116362002-09-02 21:29:40 +000043 self.text.insert(mark, s, tags)
David Scherer7aced172000-08-15 01:13:23 +000044 self.text.see(mark)
45 self.text.update()
Martin v. Löwis30d5e6c2012-07-25 11:32:26 +020046 return len(s)
David Scherer7aced172000-08-15 01:13:23 +000047
Kurt B. Kaiser66aaf742007-08-09 18:00:23 +000048 def writelines(self, lines):
49 for line in lines:
50 self.write(line)
David Scherer7aced172000-08-15 01:13:23 +000051
52 def flush(self):
53 pass
54
55 # Our own right-button menu
56
57 rmenu_specs = [
Andrew Svetlovd1837672012-11-01 22:41:19 +020058 ("Cut", "<<cut>>", "rmenu_check_cut"),
59 ("Copy", "<<copy>>", "rmenu_check_copy"),
60 ("Paste", "<<paste>>", "rmenu_check_paste"),
61 (None, None, None),
62 ("Go to file/line", "<<goto-file-line>>", None),
David Scherer7aced172000-08-15 01:13:23 +000063 ]
64
65 file_line_pats = [
Kurt B. Kaisercef4b812009-05-06 03:23:37 +000066 # order of patterns matters
David Scherer7aced172000-08-15 01:13:23 +000067 r'file "([^"]*)", line (\d+)',
68 r'([^\s]+)\((\d+)\)',
Kurt B. Kaisercef4b812009-05-06 03:23:37 +000069 r'^(\s*\S.*?):\s*(\d+):', # Win filename, maybe starting with spaces
70 r'([^\s]+):\s*(\d+):', # filename or path, ltrim
71 r'^\s*(\S.*?):\s*(\d+):', # Win abs path with embedded spaces, ltrim
David Scherer7aced172000-08-15 01:13:23 +000072 ]
73
74 file_line_progs = None
75
76 def goto_file_line(self, event=None):
77 if self.file_line_progs is None:
78 l = []
79 for pat in self.file_line_pats:
80 l.append(re.compile(pat, re.IGNORECASE))
81 self.file_line_progs = l
82 # x, y = self.event.x, self.event.y
83 # self.text.mark_set("insert", "@%d,%d" % (x, y))
84 line = self.text.get("insert linestart", "insert lineend")
85 result = self._file_line_helper(line)
86 if not result:
87 # Try the previous line. This is handy e.g. in tracebacks,
88 # where you tend to right-click on the displayed source line
89 line = self.text.get("insert -1line linestart",
90 "insert -1line lineend")
91 result = self._file_line_helper(line)
92 if not result:
93 tkMessageBox.showerror(
94 "No special line",
95 "The line you point at doesn't look like "
96 "a valid file name followed by a line number.",
Terry Jan Reedy3be2e542015-09-25 22:22:55 -040097 parent=self.text)
David Scherer7aced172000-08-15 01:13:23 +000098 return
99 filename, lineno = result
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000100 edit = self.flist.open(filename)
David Scherer7aced172000-08-15 01:13:23 +0000101 edit.gotoline(lineno)
David Scherer7aced172000-08-15 01:13:23 +0000102
103 def _file_line_helper(self, line):
104 for prog in self.file_line_progs:
Georg Brandl7b2669b2009-04-27 16:58:05 +0000105 match = prog.search(line)
106 if match:
107 filename, lineno = match.group(1, 2)
108 try:
109 f = open(filename, "r")
110 f.close()
111 break
Andrew Svetlovf7a17b42012-12-25 16:47:37 +0200112 except OSError:
Georg Brandl7b2669b2009-04-27 16:58:05 +0000113 continue
David Scherer7aced172000-08-15 01:13:23 +0000114 else:
115 return None
David Scherer7aced172000-08-15 01:13:23 +0000116 try:
117 return filename, int(lineno)
118 except TypeError:
119 return None
120
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000121# These classes are currently not used but might come in handy
David Scherer7aced172000-08-15 01:13:23 +0000122
123class OnDemandOutputWindow:
David Scherer7aced172000-08-15 01:13:23 +0000124
125 tagdefs = {
126 # XXX Should use IdlePrefs.ColorPrefs
David Scherer7aced172000-08-15 01:13:23 +0000127 "stdout": {"foreground": "blue"},
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000128 "stderr": {"foreground": "#007700"},
129 }
130
David Scherer7aced172000-08-15 01:13:23 +0000131 def __init__(self, flist):
132 self.flist = flist
133 self.owin = None
David Scherer7aced172000-08-15 01:13:23 +0000134
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000135 def write(self, s, tags, mark):
136 if not self.owin:
David Scherer7aced172000-08-15 01:13:23 +0000137 self.setup()
138 self.owin.write(s, tags, mark)
139
David Scherer7aced172000-08-15 01:13:23 +0000140 def setup(self):
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000141 self.owin = owin = OutputWindow(self.flist)
David Scherer7aced172000-08-15 01:13:23 +0000142 text = owin.text
David Scherer7aced172000-08-15 01:13:23 +0000143 for tag, cnf in self.tagdefs.items():
144 if cnf:
Raymond Hettinger931237e2003-07-09 18:48:24 +0000145 text.tag_configure(tag, **cnf)
David Scherer7aced172000-08-15 01:13:23 +0000146 text.tag_raise('sel')
Kurt B. Kaiser969de452002-06-12 03:28:57 +0000147 self.write = self.owin.write