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