mirror of
https://github.com/python/cpython.git
synced 2025-07-25 20:24:11 +00:00

Ho ho ho -- that's trickier than it sounded! The colorizer is working with "line.col" strings instead of Text marks, and the absolute coordinates of the point of interest can change across the self.update call (voice of baffled experience, when two quick backspaces no longer fooled it, but a backspace followed by a quick ENTER did <wink>). Anyway, the attached appears to do the trick. CPU usage goes way up when typing quickly into a long triple-quoted string, but the latency is fine for me (a relatively fast typist on a relatively slow machine). Most of the changes here are left over from reducing the # of vrbl names to help me reason about the logic better; I hope the code is a *little* easier to
731 lines
22 KiB
Python
731 lines
22 KiB
Python
#! /usr/bin/env python
|
|
|
|
import os
|
|
import sys
|
|
import string
|
|
import getopt
|
|
import re
|
|
|
|
import linecache
|
|
from code import InteractiveInterpreter
|
|
|
|
from Tkinter import *
|
|
import tkMessageBox
|
|
|
|
from EditorWindow import EditorWindow, fixwordbreaks
|
|
from FileList import FileList
|
|
from ColorDelegator import ColorDelegator
|
|
from OutputWindow import OutputWindow
|
|
import idlever
|
|
|
|
# We need to patch linecache.checkcache, because we don't want it
|
|
# to throw away our <pyshell#...> entries.
|
|
# Rather than repeating its code here, we save those entries,
|
|
# then call the original function, and then restore the saved entries.
|
|
def linecache_checkcache(orig_checkcache=linecache.checkcache):
|
|
cache = linecache.cache
|
|
save = {}
|
|
for filename in cache.keys():
|
|
if filename[:1] + filename[-1:] == '<>':
|
|
save[filename] = cache[filename]
|
|
orig_checkcache()
|
|
cache.update(save)
|
|
linecache.checkcache = linecache_checkcache
|
|
|
|
|
|
# Note: <<newline-and-indent>> event is defined in AutoIndent.py
|
|
|
|
#$ event <<plain-newline-and-indent>>
|
|
#$ win <Control-j>
|
|
#$ unix <Control-j>
|
|
|
|
#$ event <<beginning-of-line>>
|
|
#$ win <Control-a>
|
|
#$ win <Home>
|
|
#$ unix <Control-a>
|
|
#$ unix <Home>
|
|
|
|
#$ event <<history-next>>
|
|
#$ win <Alt-n>
|
|
#$ unix <Alt-n>
|
|
|
|
#$ event <<history-previous>>
|
|
#$ win <Alt-p>
|
|
#$ unix <Alt-p>
|
|
|
|
#$ event <<interrupt-execution>>
|
|
#$ win <Control-c>
|
|
#$ unix <Control-c>
|
|
|
|
#$ event <<end-of-file>>
|
|
#$ win <Control-d>
|
|
#$ unix <Control-d>
|
|
|
|
#$ event <<open-stack-viewer>>
|
|
|
|
#$ event <<toggle-debugger>>
|
|
|
|
|
|
class PyShellEditorWindow(EditorWindow):
|
|
|
|
# Regular text edit window when a shell is present
|
|
# XXX ought to merge with regular editor window
|
|
|
|
def __init__(self, *args):
|
|
apply(EditorWindow.__init__, (self,) + args)
|
|
self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
|
|
self.text.bind("<<open-python-shell>>", self.flist.open_shell)
|
|
|
|
rmenu_specs = [
|
|
("Set breakpoint here", "<<set-breakpoint-here>>"),
|
|
]
|
|
|
|
def set_breakpoint_here(self, event=None):
|
|
if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
|
|
self.text.bell()
|
|
return
|
|
self.flist.pyshell.interp.debugger.set_breakpoint_here(self)
|
|
|
|
|
|
class PyShellFileList(FileList):
|
|
|
|
# File list when a shell is present
|
|
|
|
EditorWindow = PyShellEditorWindow
|
|
|
|
pyshell = None
|
|
|
|
def open_shell(self, event=None):
|
|
if self.pyshell:
|
|
self.pyshell.wakeup()
|
|
else:
|
|
self.pyshell = PyShell(self)
|
|
self.pyshell.begin()
|
|
return self.pyshell
|
|
|
|
|
|
class ModifiedColorDelegator(ColorDelegator):
|
|
|
|
# Colorizer for the shell window itself
|
|
|
|
def recolorize_main(self):
|
|
self.tag_remove("TODO", "1.0", "iomark")
|
|
self.tag_add("SYNC", "1.0", "iomark")
|
|
ColorDelegator.recolorize_main(self)
|
|
|
|
tagdefs = ColorDelegator.tagdefs.copy()
|
|
cprefs = ColorDelegator.cprefs
|
|
|
|
tagdefs.update({
|
|
"stdin": {"foreground": cprefs.CStdIn[0],
|
|
"background": cprefs.CStdIn[1]},
|
|
"stdout": {"foreground": cprefs.CStdOut[0],
|
|
"background": cprefs.CStdOut[1]},
|
|
"stderr": {"foreground": cprefs.CStdErr[0],
|
|
"background": cprefs.CStdErr[1]},
|
|
"console": {"foreground": cprefs.CConsole[0],
|
|
"background": cprefs.CConsole[1]},
|
|
"ERROR": {"background": cprefs.CError[0],
|
|
"background": cprefs.CError[1]},
|
|
None: {"foreground": cprefs.CNormal[0],
|
|
"background": cprefs.CNormal[1]},
|
|
})
|
|
|
|
|
|
class ModifiedInterpreter(InteractiveInterpreter):
|
|
|
|
def __init__(self, tkconsole):
|
|
self.tkconsole = tkconsole
|
|
locals = sys.modules['__main__'].__dict__
|
|
InteractiveInterpreter.__init__(self, locals=locals)
|
|
|
|
gid = 0
|
|
|
|
def execsource(self, source):
|
|
# Like runsource() but assumes complete exec source
|
|
filename = self.stuffsource(source)
|
|
self.execfile(filename, source)
|
|
|
|
def execfile(self, filename, source=None):
|
|
# Execute an existing file
|
|
if source is None:
|
|
source = open(filename, "r").read()
|
|
try:
|
|
code = compile(source, filename, "exec")
|
|
except (OverflowError, SyntaxError):
|
|
self.tkconsole.resetoutput()
|
|
InteractiveInterpreter.showsyntaxerror(self, filename)
|
|
else:
|
|
self.runcode(code)
|
|
|
|
def runsource(self, source):
|
|
# Extend base class to stuff the source in the line cache first
|
|
filename = self.stuffsource(source)
|
|
self.more = 0
|
|
return InteractiveInterpreter.runsource(self, source, filename)
|
|
|
|
def stuffsource(self, source):
|
|
# Stuff source in the filename cache
|
|
filename = "<pyshell#%d>" % self.gid
|
|
self.gid = self.gid + 1
|
|
lines = string.split(source, "\n")
|
|
linecache.cache[filename] = len(source)+1, 0, lines, filename
|
|
return filename
|
|
|
|
def showsyntaxerror(self, filename=None):
|
|
# Extend base class to color the offending position
|
|
# (instead of printing it and pointing at it with a caret)
|
|
text = self.tkconsole.text
|
|
stuff = self.unpackerror()
|
|
if not stuff:
|
|
self.tkconsole.resetoutput()
|
|
InteractiveInterpreter.showsyntaxerror(self, filename)
|
|
return
|
|
msg, lineno, offset, line = stuff
|
|
if lineno == 1:
|
|
pos = "iomark + %d chars" % (offset-1)
|
|
else:
|
|
pos = "iomark linestart + %d lines + %d chars" % (lineno-1,
|
|
offset-1)
|
|
text.tag_add("ERROR", pos)
|
|
text.see(pos)
|
|
char = text.get(pos)
|
|
if char and char in string.letters + string.digits + "_":
|
|
text.tag_add("ERROR", pos + " wordstart", pos)
|
|
self.tkconsole.resetoutput()
|
|
self.write("SyntaxError: %s\n" % str(msg))
|
|
|
|
def unpackerror(self):
|
|
type, value, tb = sys.exc_info()
|
|
ok = type is SyntaxError
|
|
if ok:
|
|
try:
|
|
msg, (dummy_filename, lineno, offset, line) = value
|
|
except:
|
|
ok = 0
|
|
if ok:
|
|
return msg, lineno, offset, line
|
|
else:
|
|
return None
|
|
|
|
def showtraceback(self):
|
|
# Extend base class method to reset output properly
|
|
text = self.tkconsole.text
|
|
self.tkconsole.resetoutput()
|
|
self.checklinecache()
|
|
InteractiveInterpreter.showtraceback(self)
|
|
|
|
def checklinecache(self):
|
|
c = linecache.cache
|
|
for key in c.keys():
|
|
if key[:1] + key[-1:] != "<>":
|
|
del c[key]
|
|
|
|
debugger = None
|
|
|
|
def setdebugger(self, debugger):
|
|
self.debugger = debugger
|
|
|
|
def getdebugger(self):
|
|
return self.debugger
|
|
|
|
def runcode(self, code):
|
|
# Override base class method
|
|
debugger = self.debugger
|
|
try:
|
|
self.tkconsole.beginexecuting()
|
|
try:
|
|
if debugger:
|
|
debugger.run(code, self.locals)
|
|
else:
|
|
exec code in self.locals
|
|
except SystemExit:
|
|
if tkMessageBox.askyesno(
|
|
"Exit?",
|
|
"Do you want to exit altogether?",
|
|
default="yes",
|
|
master=self.tkconsole.text):
|
|
raise
|
|
else:
|
|
self.showtraceback()
|
|
if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
|
|
self.tkconsole.open_stack_viewer()
|
|
except:
|
|
self.showtraceback()
|
|
if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
|
|
self.tkconsole.open_stack_viewer()
|
|
|
|
finally:
|
|
self.tkconsole.endexecuting()
|
|
|
|
def write(self, s):
|
|
# Override base class write
|
|
self.tkconsole.console.write(s)
|
|
|
|
|
|
class PyShell(OutputWindow):
|
|
|
|
shell_title = "Python Shell"
|
|
|
|
# Override classes
|
|
ColorDelegator = ModifiedColorDelegator
|
|
|
|
# Override menu bar specs
|
|
menu_specs = PyShellEditorWindow.menu_specs[:]
|
|
menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug"))
|
|
|
|
# New classes
|
|
from History import History
|
|
|
|
def __init__(self, flist=None):
|
|
self.interp = ModifiedInterpreter(self)
|
|
if flist is None:
|
|
root = Tk()
|
|
fixwordbreaks(root)
|
|
root.withdraw()
|
|
flist = PyShellFileList(root)
|
|
|
|
OutputWindow.__init__(self, flist, None, None)
|
|
|
|
import __builtin__
|
|
__builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
|
|
|
|
self.auto = self.extensions["AutoIndent"] # Required extension
|
|
self.auto.config(prefertabs=1)
|
|
|
|
text = self.text
|
|
text.configure(wrap="char")
|
|
text.bind("<<newline-and-indent>>", self.enter_callback)
|
|
text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
|
|
text.bind("<<interrupt-execution>>", self.cancel_callback)
|
|
text.bind("<<beginning-of-line>>", self.home_callback)
|
|
text.bind("<<end-of-file>>", self.eof_callback)
|
|
text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
|
|
text.bind("<<toggle-debugger>>", self.toggle_debugger)
|
|
text.bind("<<open-python-shell>>", self.flist.open_shell)
|
|
text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
|
|
|
|
self.save_stdout = sys.stdout
|
|
self.save_stderr = sys.stderr
|
|
self.save_stdin = sys.stdin
|
|
sys.stdout = PseudoFile(self, "stdout")
|
|
sys.stderr = PseudoFile(self, "stderr")
|
|
sys.stdin = self
|
|
self.console = PseudoFile(self, "console")
|
|
|
|
self.history = self.History(self.text)
|
|
|
|
reading = 0
|
|
executing = 0
|
|
canceled = 0
|
|
endoffile = 0
|
|
|
|
def toggle_debugger(self, event=None):
|
|
if self.executing:
|
|
tkMessageBox.showerror("Don't debug now",
|
|
"You can only toggle the debugger when idle",
|
|
master=self.text)
|
|
self.set_debugger_indicator()
|
|
return "break"
|
|
else:
|
|
db = self.interp.getdebugger()
|
|
if db:
|
|
self.close_debugger()
|
|
else:
|
|
self.open_debugger()
|
|
|
|
def set_debugger_indicator(self):
|
|
db = self.interp.getdebugger()
|
|
self.setvar("<<toggle-debugger>>", not not db)
|
|
|
|
def toggle_jit_stack_viewer( self, event=None):
|
|
pass # All we need is the variable
|
|
|
|
def close_debugger(self):
|
|
db = self.interp.getdebugger()
|
|
if db:
|
|
self.interp.setdebugger(None)
|
|
db.close()
|
|
self.resetoutput()
|
|
self.console.write("[DEBUG OFF]\n")
|
|
sys.ps1 = ">>> "
|
|
self.showprompt()
|
|
self.set_debugger_indicator()
|
|
|
|
def open_debugger(self):
|
|
import Debugger
|
|
self.interp.setdebugger(Debugger.Debugger(self))
|
|
sys.ps1 = "[DEBUG ON]\n>>> "
|
|
self.showprompt()
|
|
self.set_debugger_indicator()
|
|
|
|
def beginexecuting(self):
|
|
# Helper for ModifiedInterpreter
|
|
self.resetoutput()
|
|
self.executing = 1
|
|
self._cancel_check = self.cancel_check
|
|
##sys.settrace(self._cancel_check)
|
|
|
|
def endexecuting(self):
|
|
# Helper for ModifiedInterpreter
|
|
sys.settrace(None)
|
|
self.executing = 0
|
|
self.canceled = 0
|
|
|
|
def close(self):
|
|
# Extend base class method
|
|
if self.executing:
|
|
# XXX Need to ask a question here
|
|
if not tkMessageBox.askokcancel(
|
|
"Kill?",
|
|
"The program is still running; do you want to kill it?",
|
|
default="ok",
|
|
master=self.text):
|
|
return "cancel"
|
|
self.canceled = 1
|
|
if self.reading:
|
|
self.top.quit()
|
|
return "cancel"
|
|
reply = PyShellEditorWindow.close(self)
|
|
if reply != "cancel":
|
|
self.flist.pyshell = None
|
|
# Restore std streams
|
|
sys.stdout = self.save_stdout
|
|
sys.stderr = self.save_stderr
|
|
sys.stdin = self.save_stdin
|
|
# Break cycles
|
|
self.interp = None
|
|
self.console = None
|
|
return reply
|
|
|
|
def ispythonsource(self, filename):
|
|
# Override this so EditorWindow never removes the colorizer
|
|
return 1
|
|
|
|
def short_title(self):
|
|
return self.shell_title
|
|
|
|
def begin(self):
|
|
self.resetoutput()
|
|
self.write("Python %s on %s\n%s\nIDLE %s -- press F1 for help\n" %
|
|
(sys.version, sys.platform, sys.copyright,
|
|
idlever.IDLE_VERSION))
|
|
try:
|
|
sys.ps1
|
|
except AttributeError:
|
|
sys.ps1 = ">>> "
|
|
self.showprompt()
|
|
import Tkinter
|
|
Tkinter._default_root = None
|
|
|
|
def interact(self):
|
|
self.begin()
|
|
self.top.mainloop()
|
|
|
|
def readline(self):
|
|
save = self.reading
|
|
try:
|
|
self.reading = 1
|
|
self.top.mainloop()
|
|
finally:
|
|
self.reading = save
|
|
line = self.text.get("iomark", "end-1c")
|
|
self.resetoutput()
|
|
if self.canceled:
|
|
self.canceled = 0
|
|
raise KeyboardInterrupt
|
|
if self.endoffile:
|
|
self.endoffile = 0
|
|
return ""
|
|
return line
|
|
|
|
def cancel_callback(self, event):
|
|
try:
|
|
if self.text.compare("sel.first", "!=", "sel.last"):
|
|
return # Active selection -- always use default binding
|
|
except:
|
|
pass
|
|
if not (self.executing or self.reading):
|
|
self.resetoutput()
|
|
self.write("KeyboardInterrupt\n")
|
|
self.showprompt()
|
|
return "break"
|
|
self.endoffile = 0
|
|
self.canceled = 1
|
|
if self.reading:
|
|
self.top.quit()
|
|
return "break"
|
|
|
|
def eof_callback(self, event):
|
|
if self.executing and not self.reading:
|
|
return # Let the default binding (delete next char) take over
|
|
if not (self.text.compare("iomark", "==", "insert") and
|
|
self.text.compare("insert", "==", "end-1c")):
|
|
return # Let the default binding (delete next char) take over
|
|
if not self.executing:
|
|
## if not tkMessageBox.askokcancel(
|
|
## "Exit?",
|
|
## "Are you sure you want to exit?",
|
|
## default="ok", master=self.text):
|
|
## return "break"
|
|
self.resetoutput()
|
|
self.close()
|
|
else:
|
|
self.canceled = 0
|
|
self.endoffile = 1
|
|
self.top.quit()
|
|
return "break"
|
|
|
|
def home_callback(self, event):
|
|
if event.state != 0 and event.keysym == "Home":
|
|
return # <Modifier-Home>; fall back to class binding
|
|
if self.text.compare("iomark", "<=", "insert") and \
|
|
self.text.compare("insert linestart", "<=", "iomark"):
|
|
self.text.mark_set("insert", "iomark")
|
|
self.text.tag_remove("sel", "1.0", "end")
|
|
self.text.see("insert")
|
|
return "break"
|
|
|
|
def linefeed_callback(self, event):
|
|
# Insert a linefeed without entering anything (still autoindented)
|
|
if self.reading:
|
|
self.text.insert("insert", "\n")
|
|
self.text.see("insert")
|
|
else:
|
|
self.auto.auto_indent(event)
|
|
return "break"
|
|
|
|
def enter_callback(self, event):
|
|
if self.executing and not self.reading:
|
|
return # Let the default binding (insert '\n') take over
|
|
# If some text is selected, recall the selection
|
|
# (but only if this before the I/O mark)
|
|
try:
|
|
sel = self.text.get("sel.first", "sel.last")
|
|
if sel:
|
|
if self.text.compare("sel.last", "<=", "iomark"):
|
|
self.recall(sel)
|
|
return "break"
|
|
except:
|
|
pass
|
|
# If we're strictly before the line containing iomark, recall
|
|
# the current line, less a leading prompt, less leading or
|
|
# trailing whitespace
|
|
if self.text.compare("insert", "<", "iomark linestart"):
|
|
# Check if there's a relevant stdin range -- if so, use it
|
|
prev = self.text.tag_prevrange("stdin", "insert")
|
|
if prev and self.text.compare("insert", "<", prev[1]):
|
|
self.recall(self.text.get(prev[0], prev[1]))
|
|
return "break"
|
|
next = self.text.tag_nextrange("stdin", "insert")
|
|
if next and self.text.compare("insert lineend", ">=", next[0]):
|
|
self.recall(self.text.get(next[0], next[1]))
|
|
return "break"
|
|
# No stdin mark -- just get the current line
|
|
self.recall(self.text.get("insert linestart", "insert lineend"))
|
|
return "break"
|
|
# If we're in the current input before its last line,
|
|
# insert a newline right at the insert point
|
|
if self.text.compare("insert", "<", "end-1c linestart"):
|
|
self.auto.auto_indent(event)
|
|
return "break"
|
|
# We're in the last line; append a newline and submit it
|
|
self.text.mark_set("insert", "end-1c")
|
|
if self.reading:
|
|
self.text.insert("insert", "\n")
|
|
self.text.see("insert")
|
|
else:
|
|
self.auto.auto_indent(event)
|
|
self.text.tag_add("stdin", "iomark", "end-1c")
|
|
self.text.update_idletasks()
|
|
if self.reading:
|
|
self.top.quit() # Break out of recursive mainloop() in raw_input()
|
|
else:
|
|
self.runit()
|
|
return "break"
|
|
|
|
def recall(self, s):
|
|
if self.history:
|
|
self.history.recall(s)
|
|
|
|
def runit(self):
|
|
line = self.text.get("iomark", "end-1c")
|
|
# Strip off last newline and surrounding whitespace.
|
|
# (To allow you to hit return twice to end a statement.)
|
|
i = len(line)
|
|
while i > 0 and line[i-1] in " \t":
|
|
i = i-1
|
|
if i > 0 and line[i-1] == "\n":
|
|
i = i-1
|
|
while i > 0 and line[i-1] in " \t":
|
|
i = i-1
|
|
line = line[:i]
|
|
more = self.interp.runsource(line)
|
|
if not more:
|
|
self.showprompt()
|
|
|
|
def cancel_check(self, frame, what, args,
|
|
dooneevent=tkinter.dooneevent,
|
|
dontwait=tkinter.DONT_WAIT):
|
|
# Hack -- use the debugger hooks to be able to handle events
|
|
# and interrupt execution at any time.
|
|
# This slows execution down quite a bit, so you may want to
|
|
# disable this (by not calling settrace() in runcode() above)
|
|
# for full-bore (uninterruptable) speed.
|
|
# XXX This should become a user option.
|
|
if self.canceled:
|
|
return
|
|
dooneevent(dontwait)
|
|
if self.canceled:
|
|
self.canceled = 0
|
|
raise KeyboardInterrupt
|
|
return self._cancel_check
|
|
|
|
def open_stack_viewer(self, event=None):
|
|
try:
|
|
sys.last_traceback
|
|
except:
|
|
tkMessageBox.showerror("No stack trace",
|
|
"There is no stack trace yet.\n"
|
|
"(sys.last_traceback is not defined)",
|
|
master=self.text)
|
|
return
|
|
from StackViewer import StackBrowser
|
|
sv = StackBrowser(self.root, self.flist)
|
|
|
|
def showprompt(self):
|
|
self.resetoutput()
|
|
try:
|
|
s = str(sys.ps1)
|
|
except:
|
|
s = ""
|
|
self.console.write(s)
|
|
self.text.mark_set("insert", "end-1c")
|
|
|
|
def resetoutput(self):
|
|
source = self.text.get("iomark", "end-1c")
|
|
if self.history:
|
|
self.history.history_store(source)
|
|
if self.text.get("end-2c") != "\n":
|
|
self.text.insert("end-1c", "\n")
|
|
self.text.mark_set("iomark", "end-1c")
|
|
sys.stdout.softspace = 0
|
|
|
|
def write(self, s, tags=()):
|
|
self.text.mark_gravity("iomark", "right")
|
|
OutputWindow.write(self, s, tags, "iomark")
|
|
self.text.mark_gravity("iomark", "left")
|
|
if self.canceled:
|
|
self.canceled = 0
|
|
raise KeyboardInterrupt
|
|
|
|
class PseudoFile:
|
|
|
|
def __init__(self, shell, tags):
|
|
self.shell = shell
|
|
self.tags = tags
|
|
|
|
def write(self, s):
|
|
self.shell.write(s, self.tags)
|
|
|
|
def writelines(self, l):
|
|
map(self.write, l)
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
|
|
usage_msg = """\
|
|
usage: idle.py [-c command] [-d] [-e] [-s] [-t title] [arg] ...
|
|
|
|
-c command run this command
|
|
-d enable debugger
|
|
-e edit mode; arguments are files to be edited
|
|
-s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
|
|
-t title set title of shell window
|
|
|
|
When neither -c nor -e is used, and there are arguments, and the first
|
|
argument is not '-', the first argument is run as a script. Remaining
|
|
arguments are arguments to the script or to the command run by -c.
|
|
"""
|
|
|
|
def main():
|
|
cmd = None
|
|
edit = 0
|
|
debug = 0
|
|
startup = 0
|
|
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], "c:deist:")
|
|
except getopt.error, msg:
|
|
sys.stderr.write("Error: %s\n" % str(msg))
|
|
sys.stderr.write(usage_msg)
|
|
sys.exit(2)
|
|
|
|
for o, a in opts:
|
|
if o == '-c':
|
|
cmd = a
|
|
if o == '-d':
|
|
debug = 1
|
|
if o == '-e':
|
|
edit = 1
|
|
if o == '-s':
|
|
startup = 1
|
|
if o == '-t':
|
|
PyShell.shell_title = a
|
|
|
|
if not edit:
|
|
if cmd:
|
|
sys.argv = ["-c"] + args
|
|
else:
|
|
sys.argv = args or [""]
|
|
|
|
for i in range(len(sys.path)):
|
|
sys.path[i] = os.path.abspath(sys.path[i])
|
|
|
|
pathx = []
|
|
if edit:
|
|
for filename in args:
|
|
pathx.append(os.path.dirname(filename))
|
|
elif args and args[0] != "-":
|
|
pathx.append(os.path.dirname(args[0]))
|
|
else:
|
|
pathx.append(os.curdir)
|
|
for dir in pathx:
|
|
dir = os.path.abspath(dir)
|
|
if not dir in sys.path:
|
|
sys.path.insert(0, dir)
|
|
|
|
global flist, root
|
|
root = Tk()
|
|
fixwordbreaks(root)
|
|
root.withdraw()
|
|
flist = PyShellFileList(root)
|
|
|
|
if edit:
|
|
for filename in args:
|
|
flist.open(filename)
|
|
|
|
shell = PyShell(flist)
|
|
interp = shell.interp
|
|
flist.pyshell = shell
|
|
|
|
if startup:
|
|
filename = os.environ.get("IDLESTARTUP") or \
|
|
os.environ.get("PYTHONSTARTUP")
|
|
if filename and os.path.isfile(filename):
|
|
interp.execfile(filename)
|
|
|
|
if debug:
|
|
shell.open_debugger()
|
|
if cmd:
|
|
interp.execsource(cmd)
|
|
elif not edit and args and args[0] != "-":
|
|
interp.execfile(args[0])
|
|
|
|
shell.begin()
|
|
root.mainloop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|