PyShell.py revision 4b2c468e7464dc29700b50afcfc0bf101bea7fb8
17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#! /usr/bin/env python
2bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedyfrom __future__ import print_function
37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os
56e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiserimport os.path
67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys
77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport string
87aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport getopt
97aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re
105d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport socket
115d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport time
12003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiserimport threading
13e2b5624ee8cc4ac505162e6b3d99cfb4c2e8aa77Martin v. Löwisimport io
147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport linecache
167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom code import InteractiveInterpreter
174ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedyfrom platform import python_version, system
187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
192303b1c19abd79c94da327d630cbac6f4e83a05cKurt B. Kaisertry:
206634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandl    from Tkinter import *
212303b1c19abd79c94da327d630cbac6f4e83a05cKurt B. Kaiserexcept ImportError:
22bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy    print("** IDLE can't import Tkinter.\n"
23bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy          "Your Python may not be configured for Tk. **", file=sys.__stderr__)
242303b1c19abd79c94da327d630cbac6f4e83a05cKurt B. Kaiser    sys.exit(1)
256634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandlimport tkMessageBox
267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
27d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.EditorWindow import EditorWindow, fixwordbreaks
28d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.FileList import FileList
29d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.ColorDelegator import ColorDelegator
30d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.UndoDelegator import UndoDelegator
31d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.OutputWindow import OutputWindow
32d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib.configHandler import idleConf
33d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import rpc
34d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import Debugger
35d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import RemoteDebugger
36d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xiclunafrom idlelib import macosxSupport
374b2c468e7464dc29700b50afcfc0bf101bea7fb8Serhiy Storchakafrom idlelib import IOBinding
385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
39b97641994617115321719d4ecf797a461e2d5cf2Kurt B. KaiserIDENTCHARS = string.ascii_letters + string.digits + "_"
40013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. KaiserHOST = '127.0.0.1' # python execution server on localhost loopback
41013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. KaiserPORT = 0  # someday pass in host, port for remote debug capability
42b97641994617115321719d4ecf797a461e2d5cf2Kurt B. Kaiser
43a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaisertry:
44a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser    from signal import SIGTERM
45a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiserexcept ImportError:
46a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser    SIGTERM = 15
47a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser
4849a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# Override warnings module to write to warning_stream.  Initialize to send IDLE
4949a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# internal warnings to the console.  ScriptBinding.check_syntax() will
5049a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# temporarily redirect the stream to the shell window to display warnings when
5149a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser# checking user's code.
528eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedywarning_stream = sys.__stderr__  # None, at least on Windows, if no console.
538eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedyimport warnings
548eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
558eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedydef idle_formatwarning(message, category, filename, lineno, line=None):
568eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    """Format warnings the IDLE way."""
578eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
588eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    s = "\nWarning (from warnings module):\n"
598eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    s += '  File \"%s\", line %s\n' % (filename, lineno)
608eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    if line is None:
618eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        line = linecache.getline(filename, lineno)
628eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    line = line.strip()
638eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    if line:
648eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        s += "    %s\n" % line
658eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    s += "%s: %s\n" % (category.__name__, message)
668eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    return s
678eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
688eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedydef idle_showwarning(
698eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        message, category, filename, lineno, file=None, line=None):
708eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    """Show Idle-format warning (after replacing warnings.showwarning).
718eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
728eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    The differences are the formatter called, the file=None replacement,
738eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    which can be None, the capture of the consequence AttributeError,
748eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    and the output of a hard-coded prompt.
758eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    """
768eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    if file is None:
778eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        file = warning_stream
788eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    try:
798eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        file.write(idle_formatwarning(
808eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy                message, category, filename, lineno, line=line))
818eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        file.write(">>> ")
828eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    except (AttributeError, IOError):
838eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        pass  # if file (probably __stderr__) is invalid, skip warning.
848eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
858eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy_warnings_showwarning = None
868eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
878eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedydef capture_warnings(capture):
888eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    "Replace warning.showwarning with idle_showwarning, or reverse."
898eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
908eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    global _warnings_showwarning
918eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    if capture:
928eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        if _warnings_showwarning is None:
938eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy            _warnings_showwarning = warnings.showwarning
948eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy            warnings.showwarning = idle_showwarning
958eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    else:
968eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy        if _warnings_showwarning is not None:
978eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy            warnings.showwarning = _warnings_showwarning
988eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy            _warnings_showwarning = None
998eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
1008eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedycapture_warnings(True)
1015d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
102f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiserdef extended_linecache_checkcache(filename=None,
103f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser                                  orig_checkcache=linecache.checkcache):
10445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    """Extend linecache.checkcache to preserve the <pyshell#...> entries
10545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
106f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    Rather than repeating the linecache code, patch it to save the
107f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    <pyshell#...> entries, call the original linecache.checkcache()
108f198ac2db28109c0761395b80c7b482f9167f515Guilherme Polo    (skipping them), and then restore the saved entries.
109f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser
110f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    orig_checkcache is bound at definition time to the original
111f7a8899f33fb0a1efe6cb57fc1b712fa1059d0a6Kurt B. Kaiser    method, allowing it to be patched.
11245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    """
1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache = linecache.cache
1147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    save = {}
115f198ac2db28109c0761395b80c7b482f9167f515Guilherme Polo    for key in list(cache):
116f198ac2db28109c0761395b80c7b482f9167f515Guilherme Polo        if key[:1] + key[-1:] == '<>':
117f198ac2db28109c0761395b80c7b482f9167f515Guilherme Polo            save[key] = cache.pop(key)
118f198ac2db28109c0761395b80c7b482f9167f515Guilherme Polo    orig_checkcache(filename)
1197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache.update(save)
1206655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
121818855939ac016492cb59d1fc2fea94cc0764855Kurt B. Kaiser# Patch linecache.checkcache():
122818855939ac016492cb59d1fc2fea94cc0764855Kurt B. Kaiserlinecache.checkcache = extended_linecache_checkcache
1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
1257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellEditorWindow(EditorWindow):
126183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    "Regular text edit window in IDLE, supports breakpoints"
12745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
1287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, *args):
12945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.breakpoints = []
130931237e2e66975c54e2ac6c5e503ee2992a22bcfRaymond Hettinger        EditorWindow.__init__(self, *args)
1317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
13245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
1337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
1347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
135bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
136bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                                           'breakpoints.lst')
137a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        # whenever a file is changed, restore breakpoints
138bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        def filename_changed_hook(old_hook=self.io.filename_change_hook,
139bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                                  self=self):
140a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            self.restore_file_breaks()
141a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            old_hook()
142a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.io.set_filename_change_hook(filename_changed_hook)
143d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy        if self.io.filename:
144d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            self.restore_file_breaks()
14525327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy        self.color_breakpoint_text()
146a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
1475018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov    rmenu_specs = [
1485018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        ("Cut", "<<cut>>", "rmenu_check_cut"),
1495018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        ("Copy", "<<copy>>", "rmenu_check_copy"),
1505018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        ("Paste", "<<paste>>", "rmenu_check_paste"),
1515018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        ("Set Breakpoint", "<<set-breakpoint-here>>", None),
1525018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        ("Clear Breakpoint", "<<clear-breakpoint-here>>", None)
1535018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov    ]
1547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
15525327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy    def color_breakpoint_text(self, color=True):
15625327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy        "Turn colorizing of breakpoint text on or off"
15708da46e10f3fb49ecb2d69bc934667e5a352b2a7Terry Jan Reedy        if self.io is None:
15808da46e10f3fb49ecb2d69bc934667e5a352b2a7Terry Jan Reedy            # possible due to update in restore_file_breaks
15908da46e10f3fb49ecb2d69bc934667e5a352b2a7Terry Jan Reedy            return
16025327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy        if color:
16125327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy            theme = idleConf.GetOption('main','Theme','name')
16225327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy            cfg = idleConf.GetHighlight(theme, "break")
16325327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy        else:
16425327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy            cfg = {'foreground': '', 'background': ''}
16525327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy        self.text.tag_config('BREAK', cfg)
16625327d4d3bc1bab8b0263a44f8d8790ce03c7877Terry Jan Reedy
167a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def set_breakpoint(self, lineno):
16845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text = self.text
16945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        filename = self.io.filename
170a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
17145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
1722848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy            self.breakpoints.index(lineno)
173a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        except ValueError:  # only add if missing, i.e. do once
17445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints.append(lineno)
17545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:    # update the subprocess debugger
17645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug = self.flist.pyshell.interp.debugger
17745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.set_breakpoint_here(filename, lineno)
17845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except: # but debugger may not be active right now....
17945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
1807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
181a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def set_breakpoint_here(self, event=None):
182a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text = self.text
183a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        filename = self.io.filename
184a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        if not filename:
185a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            text.bell()
186a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey            return
187a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        lineno = int(float(text.index("insert")))
188a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.set_breakpoint(lineno)
189a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
190669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser    def clear_breakpoint_here(self, event=None):
19145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text = self.text
19245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        filename = self.io.filename
19345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if not filename:
19445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text.bell()
195669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            return
19645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        lineno = int(float(text.index("insert")))
19745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
19845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints.remove(lineno)
19945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except:
20045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
20145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        text.tag_remove("BREAK", "insert linestart",\
20245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                        "insert lineend +1char")
20345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        try:
20445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug = self.flist.pyshell.interp.debugger
20545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.clear_breakpoint_here(filename, lineno)
20645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        except:
20745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            pass
20845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
20945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def clear_file_breaks(self):
21045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if self.breakpoints:
21145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text = self.text
21245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            filename = self.io.filename
21345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            if not filename:
21445186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                text.bell()
21545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                return
21645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            self.breakpoints = []
21745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            text.tag_remove("BREAK", "1.0", END)
21845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            try:
21945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                debug = self.flist.pyshell.interp.debugger
22045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                debug.clear_file_breaks(filename)
22145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            except:
22245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser                pass
22345186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
224a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def store_file_breaks(self):
225bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        "Save breakpoints when file is saved"
226bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
227bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     be run.  The breaks are saved at that time.  If we introduce
228bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     a temporary file save feature the save breaks functionality
229bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     needs to be re-verified, since the breaks at the time the
230bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     temp file is created may differ from the breaks at the last
2317f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     permanent save of the file.  Currently, a break introduced
2327f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     after a save will be effective, but not persistent.
2337f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     This is necessary to keep the saved breaks synched with the
2347f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        #     saved file.
235bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #
236987a02b5cfe57c4430f2cd72d20aaa0d513ec7c3Terry Jan Reedy        #     Breakpoints are set as tagged ranges in the text.
237987a02b5cfe57c4430f2cd72d20aaa0d513ec7c3Terry Jan Reedy        #     Since a modified file has to be saved before it is
238bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     run, and since self.breakpoints (from which the subprocess
239bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     debugger is loaded) is updated during the save, the visible
240bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     breaks stay synched with the subprocess even if one of these
241bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        #     unexpected breakpoint deletions occurs.
242bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        breaks = self.breakpoints
243bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        filename = self.io.filename
244a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        try:
24540ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily            with open(self.breakpointPath,"r") as old_file:
24640ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                lines = old_file.readlines()
247a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        except IOError:
248bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            lines = []
24940ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily        try:
25040ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily            with open(self.breakpointPath,"w") as new_file:
25140ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                for line in lines:
25240ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                    if not line.startswith(filename + '='):
25340ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                        new_file.write(line)
25440ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                self.update_breakpoints()
25540ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                breaks = self.breakpoints
25640ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                if breaks:
25740ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                    new_file.write(filename + '=' + str(breaks) + '\n')
25840ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily        except IOError as err:
25940ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily            if not getattr(self.root, "breakpoint_error_displayed", False):
26040ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                self.root.breakpoint_error_displayed = True
26140ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                tkMessageBox.showerror(title='IDLE Error',
26240ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                    message='Unable to update breakpoint list:\n%s'
26340ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                        % str(err),
26440ad04171d7f3773ed29a3ff13a1d58eefab57c2Ned Deily                    parent=self.text)
265a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
266a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey    def restore_file_breaks(self):
267a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        self.text.update()   # this enables setting "BREAK" tags to be visible
268d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy        if self.io is None:
269d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            # can happen if IDLE closes due to the .update() call
270d7c9d9cdcdc179a0c9a458c70f814cd9db024e5dRoger Serwy            return
271bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        filename = self.io.filename
272bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        if filename is None:
273bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            return
27469371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey        if os.path.isfile(self.breakpointPath):
275bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            lines = open(self.breakpointPath,"r").readlines()
27669371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey            for line in lines:
277bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                if line.startswith(filename + '='):
2786655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser                    breakpoint_linenumbers = eval(line[len(filename)+1:])
27969371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey                    for breakpoint_linenumber in breakpoint_linenumbers:
28069371d6530cf6a14742e3d907dcbe03de06f8406Chui Tey                        self.set_breakpoint(breakpoint_linenumber)
281a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey
282bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser    def update_breakpoints(self):
283bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        "Retrieves all the breakpoints in the current window"
284a2adb0f6d99124101adbeac017b2d5623ad864baChui Tey        text = self.text
285bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        ranges = text.tag_ranges("BREAK")
286bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        linenumber_list = self.ranges_to_linenumbers(ranges)
287bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        self.breakpoints = linenumber_list
288bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser
289bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser    def ranges_to_linenumbers(self, ranges):
290bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        lines = []
291bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        for index in range(0, len(ranges), 2):
2928a15c37df7415189f6e9291df074fba68b68df43Andrew Svetlov            lineno = int(float(ranges[index].string))
2938a15c37df7415189f6e9291df074fba68b68df43Andrew Svetlov            end = int(float(ranges[index+1].string))
294bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser            while lineno < end:
295bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                lines.append(lineno)
296bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser                lineno += 1
297bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser        return lines
298bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser
29911220fad1d7eee24f1d9809c6d5023875099cb37Kurt B. Kaiser# XXX 13 Dec 2002 KBK Not used currently
300bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#    def saved_change_hook(self):
301bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        "Extend base method - clear breaks if module is modified"
302bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        if not self.get_saved():
303bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#            self.clear_file_breaks()
304bfed346259b27a51153b1f1bf5e4f062247e6246Kurt B. Kaiser#        EditorWindow.saved_change_hook(self)
30545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
30645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def _close(self):
30745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        "Extend base method - clear breaks when module is closed"
30845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.clear_file_breaks()
30945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        EditorWindow._close(self)
3106655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
3117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellFileList(FileList):
313183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    "Extend base class: IDLE supports a shell and breakpoints"
3147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
315183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    # override FileList's class variable, instances return PyShellEditorWindow
316183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser    # instead of EditorWindow when new edit windows are created.
3177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    EditorWindow = PyShellEditorWindow
3187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    pyshell = None
3207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_shell(self, event=None):
3227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.pyshell:
323183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            self.pyshell.top.wakeup()
3247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell = PyShell(self)
326af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            if self.pyshell:
327af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                if not self.pyshell.begin():
328af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                    return None
3297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.pyshell
3307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedColorDelegator(ColorDelegator):
33383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: colorizer for the shell window itself"
3346655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
335b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def __init__(self):
336b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.__init__(self)
337b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.LoadTagDefs()
3387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recolorize_main(self):
3407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_remove("TODO", "1.0", "iomark")
3417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_add("SYNC", "1.0", "iomark")
3427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ColorDelegator.recolorize_main(self)
3436655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
344b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def LoadTagDefs(self):
345b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.LoadTagDefs(self)
346b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        theme = idleConf.GetOption('main','Theme','name')
347b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.tagdefs.update({
348b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdin": {'background':None,'foreground':None},
349b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdout": idleConf.GetHighlight(theme, "stdout"),
350b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stderr": idleConf.GetHighlight(theme, "stderr"),
351b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "console": idleConf.GetHighlight(theme, "console"),
352b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        })
3537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3545e247b705e3bdd77967bca76601b791003389adaNed Deily    def removecolors(self):
3555e247b705e3bdd77967bca76601b791003389adaNed Deily        # Don't remove shell color tags before "iomark"
3565e247b705e3bdd77967bca76601b791003389adaNed Deily        for tag in self.tagdefs:
3575e247b705e3bdd77967bca76601b791003389adaNed Deily            self.tag_remove(tag, "iomark", "end")
3585e247b705e3bdd77967bca76601b791003389adaNed Deily
3597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedUndoDelegator(UndoDelegator):
36083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: forbid insert/delete before the I/O mark"
3617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def insert(self, index, chars, tags=None):
3637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
3647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index, "<", "iomark"):
3657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
3667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
3677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
3687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
3697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.insert(self, index, chars, tags)
3707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def delete(self, index1, index2=None):
3727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
3737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index1, "<", "iomark"):
3747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
3757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
3767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
3777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
3787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.delete(self, index1, index2)
3797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
38067fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
38167fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiserclass MyRPCClient(rpc.RPCClient):
38267fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
38367fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser    def handle_EOF(self):
38467fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        "Override the base class - just re-raise EOFError"
38567fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        raise EOFError
38667fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser
3878d1f11b0ef7ec31db75a4e640e9dfd75fc4ee08dKurt B. Kaiser
3887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedInterpreter(InteractiveInterpreter):
3897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, tkconsole):
3917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole = tkconsole
3927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        locals = sys.modules['__main__'].__dict__
3937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.__init__(self, locals=locals)
39494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = None
3956f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = False
396013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        self.subprocess_arglist = None
397013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        self.port = PORT
39886d669bdb849ab5cf99623494c706a5ab416e84eNed Deily        self.original_compiler_flags = self.compile.compiler.flags
3997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
40016ce43a6d8c4f6e0da088c8bc68dbbbdbb2e9a36Roger Serwy    _afterid = None
4015d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcclt = None
4025d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcpid = None
4035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
4046655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser    def spawn_subprocess(self):
405c8a730bf72b1c95651a8a39766bf56635956a2e0Florent Xicluna        if self.subprocess_arglist is None:
406013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            self.subprocess_arglist = self.build_subprocess_arglist()
40762df0448850000739edd1df8b4c0e702119d476eKurt B. Kaiser        args = self.subprocess_arglist
408b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser        self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
40963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser
410f53dec2e4e8a017641db4de73456a2724a75e64bTony Lownds    def build_subprocess_arglist(self):
411013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        assert (self.port!=0), (
412013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "Socket should have been assigned a port number.")
4132398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        w = ['-W' + s for s in sys.warnoptions]
414d076153ee8a9e4e2e7ecd3ff77fdb3b7aaf7ef77Georg Brandl        if 1/2 > 0: # account for new division
415d076153ee8a9e4e2e7ecd3ff77fdb3b7aaf7ef77Georg Brandl            w.append('-Qnew')
4162398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # Maybe IDLE is installed and is being accessed via sys.path,
4172398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # or maybe it's not installed and the idle.py script is being
4182398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        # run from the IDLE source directory.
41962df0448850000739edd1df8b4c0e702119d476eKurt B. Kaiser        del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
42062df0448850000739edd1df8b4c0e702119d476eKurt B. Kaiser                                       default=False, type='bool')
4212398d578a367aa0f9155afb7275a5aec4e5caef9Tony Lownds        if __name__ == 'idlelib.PyShell':
42270a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
423f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        else:
42470a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            command = "__import__('run').main(%r)" % (del_exitf,)
425b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser        if sys.platform[:3] == 'win' and ' ' in sys.executable:
426b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser            # handle embedded space in path by quoting the argument
427b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser            decorated_exec = '"%s"' % sys.executable
428b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser        else:
429b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser            decorated_exec = sys.executable
430b785518d051dab322feafaed0fc79d7218ce6cb0Kurt B. Kaiser        return [decorated_exec] + w + ["-c", command, str(self.port)]
431f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds
43263857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    def start_subprocess(self):
433013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        addr = (HOST, self.port)
434013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        # GUI makes several attempts to acquire socket, listens for connection
4355db4843c5e7d2b420b9ca9189b9e30669b62e55eKurt B. Kaiser        for i in range(3):
4365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            time.sleep(i)
4375d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
43867fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.rpcclt = MyRPCClient(addr)
4395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                break
4402848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy            except socket.error:
441af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                pass
4425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
443af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_port_binding_error()
444af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
445013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
446013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        self.port = self.rpcclt.listening_sock.getsockname()[1]
447013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        # if PORT was not 0, probably working with a remote execution server
448013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        if PORT != 0:
449013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            # To allow reconnection within the 2MSL wait (cf. Stevens TCP
450013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            # V1, 18.6),  set SO_REUSEADDR.  Note that this can be problematic
451013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            # on Windows since the implementation allows two active sockets on
452013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            # the same address!
453013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
454013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser                                           socket.SO_REUSEADDR, 1)
455013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        self.spawn_subprocess()
456013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser        #time.sleep(20) # test to simulate GUI not accepting connection
457b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser        # Accept the connection from the Python execution server
458af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        self.rpcclt.listening_sock.settimeout(10)
459af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
460af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.accept()
4612848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy        except socket.timeout:
462af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_no_subprocess_error()
463af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
4649abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.rpcclt.register("console", self.tkconsole)
4659abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.rpcclt.register("stdin", self.tkconsole.stdin)
466969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdout", self.tkconsole.stdout)
467969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stderr", self.tkconsole.stderr)
4685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt.register("flist", self.tkconsole.flist)
4698cd0def10dc028e3522a04bd136c67f92f90da04Kurt B. Kaiser        self.rpcclt.register("linecache", linecache)
4709f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        self.rpcclt.register("interp", self)
471b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        self.transfer_path(with_cwd=True)
4725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.poll_subprocess()
473af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        return self.rpcclt
4745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
475b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy    def restart_subprocess(self, with_cwd=False):
4766f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        if self.restarting:
477af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return self.rpcclt
4786f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = True
47963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        # close only the subprocess debugger
48045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        debug = self.getdebugger()
48145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if debug:
482003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            try:
4839ec454ec00088e051195e80363499a14cafc131aKurt B. Kaiser                # Only close subprocess debugger, don't unregister gui_adap!
484003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser                RemoteDebugger.close_subprocess_debugger(self.rpcclt)
485003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            except:
486003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser                pass
487003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        # Kill subprocess, spawn a new one, accept connection.
488a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt.close()
489a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.unix_terminate()
4907f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        console = self.tkconsole
4916f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        was_executing = console.executing
4927f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        console.executing = False
49363857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.spawn_subprocess()
494af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
495af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.accept()
4962848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy        except socket.timeout:
497af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.display_no_subprocess_error()
498af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return None
499b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        self.transfer_path(with_cwd=with_cwd)
500ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        console.stop_readline()
5011061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        # annotate restart in shell window and mark it
5024cc5ef5dbe12cbc9dc1a00c7583ffd0117f4c31eKurt B. Kaiser        console.text.delete("iomark", "end-1c")
5036f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        if was_executing:
5046f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser            console.write('\n')
5056f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser            console.showprompt()
5061061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        halfbar = ((int(console.width) - 16) // 2) * '='
5071061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        console.write(halfbar + ' RESTART ' + halfbar)
5081061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        console.text.mark_set("restart", "end-1c")
5091061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        console.text.mark_gravity("restart", "left")
5107f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        console.showprompt()
511003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        # restart subprocess debugger
51245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        if debug:
5139ec454ec00088e051195e80363499a14cafc131aKurt B. Kaiser            # Restarted debugger connects to current instance of debug GUI
5142848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy            RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
51545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            # reload remote debugger breakpoints for all PyShellEditWindows
51645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser            debug.load_breakpoints()
51786d669bdb849ab5cf99623494c706a5ab416e84eNed Deily        self.compile.compiler.flags = self.original_compiler_flags
5186f805942290b8d83f0e229de98c8d0d7a2a7c3e8Kurt B. Kaiser        self.restarting = False
519af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        return self.rpcclt
52045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
521003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def __request_interrupt(self):
522a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
523003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser
524003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def interrupt_subprocess(self):
525a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        threading.Thread(target=self.__request_interrupt).start()
526003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser
527a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser    def kill_subprocess(self):
52816ce43a6d8c4f6e0da088c8bc68dbbbdbb2e9a36Roger Serwy        if self._afterid is not None:
52916ce43a6d8c4f6e0da088c8bc68dbbbdbb2e9a36Roger Serwy            self.tkconsole.text.after_cancel(self._afterid)
530af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        try:
531af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            self.rpcclt.close()
532af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        except AttributeError:  # no socket
533af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            pass
534a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.unix_terminate()
535a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.tkconsole.executing = False
536a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        self.rpcclt = None
53711c53e2ea7f7d2a2969c98e81c1489c4e72254c4Kurt B. Kaiser
538a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser    def unix_terminate(self):
539a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        "UNIX: make sure subprocess is terminated and collect status"
540a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        if hasattr(os, 'kill'):
541a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            try:
542a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                os.kill(self.rpcpid, SIGTERM)
543a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            except OSError:
544a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                # process already terminated:
545a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                return
546a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            else:
547a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                try:
548a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                    os.waitpid(self.rpcpid, 0)
549a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                except OSError:
550a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser                    return
55111c53e2ea7f7d2a2969c98e81c1489c4e72254c4Kurt B. Kaiser
552b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy    def transfer_path(self, with_cwd=False):
553b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        if with_cwd:        # Issue 13506
554b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy            path = ['']     # include Current Working Directory
555b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy            path.extend(sys.path)
556b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        else:
557b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy            path = sys.path
5581d4ae48f48b2da82a89769a714644eb55a541888Terry Jan Reedy
559f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        self.runcommand("""if 1:
560f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        import sys as _sys
56170a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald        _sys.path = %r
562f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        del _sys
563b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        \n""" % (path,))
564f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
5655d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    active_seq = None
5665d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def poll_subprocess(self):
5685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
5695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is None:
5705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
571003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        try:
572a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            response = clt.pollresponse(self.active_seq, wait=0.05)
573a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        except (EOFError, IOError, KeyboardInterrupt):
574a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            # lost connection or subprocess terminated itself, restart
575a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            # [the KBI is from rpc.SocketIO.handle_EOF()]
57667fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if self.tkconsole.closing:
57767fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                return
578003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            response = None
579003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.restart_subprocess()
5805d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if response:
5815d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.resetoutput()
5825d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = None
5835d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            how, what = response
584bc2861313cc53711d837a0e8a5bf303bf5291bf3Kurt B. Kaiser            console = self.tkconsole.console
5855d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            if how == "OK":
5865d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if what is not None:
587bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                    print(repr(what), file=console)
5885d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "EXCEPTION":
5895d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
5905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    self.remote_stack_viewer()
5915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "ERROR":
5920930c43e43f79617a33a6c3be32afbe184780307Kurt B. Kaiser                errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
593bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                print(errmsg, what, file=sys.__stderr__)
594bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                print(errmsg, what, file=console)
595bc2861313cc53711d837a0e8a5bf303bf5291bf3Kurt B. Kaiser            # we received a response to the currently active seq number:
596d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser            try:
597d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                self.tkconsole.endexecuting()
598d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser            except AttributeError:  # shell may have closed
599d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                pass
60088957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        # Reschedule myself
60188957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        if not self.tkconsole.closing:
60216ce43a6d8c4f6e0da088c8bc68dbbbdbb2e9a36Roger Serwy            self._afterid = self.tkconsole.text.after(
60316ce43a6d8c4f6e0da088c8bc68dbbbdbb2e9a36Roger Serwy                self.tkconsole.pollinterval, self.poll_subprocess)
6045d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
60545186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    debugger = None
60645186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
60745186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def setdebugger(self, debugger):
60845186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        self.debugger = debugger
60945186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
61045186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser    def getdebugger(self):
61145186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser        return self.debugger
61245186c4ce08093d5f0d2f141f6e557e9726aedb4Kurt B. Kaiser
6139f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser    def open_remote_stack_viewer(self):
6149f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        """Initiate the remote stack viewer from a separate thread.
6159f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6169f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        This method is called from the subprocess, and by returning from this
6179f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        method we allow the subprocess to unblock.  After a bit the shell
6189f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        requests the subprocess to open the remote stack viewer which returns a
619c569cfebcebd3d3c8cf77e6c8971a19c78ff7261Ezio Melotti        static object looking at the last exception.  It is queried through
6209f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        the RPC mechanism.
6219f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6229f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        """
6239f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        self.tkconsole.text.after(300, self.remote_stack_viewer)
6249f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser        return
6259f3660972003dddcc1cced41934488513e277220Kurt B. Kaiser
6265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def remote_stack_viewer(self):
627d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna        from idlelib import RemoteObjectBrowser
628a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser        oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
6295d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if oid is None:
6305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.root.bell()
6315d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
6325d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
633d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna        from idlelib.TreeWidget import ScrolledCanvas, TreeNode
6345d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        top = Toplevel(self.tkconsole.root)
63573360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser        theme = idleConf.GetOption('main','Theme','name')
63673360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser        background = idleConf.GetHighlight(theme, 'normal')['background']
63773360a3e61274ffcc4c9fc3d09746bd6603e92a5Kurt B. Kaiser        sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
6385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc.frame.pack(expand=1, fill="both")
6395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node = TreeNode(sc.canvas, None, item)
6405d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node.expand()
6415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # XXX Should GC the remote tree when closing the window
6425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
6437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    gid = 0
6447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execsource(self, source):
64683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Like runsource() but assumes complete exec source"
6477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
6487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.execfile(filename, source)
6497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execfile(self, filename, source=None):
65183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Execute an existing file"
6527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if source is None:
6537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            source = open(filename, "r").read()
6547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            code = compile(source, filename, "exec")
6567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except (OverflowError, SyntaxError):
6577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
658bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy            print('*** Error in script or command!\n'
659bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                  'Traceback (most recent call last):',
660bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                  file=self.tkconsole.stderr)
6617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
6626e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            self.tkconsole.showprompt()
6637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
6647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runcode(code)
6657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runsource(self, source):
66783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method: Stuff the source in the line cache first"
6687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
6697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.more = 0
67094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = warnings.filters[:]
67194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        warnings.filterwarnings(action="error", category=SyntaxWarning)
6724b2c468e7464dc29700b50afcfc0bf101bea7fb8Serhiy Storchaka        if isinstance(source, unicode) and IOBinding.encoding != 'utf-8':
673837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser            try:
6744b2c468e7464dc29700b50afcfc0bf101bea7fb8Serhiy Storchaka                source = '# -*- coding: %s -*-\n%s' % (
6754b2c468e7464dc29700b50afcfc0bf101bea7fb8Serhiy Storchaka                        IOBinding.encoding,
6764b2c468e7464dc29700b50afcfc0bf101bea7fb8Serhiy Storchaka                        source.encode(IOBinding.encoding))
677837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser            except UnicodeError:
678837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                self.tkconsole.resetoutput()
679cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                self.write("Unsupported characters in input\n")
680837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                return
68194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        try:
682935ea9a0b291b2ce42a5cf02d9f2f2955e21a6aaKurt B. Kaiser            # InteractiveInterpreter.runsource() calls its runcode() method,
683935ea9a0b291b2ce42a5cf02d9f2f2955e21a6aaKurt B. Kaiser            # which is overridden (see below)
68494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            return InteractiveInterpreter.runsource(self, source, filename)
68594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        finally:
68694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            if self.save_warnings_filters is not None:
68794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                warnings.filters[:] = self.save_warnings_filters
68894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                self.save_warnings_filters = None
6897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def stuffsource(self, source):
69183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Stuff source in the filename cache"
6927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = "<pyshell#%d>" % self.gid
6937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.gid = self.gid + 1
694837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        lines = source.split("\n")
6957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        linecache.cache[filename] = len(source)+1, 0, lines, filename
6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return filename
6976655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
69811659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser    def prepend_syspath(self, filename):
69911659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser        "Prepend sys.path with file's directory if not already included"
70011659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser        self.runcommand("""if 1:
70170a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            _filename = %r
70211659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            import sys as _sys
70311659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            from os.path import dirname as _dirname
70411659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            _dir = _dirname(_filename)
70511659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            if not _dir in _sys.path:
70611659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser                _sys.path.insert(0, _dir)
70711659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            del _filename, _sys, _dirname, _dir
70870a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            \n""" % (filename,))
70911659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser
7107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showsyntaxerror(self, filename=None):
71183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """Extend base class method: Add Colorizing
71283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
71383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        Color the offending position instead of printing it and pointing at it
71483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        with a caret.
71583118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
71683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """
7177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.tkconsole.text
7187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        stuff = self.unpackerror()
7196e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser        if stuff:
7206e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            msg, lineno, offset, line = stuff
7216e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            if lineno == 1:
7226e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser                pos = "iomark + %d chars" % (offset-1)
7236e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            else:
7246e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser                pos = "iomark linestart + %d lines + %d chars" % \
7256e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser                      (lineno-1, offset-1)
7266e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            text.tag_add("ERROR", pos)
7276e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            text.see(pos)
7286e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            char = text.get(pos)
7296e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            if char and char in IDENTCHARS:
7306e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser                text.tag_add("ERROR", pos + " wordstart", pos)
7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
7326e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            self.write("SyntaxError: %s\n" % str(msg))
7337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7346e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            self.tkconsole.resetoutput()
7356e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser            InteractiveInterpreter.showsyntaxerror(self, filename)
7366e44cc236900c8f85164e543d0d3e7f429a1f1c8Kurt B. Kaiser        self.tkconsole.showprompt()
7377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def unpackerror(self):
7397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        type, value, tb = sys.exc_info()
7407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ok = type is SyntaxError
7417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
7427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
7437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                msg, (dummy_filename, lineno, offset, line) = value
744bea57c6c355ba98cd9019d13e5adf7d715377edfKurt B. Kaiser                if not offset:
745bea57c6c355ba98cd9019d13e5adf7d715377edfKurt B. Kaiser                    offset = 0
7467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
7477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                ok = 0
7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
7497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return msg, lineno, offset, line
7507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return None
7527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showtraceback(self):
75483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method to reset output properly"
7557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.checklinecache()
7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.showtraceback(self)
7585d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
7595d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.open_stack_viewer()
7607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def checklinecache(self):
7627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        c = linecache.cache
7637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for key in c.keys():
7647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if key[:1] + key[-1:] != "<>":
7657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del c[key]
7667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def runcommand(self, code):
76883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Run the code without invoking the debugger"
7695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # The code better not raise an exception!
7705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
771f4c4f115d80a26eb83d90593c24a1580f236c443Neal Norwitz            self.display_executing_dialog()
7725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return 0
7735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.rpcclt:
774a00050f209acf2201b2382f9d534a2595bacf5c3Kurt B. Kaiser            self.rpcclt.remotequeue("exec", "runcode", (code,), {})
7755d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
7765d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            exec code in self.locals
7775d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        return 1
7785d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
7797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runcode(self, code):
78083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
7815d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
782003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.interp.restart_subprocess()
7835d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.checklinecache()
78494bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        if self.save_warnings_filters is not None:
78594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            warnings.filters[:] = self.save_warnings_filters
78694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            self.save_warnings_filters = None
7877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        debugger = self.debugger
7887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
7897f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.tkconsole.beginexecuting()
790dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            if not debugger and self.rpcclt is not None:
791dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
792dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                                                        (code,), {})
793dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            elif debugger:
794dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                debugger.run(code, self.locals)
795dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            else:
796dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                exec code in self.locals
797dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser        except SystemExit:
798dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            if not self.tkconsole.closing:
799dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                if tkMessageBox.askyesno(
800dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    "Exit?",
801dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    "Do you want to exit altogether?",
802dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    default="yes",
803dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    master=self.tkconsole.text):
804f137e1df2c02f5782c5b0f18a2b3b649f255f63aKurt B. Kaiser                    raise
805dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                else:
806dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    self.showtraceback()
807dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            else:
808dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                raise
809dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser        except:
810dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            if use_subprocess:
811bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                print("IDLE internal error in runcode()",
812bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                      file=self.tkconsole.stderr)
8137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.showtraceback()
814dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                self.tkconsole.endexecuting()
815dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser            else:
816dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                if self.tkconsole.canceled:
817dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    self.tkconsole.canceled = False
818bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                    print("KeyboardInterrupt", file=self.tkconsole.stderr)
819dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                else:
820dddeb0eec4dcb1ba3c408a54ad01e1a1ea4d5670Kurt B. Kaiser                    self.showtraceback()
8217f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        finally:
8227f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            if not use_subprocess:
823d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                try:
824d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                    self.tkconsole.endexecuting()
825d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                except AttributeError:  # shell may have closed
826d112bc7958151fa17c4ccb27413c43e45b8476fbKurt B. Kaiser                    pass
8277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
82983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
8307f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        self.tkconsole.stderr.write(s)
8317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
832af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_port_binding_error(self):
833af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
834af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Port Binding Error",
835013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "IDLE can't bind to a TCP/IP port, which is necessary to "
836013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "communicate with its Python execution server.  This might be "
837013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "because no networking is installed on this computer.  "
838013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "Run IDLE with the -n command line switch to start without a "
839013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "subprocess and refer to Help/IDLE Help 'Running without a "
840013d6cc0df238013075930c5adb1c4724f38aa49Kurt B. Kaiser            "subprocess' for further details.",
841af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            master=self.tkconsole.text)
842af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
843af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_no_subprocess_error(self):
844af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
845af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Subprocess Startup Error",
846af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "IDLE's subprocess didn't make connection.  Either IDLE can't "
847af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "start a subprocess or personal firewall software is blocking "
848af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "the connection.",
849af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            master=self.tkconsole.text)
850af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
851af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    def display_executing_dialog(self):
852af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser        tkMessageBox.showerror(
853af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "Already executing",
854af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "The Python Shell window is already executing a command; "
855af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            "please wait until it is finished.",
856af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            master=self.tkconsole.text)
857af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
858af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser
8597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShell(OutputWindow):
8607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
861d676a3a221b99e1b352e18be0939158dfc37ef82Terry Jan Reedy    shell_title = "Python " + python_version() + " Shell"
8627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Override classes
8647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ColorDelegator = ModifiedColorDelegator
8657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    UndoDelegator = ModifiedUndoDelegator
8667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
867f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # Override menus
868dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    menu_specs = [
869dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("file", "_File"),
870dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("edit", "_Edit"),
8714cc5ef5dbe12cbc9dc1a00c7583ffd0117f4c31eKurt B. Kaiser        ("debug", "_Debug"),
8721061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        ("options", "_Options"),
873b5daa3d6db429017dea1e4f15b78557e03b5f847Ned Deily        ("windows", "_Window"),
874dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("help", "_Help"),
875dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    ]
8767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
87719302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren
8787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # New classes
879d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna    from idlelib.IdleHistory import History
8807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, flist=None):
8828f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if use_subprocess:
88367fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            ms = self.menu_specs
88467fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if ms[2][0] != "shell":
8857ae354846fff616746eeba6d27ccd5c175591caeKurt B. Kaiser                ms.insert(2, ("shell", "She_ll"))
8867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = ModifiedInterpreter(self)
8877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if flist is None:
8887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root = Tk()
8897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            fixwordbreaks(root)
8907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root.withdraw()
8917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            flist = PyShellFileList(root)
8925afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.__init__(self, flist, None, None)
8945afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
8956af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser##        self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
8966af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.usetabs = True
8976af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        # indentwidth must be 8 when using tabs.  See note in EditorWindow:
8986af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.indentwidth = 8
8996af44986029c84c4c5df62a64c60a6ed978a3693Kurt B. Kaiser        self.context_use_ps1 = True
9005afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
9017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.text
9027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.configure(wrap="char")
9037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<newline-and-indent>>", self.enter_callback)
9047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
9057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<interrupt-execution>>", self.cancel_callback)
9067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<end-of-file>>", self.eof_callback)
9077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
90857bfe5dc5a4873026679fb911939beb69e35a9e8Kurt B. Kaiser        text.bind("<<toggle-debugger>>", self.toggle_debugger)
9097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
9108f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if use_subprocess:
9118f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            text.bind("<<view-restart>>", self.view_restart_mark)
9128f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            text.bind("<<restart-shell>>", self.restart_shell)
9135afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
9147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdout = sys.stdout
9157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stderr = sys.stderr
9167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdin = sys.stdin
917d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna        from idlelib import IOBinding
9189abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.stdin = PseudoInputFile(self, "stdin", IOBinding.encoding)
9199abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.stdout = PseudoOutputFile(self, "stdout", IOBinding.encoding)
9209abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.stderr = PseudoOutputFile(self, "stderr", IOBinding.encoding)
9219abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self.console = PseudoOutputFile(self, "console", IOBinding.encoding)
9225d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not use_subprocess:
9235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdout = self.stdout
9245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stderr = self.stderr
925e2b5624ee8cc4ac505162e6b3d99cfb4c2e8aa77Martin v. Löwis            sys.stdin = self.stdin
9265afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
9277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = self.History(self.text)
9285afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
92988957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        self.pollinterval = 50  # millisec
9305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
9314d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser    def get_standard_extension_names(self):
9324d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser        return idleConf.GetExtensions(shell_only=True)
9334d5bc6031ca883201f87e0e3c94e5746f9f91439Kurt B. Kaiser
934003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    reading = False
935003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    executing = False
936003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    canceled = False
937003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    endoffile = False
938003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    closing = False
939ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy    _stop_readline_flag = False
9407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
94149a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser    def set_warning_stream(self, stream):
942d91614234375621f3b78cb9c8c5a58b77c961fe8Skip Montanaro        global warning_stream
943d91614234375621f3b78cb9c8c5a58b77c961fe8Skip Montanaro        warning_stream = stream
94449a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser
94549a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser    def get_warning_stream(self):
94649a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser        return warning_stream
94749a5fe107fceb0239d87119842b20a7421043b5aKurt B. Kaiser
9487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_debugger(self, event=None):
9497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
9507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("Don't debug now",
9517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "You can only toggle the debugger when idle",
9527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
9537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.set_debugger_indicator()
9547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
9557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
9567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db = self.interp.getdebugger()
9577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if db:
9587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.close_debugger()
9597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            else:
9607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.open_debugger()
9617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_debugger_indicator(self):
9637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
9647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.setvar("<<toggle-debugger>>", not not db)
9657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9661061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def toggle_jit_stack_viewer(self, event=None):
9677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass # All we need is the variable
9687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close_debugger(self):
9707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
9717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if db:
9727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.interp.setdebugger(None)
9737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db.close()
974ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser            if self.interp.rpcclt:
975ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser                RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
9767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
9777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.console.write("[DEBUG OFF]\n")
9787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
9797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
9807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
9817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_debugger(self):
9835d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
9847f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
9857f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                                                           self)
9867f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        else:
9877f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            dbg_gui = Debugger.Debugger(self)
9887f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        self.interp.setdebugger(dbg_gui)
9897f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        dbg_gui.load_breakpoints()
9905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sys.ps1 = "[DEBUG ON]\n>>> "
9915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
9925d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_debugger_indicator()
9935d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
9947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def beginexecuting(self):
995ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser        "Helper for ModifiedInterpreter"
9967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
9977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 1
9987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def endexecuting(self):
100083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Helper for ModifiedInterpreter"
10017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 0
10027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.canceled = 0
10035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
10047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close(self):
100683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow.close()"
10077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
1008003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            response = tkMessageBox.askokcancel(
10097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "Kill?",
1010003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser                "The program is still running!\n Do you want to kill it?",
10117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                default="ok",
10127f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                parent=self.text)
10135b63acd31e0e40c1a9a9e9762905b0054ff37994Benjamin Peterson            if response is False:
10147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "cancel"
1015ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        self.stop_readline()
10165c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        self.canceled = True
101767fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser        self.closing = True
101888957d8d0d9bf6d45603171927aa82d921bf9697Kurt B. Kaiser        return EditorWindow.close(self)
10197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def _close(self):
102183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow._close(), shut down debugger and execution server"
10227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.close_debugger()
10237f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        if use_subprocess:
10247f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.interp.kill_subprocess()
10257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Restore std streams
10267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout = self.save_stdout
10277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stderr = self.save_stderr
10287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdin = self.save_stdin
10297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Break cycles
10307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = None
10317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = None
10327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell = None
10337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = None
103483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        EditorWindow._close(self)
10357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def ispythonsource(self, filename):
103783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override EditorWindow method: never remove the colorizer"
1038837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
10397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def short_title(self):
10417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.shell_title
10427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
104394bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser    COPYRIGHT = \
10448f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser          'Type "copyright", "credits" or "license()" for more information.'
104594bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser
10467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def begin(self):
10477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
10487f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        if use_subprocess:
10497f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            nosub = ''
1050af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            client = self.interp.start_subprocess()
1051af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            if not client:
1052af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser                self.close()
10537663729ec72f5ffe44b8e7f76bdb56d8663c5e6eKurt B. Kaiser                return False
10547f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser        else:
10557f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            nosub = "==== No Subprocess ===="
1056bf3f69ee85d3c497bfdeae3ac3338c1409ca454cRaymond Hettinger        self.write("Python %s on %s\n%s\n%s" %
1057bf3f69ee85d3c497bfdeae3ac3338c1409ca454cRaymond Hettinger                   (sys.version, sys.platform, self.COPYRIGHT, nosub))
10587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
10596634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandl        import Tkinter
10606634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandl        Tkinter._default_root = None # 03Jan04 KBK What's this?
10617663729ec72f5ffe44b8e7f76bdb56d8663c5e6eKurt B. Kaiser        return True
10627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1063ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy    def stop_readline(self):
1064ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        if not self.reading:  # no nested mainloop to exit.
1065ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy            return
1066ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        self._stop_readline_flag = True
1067ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        self.top.quit()
1068ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy
10697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def readline(self):
10707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        save = self.reading
10717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
10727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = 1
10735c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            self.top.mainloop()  # nested mainloop()
10747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
10757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = save
1076ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy        if self._stop_readline_flag:
1077ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy            self._stop_readline_flag = False
1078ad8cad3c6d18f1455de9b4d3d370702eb3a1ee9fRoger Serwy            return ""
10797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
10805c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if len(line) == 0:  # may be EOF if we quit our mainloop with Ctrl-C
10815c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            line = "\n"
1082bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis        if isinstance(line, unicode):
1083d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna            from idlelib import IOBinding
1084bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis            try:
1085bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis                line = line.encode(IOBinding.encoding)
1086bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis            except UnicodeError:
1087bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis                pass
10887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
10897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
10907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
10915c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            if not use_subprocess:
10925c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser                raise KeyboardInterrupt
10937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.endoffile:
10947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 0
10955c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            line = ""
10967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return line
10977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
10987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
1099837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
11007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1101003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser    def cancel_callback(self, event=None):
11027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
11037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.text.compare("sel.first", "!=", "sel.last"):
11047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return # Active selection -- always use default binding
11057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
11067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
11077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.executing or self.reading):
11087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
11097f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            self.interp.write("KeyboardInterrupt\n")
11107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
11117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
11127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.endoffile = 0
1113003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        self.canceled = 1
11145c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if (self.executing and self.interp.rpcclt):
111567fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            if self.interp.getdebugger():
111667fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.interp.restart_subprocess()
111767fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser            else:
111867fd0ea46d187ccab90ed574207bc88503bde3eaKurt B. Kaiser                self.interp.interrupt_subprocess()
11195c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser        if self.reading:
11205c3df35b6b1f48cb48c91b0c7a8754590a694171Kurt B. Kaiser            self.top.quit()  # exit the nested mainloop() in readline()
11217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def eof_callback(self, event):
11247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
11257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
11267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.text.compare("iomark", "==", "insert") and
11277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.text.compare("insert", "==", "end-1c")):
11287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
11297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.executing:
11307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
11317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.close()
11327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
11337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
11347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 1
11357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
11367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def linefeed_callback(self, event):
11397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Insert a linefeed without entering anything (still autoindented)
11407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
11417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
11427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
11437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1144822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
11457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
11467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
11477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def enter_callback(self, event):
11487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
11497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (insert '\n') take over
11507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If some text is selected, recall the selection
11517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (but only if this before the I/O mark)
11527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
11537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sel = self.text.get("sel.first", "sel.last")
11547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if sel:
11557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if self.text.compare("sel.last", "<=", "iomark"):
1156a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                    self.recall(sel, event)
11577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    return "break"
11587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
11597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
11607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're strictly before the line containing iomark, recall
11617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # the current line, less a leading prompt, less leading or
11627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # trailing whitespace
11637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "iomark linestart"):
11647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Check if there's a relevant stdin range -- if so, use it
11657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            prev = self.text.tag_prevrange("stdin", "insert")
11667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if prev and self.text.compare("insert", "<", prev[1]):
1167a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                self.recall(self.text.get(prev[0], prev[1]), event)
11687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
11697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            next = self.text.tag_nextrange("stdin", "insert")
11707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if next and self.text.compare("insert lineend", ">=", next[0]):
1171a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser                self.recall(self.text.get(next[0], next[1]), event)
11727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
11734ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser            # No stdin mark -- just get the current line, less any prompt
1174b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            indices = self.text.tag_nextrange("console", "insert linestart")
1175b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            if indices and \
1176b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser               self.text.compare(indices[0], "<=", "insert linestart"):
1177b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser                self.recall(self.text.get(indices[1], "insert lineend"), event)
1178b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser            else:
1179b17544551fc8dfd1304d5679c6e444cad4d34d97Kurt B. Kaiser                self.recall(self.text.get("insert linestart", "insert lineend"), event)
11807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
1181822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser        # If we're between the beginning of the line and the iomark, i.e.
11824ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser        # in the prompt area, move to the end of the prompt
1183822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser        if self.text.compare("insert", "<", "iomark"):
11844ada7ad3bc9ab269189ed20e57943d9721664debKurt B. Kaiser            self.text.mark_set("insert", "iomark")
11857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input and there's only whitespace
11867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # beyond the cursor, erase that whitespace first
11877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        s = self.text.get("insert", "end-1c")
1188837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        if s and not s.strip():
11897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.delete("insert", "end-1c")
11907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input before its last line,
11917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # insert a newline right at the insert point
11927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "end-1c linestart"):
1193822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
11947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
11957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # We're in the last line; append a newline and submit it
11967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
11977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
11987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
11997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
12007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1201822a77fcc761b3c9992950ddf48b3f0bec917b4dKurt B. Kaiser            self.newline_and_indent_event(event)
12027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.tag_add("stdin", "iomark", "end-1c")
12037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.update_idletasks()
12047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
12057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit() # Break out of recursive mainloop() in raw_input()
12067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
12077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runit()
12087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
12097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1210a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser    def recall(self, s, event):
1211cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser        # remove leading and trailing empty or whitespace lines
1212cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser        s = re.sub(r'^\s*\n', '' , s)
1213cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser        s = re.sub(r'\n\s*$', '', s)
1214cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser        lines = s.split('\n')
1215a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        self.text.undo_block_start()
1216a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        try:
1217a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.tag_remove("sel", "1.0", "end")
1218a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.mark_set("insert", "end-1c")
1219cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser            prefix = self.text.get("insert linestart", "insert")
1220cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser            if prefix.rstrip().endswith(':'):
12218fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser                self.newline_and_indent_event(event)
1222cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                prefix = self.text.get("insert linestart", "insert")
1223cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser            self.text.insert("insert", lines[0].strip())
12248fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser            if len(lines) > 1:
1225cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
1226cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                new_base_indent  = re.search(r'^([ \t]*)', prefix).group(0)
12278fa7eb563bb9a14651bcdc8ee60c5e45302c2f59Kurt B. Kaiser                for line in lines[1:]:
1228cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                    if line.startswith(orig_base_indent):
1229cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                        # replace orig base indentation with new indentation
1230cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                        line = new_base_indent + line[len(orig_base_indent):]
1231cd3d8bee022cda55c43c2130122d092f5059d115Kurt B. Kaiser                    self.text.insert('insert', '\n'+line.rstrip())
1232a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser        finally:
1233a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.see("insert")
1234a7daba6866136d1c554ba6bf278e9ddaf52ecac6Kurt B. Kaiser            self.text.undo_block_stop()
12357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runit(self):
12377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
12387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Strip off last newline and surrounding whitespace.
12397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (To allow you to hit return twice to end a statement.)
12407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        i = len(line)
12417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
12427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if i > 0 and line[i-1] == "\n":
12447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
12467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
12477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = line[:i]
12482848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy        self.interp.runsource(line)
12497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_stack_viewer(self, event=None):
12515d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
12525d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.interp.remote_stack_viewer()
12537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
12547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.last_traceback
12557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
12567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("No stack trace",
12577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "There is no stack trace yet.\n"
12587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "(sys.last_traceback is not defined)",
12597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
12607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
1261d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna        from idlelib.StackViewer import StackBrowser
12622848925ed252769d5fcc4ee1ba91a250810b1b55Terry Jan Reedy        StackBrowser(self.root, self.flist)
12637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12641061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def view_restart_mark(self, event=None):
12651061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        self.text.see("iomark")
12661061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser        self.text.see("restart")
12671061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser
12681061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser    def restart_shell(self, event=None):
1269b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        "Callback for Run/Restart Shell Cntl-F6"
1270b98000ab5bd3fcb3774666ce3bb127e71634c349Terry Jan Reedy        self.interp.restart_subprocess(with_cwd=True)
12711061e7270b13a0e632c5a28791a46e38b48a39a0Kurt B. Kaiser
12727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showprompt(self):
12737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
12747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
12757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = str(sys.ps1)
12767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
12777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = ""
12787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console.write(s)
12797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
12805d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
1281dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        self.io.reset_undo()
12827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def resetoutput(self):
12847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        source = self.text.get("iomark", "end-1c")
12857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
1286b638a38dc07dcc87c62eac5177b96824e2e8dfa2Terry Jan Reedy            self.history.store(source)
12877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.get("end-2c") != "\n":
12887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("end-1c", "\n")
12897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("iomark", "end-1c")
12905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
12917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout.softspace = 0
12927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
12937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s, tags=()):
1294003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        try:
1295003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.text.mark_gravity("iomark", "right")
1296003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            OutputWindow.write(self, s, tags, "iomark")
1297003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            self.text.mark_gravity("iomark", "left")
1298003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser        except:
1299003091cd51c5278e3ef76b6db01bd719b8b1c416Kurt B. Kaiser            pass
13007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
13017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
13027f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser            if not use_subprocess:
13037f38ec0849fd2b19e660350c59d42b8b5cfae2d1Kurt B. Kaiser                raise KeyboardInterrupt
13047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13055018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov    def rmenu_check_cut(self):
13065018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        try:
13075018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov            if self.text.compare('sel.first', '<', 'iomark'):
13085018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov                return 'disabled'
13095018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        except TclError: # no selection, so the index 'sel.first' doesn't exist
13105018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov            return 'disabled'
13115018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        return super(PyShell, self).rmenu_check_cut()
13125018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov
13135018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov    def rmenu_check_paste(self):
13145018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        if self.text.compare('insert', '<', 'iomark'):
13155018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov            return 'disabled'
13165018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov        return super(PyShell, self).rmenu_check_paste()
13175018db76aa433430e1bdb0826086df1c025a1f70Andrew Svetlov
13189abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchakaclass PseudoFile(io.TextIOBase):
13197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1320bcc651a1f954bad7a14d93d41e95728072e48ea0Martin v. Löwis    def __init__(self, shell, tags, encoding=None):
13217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.shell = shell
13227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tags = tags
13235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.softspace = 0
13249abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self._encoding = encoding
13259abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13269abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    @property
13279abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def encoding(self):
13289abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return self._encoding
13299abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13309abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    @property
13319abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def name(self):
13329abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return '<%s>' % self.tags
13339abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13349abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def isatty(self):
13359abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return True
13369abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13379abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13389abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchakaclass PseudoOutputFile(PseudoFile):
13399abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13409abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def writable(self):
13419abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return True
13427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
13449abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if self.closed:
13459abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            raise ValueError("write to closed file")
13467057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka        if type(s) not in (unicode, str, bytearray):
13477057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka            # See issue #19481
13487057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka            if isinstance(s, unicode):
1349ac5164dd985397e5bbf89c2789738601b7a47a72Serhiy Storchaka                s = unicode.__getitem__(s, slice(None))
13507057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka            elif isinstance(s, str):
13517057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka                s = str.__str__(s)
13527057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka            elif isinstance(s, bytearray):
13537057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka                s = bytearray.__str__(s)
13547057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka            else:
13557057f3fa4db3df28148c6b764e92789b07271689Serhiy Storchaka                raise TypeError('must be string, not ' + type(s).__name__)
13569abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return self.shell.write(s, self.tags)
13577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13599abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchakaclass PseudoInputFile(PseudoFile):
13607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13619abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def __init__(self, shell, tags, encoding=None):
13629abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        PseudoFile.__init__(self, shell, tags, encoding)
13639abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self._line_buffer = ''
13647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
13659abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def readable(self):
13669abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return True
1367e2b5624ee8cc4ac505162e6b3d99cfb4c2e8aa77Martin v. Löwis
13689abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def read(self, size=-1):
13699abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if self.closed:
13709abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            raise ValueError("read from closed file")
13719abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if size is None:
13729abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            size = -1
13739abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        elif not isinstance(size, int):
13749abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            raise TypeError('must be int, not ' + type(size).__name__)
13759abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        result = self._line_buffer
13769abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self._line_buffer = ''
13779abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if size < 0:
13789abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            while True:
13799abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                line = self.shell.readline()
13809abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                if not line: break
13819abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                result += line
13829abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        else:
13839abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            while len(result) < size:
13849abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                line = self.shell.readline()
13859abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                if not line: break
13869abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka                result += line
13879abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            self._line_buffer = result[size:]
13889abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            result = result[:size]
13899abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return result
13909abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka
13919abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka    def readline(self, size=-1):
13929abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if self.closed:
13939abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            raise ValueError("read from closed file")
13949abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if size is None:
13959abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            size = -1
13969abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        elif not isinstance(size, int):
13979abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            raise TypeError('must be int, not ' + type(size).__name__)
13989abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        line = self._line_buffer or self.shell.readline()
13999abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        if size < 0:
14009abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka            size = len(line)
14010b6b335253949df26c369ecce35199e9dc2b86f5Serhiy Storchaka        eol = line.find('\n', 0, size)
14020b6b335253949df26c369ecce35199e9dc2b86f5Serhiy Storchaka        if eol >= 0:
14030b6b335253949df26c369ecce35199e9dc2b86f5Serhiy Storchaka            size = eol + 1
14049abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        self._line_buffer = line[size:]
14059abc830c6a7b490f7ae248e5fa63c50e55d98cccSerhiy Storchaka        return line[:size]
1406e2b5624ee8cc4ac505162e6b3d99cfb4c2e8aa77Martin v. Löwis
140753dc4f0148f08d0da5c394089b7061cd77269fc0Roger Serwy    def close(self):
140853dc4f0148f08d0da5c394089b7061cd77269fc0Roger Serwy        self.shell.close()
140953dc4f0148f08d0da5c394089b7061cd77269fc0Roger Serwy
1410969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
14117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererusage_msg = """\
14127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
141311659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. KaiserUSAGE: idle  [-deins] [-t title] [file]*
141411659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser       idle  [-dns] [-t title] (-c cmd | -r file) [arg]*
141511659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser       idle  [-dns] [-t title] - [arg]*
14166655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser
1417f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -h         print this help message and exit
14188f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser  -n         run IDLE without a subprocess (see Help/IDLE Help for details)
1419f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1420f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserThe following options will override the IDLE 'settings' configuration:
1421f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1422f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -e         open an edit window
1423f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -i         open a shell window
1424f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1425f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserThe following options imply -i and will open a shell:
1426f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1427f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -c cmd     run the command in a shell, or
1428f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -r file    run script from file
1429f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1430f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -d         enable the debugger
1431f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
1432f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser  -t title   set title of shell window
1433f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1434f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserA default edit window will be bypassed when -c, -r, or - are used.
1435f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1436f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
1437f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1438f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. KaiserExamples:
14397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1440f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle
1441f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open an edit window or shell depending on IDLE's configuration.
144296d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser
1443f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle foo.py foobar.py
1444f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Edit the files, also open a shell if configured to start with shell.
1445f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1446f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle -est "Baz" foo.py
1447f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
1448f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        window with the title "Baz".
1449f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1450f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle -c "import sys; print sys.argv" "foo"
1451f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window and run the command, passing "-c" in sys.argv[0]
1452f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        and "foo" in sys.argv[1].
1453f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1454f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiseridle -d -s -r foo.py "Hello World"
1455f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window, run a startup script, enable the debugger, and
1456f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
1457f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv[1].
1458f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
1459f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiserecho "import sys; print sys.argv" | idle - "foobar"
1460f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        Open a shell window, run the script piped in, passing '' in sys.argv[0]
1461f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        and "foobar" in sys.argv[1].
14627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer"""
14637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1464969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef main():
1465f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    global flist, root, use_subprocess
1466f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser
14678eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    capture_warnings(True)
14688f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser    use_subprocess = True
146934d0c66ef2bcfae00beb9f2b14e393cd00f499e4Roger Serwy    enable_shell = False
1470f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    enable_edit = False
1471f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    debug = False
1472969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    cmd = None
1473969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    script = None
1474f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    startup = False
1475969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    try:
14768f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
14772b149860a052606500cc4293db29cde5c85bf288Terry Jan Reedy    except getopt.error as msg:
1478bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy        print("Error: %s\n%s" % (msg, usage_msg), file=sys.stderr)
1479969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.exit(2)
1480969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for o, a in opts:
1481969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-c':
1482969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            cmd = a
1483f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1484969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-d':
1485f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            debug = True
1486f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1487969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-e':
1488f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_edit = True
1489f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if o == '-h':
1490f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            sys.stdout.write(usage_msg)
1491f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            sys.exit()
1492f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if o == '-i':
1493f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
14948f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser        if o == '-n':
14958f570a768fcefef5e8c9f9cf1facc4f8cdc3ef3fKurt B. Kaiser            use_subprocess = False
1496969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-r':
1497969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            script = a
1498f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            if os.path.isfile(script):
1499f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                pass
1500f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            else:
1501bee003cf539c79ae4a047f47ce4ea7dc377763e5Terry Jan Reedy                print("No script file: ", script, file=sys.stderr)
1502f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                sys.exit()
1503f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1504969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-s':
1505f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            startup = True
1506f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1507969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-t':
1508969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            PyShell.shell_title = a
1509f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            enable_shell = True
1510f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if args and args[0] == '-':
1511f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        cmd = sys.stdin.read()
1512f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        enable_shell = True
1513f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # process sys.argv and sys.path:
1514969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for i in range(len(sys.path)):
1515969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.path[i] = os.path.abspath(sys.path[i])
1516f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if args and args[0] == '-':
1517f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = [''] + args[1:]
1518f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif cmd:
1519f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = ['-c'] + args
1520f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif script:
1521f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        sys.argv = [script] + args
1522f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    elif args:
1523f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        enable_edit = True
1524f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        pathx = []
1525969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
1526969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            pathx.append(os.path.dirname(filename))
1527f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        for dir in pathx:
1528f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            dir = os.path.abspath(dir)
1529d630c04ab1ab35e2ec6eeeaba9bdcb9f8e730e78Florent Xicluna            if dir not in sys.path:
1530f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                sys.path.insert(0, dir)
1531ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser    else:
1532ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser        dir = os.getcwd()
1533ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser        if not dir in sys.path:
1534ff002b93057d1ba8662caed8f9bcbb643fe66c8aKurt B. Kaiser            sys.path.insert(0, dir)
1535f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # check the IDLE settings configuration (but command line overrides)
1536f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    edit_start = idleConf.GetOption('main', 'General',
15376655e4bc2752f1114a2e1f9a63ffd4191fa50d0dKurt B. Kaiser                                    'editor-on-startup', type='bool')
1538f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    enable_edit = enable_edit or edit_start
153934d0c66ef2bcfae00beb9f2b14e393cd00f499e4Roger Serwy    enable_shell = enable_shell or not enable_edit
1540f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    # start editor and/or shell windows:
1541969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root = Tk(className="Idle")
154219302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren
15434ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy    # set application icon
15444ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy    icondir = os.path.join(os.path.dirname(__file__), 'Icons')
15454ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy    if system() == 'Windows':
15464ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        iconfile = os.path.join(icondir, 'idle.ico')
15474ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        root.wm_iconbitmap(default=iconfile)
15484ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy    elif TkVersion >= 8.5:
15494ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        ext = '.png' if TkVersion >= 8.6 else '.gif'
15504ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext))
15514ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy                     for size in (16, 32, 48)]
15524ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        icons = [PhotoImage(file=iconfile) for iconfile in iconfiles]
15534ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy        root.tk.call('wm', 'iconphoto', str(root), "-default", *icons)
15544ade2d25fc585876540ac9d591a44469fd853462Terry Jan Reedy
1555969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    fixwordbreaks(root)
1556969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.withdraw()
1557969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist = PyShellFileList(root)
155819302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren    macosxSupport.setupApp(root, flist)
155919302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren
1560f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if enable_edit:
1561f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if not (cmd or script):
15627c010ee00cc0bfb859c326d9a78bd8dd2bf92246Andrew Svetlov            for filename in args[:]:
15637c010ee00cc0bfb859c326d9a78bd8dd2bf92246Andrew Svetlov                if flist.open(filename) is None:
15647c010ee00cc0bfb859c326d9a78bd8dd2bf92246Andrew Svetlov                    # filename is a directory actually, disconsider it
15657c010ee00cc0bfb859c326d9a78bd8dd2bf92246Andrew Svetlov                    args.remove(filename)
1566f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            if not args:
1567f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser                flist.new()
1568278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily
1569af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser    if enable_shell:
157019302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren        shell = flist.open_shell()
157119302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren        if not shell:
1572af3eb878027954fa578f43ba490599d13215eb3aKurt B. Kaiser            return # couldn't open shell
157357847df4e59015c141e645b47112829cf41b582aNed Deily        if macosxSupport.isAquaTk() and flist.dict:
157419302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren            # On OSX: when the user has double-clicked on a file that causes
15754f96f1f2b5068b8e8bd8d0f83f856b6e2883a3abTim Peters            # IDLE to be launched the shell window will open just in front of
15764f96f1f2b5068b8e8bd8d0f83f856b6e2883a3abTim Peters            # the file she wants to see. Lower the interpreter window when
157719302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren            # there are open files.
157819302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren            shell.top.lower()
1579278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily    else:
1580278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        shell = flist.pyshell
158119302d927e6688e02553df16177e4867e2d0e3b3Ronald Oussoren
1582278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily    # Handle remaining options. If any of these are set, enable_shell
1583278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily    # was set also, so shell must be true to reach here.
1584f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser    if debug:
1585f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        shell.open_debugger()
1586969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if startup:
1587969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        filename = os.environ.get("IDLESTARTUP") or \
1588969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser                   os.environ.get("PYTHONSTARTUP")
1589969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if filename and os.path.isfile(filename):
1590f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execfile(filename)
1591278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily    if cmd or script:
1592f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        shell.interp.runcommand("""if 1:
1593f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            import sys as _sys
159470a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            _sys.argv = %r
1595f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            del _sys
159670a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald            \n""" % (sys.argv,))
1597f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        if cmd:
1598f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execsource(cmd)
1599f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser        elif script:
160011659ade1e63095ac6217b4e190c14b494ddcf82Kurt B. Kaiser            shell.interp.prepend_syspath(script)
1601f06eed08a899e941c1e6db9b1b5fb126f9e33b85Kurt B. Kaiser            shell.interp.execfile(script)
1602278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily    elif shell:
1603278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        # If there is a shell window and no cmd or script in progress,
1604278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        # check for problematic OS X Tk versions and print a warning
1605278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        # message in the IDLE shell window; this is less intrusive
1606278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        # than always opening a separate window.
1607278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        tkversionwarning = macosxSupport.tkVersionWarning(root)
1608278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily        if tkversionwarning:
1609278543d5392967fb4bfe2d3b3f71c2281500c458Ned Deily            shell.interp.runcommand("print('%s')" % tkversionwarning)
16102a6f4b33271742f66a8e58a5ffd37e890e0acae3Ned Deily
1611eaa7e7825e9f4b211bc104cfde6cc951f9dcb94eTerry Jan Reedy    while flist.inversedict:  # keep IDLE running while files are open.
1612eaa7e7825e9f4b211bc104cfde6cc951f9dcb94eTerry Jan Reedy        root.mainloop()
1613969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.destroy()
16148eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy    capture_warnings(False)
1615969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
16167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == "__main__":
16179e8b828f07d0a55676e987b4ca70c247853f5695Kurt B. Kaiser    sys.modules['PyShell'] = sys.modules['__main__']
16187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    main()
16198eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedy
16208eab008b53c9aeb1ceabac378ec4bf306fdde44bTerry Jan Reedycapture_warnings(False)  # Make sure turned off; see issue 18081
1621