PyShell.py revision 83118c6cb36cf9a424bec1b9a2ef8c8760bae8f5
17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#! /usr/bin/env python
27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os
47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys
57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport string
67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport getopt
77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re
85d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport socket
95d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport time
1094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiserimport warnings
115d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport traceback
127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport linecache
147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom code import InteractiveInterpreter
157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom Tkinter import *
177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport tkMessageBox
187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom EditorWindow import EditorWindow, fixwordbreaks
207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom FileList import FileList
217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom ColorDelegator import ColorDelegator
227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom UndoDelegator import UndoDelegator
23969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserfrom OutputWindow import OutputWindow
249930061ce28b1fc60d267ae3474c74a41e655cd5Steven M. Gavafrom configHandler import idleConf
257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport idlever
267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
275d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport rpc
285d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
29969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser# XX hardwire this for now, remove later  KBK 09Jun02
30969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiseruse_subprocess = 1 # Set to 1 to spawn subprocess for command execution
315d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
325d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey# Change warnings module to write to sys.__stderr__
335d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teytry:
345d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    import warnings
355d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyexcept ImportError:
365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    pass
375d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyelse:
385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def idle_showwarning(message, category, filename, lineno):
395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        file = sys.__stderr__
405d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        file.write(warnings.formatwarning(message, category, filename, lineno))
415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    warnings.showwarning = idle_showwarning
425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# We need to patch linecache.checkcache, because we don't want it
447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# to throw away our <pyshell#...> entries.
457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# Rather than repeating its code here, we save those entries,
467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# then call the original function, and then restore the saved entries.
477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef linecache_checkcache(orig_checkcache=linecache.checkcache):
487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache = linecache.cache
497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    save = {}
507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    for filename in cache.keys():
517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if filename[:1] + filename[-1:] == '<>':
527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            save[filename] = cache[filename]
537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    orig_checkcache()
547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache.update(save)
557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererlinecache.checkcache = linecache_checkcache
567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# Note: <<newline-and-indent>> event is defined in AutoIndent.py
597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<plain-newline-and-indent>>
617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Control-j>
627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Control-j>
637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<beginning-of-line>>
657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Control-a>
667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Home>
677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Control-a>
687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Home>
697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<history-next>>
717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Alt-n>
727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Alt-n>
737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<history-previous>>
757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Alt-p>
767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Alt-p>
777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<interrupt-execution>>
797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Control-c>
807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Control-c>
817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<end-of-file>>
837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ win <Control-d>
847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ unix <Control-d>
857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<open-stack-viewer>>
877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#$ event <<toggle-debugger>>
897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellEditorWindow(EditorWindow):
927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Regular text edit window when a shell is present
947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # XXX ought to merge with regular editor window
957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, *args):
977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        apply(EditorWindow.__init__, (self,) + args)
987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
99669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        self.text.bind("<<clear-breakpoint-here>>",
100669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser                       self.clear_breakpoint_here)
1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
1027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    rmenu_specs = [
104669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        ("Set Breakpoint", "<<set-breakpoint-here>>"),
105669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        ("Clear Breakpoint", "<<clear-breakpoint-here>>")
1067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ]
1077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_breakpoint_here(self, event=None):
1097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
1107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.bell()
1117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
1127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell.interp.debugger.set_breakpoint_here(self)
1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
114669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser    def clear_breakpoint_here(self, event=None):
115669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
116669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            self.text.bell()
117669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            return
118669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        self.flist.pyshell.interp.debugger.clear_breakpoint_here(self)
119669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser
1207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellFileList(FileList):
12283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: file list when a shell is present"
1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    EditorWindow = PyShellEditorWindow
1257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    pyshell = None
1277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_shell(self, event=None):
1297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.pyshell:
1307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell.wakeup()
1317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell = PyShell(self)
1337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell.begin()
1347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.pyshell
1357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedColorDelegator(ColorDelegator):
13883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: colorizer for the shell window itself"
139b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava
140b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def __init__(self):
141b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.__init__(self)
142b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.LoadTagDefs()
1437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recolorize_main(self):
1457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_remove("TODO", "1.0", "iomark")
1467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_add("SYNC", "1.0", "iomark")
1477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ColorDelegator.recolorize_main(self)
148b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava
149b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def LoadTagDefs(self):
150b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.LoadTagDefs(self)
151b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        theme = idleConf.GetOption('main','Theme','name')
152b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.tagdefs.update({
153b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdin": {'background':None,'foreground':None},
154b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdout": idleConf.GetHighlight(theme, "stdout"),
155b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stderr": idleConf.GetHighlight(theme, "stderr"),
156b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "console": idleConf.GetHighlight(theme, "console"),
157b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "ERROR": idleConf.GetHighlight(theme, "error"),
158b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            None: idleConf.GetHighlight(theme, "normal"),
159b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        })
1607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedUndoDelegator(UndoDelegator):
16283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: forbid insert/delete before the I/O mark"
1637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def insert(self, index, chars, tags=None):
1657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
1667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index, "<", "iomark"):
1677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
1687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
1697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
1707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
1717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.insert(self, index, chars, tags)
1727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def delete(self, index1, index2=None):
1747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
1757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index1, "<", "iomark"):
1767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
1777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
1787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
1797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
1807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.delete(self, index1, index2)
1817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedInterpreter(InteractiveInterpreter):
1837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, tkconsole):
1857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole = tkconsole
1867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        locals = sys.modules['__main__'].__dict__
1877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.__init__(self, locals=locals)
18894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = None
1897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcclt = None
1915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcpid = None
1925d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
1935d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def spawn_subprocess(self):
1945d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        port = 8833
1955d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        addr = ("localhost", port)
1965d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        w = ['-W' + s for s in sys.warnoptions]
1975d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        args = [sys.executable] + w + ["-c", "__import__('run').main()",
1985d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                                       str(port)]
1995d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcpid = os.spawnv(os.P_NOWAIT, args[0], args)
2005d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        for i in range(5):
2015d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            time.sleep(i)
2025d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
2035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                self.rpcclt = rpc.RPCClient(addr)
2045d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                break
2055d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            except socket.error, err:
2065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if i > 3:
2075d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    print >>sys.__stderr__, "Socket error:", err, "; retry..."
2085d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
209969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            # XXX Make this a dialog?  #GvR
2105d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            print >>sys.__stderr__, "Can't spawn subprocess!"
211969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            # XXX Add Stephen's error msg, resolve the two later... KBK 09Jun02
212969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            display_port_binding_error()
2135d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
214969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdin", self.tkconsole)
215969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdout", self.tkconsole.stdout)
216969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stderr", self.tkconsole.stderr)
2175d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt.register("flist", self.tkconsole.flist)
2185d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.poll_subprocess()
2195d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2205d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    active_seq = None
2215d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2225d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def poll_subprocess(self):
2235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
2245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is None:
2255d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
2265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        response = clt.pollresponse(self.active_seq)
2275d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.tkconsole.text.after(50, self.poll_subprocess)
2285d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if response:
2295d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.resetoutput()
2305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = None
2315d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            how, what = response
2325d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            file = self.tkconsole.console
2335d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            if how == "OK":
2345d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if what is not None:
2355d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    print >>file, `what`
2365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "EXCEPTION":
2375d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                mod, name, args, tb = what
2385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, 'Traceback (most recent call last):'
2395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                while tb and tb[0][0] in ("run.py", "rpc.py"):
2405d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    del tb[0]
2415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                while tb and tb[-1][0] in ("run.py", "rpc.py"):
2425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    del tb[-1]
2435d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                for i in range(len(tb)):
2445d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    fn, ln, nm, line = tb[i]
2455d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    if not line and fn.startswith("<pyshell#"):
2465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                        line = linecache.getline(fn, ln)
2475d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                        tb[i] = fn, ln, nm, line
2485d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                traceback.print_list(tb, file=file)
2495d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if mod and mod != "exceptions":
2505d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    name = mod + "." + name
2515d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, name + ":", " ".join(map(str, args))
2525d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
2535d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    self.remote_stack_viewer()
2545d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "ERROR":
2555d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>sys.__stderr__, "Oops:", how, what
2565d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, "Oops:", how, what
2575d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.endexecuting()
2585d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2595d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def kill_subprocess(self):
2605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
2615d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt = None
2625d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is not None:
2635d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            clt.close()
2645d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2655d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def remote_stack_viewer(self):
2665d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        import RemoteObjectBrowser
2675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        oid = self.rpcclt.remotecall("exec", "stackviewer", ("flist",), {})
2685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if oid is None:
2695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.root.bell()
2705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
2715d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
2725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        from TreeWidget import ScrolledCanvas, TreeNode
2735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        top = Toplevel(self.tkconsole.root)
2745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
2755d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc.frame.pack(expand=1, fill="both")
2765d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node = TreeNode(sc.canvas, None, item)
2775d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node.expand()
2785d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # XXX Should GC the remote tree when closing the window
2795d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    gid = 0
2817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
2827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execsource(self, source):
28383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Like runsource() but assumes complete exec source"
2847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
2857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.execfile(filename, source)
2867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
2877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execfile(self, filename, source=None):
28883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Execute an existing file"
2897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if source is None:
2907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            source = open(filename, "r").read()
2917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
2927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            code = compile(source, filename, "exec")
2937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except (OverflowError, SyntaxError):
2947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
2957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
2967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
2977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runcode(code)
2987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
2997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runsource(self, source):
30083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method: Stuff the source in the line cache first"
3017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
3027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.more = 0
30394bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = warnings.filters[:]
30494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        warnings.filterwarnings(action="error", category=SyntaxWarning)
30594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        try:
30694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            return InteractiveInterpreter.runsource(self, source, filename)
30794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        finally:
30894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            if self.save_warnings_filters is not None:
30994bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                warnings.filters[:] = self.save_warnings_filters
31094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                self.save_warnings_filters = None
3117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def stuffsource(self, source):
31383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Stuff source in the filename cache"
3147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = "<pyshell#%d>" % self.gid
3157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.gid = self.gid + 1
3167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        lines = string.split(source, "\n")
3177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        linecache.cache[filename] = len(source)+1, 0, lines, filename
3187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return filename
3197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showsyntaxerror(self, filename=None):
32183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """Extend base class method: Add Colorizing
32283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
32383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        Color the offending position instead of printing it and pointing at it
32483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        with a caret.
32583118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
32683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """
3277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.tkconsole.text
3287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        stuff = self.unpackerror()
3297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not stuff:
3307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
3327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
3337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        msg, lineno, offset, line = stuff
3347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if lineno == 1:
3357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pos = "iomark + %d chars" % (offset-1)
3367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pos = "iomark linestart + %d lines + %d chars" % (lineno-1,
3387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                                                              offset-1)
3397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.tag_add("ERROR", pos)
3407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.see(pos)
3417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        char = text.get(pos)
3427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if char and char in string.letters + string.digits + "_":
3437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            text.tag_add("ERROR", pos + " wordstart", pos)
3447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
3457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.write("SyntaxError: %s\n" % str(msg))
3467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def unpackerror(self):
3487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        type, value, tb = sys.exc_info()
3497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ok = type is SyntaxError
3507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
3517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
3527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                msg, (dummy_filename, lineno, offset, line) = value
3537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
3547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                ok = 0
3557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
3567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return msg, lineno, offset, line
3577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return None
3597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showtraceback(self):
36183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method to reset output properly"
3627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
3637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.checklinecache()
3647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.showtraceback(self)
3655d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
3665d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.open_stack_viewer()
3677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def checklinecache(self):
3697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        c = linecache.cache
3707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for key in c.keys():
3717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if key[:1] + key[-1:] != "<>":
3727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del c[key]
3737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    debugger = None
3757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def setdebugger(self, debugger):
3777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.debugger = debugger
3787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def getdebugger(self):
3807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.debugger
3817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3825d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def runcommand(self, code):
38383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Run the code without invoking the debugger"
3845d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # The code better not raise an exception!
3855d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
3865d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            tkMessageBox.showerror(
3875d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "Already executing",
3885d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "The Python Shell window is already executing a command; "
3895d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "please wait until it is finished.",
3905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                master=self.tkconsole.text)
3915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return 0
3925d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.rpcclt:
3935d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.rpcclt.remotecall("exec", "runcode", (code,), {})
3945d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
3955d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            exec code in self.locals
3965d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        return 1
3975d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
3987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runcode(self, code):
39983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
4005d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
4015d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            tkMessageBox.showerror(
4025d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "Already executing",
4035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "The Python Shell window is already executing a command; "
4045d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                "please wait until it is finished.",
4055d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                master=self.tkconsole.text)
4065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
40783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        #
4085d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.checklinecache()
40994bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        if self.save_warnings_filters is not None:
41094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            warnings.filters[:] = self.save_warnings_filters
41194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            self.save_warnings_filters = None
4127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        debugger = self.debugger
4135d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not debugger and self.rpcclt is not None:
4145d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.beginexecuting()
4155d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = self.rpcclt.asynccall("exec", "runcode",
4165d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                                                    (code,), {})
4175d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
41883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        #
4197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
4207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.beginexecuting()
4217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
4227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if debugger:
4237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    debugger.run(code, self.locals)
4247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                else:
4257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    exec code in self.locals
4267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except SystemExit:
4277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if tkMessageBox.askyesno(
4287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    "Exit?",
4297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    "Do you want to exit altogether?",
4307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    default="yes",
4317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    master=self.tkconsole.text):
4327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    raise
4337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                else:
4347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    self.showtraceback()
4357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
4367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.showtraceback()
43783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        #
4387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
4397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.endexecuting()
4407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
44283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
4437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.console.write(s)
4447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShell(OutputWindow):
4467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    shell_title = "Python Shell"
4487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Override classes
4507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ColorDelegator = ModifiedColorDelegator
4517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    UndoDelegator = ModifiedUndoDelegator
4527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Override menu bar specs
4547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    menu_specs = PyShellEditorWindow.menu_specs[:]
4553b55a891a197212b34b0c077f72cb3af752468ecSteven M. Gava    menu_specs.insert(len(menu_specs)-3, ("debug", "_Debug"))
4567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # New classes
4587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    from IdleHistory import History
4597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, flist=None):
4617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = ModifiedInterpreter(self)
4627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if flist is None:
4637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root = Tk()
4647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            fixwordbreaks(root)
4657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root.withdraw()
4667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            flist = PyShellFileList(root)
4677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.__init__(self, flist, None, None)
4697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import __builtin__
4717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
4727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.auto = self.extensions["AutoIndent"] # Required extension
4747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.auto.config(usetabs=1, indentwidth=8, context_use_ps1=1)
4757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.text
4777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.configure(wrap="char")
4787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<newline-and-indent>>", self.enter_callback)
4797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
4807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<interrupt-execution>>", self.cancel_callback)
4817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<beginning-of-line>>", self.home_callback)
4827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<end-of-file>>", self.eof_callback)
4837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
4847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-debugger>>", self.toggle_debugger)
4857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-python-shell>>", self.flist.open_shell)
4867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
4877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdout = sys.stdout
4897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stderr = sys.stderr
4907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdin = sys.stdin
4915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.stdout = PseudoFile(self, "stdout")
4925d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.stderr = PseudoFile(self, "stderr")
4937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = PseudoFile(self, "console")
4945d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not use_subprocess:
4955d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdout = self.stdout
4965d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stderr = self.stderr
4975d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdin = self
4987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = self.History(self.text)
5007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5015d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if use_subprocess:
5025d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.interp.spawn_subprocess()
5035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    reading = 0
5057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    executing = 0
5067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    canceled = 0
5077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    endoffile = 0
5087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_debugger(self, event=None):
5107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
5117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("Don't debug now",
5127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "You can only toggle the debugger when idle",
5137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
5147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.set_debugger_indicator()
5157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
5167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
5177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db = self.interp.getdebugger()
5187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if db:
5197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.close_debugger()
5207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            else:
5217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.open_debugger()
5227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_debugger_indicator(self):
5247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
5257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.setvar("<<toggle-debugger>>", not not db)
5267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_jit_stack_viewer( self, event=None):
5287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass # All we need is the variable
5297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close_debugger(self):
5317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
5327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if db:
5337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.interp.setdebugger(None)
5347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db.close()
5357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
5367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.console.write("[DEBUG OFF]\n")
5377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
5387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
5397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
5407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_debugger(self):
5420e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # XXX KBK 13Jun02 An RPC client always exists now? Open remote
5430e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # debugger and return...dike the rest of this fcn and combine
5440e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # with open_remote_debugger?
5455d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
5465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.open_remote_debugger()
5477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import Debugger
5487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp.setdebugger(Debugger.Debugger(self))
5497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.ps1 = "[DEBUG ON]\n>>> "
5507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
5517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
5527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5535d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def open_remote_debugger(self):
5545d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        import RemoteDebugger
5555d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, self)
5565d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.interp.setdebugger(gui)
5575d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sys.ps1 = "[DEBUG ON]\n>>> "
5585d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
5595d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_debugger_indicator()
5605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def beginexecuting(self):
5627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Helper for ModifiedInterpreter
5637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
5647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 1
5657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##self._cancel_check = self.cancel_check
5667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##sys.settrace(self._cancel_check)
5677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def endexecuting(self):
56983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Helper for ModifiedInterpreter"
5707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##sys.settrace(None)
5717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##self._cancel_check = None
5727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 0
5737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.canceled = 0
5745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
5757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close(self):
57783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow.close()"
5787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
5797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # XXX Need to ask a question here
5807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if not tkMessageBox.askokcancel(
5817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "Kill?",
5827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "The program is still running; do you want to kill it?",
5837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                default="ok",
5847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text):
5857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "cancel"
5867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 1
5877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.reading:
5887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.top.quit()
5897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "cancel"
59083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        return EditorWindow.close(self)
5917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def _close(self):
59383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow._close(), shut down debugger and execution server"
5947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.close_debugger()
5955d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.interp.kill_subprocess()
5967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Restore std streams
5977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout = self.save_stdout
5987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stderr = self.save_stderr
5997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdin = self.save_stdin
6007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Break cycles
6017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = None
6027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = None
6037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.auto = None
6047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell = None
6057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = None
60683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        EditorWindow._close(self)
6077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def ispythonsource(self, filename):
60983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override EditorWindow method: never remove the colorizer"
6107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return 1
6117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def short_title(self):
6137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.shell_title
6147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
61594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser    COPYRIGHT = \
61694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser              'Type "copyright", "credits" or "license" for more information.'
61794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser
6187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def begin(self):
6197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
620969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.write("Python %s on %s\n%s\nGRPC IDLE Fork %s\n" %
62194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                   (sys.version, sys.platform, self.COPYRIGHT,
6227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    idlever.IDLE_VERSION))
6237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1
6257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except AttributeError:
6267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
6277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
6287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import Tkinter
6297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        Tkinter._default_root = None
6307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def interact(self):
6327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.begin()
6337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.top.mainloop()
6347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def readline(self):
6367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        save = self.reading
6377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = 1
6397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.mainloop()
6407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
6417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = save
6427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
6437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
6447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
6457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
6467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
6477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.endoffile:
6487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 0
6497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return ""
6507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return line
6517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
6537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return 1
6547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def cancel_callback(self, event):
6567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.text.compare("sel.first", "!=", "sel.last"):
6587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return # Active selection -- always use default binding
6597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
6607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
6617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.executing or self.reading):
6627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
6637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.write("KeyboardInterrupt\n")
6647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
6657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
6667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.endoffile = 0
6677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
6685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.canceled = 1
6697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
6705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        elif (self.executing and self.interp.rpcclt and
6715d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey              self.interp.rpcpid and hasattr(os, "kill")):
6725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
6735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                from signal import SIGINT
6745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            except ImportError:
6755d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                SIGINT = 2
6765d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            os.kill(self.interp.rpcpid, SIGINT)
6775d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
6785d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.canceled = 1
6797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
6807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def eof_callback(self, event):
6827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
6837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
6847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.text.compare("iomark", "==", "insert") and
6857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.text.compare("insert", "==", "end-1c")):
6867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
6877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.executing:
6887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
6897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.close()
6907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
6917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
6927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 1
6937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
6947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
6957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def home_callback(self, event):
6977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if event.state != 0 and event.keysym == "Home":
6987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # <Modifier-Home>; fall back to class binding
6997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("iomark", "<=", "insert") and \
7007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer           self.text.compare("insert linestart", "<=", "iomark"):
7017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.mark_set("insert", "iomark")
7027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.tag_remove("sel", "1.0", "end")
7037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def linefeed_callback(self, event):
7077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Insert a linefeed without entering anything (still autoindented)
7087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
7107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.auto.auto_indent(event)
7137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
7147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def enter_callback(self, event):
7167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
7177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (insert '\n') take over
7187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If some text is selected, recall the selection
7197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (but only if this before the I/O mark)
7207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
7217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sel = self.text.get("sel.first", "sel.last")
7227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if sel:
7237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if self.text.compare("sel.last", "<=", "iomark"):
7247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    self.recall(sel)
7257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    return "break"
7267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
7277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
7287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're strictly before the line containing iomark, recall
7297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # the current line, less a leading prompt, less leading or
7307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # trailing whitespace
7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "iomark linestart"):
7327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Check if there's a relevant stdin range -- if so, use it
7337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            prev = self.text.tag_prevrange("stdin", "insert")
7347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if prev and self.text.compare("insert", "<", prev[1]):
7357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.recall(self.text.get(prev[0], prev[1]))
7367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
7377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            next = self.text.tag_nextrange("stdin", "insert")
7387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if next and self.text.compare("insert lineend", ">=", next[0]):
7397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.recall(self.text.get(next[0], next[1]))
7407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
7417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # No stdin mark -- just get the current line
7427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.recall(self.text.get("insert linestart", "insert lineend"))
7437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input and there's only whitespace
7457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # beyond the cursor, erase that whitespace first
7467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        s = self.text.get("insert", "end-1c")
7477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if s and not string.strip(s):
7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.delete("insert", "end-1c")
7497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input before its last line,
7507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # insert a newline right at the insert point
7517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "end-1c linestart"):
7527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.auto.auto_indent(event)
7537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # We're in the last line; append a newline and submit it
7557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
7587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.auto.auto_indent(event)
7617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.tag_add("stdin", "iomark", "end-1c")
7627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.update_idletasks()
7637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit() # Break out of recursive mainloop() in raw_input()
7657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runit()
7677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
7687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recall(self, s):
7707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
7717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.history.recall(s)
7727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runit(self):
7747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
7757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Strip off last newline and surrounding whitespace.
7767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (To allow you to hit return twice to end a statement.)
7777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        i = len(line)
7787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
7797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if i > 0 and line[i-1] == "\n":
7817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
7837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = line[:i]
7857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        more = self.interp.runsource(line)
7867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def cancel_check(self, frame, what, args,
7887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                     dooneevent=tkinter.dooneevent,
7897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                     dontwait=tkinter.DONT_WAIT):
7907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Hack -- use the debugger hooks to be able to handle events
7917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # and interrupt execution at any time.
7927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # This slows execution down quite a bit, so you may want to
7937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # disable this (by not calling settrace() in runcode() above)
7947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # for full-bore (uninterruptable) speed.
7957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # XXX This should become a user option.
7967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
7977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
7987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        dooneevent(dontwait)
7997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
8007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
8017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
8027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self._cancel_check
8037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_stack_viewer(self, event=None):
8055d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
8065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.interp.remote_stack_viewer()
8077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
8087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.last_traceback
8097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
8107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("No stack trace",
8117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "There is no stack trace yet.\n"
8127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "(sys.last_traceback is not defined)",
8137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
8147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
8157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        from StackViewer import StackBrowser
8167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sv = StackBrowser(self.root, self.flist)
8177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showprompt(self):
8197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
8207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
8217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = str(sys.ps1)
8227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
8237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = ""
8247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console.write(s)
8257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
8265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
8277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def resetoutput(self):
8297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        source = self.text.get("iomark", "end-1c")
8307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
8317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.history.history_store(source)
8327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.get("end-2c") != "\n":
8337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("end-1c", "\n")
8347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("iomark", "end-1c")
8355d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
8367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout.softspace = 0
8377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s, tags=()):
8397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_gravity("iomark", "right")
8407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.write(self, s, tags, "iomark")
8417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_gravity("iomark", "left")
8427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
8437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
8447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
8457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PseudoFile:
8477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, shell, tags):
8497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.shell = shell
8507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tags = tags
8515d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.softspace = 0
8527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
8547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.shell.write(s, self.tags)
8557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def writelines(self, l):
8577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        map(self.write, l)
8587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def flush(self):
8607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass
8617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
8637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return 1
8647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
865969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
8667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererusage_msg = """\
86796d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiserusage: idle.py [-c command] [-d] [-i] [-r script] [-s] [-t title] [arg] ...
8687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
86996d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiseridle file(s)    (without options) edit the file(s)
8707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
87196d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-c cmd     run the command in a shell
87296d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-d         enable the debugger
8735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey-e         edit mode; arguments are files to be edited
87496d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-i         open an interactive shell
87596d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-i file(s) open a shell and also an editor window for each file
876969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser-r
87796d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
87896d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-t title   set title of shell window
87996d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser
88096d88422373ffb32aef75157647e0575a0471c03Kurt B. KaiserRemaining arguments are applied to the command (-c) or script (-r).
8817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer"""
8827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
883969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef main():
884969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    cmd = None
885969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    edit = 0
886969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    debug = 0
887969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    script = None
888969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    startup = 0
889969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
890969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    try:
891969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        opts, args = getopt.getopt(sys.argv[1:], "c:deir:st:")
892969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    except getopt.error, msg:
893969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.stderr.write("Error: %s\n" % str(msg))
894969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.stderr.write(usage_msg)
895969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.exit(2)
896969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
897969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for o, a in opts:
898969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-c':
899969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            cmd = a
900969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-d':
901969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            debug = 1
902969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-e':
903969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            edit = 1
904969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-r':
905969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            script = a
906969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-s':
907969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            startup = 1
908969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-t':
909969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            PyShell.shell_title = a
910969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
911969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if args and args[0] != "-": edit = 1
912969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
913969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for i in range(len(sys.path)):
914969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.path[i] = os.path.abspath(sys.path[i])
915969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
916969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    pathx = []
917969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if edit:
918969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
919969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            pathx.append(os.path.dirname(filename))
920969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    elif args and args[0] != "-":
921969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        pathx.append(os.path.dirname(args[0]))
922969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    else:
923969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        pathx.append(os.curdir)
924969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for dir in pathx:
925969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        dir = os.path.abspath(dir)
926969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if not dir in sys.path:
927969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.path.insert(0, dir)
928969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
929969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    global flist, root
930969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root = Tk(className="Idle")
931969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    fixwordbreaks(root)
932969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.withdraw()
933969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist = PyShellFileList(root)
934969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
935969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if edit:
936969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
937969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            flist.open(filename)
938969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if not args:
939969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            flist.new()
940969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    else:
941969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if cmd:
942969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.argv = ["-c"] + args
943969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        else:
944969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.argv = args or [""]
945969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
946969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    shell = PyShell(flist)
947969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    interp = shell.interp
948969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist.pyshell = shell
949969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
950969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if startup:
951969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        filename = os.environ.get("IDLESTARTUP") or \
952969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser                   os.environ.get("PYTHONSTARTUP")
953969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if filename and os.path.isfile(filename):
954969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            interp.execfile(filename)
955969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
956969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if debug:
957969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        shell.open_debugger()
958969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if cmd:
959969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        interp.execsource(cmd)
960969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    elif script:
961969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if os.path.isfile(script):
962969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            interp.execfile(script)
963969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        else:
964969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            print "No script file: ", script
965969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    shell.begin()
966969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.mainloop()
967969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.destroy()
968969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
969969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef display_port_binding_error():
970969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    print """\
9711f733baa04a56eed0a5823158205fc04502e3050Steven M. GavaIDLE cannot run.
9721f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
973969de458aa12e831942637bbcd9994b29dc86252Kurt B. KaiserIDLE needs to use a specific TCP/IP port (8833) in order to execute and
9741f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavadebug programs. IDLE is unable to bind to this port, and so cannot
9751f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavastart. Here are some possible causes of this problem:
9761f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
9771f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava  1. TCP/IP networking is not installed or not working on this computer
9781f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava  2. Another program is running that uses this port
979969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser  3. Personal firewall software is preventing IDLE from using this port
9801f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
9811f733baa04a56eed0a5823158205fc04502e3050Steven M. GavaIDLE makes and accepts connections only with this computer, and does not
982969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaisercommunicate over the internet in any way. Its use of port 8833 should not
9831f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavabe a security risk on a single-user machine.
9841f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava"""
9857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == "__main__":
9877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    main()
988