blob: 6c0ecd71343b7d15ed8ece6b5edfd304b945e6d4 [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001import W
2import Wkeys
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00003from Carbon import Fm
Just van Rossum40f9b7b1999-01-30 22:39:17 +00004import WASTEconst
5from types import *
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00006from Carbon import Events
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007import string
8import sys
9import traceback
10import MacOS
11import MacPrefs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000012from Carbon import Qd
Just van Rossum40f9b7b1999-01-30 22:39:17 +000013import PyInteractive
14
15if not hasattr(sys, 'ps1'):
16 sys.ps1 = '>>> '
17if not hasattr(sys, 'ps2'):
18 sys.ps2 = '... '
19
20def inspect(foo): # JJS 1/25/99
21 "Launch the browser on the given object. This is a general built-in function."
22 import PyBrowser
23 PyBrowser.Browser(foo)
24
25class ConsoleTextWidget(W.EditText):
26
27 def __init__(self, *args, **kwargs):
28 apply(W.EditText.__init__, (self,) + args, kwargs)
29 self._inputstart = 0
30 self._buf = ''
31 self.pyinteractive = PyInteractive.PyInteractive()
32
33 import __main__
34 self._namespace = __main__.__dict__
35 self._namespace['inspect'] = inspect # JJS 1/25/99
36
37 def insert(self, text):
38 self.checkselection()
39 self.ted.WEInsert(text, None, None)
40 self.changed = 1
41 self.selchanged = 1
42
43 def set_namespace(self, dict):
44 if type(dict) <> DictionaryType:
45 raise TypeError, "The namespace needs to be a dictionary"
46 if 'inspect' not in dict.keys(): dict['inspect'] = inspect # JJS 1/25/99
47 self._namespace = dict
48
49 def open(self):
Just van Rossume6e745f2001-08-06 11:12:18 +000050 import __main__
Just van Rossum40f9b7b1999-01-30 22:39:17 +000051 W.EditText.open(self)
Just van Rossume6e745f2001-08-06 11:12:18 +000052 self.write('Python %s\n' % sys.version)
53 self.write('Type "copyright", "credits" or "license" for more information.\n')
54 self.write('MacPython IDE %s\n' % __main__.__version__)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000055 self.write(sys.ps1)
56 self.flush()
57
58 def key(self, char, event):
59 (what, message, when, where, modifiers) = event
60 if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
61 if char not in Wkeys.navigationkeys:
62 self.checkselection()
63 if char == Wkeys.enterkey:
64 char = Wkeys.returnkey
65 selstart, selend = self.getselection()
66 if char == Wkeys.backspacekey:
67 if selstart <= (self._inputstart - (selstart <> selend)):
68 return
69 self.ted.WEKey(ord(char), modifiers)
70 if char not in Wkeys.navigationkeys:
71 self.changed = 1
72 if char not in Wkeys.scrollkeys:
73 self.selchanged = 1
74 self.updatescrollbars()
75 if char == Wkeys.returnkey:
76 text = self.get()[self._inputstart:selstart]
77 text = string.join(string.split(text, "\r"), "\n")
Jack Jansen815d2bf2002-01-21 23:00:52 +000078 if hasattr(MacOS, 'EnableAppswitch'):
79 saveyield = MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000080 self.pyinteractive.executeline(text, self, self._namespace)
Jack Jansen815d2bf2002-01-21 23:00:52 +000081 if hasattr(MacOS, 'EnableAppswitch'):
82 MacOS.EnableAppswitch(saveyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000083 selstart, selend = self.getselection()
84 self._inputstart = selstart
85
86 def domenu_save_as(self, *args):
87 import macfs
88 fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt')
89 if not ok:
90 return
91 f = open(fss.as_pathname(), 'wb')
92 f.write(self.get())
93 f.close()
94 fss.SetCreatorType(W._signature, 'TEXT')
95
96 def write(self, text):
97 self._buf = self._buf + text
98 if '\n' in self._buf:
99 self.flush()
100
101 def flush(self):
102 stuff = string.split(self._buf, '\n')
103 stuff = string.join(stuff, '\r')
104 self.setselection_at_end()
105 self.ted.WEInsert(stuff, None, None)
106 selstart, selend = self.getselection()
107 self._inputstart = selstart
108 self._buf = ""
109 self.ted.WEClearUndo()
110 self.updatescrollbars()
111
112 def selection_ok(self):
113 selstart, selend = self.getselection()
114 return not (selstart < self._inputstart or selend < self._inputstart)
115
116 def checkselection(self):
117 if not self.selection_ok():
118 self.setselection_at_end()
119
120 def setselection_at_end(self):
121 end = self.ted.WEGetTextLength()
122 self.setselection(end, end)
123 self.updatescrollbars()
124
125 def domenu_cut(self, *args):
126 if not self.selection_ok():
127 return
128 W.EditText.domenu_cut(self)
129
130 def domenu_paste(self, *args):
131 if not self.selection_ok():
132 self.setselection_at_end()
133 W.EditText.domenu_paste(self)
134
135 def domenu_clear(self, *args):
136 if not self.selection_ok():
137 return
138 W.EditText.domenu_clear(self)
139
140
141class PyConsole(W.Window):
142
143 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)),
144 tabsettings = (32, 0), unclosable = 0):
145 W.Window.__init__(self,
146 bounds,
147 "Python Interactive",
148 minsize = (200, 100),
149 tabbable = 0,
150 show = show)
151
152 self._unclosable = unclosable
153 consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5),
154 fontsettings = fontsettings, tabsettings = tabsettings)
155 self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
156 self.consoletext = consoletext
157 self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
158 self.namespacemenu.bind('<click>', self.makenamespacemenu)
159 self.open()
160
161 def makenamespacemenu(self, *args):
162 W.SetCursor('watch')
163 namespacelist = self.getnamespacelist()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000164 self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings),
165 ["Namespace"] + namespacelist, ("Browse namespace\xc9", self.browsenamespace)])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000166 currentname = self.consoletext._namespace["__name__"]
167 for i in range(len(namespacelist)):
168 if namespacelist[i][0] == currentname:
169 break
170 else:
171 return
172 # XXX this functionality should be generally available in Wmenus
173 submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
174 menu = self.namespacemenu.menu.bar.menus[submenuid]
Jack Jansenafd0aa62001-01-29 13:29:47 +0000175 menu.menu.CheckMenuItem(i + 1, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000176
177 def browsenamespace(self):
178 import PyBrowser, W
179 W.SetCursor('watch')
180 PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
181
182 def clearbuffer(self):
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000183 from Carbon import Res
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000184 self.consoletext.ted.WEUseText(Res.Resource(''))
185 self.consoletext.write(sys.ps1)
186 self.consoletext.flush()
187
188 def getnamespacelist(self):
189 import os
190 import __main__
191 editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
192
193 namespaces = [ ("__main__",__main__.__dict__) ]
194 for ed in editors:
195 modname = os.path.splitext(ed.title)[0]
196 if sys.modules.has_key(modname):
197 module = sys.modules[modname]
198 namespaces.append((modname, module.__dict__))
199 else:
200 if ed.title[-3:] == '.py':
201 modname = ed.title[:-3]
202 else:
203 modname = ed.title
204 ed.globals["__name__"] = modname
205 namespaces.append((modname, ed.globals))
206 return namespaces
207
208 def dofontsettings(self):
209 import FontSettings
210 settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
211 self.consoletext.gettabsettings())
212 if settings:
213 fontsettings, tabsettings = settings
214 self.consoletext.setfontsettings(fontsettings)
215 self.consoletext.settabsettings(tabsettings)
216
217 def show(self, onoff = 1):
218 W.Window.show(self, onoff)
219 if onoff:
220 self.select()
221
222 def close(self):
223 if self._unclosable:
224 self.show(0)
225 return -1
226 W.Window.close(self)
227
228 def writeprefs(self):
229 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
230 prefs.console.show = self.isvisible()
231 prefs.console.windowbounds = self.getbounds()
232 prefs.console.fontsettings = self.consoletext.getfontsettings()
233 prefs.console.tabsettings = self.consoletext.gettabsettings()
234 prefs.save()
235
236
237class OutputTextWidget(W.EditText):
238
239 def domenu_save_as(self, *args):
240 title = self._parentwindow.gettitle()
241 import macfs
242 fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt')
243 if not ok:
244 return
245 f = open(fss.as_pathname(), 'wb')
246 f.write(self.get())
247 f.close()
248 fss.SetCreatorType(W._signature, 'TEXT')
249
250
251class PyOutput:
252
253 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
254 self.bounds = bounds
255 self.fontsettings = fontsettings
256 self.tabsettings = tabsettings
257 self.w = None
258 self.closed = 1
259 self._buf = ''
260 # should be able to set this
261 self.savestdout, self.savestderr = sys.stdout, sys.stderr
262 sys.stderr = sys.stdout = self
263 if show:
264 self.show()
265
266 def setupwidgets(self):
267 self.w = W.Window(self.bounds, "Output",
268 minsize = (200, 100),
269 tabbable = 0)
270 self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5),
271 fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000272 menuitems = [("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000273 self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
274
275 self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
276 self.w.bind("<close>", self.close)
277 self.w.bind("<activate>", self.activate)
278
279 def write(self, text):
Jack Jansen815d2bf2002-01-21 23:00:52 +0000280 if hasattr(MacOS, 'EnableAppswitch'):
281 oldyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000282 try:
283 self._buf = self._buf + text
284 if '\n' in self._buf:
285 self.flush()
286 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000287 if hasattr(MacOS, 'EnableAppswitch'):
288 MacOS.EnableAppswitch(oldyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000289
290 def flush(self):
291 self.show()
292 stuff = string.split(self._buf, '\n')
293 stuff = string.join(stuff, '\r')
294 end = self.w.outputtext.ted.WEGetTextLength()
295 self.w.outputtext.setselection(end, end)
296 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
297 self.w.outputtext.ted.WEInsert(stuff, None, None)
298 self._buf = ""
299 self.w.outputtext.updatescrollbars()
300 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
301
302 def show(self):
303 if self.closed:
304 if not self.w:
305 self.setupwidgets()
306 self.w.open()
307 self.w.outputtext.updatescrollbars()
308 self.closed = 0
309 else:
310 self.w.show(1)
311 self.closed = 0
312 self.w.select()
313
314 def writeprefs(self):
315 if self.w is not None:
316 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
317 prefs.output.show = self.w.isvisible()
318 prefs.output.windowbounds = self.w.getbounds()
319 prefs.output.fontsettings = self.w.outputtext.getfontsettings()
320 prefs.output.tabsettings = self.w.outputtext.gettabsettings()
321 prefs.save()
322
323 def dofontsettings(self):
324 import FontSettings
325 settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
326 self.w.outputtext.gettabsettings())
327 if settings:
328 fontsettings, tabsettings = settings
329 self.w.outputtext.setfontsettings(fontsettings)
330 self.w.outputtext.settabsettings(tabsettings)
331
332 def clearbuffer(self):
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000333 from Carbon import Res
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000334 self.w.outputtext.set('')
335
336 def activate(self, onoff):
337 if onoff:
338 self.closed = 0
339
340 def close(self):
341 self.w.show(0)
342 self.closed = 1
343 return -1
344
345
346class SimpleStdin:
347
348 def readline(self):
349 import EasyDialogs
Jack Jansendac238b2001-05-26 20:01:41 +0000350 # A trick to make the input dialog box a bit more palatable
351 if hasattr(sys.stdout, '_buf'):
352 prompt = sys.stdout._buf
353 else:
354 prompt = ""
355 if not prompt:
356 prompt = "Stdin input:"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000357 sys.stdout.flush()
Jack Jansendac238b2001-05-26 20:01:41 +0000358 rv = EasyDialogs.AskString(prompt)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000359 if rv is None:
360 return ""
Just van Rossum226275f2001-12-27 10:29:07 +0000361 rv = rv + "\n" # readline should include line terminator
362 sys.stdout.write(rv) # echo user's reply
363 return rv
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000364
365
366def installconsole(defaultshow = 1):
367 global console
368 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
369 if not prefs.console or not hasattr(prefs.console, 'show'):
370 prefs.console.show = defaultshow
371 if not hasattr(prefs.console, "windowbounds"):
372 prefs.console.windowbounds = (450, 250)
373 if not hasattr(prefs.console, "fontsettings"):
374 prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
375 if not hasattr(prefs.console, "tabsettings"):
376 prefs.console.tabsettings = (32, 0)
377 console = PyConsole(prefs.console.windowbounds, prefs.console.show,
378 prefs.console.fontsettings, prefs.console.tabsettings, 1)
379
380def installoutput(defaultshow = 0, OutPutWindow = PyOutput):
381 global output
382
383 # quick 'n' dirty std in emulation
384 sys.stdin = SimpleStdin()
385
386 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
387 if not prefs.output or not hasattr(prefs.output, 'show'):
388 prefs.output.show = defaultshow
389 if not hasattr(prefs.output, "windowbounds"):
390 prefs.output.windowbounds = (450, 250)
391 if not hasattr(prefs.output, "fontsettings"):
392 prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
393 if not hasattr(prefs.output, "tabsettings"):
394 prefs.output.tabsettings = (32, 0)
395 output = OutPutWindow(prefs.output.windowbounds, prefs.output.show,
396 prefs.output.fontsettings, prefs.output.tabsettings)