blob: 23f301b4ef352574af373520d080a4d1f4899ff9 [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()
Just van Rossum4e720382002-02-04 11:53:53 +0000111 if Qd.QDIsPortBuffered(self._parentwindow.wid):
112 Qd.QDFlushPortBuffer(self._parentwindow.wid, None)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000113
114 def selection_ok(self):
115 selstart, selend = self.getselection()
116 return not (selstart < self._inputstart or selend < self._inputstart)
117
118 def checkselection(self):
119 if not self.selection_ok():
120 self.setselection_at_end()
121
122 def setselection_at_end(self):
123 end = self.ted.WEGetTextLength()
124 self.setselection(end, end)
125 self.updatescrollbars()
126
127 def domenu_cut(self, *args):
128 if not self.selection_ok():
129 return
130 W.EditText.domenu_cut(self)
131
132 def domenu_paste(self, *args):
133 if not self.selection_ok():
134 self.setselection_at_end()
135 W.EditText.domenu_paste(self)
136
137 def domenu_clear(self, *args):
138 if not self.selection_ok():
139 return
140 W.EditText.domenu_clear(self)
141
142
143class PyConsole(W.Window):
144
145 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)),
146 tabsettings = (32, 0), unclosable = 0):
147 W.Window.__init__(self,
148 bounds,
149 "Python Interactive",
150 minsize = (200, 100),
151 tabbable = 0,
152 show = show)
153
154 self._unclosable = unclosable
155 consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5),
156 fontsettings = fontsettings, tabsettings = tabsettings)
157 self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
158 self.consoletext = consoletext
159 self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
160 self.namespacemenu.bind('<click>', self.makenamespacemenu)
161 self.open()
162
163 def makenamespacemenu(self, *args):
164 W.SetCursor('watch')
165 namespacelist = self.getnamespacelist()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000166 self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings),
167 ["Namespace"] + namespacelist, ("Browse namespace\xc9", self.browsenamespace)])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000168 currentname = self.consoletext._namespace["__name__"]
169 for i in range(len(namespacelist)):
170 if namespacelist[i][0] == currentname:
171 break
172 else:
173 return
174 # XXX this functionality should be generally available in Wmenus
175 submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
176 menu = self.namespacemenu.menu.bar.menus[submenuid]
Jack Jansenafd0aa62001-01-29 13:29:47 +0000177 menu.menu.CheckMenuItem(i + 1, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000178
179 def browsenamespace(self):
180 import PyBrowser, W
181 W.SetCursor('watch')
182 PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
183
184 def clearbuffer(self):
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000185 from Carbon import Res
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000186 self.consoletext.ted.WEUseText(Res.Resource(''))
187 self.consoletext.write(sys.ps1)
188 self.consoletext.flush()
189
190 def getnamespacelist(self):
191 import os
192 import __main__
193 editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
194
195 namespaces = [ ("__main__",__main__.__dict__) ]
196 for ed in editors:
197 modname = os.path.splitext(ed.title)[0]
198 if sys.modules.has_key(modname):
199 module = sys.modules[modname]
200 namespaces.append((modname, module.__dict__))
201 else:
202 if ed.title[-3:] == '.py':
203 modname = ed.title[:-3]
204 else:
205 modname = ed.title
206 ed.globals["__name__"] = modname
207 namespaces.append((modname, ed.globals))
208 return namespaces
209
210 def dofontsettings(self):
211 import FontSettings
212 settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
213 self.consoletext.gettabsettings())
214 if settings:
215 fontsettings, tabsettings = settings
216 self.consoletext.setfontsettings(fontsettings)
217 self.consoletext.settabsettings(tabsettings)
218
219 def show(self, onoff = 1):
220 W.Window.show(self, onoff)
221 if onoff:
222 self.select()
223
224 def close(self):
225 if self._unclosable:
226 self.show(0)
227 return -1
228 W.Window.close(self)
229
230 def writeprefs(self):
231 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
232 prefs.console.show = self.isvisible()
233 prefs.console.windowbounds = self.getbounds()
234 prefs.console.fontsettings = self.consoletext.getfontsettings()
235 prefs.console.tabsettings = self.consoletext.gettabsettings()
236 prefs.save()
237
238
239class OutputTextWidget(W.EditText):
240
241 def domenu_save_as(self, *args):
242 title = self._parentwindow.gettitle()
243 import macfs
244 fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt')
245 if not ok:
246 return
247 f = open(fss.as_pathname(), 'wb')
248 f.write(self.get())
249 f.close()
250 fss.SetCreatorType(W._signature, 'TEXT')
251
252
253class PyOutput:
254
255 def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
256 self.bounds = bounds
257 self.fontsettings = fontsettings
258 self.tabsettings = tabsettings
259 self.w = None
260 self.closed = 1
261 self._buf = ''
262 # should be able to set this
263 self.savestdout, self.savestderr = sys.stdout, sys.stderr
264 sys.stderr = sys.stdout = self
265 if show:
266 self.show()
267
268 def setupwidgets(self):
269 self.w = W.Window(self.bounds, "Output",
270 minsize = (200, 100),
271 tabbable = 0)
272 self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5),
273 fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000274 menuitems = [("Clear window", self.clearbuffer), ("Font settings\xc9", self.dofontsettings)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000275 self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
276
277 self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
278 self.w.bind("<close>", self.close)
279 self.w.bind("<activate>", self.activate)
280
281 def write(self, text):
Jack Jansen815d2bf2002-01-21 23:00:52 +0000282 if hasattr(MacOS, 'EnableAppswitch'):
283 oldyield = MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000284 try:
285 self._buf = self._buf + text
286 if '\n' in self._buf:
287 self.flush()
288 finally:
Jack Jansen815d2bf2002-01-21 23:00:52 +0000289 if hasattr(MacOS, 'EnableAppswitch'):
290 MacOS.EnableAppswitch(oldyield)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000291
292 def flush(self):
293 self.show()
294 stuff = string.split(self._buf, '\n')
295 stuff = string.join(stuff, '\r')
296 end = self.w.outputtext.ted.WEGetTextLength()
297 self.w.outputtext.setselection(end, end)
298 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
299 self.w.outputtext.ted.WEInsert(stuff, None, None)
300 self._buf = ""
301 self.w.outputtext.updatescrollbars()
302 self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
Just van Rossum4e720382002-02-04 11:53:53 +0000303 if Qd.QDIsPortBuffered(self.w.wid):
304 Qd.QDFlushPortBuffer(self.w.wid, None)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000305
306 def show(self):
307 if self.closed:
308 if not self.w:
309 self.setupwidgets()
310 self.w.open()
311 self.w.outputtext.updatescrollbars()
312 self.closed = 0
313 else:
314 self.w.show(1)
315 self.closed = 0
316 self.w.select()
317
318 def writeprefs(self):
319 if self.w is not None:
320 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
321 prefs.output.show = self.w.isvisible()
322 prefs.output.windowbounds = self.w.getbounds()
323 prefs.output.fontsettings = self.w.outputtext.getfontsettings()
324 prefs.output.tabsettings = self.w.outputtext.gettabsettings()
325 prefs.save()
326
327 def dofontsettings(self):
328 import FontSettings
329 settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
330 self.w.outputtext.gettabsettings())
331 if settings:
332 fontsettings, tabsettings = settings
333 self.w.outputtext.setfontsettings(fontsettings)
334 self.w.outputtext.settabsettings(tabsettings)
335
336 def clearbuffer(self):
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000337 from Carbon import Res
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000338 self.w.outputtext.set('')
339
340 def activate(self, onoff):
341 if onoff:
342 self.closed = 0
343
344 def close(self):
345 self.w.show(0)
346 self.closed = 1
347 return -1
348
349
350class SimpleStdin:
351
352 def readline(self):
353 import EasyDialogs
Jack Jansendac238b2001-05-26 20:01:41 +0000354 # A trick to make the input dialog box a bit more palatable
355 if hasattr(sys.stdout, '_buf'):
356 prompt = sys.stdout._buf
357 else:
358 prompt = ""
359 if not prompt:
360 prompt = "Stdin input:"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000361 sys.stdout.flush()
Jack Jansendac238b2001-05-26 20:01:41 +0000362 rv = EasyDialogs.AskString(prompt)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000363 if rv is None:
364 return ""
Just van Rossum226275f2001-12-27 10:29:07 +0000365 rv = rv + "\n" # readline should include line terminator
366 sys.stdout.write(rv) # echo user's reply
367 return rv
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000368
369
370def installconsole(defaultshow = 1):
371 global console
372 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
373 if not prefs.console or not hasattr(prefs.console, 'show'):
374 prefs.console.show = defaultshow
375 if not hasattr(prefs.console, "windowbounds"):
376 prefs.console.windowbounds = (450, 250)
377 if not hasattr(prefs.console, "fontsettings"):
378 prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
379 if not hasattr(prefs.console, "tabsettings"):
380 prefs.console.tabsettings = (32, 0)
381 console = PyConsole(prefs.console.windowbounds, prefs.console.show,
382 prefs.console.fontsettings, prefs.console.tabsettings, 1)
383
384def installoutput(defaultshow = 0, OutPutWindow = PyOutput):
385 global output
386
387 # quick 'n' dirty std in emulation
388 sys.stdin = SimpleStdin()
389
390 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
391 if not prefs.output or not hasattr(prefs.output, 'show'):
392 prefs.output.show = defaultshow
393 if not hasattr(prefs.output, "windowbounds"):
394 prefs.output.windowbounds = (450, 250)
395 if not hasattr(prefs.output, "fontsettings"):
396 prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
397 if not hasattr(prefs.output, "tabsettings"):
398 prefs.output.tabsettings = (32, 0)
399 output = OutPutWindow(prefs.output.windowbounds, prefs.output.show,
400 prefs.output.fontsettings, prefs.output.tabsettings)