from code
import InteractiveInterpreter
print>>sys
.__stderr
__, "** IDLE can't import Tkinter. " \
"Your Python may not be configured for Tk. **"
from EditorWindow
import EditorWindow
, fixwordbreaks
from FileList
import FileList
from ColorDelegator
import ColorDelegator
from UndoDelegator
import UndoDelegator
from OutputWindow
import OutputWindow
from configHandler
import idleConf
IDENTCHARS
= string
.ascii_letters
+ string
.digits
+ "_"
from signal
import SIGTERM
# Override warnings module to write to warning_stream. Initialize to send IDLE
# internal warnings to the console. ScriptBinding.check_syntax() will
# temporarily redirect the stream to the shell window to display warnings when
warning_stream
= sys
.__stderr
__
def idle_showwarning(message
, category
, filename
, lineno
):
file.write(warnings
.formatwarning(message
, category
, filename
, lineno
))
pass ## file (probably __stderr__) is invalid, warning dropped.
warnings
.showwarning
= idle_showwarning
def idle_formatwarning(message
, category
, filename
, lineno
):
"""Format warnings the IDLE way"""
s
= "\nWarning (from warnings module):\n"
s
+= ' File \"%s\", line %s\n' % (filename
, lineno
)
line
= linecache
.getline(filename
, lineno
).strip()
s
+= "%s: %s\n>>> " % (category
.__name
__, message
)
warnings
.formatwarning
= idle_formatwarning
def extended_linecache_checkcache(filename
=None,
orig_checkcache
=linecache
.checkcache
):
"""Extend linecache.checkcache to preserve the <pyshell#...> entries
Rather than repeating the linecache code, patch it to save the
<pyshell#...> entries, call the original linecache.checkcache()
(which destroys them), and then restore the saved entries.
orig_checkcache is bound at definition time to the original
method, allowing it to be patched.
for filename
in cache
.keys():
if filename
[:1] + filename
[-1:] == '<>':
save
[filename
] = cache
[filename
]
# Patch linecache.checkcache():
linecache
.checkcache
= extended_linecache_checkcache
class PyShellEditorWindow(EditorWindow
):
"Regular text edit window in IDLE, supports breakpoints"
def __init__(self
, *args
):
EditorWindow
.__init
__(self
, *args
)
self
.text
.bind("<<set-breakpoint-here>>", self
.set_breakpoint_here
)
self
.text
.bind("<<clear-breakpoint-here>>", self
.clear_breakpoint_here
)
self
.text
.bind("<<open-python-shell>>", self
.flist
.open_shell
)
self
.breakpointPath
= os
.path
.join(idleConf
.GetUserCfgDir(),
# whenever a file is changed, restore breakpoints
if self
.io
.filename
: self
.restore_file_breaks()
def filename_changed_hook(old_hook
=self
.io
.filename_change_hook
,
self
.restore_file_breaks()
self
.io
.set_filename_change_hook(filename_changed_hook
)
rmenu_specs
= [("Set Breakpoint", "<<set-breakpoint-here>>"),
("Clear Breakpoint", "<<clear-breakpoint-here>>")]
def set_breakpoint(self
, lineno
):
filename
= self
.io
.filename
text
.tag_add("BREAK", "%d.0" % lineno
, "%d.0" % (lineno
+1))
i
= self
.breakpoints
.index(lineno
)
except ValueError: # only add if missing, i.e. do once
self
.breakpoints
.append(lineno
)
try: # update the subprocess debugger
debug
= self
.flist
.pyshell
.interp
.debugger
debug
.set_breakpoint_here(filename
, lineno
)
except: # but debugger may not be active right now....
def set_breakpoint_here(self
, event
=None):
filename
= self
.io
.filename
lineno
= int(float(text
.index("insert")))
self
.set_breakpoint(lineno
)
def clear_breakpoint_here(self
, event
=None):
filename
= self
.io
.filename
lineno
= int(float(text
.index("insert")))
self
.breakpoints
.remove(lineno
)
text
.tag_remove("BREAK", "insert linestart",\
debug
= self
.flist
.pyshell
.interp
.debugger
debug
.clear_breakpoint_here(filename
, lineno
)
def clear_file_breaks(self
):
filename
= self
.io
.filename
text
.tag_remove("BREAK", "1.0", END
)
debug
= self
.flist
.pyshell
.interp
.debugger
debug
.clear_file_breaks(filename
)
def store_file_breaks(self
):
"Save breakpoints when file is saved"
# XXX 13 Dec 2002 KBK Currently the file must be saved before it can
# be run. The breaks are saved at that time. If we introduce
# a temporary file save feature the save breaks functionality
# needs to be re-verified, since the breaks at the time the
# temp file is created may differ from the breaks at the last
# permanent save of the file. Currently, a break introduced
# after a save will be effective, but not persistent.
# This is necessary to keep the saved breaks synched with the
# Breakpoints are set as tagged ranges in the text. Certain
# kinds of edits cause these ranges to be deleted: Inserting
# or deleting a line just before a breakpoint, and certain
# deletions prior to a breakpoint. These issues need to be
# investigated and understood. It's not clear if they are
# Tk issues or IDLE issues, or whether they can actually
# be fixed. Since a modified file has to be saved before it is
# run, and since self.breakpoints (from which the subprocess
# debugger is loaded) is updated during the save, the visible
# breaks stay synched with the subprocess even if one of these
# unexpected breakpoint deletions occurs.
breaks
= self
.breakpoints
filename
= self
.io
.filename
lines
= open(self
.breakpointPath
,"r").readlines()
new_file
= open(self
.breakpointPath
,"w")
if not line
.startswith(filename
+ '='):
self
.update_breakpoints()
breaks
= self
.breakpoints
new_file
.write(filename
+ '=' + str(breaks
) + '\n')
def restore_file_breaks(self
):
self
.text
.update() # this enables setting "BREAK" tags to be visible
filename
= self
.io
.filename
if os
.path
.isfile(self
.breakpointPath
):
lines
= open(self
.breakpointPath
,"r").readlines()
if line
.startswith(filename
+ '='):
breakpoint_linenumbers
= eval(line
[len(filename
)+1:])
for breakpoint_linenumber
in breakpoint_linenumbers
:
self
.set_breakpoint(breakpoint_linenumber
)
def update_breakpoints(self
):
"Retrieves all the breakpoints in the current window"
ranges
= text
.tag_ranges("BREAK")
linenumber_list
= self
.ranges_to_linenumbers(ranges
)
self
.breakpoints
= linenumber_list
def ranges_to_linenumbers(self
, ranges
):
for index
in range(0, len(ranges
), 2):
lineno
= int(float(ranges
[index
]))
end
= int(float(ranges
[index
+1]))
# XXX 13 Dec 2002 KBK Not used currently
# def saved_change_hook(self):
# "Extend base method - clear breaks if module is modified"
# if not self.get_saved():
# self.clear_file_breaks()
# EditorWindow.saved_change_hook(self)
"Extend base method - clear breaks when module is closed"
EditorWindow
._close
(self
)
class PyShellFileList(FileList
):
"Extend base class: IDLE supports a shell and breakpoints"
# override FileList's class variable, instances return PyShellEditorWindow
# instead of EditorWindow when new edit windows are created.
EditorWindow
= PyShellEditorWindow
def open_shell(self
, event
=None):
self
.pyshell
.top
.wakeup()
self
.pyshell
= PyShell(self
)
if not self
.pyshell
.begin():
class ModifiedColorDelegator(ColorDelegator
):
"Extend base class: colorizer for the shell window itself"
ColorDelegator
.__init
__(self
)
def recolorize_main(self
):
self
.tag_remove("TODO", "1.0", "iomark")
self
.tag_add("SYNC", "1.0", "iomark")
ColorDelegator
.recolorize_main(self
)
ColorDelegator
.LoadTagDefs(self
)
theme
= idleConf
.GetOption('main','Theme','name')
"stdin": {'background':None,'foreground':None},
"stdout": idleConf
.GetHighlight(theme
, "stdout"),
"stderr": idleConf
.GetHighlight(theme
, "stderr"),
"console": idleConf
.GetHighlight(theme
, "console"),
None: idleConf
.GetHighlight(theme
, "normal"),
class ModifiedUndoDelegator(UndoDelegator
):
"Extend base class: forbid insert/delete before the I/O mark"
def insert(self
, index
, chars
, tags
=None):
if self
.delegate
.compare(index
, "<", "iomark"):
UndoDelegator
.insert(self
, index
, chars
, tags
)
def delete(self
, index1
, index2
=None):
if self
.delegate
.compare(index1
, "<", "iomark"):
UndoDelegator
.delete(self
, index1
, index2
)
class MyRPCClient(rpc
.RPCClient
):
"Override the base class - just re-raise EOFError"
class ModifiedInterpreter(InteractiveInterpreter
):
def __init__(self
, tkconsole
):
self
.tkconsole
= tkconsole
locals = sys
.modules
['__main__'].__dict
__
InteractiveInterpreter
.__init
__(self
, locals=locals)
self
.save_warnings_filters
= None
self
.subprocess_arglist
= self
.build_subprocess_arglist()
def spawn_subprocess(self
):
args
= self
.subprocess_arglist
self
.rpcpid
= os
.spawnv(os
.P_NOWAIT
, sys
.executable
, args
)
def build_subprocess_arglist(self
):
w
= ['-W' + s
for s
in sys
.warnoptions
]
# Maybe IDLE is installed and is being accessed via sys.path,
# or maybe it's not installed and the idle.py script is being
# run from the IDLE source directory.
del_exitf
= idleConf
.GetOption('main', 'General', 'delete-exitfunc',
default
=False, type='bool')
if __name__
== 'idlelib.PyShell':
command
= "__import__('idlelib.run').run.main(%r)" % (del_exitf
,)
command
= "__import__('run').main(%r)" % (del_exitf
,)
if sys
.platform
[:3] == 'win' and ' ' in sys
.executable
:
# handle embedded space in path by quoting the argument
decorated_exec
= '"%s"' % sys
.executable
decorated_exec
= sys
.executable
return [decorated_exec
] + w
+ ["-c", command
, str(self
.port
)]
def start_subprocess(self
):
# spawning first avoids passing a listening socket to the subprocess
#time.sleep(20) # test to simulate GUI not accepting connection
addr
= (LOCALHOST
, self
.port
)
# Idle starts listening for connection on localhost
self
.rpcclt
= MyRPCClient(addr
)
except socket
.error
, err
:
self
.display_port_binding_error()
# Accept the connection from the Python execution server
self
.rpcclt
.listening_sock
.settimeout(10)
except socket
.timeout
, err
:
self
.display_no_subprocess_error()
self
.rpcclt
.register("stdin", self
.tkconsole
)
self
.rpcclt
.register("stdout", self
.tkconsole
.stdout
)
self
.rpcclt
.register("stderr", self
.tkconsole
.stderr
)
self
.rpcclt
.register("flist", self
.tkconsole
.flist
)
self
.rpcclt
.register("linecache", linecache
)
self
.rpcclt
.register("interp", self
)
def restart_subprocess(self
):
# close only the subprocess debugger
debug
= self
.getdebugger()
# Only close subprocess debugger, don't unregister gui_adap!
RemoteDebugger
.close_subprocess_debugger(self
.rpcclt
)
# Kill subprocess, spawn a new one, accept connection.
was_executing
= console
.executing
console
.executing
= False
except socket
.timeout
, err
:
self
.display_no_subprocess_error()
# annotate restart in shell window and mark it
console
.text
.delete("iomark", "end-1c")
halfbar
= ((int(console
.width
) - 16) // 2) * '='
console
.write(halfbar
+ ' RESTART ' + halfbar
)
console
.text
.mark_set("restart", "end-1c")
console
.text
.mark_gravity("restart", "left")
# restart subprocess debugger
# Restarted debugger connects to current instance of debug GUI
gui
= RemoteDebugger
.restart_subprocess_debugger(self
.rpcclt
)
# reload remote debugger breakpoints for all PyShellEditWindows
def __request_interrupt(self
):
self
.rpcclt
.remotecall("exec", "interrupt_the_server", (), {})
def interrupt_subprocess(self
):
threading
.Thread(target
=self
.__request
_interrupt
).start()
def kill_subprocess(self
):
except AttributeError: # no socket
self
.tkconsole
.executing
= False
def unix_terminate(self
):
"UNIX: make sure subprocess is terminated and collect status"
os
.kill(self
.rpcpid
, SIGTERM
)
# process already terminated:
os
.waitpid(self
.rpcpid
, 0)
_msg = 'Use File/Exit or your end-of-file key to quit IDLE'
__builtins__.quit = __builtins__.exit = _msg
def poll_subprocess(self
):
response
= clt
.pollresponse(self
.active_seq
, wait
=0.05)
except (EOFError, IOError, KeyboardInterrupt):
# lost connection or subprocess terminated itself, restart
# [the KBI is from rpc.SocketIO.handle_EOF()]
if self
.tkconsole
.closing
:
self
.restart_subprocess()
self
.tkconsole
.resetoutput()
console
= self
.tkconsole
.console
print >>console
, repr(what
)
if self
.tkconsole
.getvar("<<toggle-jit-stack-viewer>>"):
self
.remote_stack_viewer()
errmsg
= "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
print >>sys
.__stderr
__, errmsg
, what
print >>console
, errmsg
, what
# we received a response to the currently active seq number:
self
.tkconsole
.endexecuting()
if not self
.tkconsole
.closing
:
self
.tkconsole
.text
.after(self
.tkconsole
.pollinterval
,
def setdebugger(self
, debugger
):
def open_remote_stack_viewer(self
):
"""Initiate the remote stack viewer from a separate thread.
This method is called from the subprocess, and by returning from this
method we allow the subprocess to unblock. After a bit the shell
requests the subprocess to open the remote stack viewer which returns a
static object looking at the last exceptiopn. It is queried through
self
.tkconsole
.text
.after(300, self
.remote_stack_viewer
)
def remote_stack_viewer(self
):
import RemoteObjectBrowser
oid
= self
.rpcclt
.remotequeue("exec", "stackviewer", ("flist",), {})
self
.tkconsole
.root
.bell()
item
= RemoteObjectBrowser
.StubObjectTreeItem(self
.rpcclt
, oid
)
from TreeWidget
import ScrolledCanvas
, TreeNode
top
= Toplevel(self
.tkconsole
.root
)
theme
= idleConf
.GetOption('main','Theme','name')
background
= idleConf
.GetHighlight(theme
, 'normal')['background']
sc
= ScrolledCanvas(top
, bg
=background
, highlightthickness
=0)
sc
.frame
.pack(expand
=1, fill
="both")
node
= TreeNode(sc
.canvas
, None, item
)
# XXX Should GC the remote tree when closing the window
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"
source
= open(filename
, "r").read()
code
= compile(source
, filename
, "exec")
except (OverflowError, SyntaxError):
self
.tkconsole
.resetoutput()
tkerr
= self
.tkconsole
.stderr
print>>tkerr
, '*** Error in script or command!\n'
print>>tkerr
, 'Traceback (most recent call last):'
InteractiveInterpreter
.showsyntaxerror(self
, filename
)
self
.tkconsole
.showprompt()
def runsource(self
, source
):
"Extend base class method: Stuff the source in the line cache first"
filename
= self
.stuffsource(source
)
self
.save_warnings_filters
= warnings
.filters
[:]
warnings
.filterwarnings(action
="error", category
=SyntaxWarning)
if isinstance(source
, types
.UnicodeType
):
source
= source
.encode(IOBinding
.encoding
)
self
.tkconsole
.resetoutput()
self
.write("Unsupported characters in input")
return InteractiveInterpreter
.runsource(self
, source
, filename
)
if self
.save_warnings_filters
is not None:
warnings
.filters
[:] = self
.save_warnings_filters
self
.save_warnings_filters
= None
def stuffsource(self
, source
):
"Stuff source in the filename cache"
filename
= "<pyshell#%d>" % self
.gid
lines
= source
.split("\n")
linecache
.cache
[filename
] = len(source
)+1, 0, lines
, filename
def prepend_syspath(self
, filename
):
"Prepend sys.path with file's directory if not already included"
from os.path import dirname as _dirname
_dir = _dirname(_filename)
if not _dir in _sys.path:
_sys.path.insert(0, _dir)
del _filename, _sys, _dirname, _dir
def showsyntaxerror(self
, filename
=None):
"""Extend base class method: Add Colorizing
Color the offending position instead of printing it and pointing at it
text
= self
.tkconsole
.text
stuff
= self
.unpackerror()
msg
, lineno
, offset
, line
= stuff
pos
= "iomark + %d chars" % (offset
-1)
pos
= "iomark linestart + %d lines + %d chars" % \
text
.tag_add("ERROR", pos
)
if char
and char
in IDENTCHARS
:
text
.tag_add("ERROR", pos
+ " wordstart", pos
)
self
.tkconsole
.resetoutput()
self
.write("SyntaxError: %s\n" % str(msg
))
self
.tkconsole
.resetoutput()
InteractiveInterpreter
.showsyntaxerror(self
, filename
)
self
.tkconsole
.showprompt()
type, value
, tb
= sys
.exc_info()
msg
, (dummy_filename
, lineno
, offset
, line
) = value
return msg
, lineno
, offset
, line
"Extend base class method to reset output properly"
self
.tkconsole
.resetoutput()
InteractiveInterpreter
.showtraceback(self
)
if self
.tkconsole
.getvar("<<toggle-jit-stack-viewer>>"):
self
.tkconsole
.open_stack_viewer()
def checklinecache(self
):
if key
[:1] + key
[-1:] != "<>":
def runcommand(self
, code
):
"Run the code without invoking the debugger"
# The code better not raise an exception!
if self
.tkconsole
.executing
:
self
.display_executing_dialog()
self
.rpcclt
.remotequeue("exec", "runcode", (code
,), {})
"Override base class method"
if self
.tkconsole
.executing
:
self
.interp
.restart_subprocess()
if self
.save_warnings_filters
is not None:
warnings
.filters
[:] = self
.save_warnings_filters
self
.save_warnings_filters
= None
self
.tkconsole
.beginexecuting()
if not debugger
and self
.rpcclt
is not None:
self
.active_seq
= self
.rpcclt
.asyncqueue("exec", "runcode",
debugger
.run(code
, self
.locals)
if tkMessageBox
.askyesno(
"Do you want to exit altogether?",
master
=self
.tkconsole
.text
):
self
.tkconsole
.endexecuting()
"Override base class method"
self
.tkconsole
.stderr
.write(s
)
def display_port_binding_error(self
):
"IDLE can't bind TCP/IP port 8833, which is necessary to "
"communicate with its Python execution server. Either "
"no networking is installed on this computer or another "
"process (another IDLE?) is using the port. Run IDLE with the -n "
"command line switch to start without a subprocess and refer to "
"Help/IDLE Help 'Running without a subprocess' for further "
master
=self
.tkconsole
.text
)
def display_no_subprocess_error(self
):
"Subprocess Startup Error",
"IDLE's subprocess didn't make connection. Either IDLE can't "
"start a subprocess or personal firewall software is blocking "
master
=self
.tkconsole
.text
)
def display_executing_dialog(self
):
"The Python Shell window is already executing a command; "
"please wait until it is finished.",
master
=self
.tkconsole
.text
)
class PyShell(OutputWindow
):
shell_title
= "Python Shell"
ColorDelegator
= ModifiedColorDelegator
UndoDelegator
= ModifiedUndoDelegator
from IdleHistory
import History
def __init__(self
, flist
=None):
ms
.insert(2, ("shell", "_Shell"))
self
.interp
= ModifiedInterpreter(self
)
flist
= PyShellFileList(root
)
OutputWindow
.__init
__(self
, flist
, None, None)
__builtin__
.quit
= __builtin__
.exit
= "To exit, type Ctrl-D."
self
.config(usetabs
=1, indentwidth
=8, context_use_ps1
=1)
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("<<toggle-jit-stack-viewer>>", self
.toggle_jit_stack_viewer
)
text
.bind("<<view-restart>>", self
.view_restart_mark
)
text
.bind("<<restart-shell>>", self
.restart_shell
)
self
.save_stdout
= sys
.stdout
self
.save_stderr
= sys
.stderr
self
.save_stdin
= sys
.stdin
self
.stdout
= PseudoFile(self
, "stdout", IOBinding
.encoding
)
self
.stderr
= PseudoFile(self
, "stderr", IOBinding
.encoding
)
self
.console
= PseudoFile(self
, "console", IOBinding
.encoding
)
self
.history
= self
.History(self
.text
)
self
.pollinterval
= 50 # millisec
def get_standard_extension_names(self
):
return idleConf
.GetExtensions(shell_only
=True)
def set_warning_stream(self
, stream
):
def get_warning_stream(self
):
def toggle_debugger(self
, event
=None):
tkMessageBox
.showerror("Don't debug now",
"You can only toggle the debugger when idle",
self
.set_debugger_indicator()
db
= self
.interp
.getdebugger()
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()
self
.interp
.setdebugger(None)
RemoteDebugger
.close_remote_debugger(self
.interp
.rpcclt
)
self
.console
.write("[DEBUG OFF]\n")
self
.set_debugger_indicator()
dbg_gui
= RemoteDebugger
.start_remote_debugger(self
.interp
.rpcclt
,
dbg_gui
= Debugger
.Debugger(self
)
self
.interp
.setdebugger(dbg_gui
)
dbg_gui
.load_breakpoints()
sys
.ps1
= "[DEBUG ON]\n>>> "
self
.set_debugger_indicator()
def beginexecuting(self
):
"Helper for ModifiedInterpreter"
"Helper for ModifiedInterpreter"
"Extend EditorWindow.close()"
response
= tkMessageBox
.askokcancel(
"The program is still running!\n Do you want to kill it?",
# Wait for poll_subprocess() rescheduling to stop
self
.text
.after(2 * self
.pollinterval
, self
.close2
)
return EditorWindow
.close(self
)
"Extend EditorWindow._close(), shut down debugger and execution server"
self
.interp
.kill_subprocess()
sys
.stdout
= self
.save_stdout
sys
.stderr
= self
.save_stderr
sys
.stdin
= self
.save_stdin
self
.flist
.pyshell
= None
EditorWindow
._close
(self
)
def ispythonsource(self
, filename
):
"Override EditorWindow method: never remove the colorizer"
'Type "copyright", "credits" or "license()" for more information.'
****************************************************************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback
interface. This connection is not visible on any external
interface and no data is sent to or received from the Internet.
****************************************************************
client
= self
.interp
.start_subprocess()
nosub
= "==== No Subprocess ===="
self
.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
(sys
.version
, sys
.platform
, self
.COPYRIGHT
,
self
.firewallmessage
, idlever
.IDLE_VERSION
, nosub
))
Tkinter
._default
_root
= None # 03Jan04 KBK What's this?
self
.top
.mainloop() # nested mainloop()
line
= self
.text
.get("iomark", "end-1c")
if len(line
) == 0: # may be EOF if we quit our mainloop with Ctrl-C
if isinstance(line
, unicode):
line
= line
.encode(IOBinding
.encoding
)
def cancel_callback(self
, event
=None):
if self
.text
.compare("sel.first", "!=", "sel.last"):
return # Active selection -- always use default binding
if not (self
.executing
or self
.reading
):
self
.interp
.write("KeyboardInterrupt\n")
if (self
.executing
and self
.interp
.rpcclt
):
if self
.interp
.getdebugger():
self
.interp
.restart_subprocess()
self
.interp
.interrupt_subprocess()
self
.top
.quit() # exit the nested mainloop() in readline()
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
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")
def linefeed_callback(self
, event
):
# Insert a linefeed without entering anything (still autoindented)
self
.text
.insert("insert", "\n")
self
.newline_and_indent_event(event
)
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)
sel
= self
.text
.get("sel.first", "sel.last")
if self
.text
.compare("sel.last", "<=", "iomark"):
# If we're strictly before the line containing iomark, recall
# the current line, less a leading prompt, less leading or
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]))
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]))
# No stdin mark -- just get the current line, less any prompt
line
= self
.text
.get("insert linestart", "insert lineend")
last_line_of_prompt
= sys
.ps1
.split('\n')[-1]
if line
.startswith(last_line_of_prompt
):
line
= line
[len(last_line_of_prompt
):]
# If we're between the beginning of the line and the iomark, i.e.
# in the prompt area, move to the end of the prompt
if self
.text
.compare("insert", "<", "iomark"):
self
.text
.mark_set("insert", "iomark")
# If we're in the current input and there's only whitespace
# beyond the cursor, erase that whitespace first
s
= self
.text
.get("insert", "end-1c")
self
.text
.delete("insert", "end-1c")
# 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
.newline_and_indent_event(event
)
# We're in the last line; append a newline and submit it
self
.text
.mark_set("insert", "end-1c")
self
.text
.insert("insert", "\n")
self
.newline_and_indent_event(event
)
self
.text
.tag_add("stdin", "iomark", "end-1c")
self
.text
.update_idletasks()
self
.top
.quit() # Break out of recursive mainloop() in raw_input()
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.)
while i
> 0 and line
[i
-1] in " \t":
if i
> 0 and line
[i
-1] == "\n":
while i
> 0 and line
[i
-1] in " \t":
more
= self
.interp
.runsource(line
)
def open_stack_viewer(self
, event
=None):
return self
.interp
.remote_stack_viewer()
tkMessageBox
.showerror("No stack trace",
"There is no stack trace yet.\n"
"(sys.last_traceback is not defined)",
from StackViewer
import StackBrowser
sv
= StackBrowser(self
.root
, self
.flist
)
def view_restart_mark(self
, event
=None):
def restart_shell(self
, event
=None):
self
.interp
.restart_subprocess()
self
.text
.mark_set("insert", "end-1c")
self
.set_line_and_column()
source
= self
.text
.get("iomark", "end-1c")
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")
self
.set_line_and_column()
def write(self
, s
, tags
=()):
self
.text
.mark_gravity("iomark", "right")
OutputWindow
.write(self
, s
, tags
, "iomark")
self
.text
.mark_gravity("iomark", "left")
def __init__(self
, shell
, tags
, encoding
=None):
self
.shell
.write(s
, self
.tags
)
USAGE: idle [-deins] [-t title] [file]*
idle [-dns] [-t title] (-c cmd | -r file) [arg]*
idle [-dns] [-t title] - [arg]*
-h print this help message and exit
-n run IDLE without a subprocess (see Help/IDLE Help for details)
The following options will override the IDLE 'settings' configuration:
The following options imply -i and will open a shell:
-c cmd run the command in a shell, or
-r file run script from file
-s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
-t title set title of shell window
A default edit window will be bypassed when -c, -r, or - are used.
[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
Open an edit window or shell depending on IDLE's configuration.
Edit the files, also open a shell if configured to start with shell.
Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
window with the title "Baz".
idle -c "import sys; print sys.argv" "foo"
Open a shell window and run the command, passing "-c" in sys.argv[0]
and "foo" in sys.argv[1].
idle -d -s -r foo.py "Hello World"
Open a shell window, run a startup script, enable the debugger, and
run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
echo "import sys; print sys.argv" | idle - "foobar"
Open a shell window, run the script piped in, passing '' in sys.argv[0]
and "foobar" in sys.argv[1].
global flist
, root
, use_subprocess
opts
, args
= getopt
.getopt(sys
.argv
[1:], "c:deihnr:st:")
except getopt
.error
, msg
:
sys
.stderr
.write("Error: %s\n" % str(msg
))
sys
.stderr
.write(usage_msg
)
sys
.stdout
.write(usage_msg
)
if os
.path
.isfile(script
):
print "No script file: ", script
if args
and args
[0] == '-':
# process sys.argv and sys.path:
for i
in range(len(sys
.path
)):
sys
.path
[i
] = os
.path
.abspath(sys
.path
[i
])
if args
and args
[0] == '-':
sys
.argv
= [''] + args
[1:]
sys
.argv
= [script
] + args
pathx
.append(os
.path
.dirname(filename
))
dir = os
.path
.abspath(dir)
# check the IDLE settings configuration (but command line overrides)
edit_start
= idleConf
.GetOption('main', 'General',
'editor-on-startup', type='bool')
enable_edit
= enable_edit
or edit_start
enable_shell
= enable_shell
or not edit_start
# start editor and/or shell windows:
root
= Tk(className
="Idle")
flist
= PyShellFileList(root
)
if not flist
.open_shell():
return # couldn't open shell
# handle remaining options:
filename
= os
.environ
.get("IDLESTARTUP") or \
os
.environ
.get("PYTHONSTARTUP")
if filename
and os
.path
.isfile(filename
):
shell
.interp
.execfile(filename
)
if shell
and cmd
or script
:
shell
.interp
.runcommand("""if 1:
shell
.interp
.execsource(cmd
)
shell
.interp
.prepend_syspath(script
)
shell
.interp
.execfile(script
)
if __name__
== "__main__":
sys
.modules
['PyShell'] = sys
.modules
['__main__']