Guido van Rossum | f06ee5f | 1996-11-27 19:52:01 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 2 | |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 3 | # A STDWIN-based front end for the Python interpreter. |
| 4 | # |
| 5 | # This is useful if you want to avoid console I/O and instead |
| 6 | # use text windows to issue commands to the interpreter. |
| 7 | # |
| 8 | # It supports multiple interpreter windows, each with its own context. |
| 9 | # |
| 10 | # BUGS AND CAVEATS: |
| 11 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 12 | # This was written long ago as a demonstration, and slightly hacked to |
| 13 | # keep it up-to-date, but never as an industry-strength alternative |
| 14 | # interface to Python. It should be rewritten using more classes, and |
| 15 | # merged with something like wdb. |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 16 | # |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 17 | # Although this supports multiple windows, the whole application |
| 18 | # is deaf and dumb when a command is running in one window. |
| 19 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 20 | # Interrupt is (ab)used to signal EOF on input requests. |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 21 | # |
| 22 | # On UNIX (using X11), interrupts typed in the window will not be |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 23 | # seen until the next input or output operation. When you are stuck |
| 24 | # in an infinite loop, try typing ^C in the shell window where you |
| 25 | # started this interpreter. (On the Mac, interrupts work normally.) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 26 | |
| 27 | |
| 28 | import sys |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 29 | import stdwin |
| 30 | from stdwinevents import * |
| 31 | import rand |
| 32 | import mainloop |
Guido van Rossum | 4ea570d | 1992-03-30 11:01:26 +0000 | [diff] [blame] | 33 | import os |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 34 | |
| 35 | |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 36 | # Stack of windows waiting for [raw_]input(). |
| 37 | # Element [0] is the top. |
| 38 | # If there are multiple windows waiting for input, only the |
| 39 | # one on top of the stack can accept input, because the way |
| 40 | # raw_input() is implemented (using recursive mainloop() calls). |
| 41 | # |
| 42 | inputwindows = [] |
| 43 | |
| 44 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 45 | # Exception raised when input is available |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 46 | # |
| 47 | InputAvailable = 'input available for raw_input (not an error)' |
| 48 | |
| 49 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 50 | # Main program -- create the window and call the mainloop |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 51 | # |
| 52 | def main(): |
| 53 | # Hack so 'import python' won't load another copy |
| 54 | # of this if we were loaded though 'python python.py'. |
| 55 | # (Should really look at sys.argv[0]...) |
| 56 | if 'inputwindows' in dir(sys.modules['__main__']) and \ |
| 57 | sys.modules['__main__'].inputwindows is inputwindows: |
| 58 | sys.modules['python'] = sys.modules['__main__'] |
| 59 | # |
| 60 | win = makewindow() |
| 61 | mainloop.mainloop() |
| 62 | |
| 63 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 64 | # Create a new window |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 65 | # |
| 66 | def makewindow(): |
| 67 | # stdwin.setdefscrollbars(0, 1) # Not in Python 0.9.1 |
| 68 | # stdwin.setfont('monaco') # Not on UNIX! and not Python 0.9.1 |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 69 | # width, height = stdwin.textwidth('in')*40, stdwin.lineheight()*24 |
| 70 | # stdwin.setdefwinsize(width, height) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 71 | win = stdwin.open('Python interpreter ready') |
| 72 | win.editor = win.textcreate((0,0), win.getwinsize()) |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 73 | win.globals = {} # Dictionary for user's globals |
| 74 | win.command = '' # Partially read command |
| 75 | win.busy = 0 # Ready to accept a command |
| 76 | win.auto = 1 # [CR] executes command |
| 77 | win.insertOutput = 1 # Insert output at focus |
| 78 | win.insertError = 1 # Insert error output at focus |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 79 | win.setwincursor('ibeam') |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 80 | win.filename = '' # Empty if no file for this window |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 81 | makefilemenu(win) |
| 82 | makeeditmenu(win) |
| 83 | win.dispatch = pdispatch # Event dispatch function |
| 84 | mainloop.register(win) |
| 85 | return win |
| 86 | |
| 87 | |
| 88 | # Make a 'File' menu |
| 89 | # |
| 90 | def makefilemenu(win): |
| 91 | win.filemenu = mp = win.menucreate('File') |
| 92 | mp.callback = [] |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 93 | additem(mp, 'New', 'N', do_new) |
| 94 | additem(mp, 'Open...', 'O', do_open) |
| 95 | additem(mp, '', '', None) |
| 96 | additem(mp, 'Close', 'W', do_close) |
| 97 | additem(mp, 'Save', 'S', do_save) |
| 98 | additem(mp, 'Save as...', '', do_saveas) |
| 99 | additem(mp, '', '', None) |
| 100 | additem(mp, 'Quit', 'Q', do_quit) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 101 | |
| 102 | |
| 103 | # Make an 'Edit' menu |
| 104 | # |
| 105 | def makeeditmenu(win): |
| 106 | win.editmenu = mp = win.menucreate('Edit') |
| 107 | mp.callback = [] |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 108 | additem(mp, 'Cut', 'X', do_cut) |
| 109 | additem(mp, 'Copy', 'C', do_copy) |
| 110 | additem(mp, 'Paste', 'V', do_paste) |
| 111 | additem(mp, 'Clear', '', do_clear) |
| 112 | additem(mp, '', '', None) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 113 | win.iauto = len(mp.callback) |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 114 | additem(mp, 'Autoexecute', '', do_auto) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 115 | mp.check(win.iauto, win.auto) |
| 116 | win.insertOutputNum = len(mp.callback) |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 117 | additem(mp, 'Insert Output', '', do_insertOutputOption) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 118 | win.insertErrorNum = len(mp.callback) |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 119 | additem(mp, 'Insert Error', '', do_insertErrorOption) |
| 120 | additem(mp, 'Exec', '\r', do_exec) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 121 | |
| 122 | |
| 123 | # Helper to add a menu item and callback function |
| 124 | # |
| 125 | def additem(mp, text, shortcut, handler): |
| 126 | if shortcut: |
| 127 | mp.additem(text, shortcut) |
| 128 | else: |
| 129 | mp.additem(text) |
| 130 | mp.callback.append(handler) |
| 131 | |
| 132 | |
| 133 | # Dispatch a single event to the interpreter. |
| 134 | # Resize events cause a resize of the editor. |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 135 | # Some events are treated specially. |
| 136 | # Most other events are passed directly to the editor. |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 137 | # |
| 138 | def pdispatch(event): |
| 139 | type, win, detail = event |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 140 | if not win: |
| 141 | win = stdwin.getactive() |
| 142 | if not win: return |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 143 | if type == WE_CLOSE: |
| 144 | do_close(win) |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 145 | return |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 146 | elif type == WE_SIZE: |
| 147 | win.editor.move((0, 0), win.getwinsize()) |
| 148 | elif type == WE_COMMAND and detail == WC_RETURN: |
| 149 | if win.auto: |
| 150 | do_exec(win) |
| 151 | else: |
| 152 | void = win.editor.event(event) |
| 153 | elif type == WE_COMMAND and detail == WC_CANCEL: |
| 154 | if win.busy: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 155 | raise KeyboardInterrupt |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 156 | else: |
| 157 | win.command = '' |
| 158 | settitle(win) |
| 159 | elif type == WE_MENU: |
| 160 | mp, item = detail |
| 161 | mp.callback[item](win) |
| 162 | else: |
| 163 | void = win.editor.event(event) |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 164 | if win in mainloop.windows: |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 165 | # May have been deleted by close... |
| 166 | win.setdocsize(0, win.editor.getrect()[1][1]) |
| 167 | if type in (WE_CHAR, WE_COMMAND): |
| 168 | win.editor.setfocus(win.editor.getfocus()) |
| 169 | |
| 170 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 171 | # Helper to set the title of the window |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 172 | # |
| 173 | def settitle(win): |
| 174 | if win.filename == '': |
| 175 | win.settitle('Python interpreter ready') |
| 176 | else: |
| 177 | win.settitle(win.filename) |
| 178 | |
| 179 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 180 | # Helper to replace the text of the focus |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 181 | # |
| 182 | def replace(win, text): |
| 183 | win.editor.replace(text) |
| 184 | # Resize the window to display the text |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 185 | win.setdocsize(0, win.editor.getrect()[1][1]) # update the size before |
| 186 | win.editor.setfocus(win.editor.getfocus()) # move focus to the change |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 187 | |
| 188 | |
| 189 | # File menu handlers |
| 190 | # |
| 191 | def do_new(win): |
| 192 | win = makewindow() |
| 193 | # |
| 194 | def do_open(win): |
| 195 | try: |
| 196 | filename = stdwin.askfile('Open file', '', 0) |
| 197 | win = makewindow() |
| 198 | win.filename = filename |
Guido van Rossum | 4ea570d | 1992-03-30 11:01:26 +0000 | [diff] [blame] | 199 | win.editor.replace(open(filename, 'r').read()) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 200 | win.editor.setfocus(0, 0) |
| 201 | win.settitle(win.filename) |
| 202 | # |
| 203 | except KeyboardInterrupt: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 204 | pass # Don't give an error on cancel |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 205 | # |
| 206 | def do_save(win): |
| 207 | try: |
| 208 | if win.filename == '': |
| 209 | win.filename = stdwin.askfile('Open file', '', 1) |
| 210 | f = open(win.filename, 'w') |
| 211 | f.write(win.editor.gettext()) |
| 212 | # |
| 213 | except KeyboardInterrupt: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 214 | pass # Don't give an error on cancel |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 215 | |
| 216 | def do_saveas(win): |
| 217 | currentFilename = win.filename |
| 218 | win.filename = '' |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 219 | do_save(win) # Use do_save with empty filename |
| 220 | if win.filename == '': # Restore the name if do_save did not set it |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 221 | win.filename = currentFilename |
| 222 | # |
| 223 | def do_close(win): |
| 224 | if win.busy: |
| 225 | stdwin.message('Can\'t close busy window') |
| 226 | return # need to fail if quitting?? |
| 227 | win.editor = None # Break circular reference |
| 228 | #del win.editmenu # What about the filemenu?? |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 229 | mainloop.unregister(win) |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 230 | win.close() |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 231 | # |
| 232 | def do_quit(win): |
| 233 | # Call win.dispatch instead of do_close because there |
| 234 | # may be 'alien' windows in the list. |
Guido van Rossum | 63f4cdc | 1992-12-14 14:10:53 +0000 | [diff] [blame] | 235 | for win in mainloop.windows[:]: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 236 | mainloop.dispatch((WE_CLOSE, win, None)) |
| 237 | # need to catch failed close |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 238 | |
| 239 | |
| 240 | # Edit menu handlers |
| 241 | # |
| 242 | def do_cut(win): |
| 243 | text = win.editor.getfocustext() |
| 244 | if not text: |
| 245 | stdwin.fleep() |
| 246 | return |
| 247 | stdwin.setcutbuffer(0, text) |
| 248 | replace(win, '') |
| 249 | # |
| 250 | def do_copy(win): |
| 251 | text = win.editor.getfocustext() |
| 252 | if not text: |
| 253 | stdwin.fleep() |
| 254 | return |
| 255 | stdwin.setcutbuffer(0, text) |
| 256 | # |
| 257 | def do_paste(win): |
| 258 | text = stdwin.getcutbuffer(0) |
| 259 | if not text: |
| 260 | stdwin.fleep() |
| 261 | return |
| 262 | replace(win, text) |
| 263 | # |
| 264 | def do_clear(win): |
| 265 | replace(win, '') |
| 266 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 267 | |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 268 | # These would be better in a preferences dialog: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 269 | # |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 270 | def do_auto(win): |
| 271 | win.auto = (not win.auto) |
| 272 | win.editmenu.check(win.iauto, win.auto) |
| 273 | # |
| 274 | def do_insertOutputOption(win): |
| 275 | win.insertOutput = (not win.insertOutput) |
| 276 | title = ['Append Output', 'Insert Output'][win.insertOutput] |
| 277 | win.editmenu.setitem(win.insertOutputNum, title) |
| 278 | # |
| 279 | def do_insertErrorOption(win): |
| 280 | win.insertError = (not win.insertError) |
| 281 | title = ['Error Dialog', 'Insert Error'][win.insertError] |
| 282 | win.editmenu.setitem(win.insertErrorNum, title) |
| 283 | |
| 284 | |
| 285 | # Extract a command from the editor and execute it, or pass input to |
| 286 | # an interpreter waiting for it. |
| 287 | # Incomplete commands are merely placed in the window's command buffer. |
| 288 | # All exceptions occurring during the execution are caught and reported. |
| 289 | # (Tracebacks are currently not possible, as the interpreter does not |
| 290 | # save the traceback pointer until it reaches its outermost level.) |
| 291 | # |
| 292 | def do_exec(win): |
| 293 | if win.busy: |
| 294 | if win not in inputwindows: |
| 295 | stdwin.message('Can\'t run recursive commands') |
| 296 | return |
| 297 | if win <> inputwindows[0]: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 298 | stdwin.message('Please complete recursive input first') |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 299 | return |
| 300 | # |
| 301 | # Set text to the string to execute. |
| 302 | a, b = win.editor.getfocus() |
| 303 | alltext = win.editor.gettext() |
| 304 | n = len(alltext) |
| 305 | if a == b: |
| 306 | # There is no selected text, just an insert point; |
| 307 | # so execute the current line. |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 308 | while 0 < a and alltext[a-1] <> '\n': # Find beginning of line |
| 309 | a = a-1 |
| 310 | while b < n and alltext[b] <> '\n': # Find end of line after b |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 311 | b = b+1 |
| 312 | text = alltext[a:b] + '\n' |
| 313 | else: |
| 314 | # Execute exactly the selected text. |
| 315 | text = win.editor.getfocustext() |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 316 | if text[-1:] <> '\n': # Make sure text ends with \n |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 317 | text = text + '\n' |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 318 | while b < n and alltext[b] <> '\n': # Find end of line after b |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 319 | b = b+1 |
| 320 | # |
| 321 | # Set the focus to expect the output, since there is always something. |
| 322 | # Output will be inserted at end of line after current focus, |
| 323 | # or appended to the end of the text. |
| 324 | b = [n, b][win.insertOutput] |
| 325 | win.editor.setfocus(b, b) |
| 326 | # |
| 327 | # Make sure there is a preceeding newline. |
| 328 | if alltext[b-1:b] <> '\n': |
| 329 | win.editor.replace('\n') |
| 330 | # |
| 331 | # |
| 332 | if win.busy: |
| 333 | # Send it to raw_input() below |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 334 | raise InputAvailable, text |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 335 | # |
| 336 | # Like the real Python interpreter, we want to execute |
| 337 | # single-line commands immediately, but save multi-line |
| 338 | # commands until they are terminated by a blank line. |
| 339 | # Unlike the real Python interpreter, we don't do any syntax |
| 340 | # checking while saving up parts of a multi-line command. |
| 341 | # |
| 342 | # The current heuristic to determine whether a command is |
| 343 | # the first line of a multi-line command simply checks whether |
| 344 | # the command ends in a colon (followed by a newline). |
| 345 | # This is not very robust (comments and continuations will |
| 346 | # confuse it), but it is usable, and simple to implement. |
| 347 | # (It even has the advantage that single-line loops etc. |
| 348 | # don't need te be terminated by a blank line.) |
| 349 | # |
| 350 | if win.command: |
| 351 | # Already continuing |
| 352 | win.command = win.command + text |
| 353 | if win.command[-2:] <> '\n\n': |
| 354 | win.settitle('Unfinished command...') |
| 355 | return # Need more... |
| 356 | else: |
| 357 | # New command |
| 358 | win.command = text |
| 359 | if text[-2:] == ':\n': |
| 360 | win.settitle('Unfinished command...') |
| 361 | return |
| 362 | command = win.command |
| 363 | win.command = '' |
| 364 | win.settitle('Executing command...') |
| 365 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 366 | # Some hacks: |
| 367 | # - The standard files are replaced by an IOWindow instance. |
| 368 | # - A 2nd argument to exec() is used to specify the directory |
| 369 | # holding the user's global variables. (If this wasn't done, |
| 370 | # the exec would be executed in the current local environment, |
| 371 | # and the user's assignments to globals would be lost...) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 372 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 373 | save_stdin = sys.stdin |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 374 | save_stdout = sys.stdout |
| 375 | save_stderr = sys.stderr |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 376 | try: |
Guido van Rossum | d55f4d1 | 1993-12-17 14:39:12 +0000 | [diff] [blame] | 377 | sys.stdin = sys.stdout = sys.stderr = IOWindow(win) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 378 | win.busy = 1 |
| 379 | try: |
| 380 | exec(command, win.globals) |
| 381 | except KeyboardInterrupt: |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 382 | print '[Interrupt]' |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 383 | except: |
Guido van Rossum | 795a48c | 1995-03-22 12:17:10 +0000 | [diff] [blame] | 384 | if type(sys.exc_type) == type(''): |
| 385 | msg = sys.exc_type |
| 386 | else: msg = sys.exc_type.__name__ |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 387 | if sys.exc_value <> None: |
| 388 | msg = msg + ': ' + `sys.exc_value` |
| 389 | if win.insertError: |
| 390 | stdwin.fleep() |
| 391 | replace(win, msg + '\n') |
| 392 | else: |
| 393 | win.settitle('Unhandled exception') |
| 394 | stdwin.message(msg) |
| 395 | finally: |
| 396 | # Restore redirected I/O in *all* cases |
| 397 | win.busy = 0 |
| 398 | sys.stderr = save_stderr |
| 399 | sys.stdout = save_stdout |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 400 | sys.stdin = save_stdin |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 401 | settitle(win) |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 402 | |
| 403 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 404 | # Class emulating file I/O from/to a window |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 405 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 406 | class IOWindow: |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 407 | # |
Guido van Rossum | d55f4d1 | 1993-12-17 14:39:12 +0000 | [diff] [blame] | 408 | def __init__(self, win): |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 409 | self.win = win |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 410 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 411 | def readline(self, *unused_args): |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 412 | n = len(inputwindows) |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 413 | save_title = self.win.gettitle() |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 414 | title = n*'(' + 'Requesting input...' + ')'*n |
| 415 | self.win.settitle(title) |
| 416 | inputwindows.insert(0, self.win) |
| 417 | try: |
Guido van Rossum | cb4b295 | 1992-05-15 15:40:30 +0000 | [diff] [blame] | 418 | try: |
| 419 | mainloop.mainloop() |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 420 | finally: |
| 421 | del inputwindows[0] |
| 422 | self.win.settitle(save_title) |
| 423 | except InputAvailable, val: # See do_exec above |
| 424 | return val |
| 425 | except KeyboardInterrupt: |
| 426 | raise EOFError # Until we have a "send EOF" key |
| 427 | # If we didn't catch InputAvailable, something's wrong... |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 428 | raise EOFError |
| 429 | # |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 430 | def write(self, text): |
| 431 | mainloop.check() |
| 432 | replace(self.win, text) |
| 433 | mainloop.check() |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 434 | |
| 435 | |
| 436 | # Currently unused function to test a command's syntax without executing it |
| 437 | # |
| 438 | def testsyntax(s): |
| 439 | import string |
| 440 | lines = string.splitfields(s, '\n') |
| 441 | for i in range(len(lines)): lines[i] = '\t' + lines[i] |
| 442 | lines.insert(0, 'if 0:') |
| 443 | lines.append('') |
| 444 | exec(string.joinfields(lines, '\n')) |
| 445 | |
| 446 | |
Guido van Rossum | 5dd997c | 1992-12-22 14:34:43 +0000 | [diff] [blame] | 447 | # Call the main program |
Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame] | 448 | # |
| 449 | main() |