190f5ba538bf40bcf4fd41049c7bf4296d3ffc9c7Benjamin Peterson#! /usr/bin/env python3
27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
31080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedytry:
41080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    from tkinter import *
51080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedyexcept ImportError:
61080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    print("** IDLE can't import Tkinter.\n"
71080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy          "Your Python may not be configured for Tk. **", file=sys.__stderr__)
8e16265d36797d2929e653a7d49b1a53accdbec59Terry Jan Reedy    raise SystemExit(1)
91080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedyimport tkinter.messagebox as tkMessageBox
101080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedyif TkVersion < 8.5:
111080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    root = Tk()  # otherwise create root in main
121080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    root.withdraw()
131080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    tkMessageBox.showerror("Idle Cannot Start",
14e16265d36797d2929e653a7d49b1a53accdbec59Terry Jan Reedy            "Idle requires tcl/tk 8.5+, not %s." % TkVersion,
151080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy            parent=root)
16e16265d36797d2929e653a7d49b1a53accdbec59Terry Jan Reedy    raise SystemExit(1)
171080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy
18bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom code import InteractiveInterpreter
19979482a3154540ffde1cb0f374cab4421995660dVictor Stinnerimport getopt
20bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyimport io
21bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyimport linecache
227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os
236e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiserimport os.path
24bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom platform import python_version, system
257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re
265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport socket
27979482a3154540ffde1cb0f374cab4421995660dVictor Stinnerimport subprocess
28979482a3154540ffde1cb0f374cab4421995660dVictor Stinnerimport sys
29003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiserimport threading
30979482a3154540ffde1cb0f374cab4421995660dVictor Stinnerimport time
31979482a3154540ffde1cb0f374cab4421995660dVictor Stinnerimport tokenize
32bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyimport warnings
337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
34bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib import testing  # bool value
356fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib.colorizer import ColorDelegator
366fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib.config import idleConf
376fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib import debugger
386fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib import debugger_r
39bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib.editor import EditorWindow, fixwordbreaks
40bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib.filelist import FileList
416fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedyfrom idlelib import macosx
42bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib.outwin import OutputWindow
43bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib import rpc
44bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib.run import idle_formatwarning, PseudoInputFile, PseudoOutputFile
45bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedyfrom idlelib.undo import UndoDelegator
465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
47e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. KaiserHOST = '127.0.0.1' # python execution server on localhost loopback
48e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. KaiserPORT = 0  # someday pass in host, port for remote debug capability
49b97641994617115321719d4ecf797a461e2d5cf2Kurt B. Kaiser
5049a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# Override warnings module to write to warning_stream.  Initialize to send IDLE
5149a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# internal warnings to the console.  ScriptBinding.check_syntax() will
5249a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# temporarily redirect the stream to the shell window to display warnings when
5349a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# checking user's code.
5495a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedywarning_stream = sys.__stderr__  # None, at least on Windows, if no console.
5595a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
5695a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedydef idle_showwarning(
5795a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        message, category, filename, lineno, file=None, line=None):
5895a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    """Show Idle-format warning (after replacing warnings.showwarning).
5995a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
6095a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    The differences are the formatter called, the file=None replacement,
6195a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    which can be None, the capture of the consequence AttributeError,
6295a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    and the output of a hard-coded prompt.
6395a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    """
6495a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    if file is None:
6595a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        file = warning_stream
6695a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    try:
6795a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        file.write(idle_formatwarning(
6895a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy                message, category, filename, lineno, line=line))
6995a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        file.write(">>> ")
7095a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    except (AttributeError, OSError):
7195a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        pass  # if file (probably __stderr__) is invalid, skip warning.
7295a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
7395a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy_warnings_showwarning = None
7495a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
7595a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedydef capture_warnings(capture):
7695a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    "Replace warning.showwarning with idle_showwarning, or reverse."
7795a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
7895a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    global _warnings_showwarning
7995a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    if capture:
8095a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        if _warnings_showwarning is None:
8195a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy            _warnings_showwarning = warnings.showwarning
8295a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy            warnings.showwarning = idle_showwarning
8395a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    else:
8495a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy        if _warnings_showwarning is not None:
8595a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy            warnings.showwarning = _warnings_showwarning
8695a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy            _warnings_showwarning = None
8795a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
8895a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedycapture_warnings(True)
895d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
90f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiserdef extended_linecache_checkcache(filename=None,
91f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser                                  orig_checkcache=linecache.checkcache):
9245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    """Extend linecache.checkcache to preserve the <pyshell#...> entries
9345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
94f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    Rather than repeating the linecache code, patch it to save the
95f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    <pyshell#...> entries, call the original linecache.checkcache()
961fff00832639082d2d7aa354c8e6d9110171d6bcGuilherme Polo    (skipping them), and then restore the saved entries.
97f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser
98f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    orig_checkcache is bound at definition time to the original
99f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    method, allowing it to be patched.
10045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    """
1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache = linecache.cache
1027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    save = {}
1031fff00832639082d2d7aa354c8e6d9110171d6bcGuilherme Polo    for key in list(cache):
1041fff00832639082d2d7aa354c8e6d9110171d6bcGuilherme Polo        if key[:1] + key[-1:] == '<>':
1051fff00832639082d2d7aa354c8e6d9110171d6bcGuilherme Polo            save[key] = cache.pop(key)
1061fff00832639082d2d7aa354c8e6d9110171d6bcGuilherme Polo    orig_checkcache(filename)
1077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache.update(save)
1086655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
109818855939ac016492cb59d1fc2fea94cc0764855Kurt B. Kaiser# Patch linecache.checkcache():
110818855939ac016492cb59d1fc2fea94cc0764855Kurt B. Kaiserlinecache.checkcache = extended_linecache_checkcache
1117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellEditorWindow(EditorWindow):
114183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    "Regular text edit window in IDLE, supports breakpoints"
11545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
1167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, *args):
11745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.breakpoints = []
118931237e2e66975c54e2ac6c5e503ee2992a22bcfRaymond Hettinger        EditorWindow.__init__(self, *args)
1197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
12045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
1217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
1227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
123bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
124bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                                           'breakpoints.lst')
125a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        # whenever a file is changed, restore breakpoints
126bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        def filename_changed_hook(old_hook=self.io.filename_change_hook,
127bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                                  self=self):
128a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            self.restore_file_breaks()
129a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            old_hook()
130a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.io.set_filename_change_hook(filename_changed_hook)
131d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy        if self.io.filename:
132d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            self.restore_file_breaks()
133da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy        self.color_breakpoint_text()
134a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
135d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov    rmenu_specs = [
136d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        ("Cut", "<<cut>>", "rmenu_check_cut"),
137d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        ("Copy", "<<copy>>", "rmenu_check_copy"),
138d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        ("Paste", "<<paste>>", "rmenu_check_paste"),
139d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        (None, None, None),
140d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        ("Set Breakpoint", "<<set-breakpoint-here>>", None),
141d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
142d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov    ]
1437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
144da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy    def color_breakpoint_text(self, color=True):
145da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy        "Turn colorizing of breakpoint text on or off"
146efc7258377e79cff0ea41f97fa999873325e2fb5Terry Jan Reedy        if self.io is None:
147efc7258377e79cff0ea41f97fa999873325e2fb5Terry Jan Reedy            # possible due to update in restore_file_breaks
148efc7258377e79cff0ea41f97fa999873325e2fb5Terry Jan Reedy            return
149da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy        if color:
150d0c0f0041c3eb561adfa57179bc41f4dae212317Terry Jan Reedy            theme = idleConf.CurrentTheme()
151da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy            cfg = idleConf.GetHighlight(theme, "break")
152da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy        else:
153da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy            cfg = {'foreground': '', 'background': ''}
154da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy        self.text.tag_config('BREAK', cfg)
155da26cca1cef111282e4be83af0994305c6218adeTerry Jan Reedy
156a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def set_breakpoint(self, lineno):
15745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text = self.text
15845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        filename = self.io.filename
159a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
16045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
161038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy            self.breakpoints.index(lineno)
162a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        except ValueError:  # only add if missing, i.e. do once
16345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints.append(lineno)
16445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:    # update the subprocess debugger
16545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug = self.flist.pyshell.interp.debugger
16645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.set_breakpoint_here(filename, lineno)
16745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except: # but debugger may not be active right now....
16845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
1697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
170a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def set_breakpoint_here(self, event=None):
171a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text = self.text
172a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        filename = self.io.filename
173a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        if not filename:
174a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            text.bell()
175a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            return
176a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        lineno = int(float(text.index("insert")))
177a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.set_breakpoint(lineno)
178a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
179669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser    def clear_breakpoint_here(self, event=None):
18045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text = self.text
18145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        filename = self.io.filename
18245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if not filename:
18345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text.bell()
184669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            return
18545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        lineno = int(float(text.index("insert")))
18645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
18745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints.remove(lineno)
18845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except:
18945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
19045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text.tag_remove("BREAK", "insert linestart",\
19145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                        "insert lineend +1char")
19245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
19345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug = self.flist.pyshell.interp.debugger
19445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.clear_breakpoint_here(filename, lineno)
19545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except:
19645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
19745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
19845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def clear_file_breaks(self):
19945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if self.breakpoints:
20045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text = self.text
20145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            filename = self.io.filename
20245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            if not filename:
20345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                text.bell()
20445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                return
20545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints = []
20645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text.tag_remove("BREAK", "1.0", END)
20745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            try:
20845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                debug = self.flist.pyshell.interp.debugger
20945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                debug.clear_file_breaks(filename)
21045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            except:
21145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                pass
21245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
213a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def store_file_breaks(self):
214bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        "Save breakpoints when file is saved"
215bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
216bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     be run.  The breaks are saved at that time.  If we introduce
217bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     a temporary file save feature the save breaks functionality
218bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     needs to be re-verified, since the breaks at the time the
219bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     temp file is created may differ from the breaks at the last
2207f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     permanent save of the file.  Currently, a break introduced
2217f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     after a save will be effective, but not persistent.
2227f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     This is necessary to keep the saved breaks synched with the
2237f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     saved file.
224bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #
2256b04dc9bcc3f87d6ec5d298b49f2fa7644356c37Terry Jan Reedy        #     Breakpoints are set as tagged ranges in the text.
2266b04dc9bcc3f87d6ec5d298b49f2fa7644356c37Terry Jan Reedy        #     Since a modified file has to be saved before it is
227bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     run, and since self.breakpoints (from which the subprocess
228bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     debugger is loaded) is updated during the save, the visible
229bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     breaks stay synched with the subprocess even if one of these
230bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     unexpected breakpoint deletions occurs.
231bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        breaks = self.breakpoints
232bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        filename = self.io.filename
233a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        try:
23485c6772aecd9cdcd87c9f4ede62dce041f581890Victor Stinner            with open(self.breakpointPath, "r") as fp:
23585c6772aecd9cdcd87c9f4ede62dce041f581890Victor Stinner                lines = fp.readlines()
236f7a17b48d748e1835bcf9df86fb7fb318bb020f8Andrew Svetlov        except OSError:
237bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            lines = []
238f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily        try:
239f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily            with open(self.breakpointPath, "w") as new_file:
240f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                for line in lines:
241f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                    if not line.startswith(filename + '='):
242f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                        new_file.write(line)
243f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                self.update_breakpoints()
244f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                breaks = self.breakpoints
245f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                if breaks:
246f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                    new_file.write(filename + '=' + str(breaks) + '\n')
247f7a17b48d748e1835bcf9df86fb7fb318bb020f8Andrew Svetlov        except OSError as err:
248f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily            if not getattr(self.root, "breakpoint_error_displayed", False):
249f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                self.root.breakpoint_error_displayed = True
250f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                tkMessageBox.showerror(title='IDLE Error',
251f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                    message='Unable to update breakpoint list:\n%s'
252f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                        % str(err),
253f505b7425c1e46e847dfc1e4528bc178af06b085Ned Deily                    parent=self.text)
254a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
255a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def restore_file_breaks(self):
256a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.text.update()   # this enables setting "BREAK" tags to be visible
257d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy        if self.io is None:
258d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            # can happen if IDLE closes due to the .update() call
259d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            return
260bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        filename = self.io.filename
261bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        if filename is None:
262bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            return
26369371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey        if os.path.isfile(self.breakpointPath):
26485c6772aecd9cdcd87c9f4ede62dce041f581890Victor Stinner            with open(self.breakpointPath, "r") as fp:
26585c6772aecd9cdcd87c9f4ede62dce041f581890Victor Stinner                lines = fp.readlines()
26669371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey            for line in lines:
267bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                if line.startswith(filename + '='):
2686655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser                    breakpoint_linenumbers = eval(line[len(filename)+1:])
26969371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey                    for breakpoint_linenumber in breakpoint_linenumbers:
27069371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey                        self.set_breakpoint(breakpoint_linenumber)
271a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
272bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser    def update_breakpoints(self):
273bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        "Retrieves all the breakpoints in the current window"
274a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text = self.text
275bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        ranges = text.tag_ranges("BREAK")
276bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        linenumber_list = self.ranges_to_linenumbers(ranges)
277bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        self.breakpoints = linenumber_list
278bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser
279bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser    def ranges_to_linenumbers(self, ranges):
280bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        lines = []
281bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        for index in range(0, len(ranges), 2):
28206c5c6d694481a3c1e09420756f8ad6ca1762d0fAndrew Svetlov            lineno = int(float(ranges[index].string))
28306c5c6d694481a3c1e09420756f8ad6ca1762d0fAndrew Svetlov            end = int(float(ranges[index+1].string))
284bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            while lineno < end:
285bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                lines.append(lineno)
286bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                lineno += 1
287bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        return lines
288bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser
28911220fad1d7eee24f1d9809c6d5023875099cb37Kurt B. Kaiser# XXX 13 Dec 2002 KBK Not used currently
290bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#    def saved_change_hook(self):
291bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        "Extend base method - clear breaks if module is modified"
292bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        if not self.get_saved():
293bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#            self.clear_file_breaks()
294bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        EditorWindow.saved_change_hook(self)
29545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
29645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def _close(self):
29745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        "Extend base method - clear breaks when module is closed"
29845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.clear_file_breaks()
29945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        EditorWindow._close(self)
3006655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
3017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellFileList(FileList):
303183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    "Extend base class: IDLE supports a shell and breakpoints"
3047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
305183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    # override FileList's class variable, instances return PyShellEditorWindow
306183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    # instead of EditorWindow when new edit windows are created.
3077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    EditorWindow = PyShellEditorWindow
3087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    pyshell = None
3107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_shell(self, event=None):
3127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.pyshell:
313183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            self.pyshell.top.wakeup()
3147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell = PyShell(self)
316af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            if self.pyshell:
317af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                if not self.pyshell.begin():
318af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                    return None
3197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.pyshell
3207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedColorDelegator(ColorDelegator):
32383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: colorizer for the shell window itself"
3246655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
325b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def __init__(self):
326b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.__init__(self)
327b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.LoadTagDefs()
3287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recolorize_main(self):
3307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_remove("TODO", "1.0", "iomark")
3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_add("SYNC", "1.0", "iomark")
3327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ColorDelegator.recolorize_main(self)
3336655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
334b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def LoadTagDefs(self):
335b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.LoadTagDefs(self)
336d0c0f0041c3eb561adfa57179bc41f4dae212317Terry Jan Reedy        theme = idleConf.CurrentTheme()
337b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.tagdefs.update({
338b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdin": {'background':None,'foreground':None},
339b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdout": idleConf.GetHighlight(theme, "stdout"),
340b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stderr": idleConf.GetHighlight(theme, "stderr"),
341b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "console": idleConf.GetHighlight(theme, "console"),
342b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        })
3437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3448b2a56b89d6ce0d8ce3343953529e07a42ffc917Ned Deily    def removecolors(self):
3458b2a56b89d6ce0d8ce3343953529e07a42ffc917Ned Deily        # Don't remove shell color tags before "iomark"
3468b2a56b89d6ce0d8ce3343953529e07a42ffc917Ned Deily        for tag in self.tagdefs:
3478b2a56b89d6ce0d8ce3343953529e07a42ffc917Ned Deily            self.tag_remove(tag, "iomark", "end")
3488b2a56b89d6ce0d8ce3343953529e07a42ffc917Ned Deily
3497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedUndoDelegator(UndoDelegator):
35083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: forbid insert/delete before the I/O mark"
3517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def insert(self, index, chars, tags=None):
3537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
3547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index, "<", "iomark"):
3557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
3567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
3577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
3587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
3597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.insert(self, index, chars, tags)
3607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def delete(self, index1, index2=None):
3627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
3637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index1, "<", "iomark"):
3647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
3657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
3667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
3677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
3687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.delete(self, index1, index2)
3697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
37067fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
37167fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiserclass MyRPCClient(rpc.RPCClient):
37267fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
37367fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser    def handle_EOF(self):
37467fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        "Override the base class - just re-raise EOFError"
37567fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        raise EOFError
37667fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
3778d1f11b0ef7ec31db75a4e640e9dfd75fc4ee08dKurt B. Kaiser
3787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedInterpreter(InteractiveInterpreter):
3797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, tkconsole):
3817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole = tkconsole
3827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        locals = sys.modules['__main__'].__dict__
3837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.__init__(self, locals=locals)
38494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = None
3856f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = False
386e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        self.subprocess_arglist = None
387e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        self.port = PORT
3887aff4517289e2a748b238f282a777e577c9e3d3fNed Deily        self.original_compiler_flags = self.compile.compiler.flags
3897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
390036e84924a0e0bdcc3c17033ea0263a3462825e1Roger Serwy    _afterid = None
3915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcclt = None
392e5cad23a92c88440e739589430c0b22d41a44621Ned Deily    rpcsubproc = None
3935d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
3946655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser    def spawn_subprocess(self):
395fd1b0930ce6a84096d30c03a70cd9e0ee4a3178fFlorent Xicluna        if self.subprocess_arglist is None:
396e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            self.subprocess_arglist = self.build_subprocess_arglist()
397e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        self.rpcsubproc = subprocess.Popen(self.subprocess_arglist)
39863857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser
399f53dec2e4e8a017641db4de73456a2724a75e64bTony Lownds    def build_subprocess_arglist(self):
400e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        assert (self.port!=0), (
401e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "Socket should have been assigned a port number.")
4022398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        w = ['-W' + s for s in sys.warnoptions]
4032398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # Maybe IDLE is installed and is being accessed via sys.path,
4042398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # or maybe it's not installed and the idle.py script is being
4052398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # run from the IDLE source directory.
40662df0448850000739edd1df8b4c0e702119d476eKurt B. Kaiser        del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
40762df0448850000739edd1df8b4c0e702119d476eKurt B. Kaiser                                       default=False, type='bool')
4086fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        if __name__ == 'idlelib.pyshell':
40970a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
410f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        else:
41170a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            command = "__import__('run').main(%r)" % (del_exitf,)
412e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        return [sys.executable] + w + ["-c", command, str(self.port)]
413f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds
41463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    def start_subprocess(self):
415e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        addr = (HOST, self.port)
416e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        # GUI makes several attempts to acquire socket, listens for connection
4175db4843c5e7d2b420b9ca9189b9e30669b62e55eKurt B. Kaiser        for i in range(3):
4185d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            time.sleep(i)
4195d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
42067fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.rpcclt = MyRPCClient(addr)
4215d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                break
422038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy            except OSError:
423af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                pass
4245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
425af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_port_binding_error()
426af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
427e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
428e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        self.port = self.rpcclt.listening_sock.getsockname()[1]
429e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        # if PORT was not 0, probably working with a remote execution server
430e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        if PORT != 0:
431e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            # To allow reconnection within the 2MSL wait (cf. Stevens TCP
432e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            # V1, 18.6),  set SO_REUSEADDR.  Note that this can be problematic
433e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            # on Windows since the implementation allows two active sockets on
434e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            # the same address!
435e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
436e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser                                           socket.SO_REUSEADDR, 1)
437e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        self.spawn_subprocess()
438e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser        #time.sleep(20) # test to simulate GUI not accepting connection
439b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser        # Accept the connection from the Python execution server
440af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        self.rpcclt.listening_sock.settimeout(10)
441af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
442af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.accept()
443038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy        except socket.timeout:
444af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_no_subprocess_error()
445af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
44639e70a4e837a4ebfae009bc202ac274aa9005fb6Serhiy Storchaka        self.rpcclt.register("console", self.tkconsole)
44739e70a4e837a4ebfae009bc202ac274aa9005fb6Serhiy Storchaka        self.rpcclt.register("stdin", self.tkconsole.stdin)
448969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdout", self.tkconsole.stdout)
449969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stderr", self.tkconsole.stderr)
4505d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt.register("flist", self.tkconsole.flist)
4518cd0def10dc028e3522a04bd136c67f92f90da04Kurt B. Kaiser        self.rpcclt.register("linecache", linecache)
4529f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        self.rpcclt.register("interp", self)
453da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        self.transfer_path(with_cwd=True)
4545d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.poll_subprocess()
455af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        return self.rpcclt
4565d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
457231007fe142975ee5e468929af5ed69705e7547eTerry Jan Reedy    def restart_subprocess(self, with_cwd=False, filename=''):
4586f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        if self.restarting:
459af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return self.rpcclt
4606f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = True
46163857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        # close only the subprocess debugger
46245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        debug = self.getdebugger()
46345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if debug:
464003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            try:
4659ec454ec00088e051195e80363499a14cafc131aKurt B. Kaiser                # Only close subprocess debugger, don't unregister gui_adap!
4666fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy                debugger_r.close_subprocess_debugger(self.rpcclt)
467003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            except:
468003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser                pass
469003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        # Kill subprocess, spawn a new one, accept connection.
470a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt.close()
471e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        self.terminate_subprocess()
4727f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        console = self.tkconsole
4736f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        was_executing = console.executing
4747f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        console.executing = False
47563857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.spawn_subprocess()
476af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
477af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.accept()
478038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy        except socket.timeout:
479af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_no_subprocess_error()
480af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
481da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        self.transfer_path(with_cwd=with_cwd)
4826b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        console.stop_readline()
4831061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        # annotate restart in shell window and mark it
4844cc5ef5dbe12cbc9dc1a00c7583ffd0117f4c31eKurt B. Kaiser        console.text.delete("iomark", "end-1c")
485ac5004f7ced7b0d4e410af2e005dd7a400bf26acTerry Jan Reedy        tag = 'RESTART: ' + (filename if filename else 'Shell')
486231007fe142975ee5e468929af5ed69705e7547eTerry Jan Reedy        halfbar = ((int(console.width) -len(tag) - 4) // 2) * '='
487231007fe142975ee5e468929af5ed69705e7547eTerry Jan Reedy        console.write("\n{0} {1} {0}".format(halfbar, tag))
4881061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        console.text.mark_set("restart", "end-1c")
4891061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        console.text.mark_gravity("restart", "left")
490231007fe142975ee5e468929af5ed69705e7547eTerry Jan Reedy        if not filename:
491231007fe142975ee5e468929af5ed69705e7547eTerry Jan Reedy            console.showprompt()
492003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        # restart subprocess debugger
49345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if debug:
4949ec454ec00088e051195e80363499a14cafc131aKurt B. Kaiser            # Restarted debugger connects to current instance of debug GUI
4956fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy            debugger_r.restart_subprocess_debugger(self.rpcclt)
49645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            # reload remote debugger breakpoints for all PyShellEditWindows
49745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.load_breakpoints()
4987aff4517289e2a748b238f282a777e577c9e3d3fNed Deily        self.compile.compiler.flags = self.original_compiler_flags
4996f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = False
500af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        return self.rpcclt
50145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
502003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def __request_interrupt(self):
503a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
504003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser
505003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def interrupt_subprocess(self):
506a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        threading.Thread(target=self.__request_interrupt).start()
507003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser
508a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser    def kill_subprocess(self):
509036e84924a0e0bdcc3c17033ea0263a3462825e1Roger Serwy        if self._afterid is not None:
510036e84924a0e0bdcc3c17033ea0263a3462825e1Roger Serwy            self.tkconsole.text.after_cancel(self._afterid)
511af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
51255f87578a103e8da4b7c4211338bccc702bdba6eNed Deily            self.rpcclt.listening_sock.close()
51355f87578a103e8da4b7c4211338bccc702bdba6eNed Deily        except AttributeError:  # no socket
51455f87578a103e8da4b7c4211338bccc702bdba6eNed Deily            pass
51555f87578a103e8da4b7c4211338bccc702bdba6eNed Deily        try:
516af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.close()
517af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        except AttributeError:  # no socket
518af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            pass
519e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        self.terminate_subprocess()
520a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.tkconsole.executing = False
521a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt = None
52211c53e2ea7f7d2a2969c98e81c1489c4e72254c4Kurt B. Kaiser
523e5cad23a92c88440e739589430c0b22d41a44621Ned Deily    def terminate_subprocess(self):
524e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        "Make sure subprocess is terminated"
525e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        try:
526e5cad23a92c88440e739589430c0b22d41a44621Ned Deily            self.rpcsubproc.kill()
527e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        except OSError:
528e5cad23a92c88440e739589430c0b22d41a44621Ned Deily            # process already terminated
529e5cad23a92c88440e739589430c0b22d41a44621Ned Deily            return
530e5cad23a92c88440e739589430c0b22d41a44621Ned Deily        else:
531a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            try:
532e5cad23a92c88440e739589430c0b22d41a44621Ned Deily                self.rpcsubproc.wait()
533a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            except OSError:
534a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                return
53511c53e2ea7f7d2a2969c98e81c1489c4e72254c4Kurt B. Kaiser
536da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy    def transfer_path(self, with_cwd=False):
537da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        if with_cwd:        # Issue 13506
538da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy            path = ['']     # include Current Working Directory
539da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy            path.extend(sys.path)
540da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        else:
541da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy            path = sys.path
5424d82ade42471e0503d82012116d0b128d7120f7fTerry Jan Reedy
543f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        self.runcommand("""if 1:
544f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        import sys as _sys
54570a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald        _sys.path = %r
546f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        del _sys
547da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        \n""" % (path,))
548f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
5495d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    active_seq = None
5505d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5515d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def poll_subprocess(self):
5525d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
5535d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is None:
5545d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
555003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        try:
556a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            response = clt.pollresponse(self.active_seq, wait=0.05)
557f7a17b48d748e1835bcf9df86fb7fb318bb020f8Andrew Svetlov        except (EOFError, OSError, KeyboardInterrupt):
558a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            # lost connection or subprocess terminated itself, restart
559a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            # [the KBI is from rpc.SocketIO.handle_EOF()]
56067fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if self.tkconsole.closing:
56167fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                return
562003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            response = None
563003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.restart_subprocess()
5645d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if response:
5655d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.resetoutput()
5665d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = None
5675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            how, what = response
568bc2861313cc53711d837a0e8a5bf303bf5291bf3Kurt B. Kaiser            console = self.tkconsole.console
5695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            if how == "OK":
5705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if what is not None:
571be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum                    print(repr(what), file=console)
5725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "EXCEPTION":
5735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
5745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    self.remote_stack_viewer()
5755d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "ERROR":
5766fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy                errmsg = "pyshell.ModifiedInterpreter: Subprocess ERROR:\n"
577be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum                print(errmsg, what, file=sys.__stderr__)
578be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum                print(errmsg, what, file=console)
579bc2861313cc53711d837a0e8a5bf303bf5291bf3Kurt B. Kaiser            # we received a response to the currently active seq number:
58000ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters            try:
58100ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                self.tkconsole.endexecuting()
58200ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters            except AttributeError:  # shell may have closed
58300ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                pass
58488957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        # Reschedule myself
58588957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        if not self.tkconsole.closing:
586036e84924a0e0bdcc3c17033ea0263a3462825e1Roger Serwy            self._afterid = self.tkconsole.text.after(
587036e84924a0e0bdcc3c17033ea0263a3462825e1Roger Serwy                self.tkconsole.pollinterval, self.poll_subprocess)
5885d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
58945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    debugger = None
59045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
59145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def setdebugger(self, debugger):
59245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.debugger = debugger
59345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
59445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def getdebugger(self):
59545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        return self.debugger
59645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
5979f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser    def open_remote_stack_viewer(self):
5989f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        """Initiate the remote stack viewer from a separate thread.
5999f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6009f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        This method is called from the subprocess, and by returning from this
6019f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        method we allow the subprocess to unblock.  After a bit the shell
6029f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        requests the subprocess to open the remote stack viewer which returns a
6036086118ceda2630dbc5eafabfb113fae678fb6a4Ezio Melotti        static object looking at the last exception.  It is queried through
6049f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        the RPC mechanism.
6059f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6069f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        """
6079f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        self.tkconsole.text.after(300, self.remote_stack_viewer)
6089f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        return
6099f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6105d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def remote_stack_viewer(self):
6116fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        from idlelib import debugobj_r
612a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
6135d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if oid is None:
6145d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.root.bell()
6155d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
6166fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        item = debugobj_r.StubObjectTreeItem(self.rpcclt, oid)
6176fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        from idlelib.tree import ScrolledCanvas, TreeNode
6185d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        top = Toplevel(self.tkconsole.root)
619d0c0f0041c3eb561adfa57179bc41f4dae212317Terry Jan Reedy        theme = idleConf.CurrentTheme()
62073360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser        background = idleConf.GetHighlight(theme, 'normal')['background']
62173360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser        sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
6225d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc.frame.pack(expand=1, fill="both")
6235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node = TreeNode(sc.canvas, None, item)
6245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node.expand()
6255d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # XXX Should GC the remote tree when closing the window
6265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
6277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    gid = 0
6287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execsource(self, source):
63083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Like runsource() but assumes complete exec source"
6317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
6327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.execfile(filename, source)
6337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execfile(self, filename, source=None):
63583118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Execute an existing file"
6367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if source is None:
637979482a3154540ffde1cb0f374cab4421995660dVictor Stinner            with tokenize.open(filename) as fp:
63885c6772aecd9cdcd87c9f4ede62dce041f581890Victor Stinner                source = fp.read()
6397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            code = compile(source, filename, "exec")
6417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except (OverflowError, SyntaxError):
6427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
64381b062f63ace48983439857314fec8063e8c72e0Terry Jan Reedy            print('*** Error in script or command!\n'
64481b062f63ace48983439857314fec8063e8c72e0Terry Jan Reedy                 'Traceback (most recent call last):',
64581b062f63ace48983439857314fec8063e8c72e0Terry Jan Reedy                  file=self.tkconsole.stderr)
6467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
6476e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            self.tkconsole.showprompt()
6487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
6497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runcode(code)
6507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runsource(self, source):
65283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method: Stuff the source in the line cache first"
6537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
6547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.more = 0
65594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = warnings.filters[:]
65694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        warnings.filterwarnings(action="error", category=SyntaxWarning)
65798ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        # at the moment, InteractiveInterpreter expects str
65898ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        assert isinstance(source, str)
65998ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #if isinstance(source, str):
6606fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        #    from idlelib import iomenu
66198ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #    try:
6626fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        #        source = source.encode(iomenu.encoding)
66398ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #    except UnicodeError:
66498ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #        self.tkconsole.resetoutput()
66598ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #        self.write("Unsupported characters in input\n")
66698ff898c4637208f28f862a64779c2ea3f4b809dMartin v. Löwis        #        return
66794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        try:
668935ea9a0b291b2ce42a5cf02d9f2f2955e21a6aaKurt B. Kaiser            # InteractiveInterpreter.runsource() calls its runcode() method,
669935ea9a0b291b2ce42a5cf02d9f2f2955e21a6aaKurt B. Kaiser            # which is overridden (see below)
67094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            return InteractiveInterpreter.runsource(self, source, filename)
67194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        finally:
67294bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            if self.save_warnings_filters is not None:
67394bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                warnings.filters[:] = self.save_warnings_filters
67494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                self.save_warnings_filters = None
6757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def stuffsource(self, source):
67783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Stuff source in the filename cache"
6787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = "<pyshell#%d>" % self.gid
6797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.gid = self.gid + 1
680837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        lines = source.split("\n")
6817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        linecache.cache[filename] = len(source)+1, 0, lines, filename
6827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return filename
6836655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
68411659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser    def prepend_syspath(self, filename):
68511659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser        "Prepend sys.path with file's directory if not already included"
68611659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser        self.runcommand("""if 1:
68770a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            _filename = %r
68811659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            import sys as _sys
68911659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            from os.path import dirname as _dirname
69011659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            _dir = _dirname(_filename)
69111659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            if not _dir in _sys.path:
69211659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser                _sys.path.insert(0, _dir)
69311659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            del _filename, _sys, _dirname, _dir
69470a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            \n""" % (filename,))
69511659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser
6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showsyntaxerror(self, filename=None):
69733d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        """Override Interactive Interpreter method: Use Colorizing
69883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
69983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        Color the offending position instead of printing it and pointing at it
70083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        with a caret.
70183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
70283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """
70333d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        tkconsole = self.tkconsole
70433d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        text = tkconsole.text
70533d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        text.tag_remove("ERROR", "1.0", "end")
7067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        type, value, tb = sys.exc_info()
70779746426c439a8a163d95381ffffa1b2fd34348eNed Deily        msg = getattr(value, 'msg', '') or value or "<no detail available>"
70879746426c439a8a163d95381ffffa1b2fd34348eNed Deily        lineno = getattr(value, 'lineno', '') or 1
70979746426c439a8a163d95381ffffa1b2fd34348eNed Deily        offset = getattr(value, 'offset', '') or 0
71033d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        if offset == 0:
71133d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum            lineno += 1 #mark end of offending line
71233d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        if lineno == 1:
71333d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum            pos = "iomark + %d chars" % (offset-1)
7147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
71533d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum            pos = "iomark linestart + %d lines + %d chars" % \
71633d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum                  (lineno-1, offset-1)
71733d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        tkconsole.colorize_syntax_error(text, pos)
71833d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        tkconsole.resetoutput()
71933d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        self.write("SyntaxError: %s\n" % msg)
72033d2689fc900a814f0a7d2f846abe0c34024ae17Guido van Rossum        tkconsole.showprompt()
7217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showtraceback(self):
72383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method to reset output properly"
7247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
7257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.checklinecache()
7267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.showtraceback(self)
7275d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
7285d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.open_stack_viewer()
7297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def checklinecache(self):
7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        c = linecache.cache
73236e0a92442388647afaaca188c403eee9856a8dfGuido van Rossum        for key in list(c.keys()):
7337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if key[:1] + key[-1:] != "<>":
7347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del c[key]
7357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def runcommand(self, code):
73783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Run the code without invoking the debugger"
7385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # The code better not raise an exception!
7395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
740f4c4f115d80a26eb83d90593c24a1580f236c443Neal Norwitz            self.display_executing_dialog()
7415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return 0
7425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.rpcclt:
743a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            self.rpcclt.remotequeue("exec", "runcode", (code,), {})
7445d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
7457cae87ca7b0a3a7ce497cbd335c8ec82fe680476Georg Brandl            exec(code, self.locals)
7465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        return 1
7475d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runcode(self, code):
74983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
7505d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
751003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.interp.restart_subprocess()
7525d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.checklinecache()
75394bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        if self.save_warnings_filters is not None:
75494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            warnings.filters[:] = self.save_warnings_filters
75594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            self.save_warnings_filters = None
7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        debugger = self.debugger
7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
7587f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.tkconsole.beginexecuting()
759cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            if not debugger and self.rpcclt is not None:
760cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
761cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                                                        (code,), {})
762cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            elif debugger:
763cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                debugger.run(code, self.locals)
764cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            else:
765cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                exec(code, self.locals)
766cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters        except SystemExit:
767cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            if not self.tkconsole.closing:
768cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                if tkMessageBox.askyesno(
769cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    "Exit?",
770cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    "Do you want to exit altogether?",
771cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    default="yes",
7723be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy                    parent=self.tkconsole.text):
77300ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                    raise
774cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                else:
7755dc0d9708cdb347a5e7ec3ff7211ce2cfa6b26b1Guido van Rossum                    self.showtraceback()
776cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            else:
777cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                raise
778cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters        except:
779cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            if use_subprocess:
780cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                print("IDLE internal error in runcode()",
781cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                      file=self.tkconsole.stderr)
7827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.showtraceback()
783cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                self.tkconsole.endexecuting()
784cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters            else:
785cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                if self.tkconsole.canceled:
786cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    self.tkconsole.canceled = False
787cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    print("KeyboardInterrupt", file=self.tkconsole.stderr)
788cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                else:
789cf297e46b85257396560774e5492e9d71a40f32eThomas Wouters                    self.showtraceback()
7907f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        finally:
7917f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            if not use_subprocess:
79200ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                try:
79300ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                    self.tkconsole.endexecuting()
79400ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                except AttributeError:  # shell may have closed
79500ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                    pass
7967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
79883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
79930d5e6c13fc988af2a6c0f8f0cdf43092c241e8fMartin v. Löwis        return self.tkconsole.stderr.write(s)
8007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
801af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_port_binding_error(self):
802af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
803af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Port Binding Error",
804e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "IDLE can't bind to a TCP/IP port, which is necessary to "
805e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "communicate with its Python execution server.  This might be "
806e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "because no networking is installed on this computer.  "
807e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "Run IDLE with the -n command line switch to start without a "
808e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "subprocess and refer to Help/IDLE Help 'Running without a "
809e866c81d37676e54529c0d6232e7de1721e28bc7Kurt B. Kaiser            "subprocess' for further details.",
8103be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy            parent=self.tkconsole.text)
811af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
812af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_no_subprocess_error(self):
813af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
814af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Subprocess Startup Error",
815af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "IDLE's subprocess didn't make connection.  Either IDLE can't "
816af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "start a subprocess or personal firewall software is blocking "
817af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "the connection.",
8183be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy            parent=self.tkconsole.text)
819af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
820af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_executing_dialog(self):
821af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
822af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Already executing",
823af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "The Python Shell window is already executing a command; "
824af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "please wait until it is finished.",
8253be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy            parent=self.tkconsole.text)
826af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
827af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
8287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShell(OutputWindow):
8297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
83032622236d5b45fedcefa50c11afeaa5d99ff8cdcTerry Jan Reedy    shell_title = "Python " + python_version() + " Shell"
8317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Override classes
8337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ColorDelegator = ModifiedColorDelegator
8347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    UndoDelegator = ModifiedUndoDelegator
8357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
836f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # Override menus
837dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    menu_specs = [
838dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("file", "_File"),
839dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("edit", "_Edit"),
8404cc5ef5dbe12cbc9dc1a00c7583ffd0117f4c31eKurt B. Kaiser        ("debug", "_Debug"),
8411061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        ("options", "_Options"),
842ccb416fee2c680252a16a55f2640cba3bde80185Ned Deily        ("windows", "_Window"),
843dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("help", "_Help"),
844dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    ]
8457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8460e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters
8477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # New classes
8486fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy    from idlelib.history import History
8497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, flist=None):
8518f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if use_subprocess:
85267fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            ms = self.menu_specs
85367fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if ms[2][0] != "shell":
85400ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                ms.insert(2, ("shell", "She_ll"))
8557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = ModifiedInterpreter(self)
8567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if flist is None:
8577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root = Tk()
8587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            fixwordbreaks(root)
8597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root.withdraw()
8607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            flist = PyShellFileList(root)
8615afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.__init__(self, flist, None, None)
8635afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8646af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser##        self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
8656af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.usetabs = True
8666af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        # indentwidth must be 8 when using tabs.  See note in EditorWindow:
8676af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.indentwidth = 8
8686af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.context_use_ps1 = True
8695afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.text
8717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.configure(wrap="char")
8727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<newline-and-indent>>", self.enter_callback)
8737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
8747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<interrupt-execution>>", self.cancel_callback)
8757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<end-of-file>>", self.eof_callback)
8767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
87757bfe5dc5a4873026679fb911939beb69e35a9e8Kurt B. Kaiser        text.bind("<<toggle-debugger>>", self.toggle_debugger)
8787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
8798f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if use_subprocess:
8808f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            text.bind("<<view-restart>>", self.view_restart_mark)
8818f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            text.bind("<<restart-shell>>", self.restart_shell)
8825afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdout = sys.stdout
8847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stderr = sys.stderr
8857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdin = sys.stdin
8866fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        from idlelib import iomenu
8876fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        self.stdin = PseudoInputFile(self, "stdin", iomenu.encoding)
8886fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        self.stdout = PseudoOutputFile(self, "stdout", iomenu.encoding)
8896fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        self.stderr = PseudoOutputFile(self, "stderr", iomenu.encoding)
8906fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        self.console = PseudoOutputFile(self, "console", iomenu.encoding)
8915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not use_subprocess:
8925d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdout = self.stdout
8937cec252b9dd38a91911dcaa7248d74b0bb40395fKurt B. Kaiser            sys.stderr = self.stderr
894c882b7c51ab4b76bdf44cf4dab5ca1b55ccb2155Martin v. Löwis            sys.stdin = self.stdin
895f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser        try:
896f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser            # page help() text to shell.
897f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser            import pydoc # import must be done here to capture i/o rebinding.
8986fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy            # XXX KBK 27Dec07 use TextViewer someday, but must work w/o subproc
899f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser            pydoc.pager = pydoc.plainpager
900f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser        except:
901f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser            sys.stderr = sys.__stderr__
902f609a345a4adaedd5806b4ec8439b84c409b9f66Kurt B. Kaiser            raise
9035afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
9047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = self.History(self.text)
9055afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
90688957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        self.pollinterval = 50  # millisec
9075d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
9084d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser    def get_standard_extension_names(self):
9094d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser        return idleConf.GetExtensions(shell_only=True)
9104d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser
911003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    reading = False
912003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    executing = False
913003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    canceled = False
914003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    endoffile = False
915003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    closing = False
9166b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy    _stop_readline_flag = False
9177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
91849a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser    def set_warning_stream(self, stream):
919d91614234375621f3b78cb9c8c5a58b77c961fe8Skip Montanaro        global warning_stream
920d91614234375621f3b78cb9c8c5a58b77c961fe8Skip Montanaro        warning_stream = stream
92149a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser
92249a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser    def get_warning_stream(self):
92349a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser        return warning_stream
92449a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser
9257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_debugger(self, event=None):
9267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
9277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("Don't debug now",
9287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "You can only toggle the debugger when idle",
9293be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy                parent=self.text)
9307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.set_debugger_indicator()
9317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
9327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
9337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db = self.interp.getdebugger()
9347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if db:
9357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.close_debugger()
9367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            else:
9377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.open_debugger()
9387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_debugger_indicator(self):
9407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
9417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.setvar("<<toggle-debugger>>", not not db)
9427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9431061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def toggle_jit_stack_viewer(self, event=None):
9447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass # All we need is the variable
9457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close_debugger(self):
9477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
9487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if db:
9497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.interp.setdebugger(None)
9507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db.close()
951ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser            if self.interp.rpcclt:
9526fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy                debugger_r.close_remote_debugger(self.interp.rpcclt)
9537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
9547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.console.write("[DEBUG OFF]\n")
9557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
9567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
9577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
9587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_debugger(self):
9605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
9616fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy            dbg_gui = debugger_r.start_remote_debugger(self.interp.rpcclt,
9627f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                                                           self)
9637f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        else:
9646fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy            dbg_gui = debugger.Debugger(self)
9657f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        self.interp.setdebugger(dbg_gui)
9667f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        dbg_gui.load_breakpoints()
9675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sys.ps1 = "[DEBUG ON]\n>>> "
9685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
9695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_debugger_indicator()
9705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
9717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def beginexecuting(self):
972ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser        "Helper for ModifiedInterpreter"
9737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
9747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 1
9757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def endexecuting(self):
97783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Helper for ModifiedInterpreter"
9787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 0
9797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.canceled = 0
9805d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
9817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close(self):
98383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow.close()"
9847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
985003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            response = tkMessageBox.askokcancel(
9867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "Kill?",
9874379d15d4c43db3d92658826906ed6326487b333Terry Jan Reedy                "Your program is still running!\n Do you want to kill it?",
9887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                default="ok",
9897f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                parent=self.text)
9902a691a814914a9d2b2188cac25426543a14a8500Benjamin Peterson            if response is False:
9917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "cancel"
9926b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        self.stop_readline()
9935c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        self.canceled = True
99467fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        self.closing = True
99588957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        return EditorWindow.close(self)
9967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def _close(self):
99883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow._close(), shut down debugger and execution server"
9997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.close_debugger()
10007f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        if use_subprocess:
10017f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.interp.kill_subprocess()
10027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Restore std streams
10037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout = self.save_stdout
10047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stderr = self.save_stderr
10057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdin = self.save_stdin
10067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Break cycles
10077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = None
10087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = None
10097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell = None
10107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = None
101183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        EditorWindow._close(self)
10127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def ispythonsource(self, filename):
101483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override EditorWindow method: never remove the colorizer"
1015837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
10167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def short_title(self):
10187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.shell_title
10197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
102094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser    COPYRIGHT = \
10218f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser          'Type "copyright", "credits" or "license()" for more information.'
102294bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser
10237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def begin(self):
10247378df78225e9dcd3da7831c81f52f2af36692fcKurt B. Kaiser        self.text.mark_set("iomark", "insert")
10257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
10267f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        if use_subprocess:
10277f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            nosub = ''
1028af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            client = self.interp.start_subprocess()
1029af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            if not client:
1030af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                self.close()
10317663729ec72f5ffe44b8e7f76bdb56d8663c5e6eKurt B. Kaiser                return False
10327f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        else:
10339b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov            nosub = ("==== No Subprocess ====\n\n" +
103464478ac21940be5305d07dd30cad691941b0c384Andrew Svetlov                    "WARNING: Running IDLE without a Subprocess is deprecated\n" +
10359b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov                    "and will be removed in a later version. See Help/IDLE Help\n" +
10369b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov                    "for details.\n\n")
1037cd49d5323833ff15cc10a918bdb2afcb02e500a4Andrew Svetlov            sys.displayhook = rpc.displayhook
1038cd49d5323833ff15cc10a918bdb2afcb02e500a4Andrew Svetlov
1039a2a8e8be8e806e940d731a826302193e94267991Raymond Hettinger        self.write("Python %s on %s\n%s\n%s" %
1040a2a8e8be8e806e940d731a826302193e94267991Raymond Hettinger                   (sys.version, sys.platform, self.COPYRIGHT, nosub))
1041b41eadab436ce08724f2373586bef52b13839014Terry Jan Reedy        self.text.focus_force()
10427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
104314fc4270da5db43574d46d055a5f794ed33b271fGeorg Brandl        import tkinter
104414fc4270da5db43574d46d055a5f794ed33b271fGeorg Brandl        tkinter._default_root = None # 03Jan04 KBK What's this?
10457663729ec72f5ffe44b8e7f76bdb56d8663c5e6eKurt B. Kaiser        return True
10467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10476b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy    def stop_readline(self):
10486b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        if not self.reading:  # no nested mainloop to exit.
10496b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy            return
10506b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        self._stop_readline_flag = True
10516b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        self.top.quit()
10526b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy
10537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def readline(self):
10547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        save = self.reading
10557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
10567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = 1
10575c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            self.top.mainloop()  # nested mainloop()
10587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
10597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = save
10606b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy        if self._stop_readline_flag:
10616b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy            self._stop_readline_flag = False
10626b7a5ae2c100d9a28cc1879b7325dc0e615a3a10Roger Serwy            return ""
10637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
10645c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if len(line) == 0:  # may be EOF if we quit our mainloop with Ctrl-C
10655c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            line = "\n"
10667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
10677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
10687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
10695c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            if not use_subprocess:
10705c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser                raise KeyboardInterrupt
10717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.endoffile:
10727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 0
10735c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            line = ""
10747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return line
10757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
1077837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
10787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1079003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def cancel_callback(self, event=None):
10807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
10817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.text.compare("sel.first", "!=", "sel.last"):
10827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return # Active selection -- always use default binding
10837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
10847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
10857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.executing or self.reading):
10867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
10877f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.interp.write("KeyboardInterrupt\n")
10887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
10897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
10907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.endoffile = 0
1091003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        self.canceled = 1
10925c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if (self.executing and self.interp.rpcclt):
109367fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if self.interp.getdebugger():
109467fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.interp.restart_subprocess()
109567fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            else:
109667fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.interp.interrupt_subprocess()
10975c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if self.reading:
10985c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            self.top.quit()  # exit the nested mainloop() in readline()
10997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def eof_callback(self, event):
11027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
11037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
11047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.text.compare("iomark", "==", "insert") and
11057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.text.compare("insert", "==", "end-1c")):
11067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
11077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.executing:
11087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
11097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.close()
11107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
11117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
11127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 1
11137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
11147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def linefeed_callback(self, event):
11177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Insert a linefeed without entering anything (still autoindented)
11187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
11197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
11207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
11217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1122822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
11237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def enter_callback(self, event):
11267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
11277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (insert '\n') take over
11287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If some text is selected, recall the selection
11297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (but only if this before the I/O mark)
11307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
11317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sel = self.text.get("sel.first", "sel.last")
11327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if sel:
11337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if self.text.compare("sel.last", "<=", "iomark"):
1134a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                    self.recall(sel, event)
11357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    return "break"
11367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
11377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
11387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're strictly before the line containing iomark, recall
11397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # the current line, less a leading prompt, less leading or
11407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # trailing whitespace
11417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "iomark linestart"):
11427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Check if there's a relevant stdin range -- if so, use it
11437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            prev = self.text.tag_prevrange("stdin", "insert")
11447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if prev and self.text.compare("insert", "<", prev[1]):
1145a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                self.recall(self.text.get(prev[0], prev[1]), event)
11467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
11477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            next = self.text.tag_nextrange("stdin", "insert")
11487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if next and self.text.compare("insert lineend", ">=", next[0]):
1149a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                self.recall(self.text.get(next[0], next[1]), event)
11507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
11514ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser            # No stdin mark -- just get the current line, less any prompt
1152b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            indices = self.text.tag_nextrange("console", "insert linestart")
1153b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            if indices and \
1154b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser               self.text.compare(indices[0], "<=", "insert linestart"):
1155b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser                self.recall(self.text.get(indices[1], "insert lineend"), event)
1156b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            else:
1157b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser                self.recall(self.text.get("insert linestart", "insert lineend"), event)
11587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
1159822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser        # If we're between the beginning of the line and the iomark, i.e.
11604ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser        # in the prompt area, move to the end of the prompt
1161822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser        if self.text.compare("insert", "<", "iomark"):
11624ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser            self.text.mark_set("insert", "iomark")
11637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input and there's only whitespace
11647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # beyond the cursor, erase that whitespace first
11657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        s = self.text.get("insert", "end-1c")
1166837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        if s and not s.strip():
11677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.delete("insert", "end-1c")
11687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input before its last line,
11697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # insert a newline right at the insert point
11707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "end-1c linestart"):
1171822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
11727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
11737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # We're in the last line; append a newline and submit it
11747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
11757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
11767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
11777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
11787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1179822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
11807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.tag_add("stdin", "iomark", "end-1c")
11817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.update_idletasks()
11827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
1183ce96f69d69a6020c780145c89a17a8391b63624bNeal Norwitz            self.top.quit() # Break out of recursive mainloop()
11847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
11857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runit()
11867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1188a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser    def recall(self, s, event):
118900ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters        # remove leading and trailing empty or whitespace lines
119000ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters        s = re.sub(r'^\s*\n', '' , s)
119100ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters        s = re.sub(r'\n\s*$', '', s)
119200ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters        lines = s.split('\n')
1193a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        self.text.undo_block_start()
1194a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        try:
1195a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.tag_remove("sel", "1.0", "end")
1196a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.mark_set("insert", "end-1c")
119700ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters            prefix = self.text.get("insert linestart", "insert")
119800ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters            if prefix.rstrip().endswith(':'):
11998fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser                self.newline_and_indent_event(event)
120000ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                prefix = self.text.get("insert linestart", "insert")
120100ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters            self.text.insert("insert", lines[0].strip())
12028fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser            if len(lines) > 1:
120300ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
120400ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                new_base_indent  = re.search(r'^([ \t]*)', prefix).group(0)
12058fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser                for line in lines[1:]:
120600ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                    if line.startswith(orig_base_indent):
120700ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                        # replace orig base indentation with new indentation
120800ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                        line = new_base_indent + line[len(orig_base_indent):]
120900ee7baf49430d8a6eed355a5fd7a05179325747Thomas Wouters                    self.text.insert('insert', '\n'+line.rstrip())
1210a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        finally:
1211a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.see("insert")
1212a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.undo_block_stop()
12137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runit(self):
12157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
12167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Strip off last newline and surrounding whitespace.
12177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (To allow you to hit return twice to end a statement.)
12187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        i = len(line)
12197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
12207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if i > 0 and line[i-1] == "\n":
12227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
12247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = line[:i]
1226038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy        self.interp.runsource(line)
12277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_stack_viewer(self, event=None):
12295d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
12305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.interp.remote_stack_viewer()
12317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
12327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.last_traceback
12337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
12347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("No stack trace",
12357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "There is no stack trace yet.\n"
12367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "(sys.last_traceback is not defined)",
12373be2e54adcc5c8fd87f5f21e09ee4a85d230f8c5Terry Jan Reedy                parent=self.text)
12387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
12396fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        from idlelib.stackviewer import StackBrowser
1240038c16b9a07b0905cef4760e5a5e92e322f56396Terry Jan Reedy        StackBrowser(self.root, self.flist)
12417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12421061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def view_restart_mark(self, event=None):
12431061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        self.text.see("iomark")
12441061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        self.text.see("restart")
12451061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser
12461061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def restart_shell(self, event=None):
1247da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        "Callback for Run/Restart Shell Cntl-F6"
1248da4c46721066ee44843372e8bf57c6c81dec8e4aTerry Jan Reedy        self.interp.restart_subprocess(with_cwd=True)
12491061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser
12507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showprompt(self):
12517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
12527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
12537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = str(sys.ps1)
12547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
12557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = ""
12567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console.write(s)
12577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
12585d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
1259dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        self.io.reset_undo()
12607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def resetoutput(self):
12627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        source = self.text.get("iomark", "end-1c")
12637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
12640a01ac4300ff3831d63fc065eb9bac7767bfd8dcTerry Jan Reedy            self.history.store(source)
12657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.get("end-2c") != "\n":
12667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("end-1c", "\n")
12677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("iomark", "end-1c")
12685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
12697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s, tags=()):
127105bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov        if isinstance(s, str) and len(s) and max(s) > '\uffff':
127205bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            # Tk doesn't support outputting non-BMP characters
127305bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            # Let's assume what printed string is not very long,
127405bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            # find first non-BMP character and construct informative
127505bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            # UnicodeEncodeError exception.
127605bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            for start, char in enumerate(s):
127705bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov                if char > '\uffff':
127805bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov                    break
127905bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov            raise UnicodeEncodeError("UCS-2", char, start, start+1,
128005bab93339308d330d6bd718575212ae2b3dc46dAndrew Svetlov                                     'Non-BMP character not supported in Tk')
1281003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        try:
1282003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.text.mark_gravity("iomark", "right")
128330d5e6c13fc988af2a6c0f8f0cdf43092c241e8fMartin v. Löwis            count = OutputWindow.write(self, s, tags, "iomark")
1284003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.text.mark_gravity("iomark", "left")
1285003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        except:
1286cbbe98f04fb03922ff2e3b6bf35769cf63673153Kurt B. Kaiser            raise ###pass  # ### 11Aug07 KBK if we are expecting exceptions
1287cbbe98f04fb03922ff2e3b6bf35769cf63673153Kurt B. Kaiser                           # let's find out what they are and be specific.
12887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
12897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
12907f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            if not use_subprocess:
12917f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                raise KeyboardInterrupt
129230d5e6c13fc988af2a6c0f8f0cdf43092c241e8fMartin v. Löwis        return count
12937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1294d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov    def rmenu_check_cut(self):
1295d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        try:
1296d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov            if self.text.compare('sel.first', '<', 'iomark'):
1297d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov                return 'disabled'
1298d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        except TclError: # no selection, so the index 'sel.first' doesn't exist
1299d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov            return 'disabled'
1300d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        return super().rmenu_check_cut()
1301d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov
1302d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov    def rmenu_check_paste(self):
1303d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        if self.text.compare('insert','<','iomark'):
1304d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov            return 'disabled'
1305d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov        return super().rmenu_check_paste()
1306d183767ca4786c00d84e284ad6c89fa3c154bad2Andrew Svetlov
1307969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
13085ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedydef fix_x11_paste(root):
13095ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy    "Make paste replace selection on x11.  See issue #5124."
13105ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy    if root._windowingsystem == 'x11':
13115ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy        for cls in 'Text', 'Entry', 'Spinbox':
13125ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy            root.bind_class(
13135ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy                cls,
13145ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy                '<<Paste>>',
13155ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy                'catch {%W delete sel.first sel.last}\n' +
13165ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy                        root.bind_class(cls, '<<Paste>>'))
13175ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy
13185ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy
13197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererusage_msg = """\
13207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
132111659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. KaiserUSAGE: idle  [-deins] [-t title] [file]*
132211659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser       idle  [-dns] [-t title] (-c cmd | -r file) [arg]*
132311659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser       idle  [-dns] [-t title] - [arg]*
13246655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
1325f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -h         print this help message and exit
13269b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov  -n         run IDLE without a subprocess (DEPRECATED,
13279b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov             see Help/IDLE Help for details)
1328f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1329f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserThe following options will override the IDLE 'settings' configuration:
1330f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1331f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -e         open an edit window
1332f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -i         open a shell window
1333f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1334f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserThe following options imply -i and will open a shell:
1335f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1336f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -c cmd     run the command in a shell, or
1337f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -r file    run script from file
1338f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1339f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -d         enable the debugger
1340f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1341f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -t title   set title of shell window
1342f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1343f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserA default edit window will be bypassed when -c, -r, or - are used.
1344f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1345f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1346f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1347f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserExamples:
13487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1349f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle
1350f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open an edit window or shell depending on IDLE's configuration.
135196d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser
1352f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle foo.py foobar.py
1353f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Edit the files, also open a shell if configured to start with shell.
1354f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1355f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle -est "Baz" foo.py
1356f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1357f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        window with the title "Baz".
1358f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1359752abd0d3cc66f84f551650b8424248b202a16a4Neal Norwitzidle -c "import sys; print(sys.argv)" "foo"
1360f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window and run the command, passing "-c" in sys.argv[0]
1361f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        and "foo" in sys.argv[1].
1362f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1363f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle -d -s -r foo.py "Hello World"
1364f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window, run a startup script, enable the debugger, and
1365f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1366f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv[1].
1367f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1368752abd0d3cc66f84f551650b8424248b202a16a4Neal Norwitzecho "import sys; print(sys.argv)" | idle - "foobar"
1369f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window, run the script piped in, passing '' in sys.argv[0]
1370f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        and "foobar" in sys.argv[1].
13717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer"""
13727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1373969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef main():
1374f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    global flist, root, use_subprocess
1375f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
137695a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    capture_warnings(True)
13778f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser    use_subprocess = True
1378c35151cf41eda485e40aadabbbfd61822bb157e8Roger Serwy    enable_shell = False
1379f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    enable_edit = False
1380f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    debug = False
1381969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    cmd = None
1382969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    script = None
1383f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    startup = False
1384969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    try:
13858f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
1386b940e113bf90ff71b0ef57414ea2beea9d2a4bc0Guido van Rossum    except getopt.error as msg:
138781b062f63ace48983439857314fec8063e8c72e0Terry Jan Reedy        print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
1388969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.exit(2)
1389969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for o, a in opts:
1390969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-c':
1391969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            cmd = a
1392f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1393969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-d':
1394f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            debug = True
1395f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1396969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-e':
1397f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_edit = True
1398f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if o == '-h':
1399f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            sys.stdout.write(usage_msg)
1400f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            sys.exit()
1401f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if o == '-i':
1402f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
14038f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if o == '-n':
14049b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov            print(" Warning: running IDLE without a subprocess is deprecated.",
14059b1e59a2b3a4683b38762576361f8ee3361314f4Andrew Svetlov                  file=sys.stderr)
14068f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            use_subprocess = False
1407969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-r':
1408969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            script = a
1409f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            if os.path.isfile(script):
1410f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                pass
1411f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            else:
1412be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum                print("No script file: ", script)
1413f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                sys.exit()
1414f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1415969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-s':
1416f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            startup = True
1417f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1418969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-t':
1419969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            PyShell.shell_title = a
1420f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1421f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if args and args[0] == '-':
1422f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        cmd = sys.stdin.read()
1423f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        enable_shell = True
1424f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # process sys.argv and sys.path:
1425969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for i in range(len(sys.path)):
1426969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.path[i] = os.path.abspath(sys.path[i])
1427f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if args and args[0] == '-':
1428f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = [''] + args[1:]
1429f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif cmd:
1430f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = ['-c'] + args
1431f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif script:
1432f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = [script] + args
1433f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif args:
1434f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        enable_edit = True
1435f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        pathx = []
1436969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
1437969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            pathx.append(os.path.dirname(filename))
1438f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        for dir in pathx:
1439f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            dir = os.path.abspath(dir)
1440f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            if not dir in sys.path:
1441f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                sys.path.insert(0, dir)
1442ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser    else:
1443d082b6eaace23486a2e5a027d6ac1b3cd253e8eeNeal Norwitz        dir = os.getcwd()
1444d082b6eaace23486a2e5a027d6ac1b3cd253e8eeNeal Norwitz        if dir not in sys.path:
1445ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser            sys.path.insert(0, dir)
1446f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # check the IDLE settings configuration (but command line overrides)
1447f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    edit_start = idleConf.GetOption('main', 'General',
14486655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser                                    'editor-on-startup', type='bool')
1449f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    enable_edit = enable_edit or edit_start
1450c35151cf41eda485e40aadabbbfd61822bb157e8Roger Serwy    enable_shell = enable_shell or not enable_edit
14515ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy
1452f35bb9e1e93cf7d8af377b2b28e6ecea7b1a2606Terry Jan Reedy    # Setup root.  Don't break user code run in IDLE process.
1453f35bb9e1e93cf7d8af377b2b28e6ecea7b1a2606Terry Jan Reedy    # Don't change environment when testing.
1454f35bb9e1e93cf7d8af377b2b28e6ecea7b1a2606Terry Jan Reedy    if use_subprocess and not testing:
1455b60adc54d4f248d71d831d14e11cc77fe72c281eTerry Jan Reedy        NoDefaultRoot()
1456969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root = Tk(className="Idle")
14575ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy    root.withdraw()
14580e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters
1459a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy    # set application icon
1460a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy    icondir = os.path.join(os.path.dirname(__file__), 'Icons')
1461a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy    if system() == 'Windows':
1462a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy        iconfile = os.path.join(icondir, 'idle.ico')
1463a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy        root.wm_iconbitmap(default=iconfile)
14641080d13a7da30df34de7862ea46525c2f19091c7Terry Jan Reedy    else:
1465a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy        ext = '.png' if TkVersion >= 8.6 else '.gif'
1466a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy        iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
1467a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy                     for size in (16, 32, 48)]
1468d3af156ded8cb645c1bd28deae7cde4d0e033d76Serhiy Storchaka        icons = [PhotoImage(master=root, file=iconfile)
1469d3af156ded8cb645c1bd28deae7cde4d0e033d76Serhiy Storchaka                 for iconfile in iconfiles]
1470a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy        root.wm_iconphoto(True, *icons)
1471a7c07d320b528dbc991f5ef2a8791026e784ea1fTerry Jan Reedy
1472b60adc54d4f248d71d831d14e11cc77fe72c281eTerry Jan Reedy    # start editor and/or shell windows:
1473969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    fixwordbreaks(root)
14745ad8599caad9f2f2fdefb927fc4bb19973d6c72eTerry Jan Reedy    fix_x11_paste(root)
1475969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist = PyShellFileList(root)
14766fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy    macosx.setupApp(root, flist)
1477f94471c1401e06df3021eafdde99c9be2c344dcbTerry Jan Reedy
1478f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if enable_edit:
1479f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if not (cmd or script):
14806b6e437626e94ad5ef3233ea9129c48957f1a41bAndrew Svetlov            for filename in args[:]:
14816b6e437626e94ad5ef3233ea9129c48957f1a41bAndrew Svetlov                if flist.open(filename) is None:
14826b6e437626e94ad5ef3233ea9129c48957f1a41bAndrew Svetlov                    # filename is a directory actually, disconsider it
14836b6e437626e94ad5ef3233ea9129c48957f1a41bAndrew Svetlov                    args.remove(filename)
1484f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            if not args:
1485f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                flist.new()
1486f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily
1487af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    if enable_shell:
14880e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters        shell = flist.open_shell()
14890e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters        if not shell:
1490af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return # couldn't open shell
14916fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        if macosx.isAquaTk() and flist.dict:
14920e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters            # On OSX: when the user has double-clicked on a file that causes
14930e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters            # IDLE to be launched the shell window will open just in front of
14940e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters            # the file she wants to see. Lower the interpreter window when
14950e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters            # there are open files.
14960e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters            shell.top.lower()
1497f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily    else:
1498f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        shell = flist.pyshell
14990e3f591aeeef9ed715f8770320f4c4c7332a8794Thomas Wouters
1500f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily    # Handle remaining options. If any of these are set, enable_shell
1501f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily    # was set also, so shell must be true to reach here.
1502f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if debug:
1503f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        shell.open_debugger()
1504969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if startup:
1505969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        filename = os.environ.get("IDLESTARTUP") or \
1506969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser                   os.environ.get("PYTHONSTARTUP")
1507969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if filename and os.path.isfile(filename):
1508f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execfile(filename)
1509f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily    if cmd or script:
1510f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        shell.interp.runcommand("""if 1:
1511f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            import sys as _sys
151270a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            _sys.argv = %r
1513f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            del _sys
151470a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            \n""" % (sys.argv,))
1515f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if cmd:
1516f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execsource(cmd)
1517f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        elif script:
151811659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            shell.interp.prepend_syspath(script)
1519f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execfile(script)
1520f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily    elif shell:
1521f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        # If there is a shell window and no cmd or script in progress,
1522f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        # check for problematic OS X Tk versions and print a warning
1523f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        # message in the IDLE shell window; this is less intrusive
1524f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        # than always opening a separate window.
15256fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy        tkversionwarning = macosx.tkVersionWarning(root)
1526f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily        if tkversionwarning:
1527f3c6589ea3890d10d6774ec7699a419313a6fb0fNed Deily            shell.interp.runcommand("print('%s')" % tkversionwarning)
15284ce92b23fe968a6866f89e31f4bfd4585c0cead2Ned Deily
1529cd6b8c67ceb4230198de9cdc971b27848c5391f0Terry Jan Reedy    while flist.inversedict:  # keep IDLE running while files are open.
1530cd6b8c67ceb4230198de9cdc971b27848c5391f0Terry Jan Reedy        root.mainloop()
1531969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.destroy()
153295a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy    capture_warnings(False)
1533969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
15347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == "__main__":
15356fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy    sys.modules['pyshell'] = sys.modules['__main__']
15367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    main()
153795a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedy
153895a3f11f95f0f1a3c35b431f9ea745cc9340a07cTerry Jan Reedycapture_warnings(False)  # Make sure turned off; see issue 18081
1539