diff options
Diffstat (limited to 'Demo/stdwin/python.py')
-rwxr-xr-x | Demo/stdwin/python.py | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/Demo/stdwin/python.py b/Demo/stdwin/python.py deleted file mode 100755 index 8a3dfce..0000000 --- a/Demo/stdwin/python.py +++ /dev/null @@ -1,449 +0,0 @@ -#! /usr/bin/env python - -# A STDWIN-based front end for the Python interpreter. -# -# This is useful if you want to avoid console I/O and instead -# use text windows to issue commands to the interpreter. -# -# It supports multiple interpreter windows, each with its own context. -# -# BUGS AND CAVEATS: -# -# This was written long ago as a demonstration, and slightly hacked to -# keep it up-to-date, but never as an industry-strength alternative -# interface to Python. It should be rewritten using more classes, and -# merged with something like wdb. -# -# Although this supports multiple windows, the whole application -# is deaf and dumb when a command is running in one window. -# -# Interrupt is (ab)used to signal EOF on input requests. -# -# On UNIX (using X11), interrupts typed in the window will not be -# seen until the next input or output operation. When you are stuck -# in an infinite loop, try typing ^C in the shell window where you -# started this interpreter. (On the Mac, interrupts work normally.) - - -import sys -import stdwin -from stdwinevents import * -import rand -import mainloop -import os - - -# Stack of windows waiting for [raw_]input(). -# Element [0] is the top. -# If there are multiple windows waiting for input, only the -# one on top of the stack can accept input, because the way -# raw_input() is implemented (using recursive mainloop() calls). -# -inputwindows = [] - - -# Exception raised when input is available -# -InputAvailable = 'input available for raw_input (not an error)' - - -# Main program -- create the window and call the mainloop -# -def main(): - # Hack so 'import python' won't load another copy - # of this if we were loaded though 'python python.py'. - # (Should really look at sys.argv[0]...) - if 'inputwindows' in dir(sys.modules['__main__']) and \ - sys.modules['__main__'].inputwindows is inputwindows: - sys.modules['python'] = sys.modules['__main__'] - # - win = makewindow() - mainloop.mainloop() - - -# Create a new window -# -def makewindow(): - # stdwin.setdefscrollbars(0, 1) # Not in Python 0.9.1 - # stdwin.setfont('monaco') # Not on UNIX! and not Python 0.9.1 - # width, height = stdwin.textwidth('in')*40, stdwin.lineheight()*24 - # stdwin.setdefwinsize(width, height) - win = stdwin.open('Python interpreter ready') - win.editor = win.textcreate((0,0), win.getwinsize()) - win.globals = {} # Dictionary for user's globals - win.command = '' # Partially read command - win.busy = 0 # Ready to accept a command - win.auto = 1 # [CR] executes command - win.insertOutput = 1 # Insert output at focus - win.insertError = 1 # Insert error output at focus - win.setwincursor('ibeam') - win.filename = '' # Empty if no file for this window - makefilemenu(win) - makeeditmenu(win) - win.dispatch = pdispatch # Event dispatch function - mainloop.register(win) - return win - - -# Make a 'File' menu -# -def makefilemenu(win): - win.filemenu = mp = win.menucreate('File') - mp.callback = [] - additem(mp, 'New', 'N', do_new) - additem(mp, 'Open...', 'O', do_open) - additem(mp, '', '', None) - additem(mp, 'Close', 'W', do_close) - additem(mp, 'Save', 'S', do_save) - additem(mp, 'Save as...', '', do_saveas) - additem(mp, '', '', None) - additem(mp, 'Quit', 'Q', do_quit) - - -# Make an 'Edit' menu -# -def makeeditmenu(win): - win.editmenu = mp = win.menucreate('Edit') - mp.callback = [] - additem(mp, 'Cut', 'X', do_cut) - additem(mp, 'Copy', 'C', do_copy) - additem(mp, 'Paste', 'V', do_paste) - additem(mp, 'Clear', '', do_clear) - additem(mp, '', '', None) - win.iauto = len(mp.callback) - additem(mp, 'Autoexecute', '', do_auto) - mp.check(win.iauto, win.auto) - win.insertOutputNum = len(mp.callback) - additem(mp, 'Insert Output', '', do_insertOutputOption) - win.insertErrorNum = len(mp.callback) - additem(mp, 'Insert Error', '', do_insertErrorOption) - additem(mp, 'Exec', '\r', do_exec) - - -# Helper to add a menu item and callback function -# -def additem(mp, text, shortcut, handler): - if shortcut: - mp.additem(text, shortcut) - else: - mp.additem(text) - mp.callback.append(handler) - - -# Dispatch a single event to the interpreter. -# Resize events cause a resize of the editor. -# Some events are treated specially. -# Most other events are passed directly to the editor. -# -def pdispatch(event): - type, win, detail = event - if not win: - win = stdwin.getactive() - if not win: return - if type == WE_CLOSE: - do_close(win) - return - elif type == WE_SIZE: - win.editor.move((0, 0), win.getwinsize()) - elif type == WE_COMMAND and detail == WC_RETURN: - if win.auto: - do_exec(win) - else: - void = win.editor.event(event) - elif type == WE_COMMAND and detail == WC_CANCEL: - if win.busy: - raise KeyboardInterrupt - else: - win.command = '' - settitle(win) - elif type == WE_MENU: - mp, item = detail - mp.callback[item](win) - else: - void = win.editor.event(event) - if win in mainloop.windows: - # May have been deleted by close... - win.setdocsize(0, win.editor.getrect()[1][1]) - if type in (WE_CHAR, WE_COMMAND): - win.editor.setfocus(win.editor.getfocus()) - - -# Helper to set the title of the window -# -def settitle(win): - if win.filename == '': - win.settitle('Python interpreter ready') - else: - win.settitle(win.filename) - - -# Helper to replace the text of the focus -# -def replace(win, text): - win.editor.replace(text) - # Resize the window to display the text - win.setdocsize(0, win.editor.getrect()[1][1]) # update the size before - win.editor.setfocus(win.editor.getfocus()) # move focus to the change - - -# File menu handlers -# -def do_new(win): - win = makewindow() -# -def do_open(win): - try: - filename = stdwin.askfile('Open file', '', 0) - win = makewindow() - win.filename = filename - win.editor.replace(open(filename, 'r').read()) - win.editor.setfocus(0, 0) - win.settitle(win.filename) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel -# -def do_save(win): - try: - if win.filename == '': - win.filename = stdwin.askfile('Open file', '', 1) - f = open(win.filename, 'w') - f.write(win.editor.gettext()) - # - except KeyboardInterrupt: - pass # Don't give an error on cancel - -def do_saveas(win): - currentFilename = win.filename - win.filename = '' - do_save(win) # Use do_save with empty filename - if win.filename == '': # Restore the name if do_save did not set it - win.filename = currentFilename -# -def do_close(win): - if win.busy: - stdwin.message('Can\'t close busy window') - return # need to fail if quitting?? - win.editor = None # Break circular reference - #del win.editmenu # What about the filemenu?? - mainloop.unregister(win) - win.close() -# -def do_quit(win): - # Call win.dispatch instead of do_close because there - # may be 'alien' windows in the list. - for win in mainloop.windows[:]: - mainloop.dispatch((WE_CLOSE, win, None)) - # need to catch failed close - - -# Edit menu handlers -# -def do_cut(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) - replace(win, '') -# -def do_copy(win): - text = win.editor.getfocustext() - if not text: - stdwin.fleep() - return - stdwin.setcutbuffer(0, text) -# -def do_paste(win): - text = stdwin.getcutbuffer(0) - if not text: - stdwin.fleep() - return - replace(win, text) -# -def do_clear(win): - replace(win, '') - - -# These would be better in a preferences dialog: -# -def do_auto(win): - win.auto = (not win.auto) - win.editmenu.check(win.iauto, win.auto) -# -def do_insertOutputOption(win): - win.insertOutput = (not win.insertOutput) - title = ['Append Output', 'Insert Output'][win.insertOutput] - win.editmenu.setitem(win.insertOutputNum, title) -# -def do_insertErrorOption(win): - win.insertError = (not win.insertError) - title = ['Error Dialog', 'Insert Error'][win.insertError] - win.editmenu.setitem(win.insertErrorNum, title) - - -# Extract a command from the editor and execute it, or pass input to -# an interpreter waiting for it. -# Incomplete commands are merely placed in the window's command buffer. -# All exceptions occurring during the execution are caught and reported. -# (Tracebacks are currently not possible, as the interpreter does not -# save the traceback pointer until it reaches its outermost level.) -# -def do_exec(win): - if win.busy: - if win not in inputwindows: - stdwin.message('Can\'t run recursive commands') - return - if win <> inputwindows[0]: - stdwin.message('Please complete recursive input first') - return - # - # Set text to the string to execute. - a, b = win.editor.getfocus() - alltext = win.editor.gettext() - n = len(alltext) - if a == b: - # There is no selected text, just an insert point; - # so execute the current line. - while 0 < a and alltext[a-1] <> '\n': # Find beginning of line - a = a-1 - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - text = alltext[a:b] + '\n' - else: - # Execute exactly the selected text. - text = win.editor.getfocustext() - if text[-1:] <> '\n': # Make sure text ends with \n - text = text + '\n' - while b < n and alltext[b] <> '\n': # Find end of line after b - b = b+1 - # - # Set the focus to expect the output, since there is always something. - # Output will be inserted at end of line after current focus, - # or appended to the end of the text. - b = [n, b][win.insertOutput] - win.editor.setfocus(b, b) - # - # Make sure there is a preceeding newline. - if alltext[b-1:b] <> '\n': - win.editor.replace('\n') - # - # - if win.busy: - # Send it to raw_input() below - raise InputAvailable, text - # - # Like the real Python interpreter, we want to execute - # single-line commands immediately, but save multi-line - # commands until they are terminated by a blank line. - # Unlike the real Python interpreter, we don't do any syntax - # checking while saving up parts of a multi-line command. - # - # The current heuristic to determine whether a command is - # the first line of a multi-line command simply checks whether - # the command ends in a colon (followed by a newline). - # This is not very robust (comments and continuations will - # confuse it), but it is usable, and simple to implement. - # (It even has the advantage that single-line loops etc. - # don't need te be terminated by a blank line.) - # - if win.command: - # Already continuing - win.command = win.command + text - if win.command[-2:] <> '\n\n': - win.settitle('Unfinished command...') - return # Need more... - else: - # New command - win.command = text - if text[-2:] == ':\n': - win.settitle('Unfinished command...') - return - command = win.command - win.command = '' - win.settitle('Executing command...') - # - # Some hacks: - # - The standard files are replaced by an IOWindow instance. - # - A 2nd argument to exec() is used to specify the directory - # holding the user's global variables. (If this wasn't done, - # the exec would be executed in the current local environment, - # and the user's assignments to globals would be lost...) - # - save_stdin = sys.stdin - save_stdout = sys.stdout - save_stderr = sys.stderr - try: - sys.stdin = sys.stdout = sys.stderr = IOWindow(win) - win.busy = 1 - try: - exec(command, win.globals) - except KeyboardInterrupt: - print '[Interrupt]' - except: - if type(sys.exc_type) == type(''): - msg = sys.exc_type - else: msg = sys.exc_type.__name__ - if sys.exc_value <> None: - msg = msg + ': ' + `sys.exc_value` - if win.insertError: - stdwin.fleep() - replace(win, msg + '\n') - else: - win.settitle('Unhandled exception') - stdwin.message(msg) - finally: - # Restore redirected I/O in *all* cases - win.busy = 0 - sys.stderr = save_stderr - sys.stdout = save_stdout - sys.stdin = save_stdin - settitle(win) - - -# Class emulating file I/O from/to a window -# -class IOWindow: - # - def __init__(self, win): - self.win = win - # - def readline(self, *unused_args): - n = len(inputwindows) - save_title = self.win.gettitle() - title = n*'(' + 'Requesting input...' + ')'*n - self.win.settitle(title) - inputwindows.insert(0, self.win) - try: - try: - mainloop.mainloop() - finally: - del inputwindows[0] - self.win.settitle(save_title) - except InputAvailable, val: # See do_exec above - return val - except KeyboardInterrupt: - raise EOFError # Until we have a "send EOF" key - # If we didn't catch InputAvailable, something's wrong... - raise EOFError - # - def write(self, text): - mainloop.check() - replace(self.win, text) - mainloop.check() - - -# Currently unused function to test a command's syntax without executing it -# -def testsyntax(s): - import string - lines = string.splitfields(s, '\n') - for i in range(len(lines)): lines[i] = '\t' + lines[i] - lines.insert(0, 'if 0:') - lines.append('') - exec(string.joinfields(lines, '\n')) - - -# Call the main program -# -main() |