summaryrefslogtreecommitdiffstats
path: root/Tools/idle/PyShell.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/idle/PyShell.py')
-rw-r--r--Tools/idle/PyShell.py267
1 files changed, 101 insertions, 166 deletions
diff --git a/Tools/idle/PyShell.py b/Tools/idle/PyShell.py
index 887da1e..6df38c3 100644
--- a/Tools/idle/PyShell.py
+++ b/Tools/idle/PyShell.py
@@ -12,9 +12,10 @@ from code import InteractiveInterpreter
from Tkinter import *
import tkMessageBox
-from EditorWindow import fixwordbreaks
-from FileList import FileList, MultiEditorWindow, MultiIOBinding
+from EditorWindow import EditorWindow, fixwordbreaks
+from FileList import FileList
from ColorDelegator import ColorDelegator
+from OutputWindow import OutputWindow
# We need to patch linecache.checkcache, because we don't want it
# to throw away our <pyshell#...> entries.
@@ -31,36 +32,54 @@ def linecache_checkcache(orig_checkcache=linecache.checkcache):
linecache.checkcache = linecache_checkcache
-class PyShellEditorWindow(MultiEditorWindow):
-
+# 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(MultiEditorWindow.__init__, (self,) + args)
- self.text.bind("<3>", self.right_menu_event)
-
- def fixedwindowsmenu(self, wmenu):
- wmenu.add_command(label="Python Shell", command=self.flist.open_shell)
- wmenu.add_separator()
-
- menu = None
-
- def right_menu_event(self, event):
- self.text.mark_set("insert", "@%d,%d" % (event.x, event.y))
- if not self.menu:
- self.make_menu()
- menu = self.menu
- iswin = sys.platform[:3] == 'win'
- if iswin:
- self.text.config(cursor="arrow")
- menu.tk_popup(event.x_root, event.y_root)
- if iswin:
- self.text.config(cursor="ibeam")
-
- def make_menu(self):
- self.menu = menu = Menu(self.text, tearoff=0)
- menu.add_command(label="Set breakpoint here",
- command=self.set_breakpoint_here)
-
- def set_breakpoint_here(self):
+ 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
@@ -68,12 +87,14 @@ class PyShellEditorWindow(MultiEditorWindow):
class PyShellFileList(FileList):
-
+
+ # File list when a shell is present
+
EditorWindow = PyShellEditorWindow
-
+
pyshell = None
- def open_shell(self):
+ def open_shell(self, event=None):
if self.pyshell:
self.pyshell.wakeup()
else:
@@ -82,43 +103,29 @@ class PyShellFileList(FileList):
return self.pyshell
-class ModifiedIOBinding(MultiIOBinding):
-
- def defaultfilename(self, mode="open"):
- if self.filename:
- return MultiIOBinding.defaultfilename(self, mode)
- else:
- try:
- pwd = os.getcwd()
- except os.error:
- pwd = ""
- return pwd, ""
-
- def open(self, event):
- # Override base class method -- don't allow reusing this window
- filename = self.askopenfile()
- if filename:
- self.flist.open(filename)
- return "break"
-
- def maybesave(self):
- # Override base class method -- don't ask any questions
- if self.text.get_saved():
- return "yes"
- else:
- return "no"
+class ModifiedColorDelegator(ColorDelegator):
+ # Colorizer for the shell window itself
-class ModifiedColorDelegator(ColorDelegator):
-
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()
+
+ tagdefs.update({
+ ##"stdin": {"background": "yellow"},
+ "stdout": {"foreground": "blue"},
+ "stderr": {"foreground": "#007700"},
+ "console": {"foreground": "#770000"},
+ "ERROR": {"background": "#FF7777"},
+ None: {"foreground": "purple"}, # default
+ })
+
class ModifiedInterpreter(InteractiveInterpreter):
-
+
def __init__(self, tkconsole):
self.tkconsole = tkconsole
InteractiveInterpreter.__init__(self)
@@ -176,7 +183,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.tkconsole.resetoutput()
self.checklinecache()
InteractiveInterpreter.showtraceback(self)
-
+
def checklinecache(self):
c = linecache.cache
for key in c.keys():
@@ -184,10 +191,10 @@ class ModifiedInterpreter(InteractiveInterpreter):
del c[key]
debugger = None
-
+
def setdebugger(self, debugger):
self.debugger = debugger
-
+
def getdebugger(self):
return self.debugger
@@ -214,25 +221,23 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.showtraceback()
finally:
self.tkconsole.endexecuting()
-
+
def write(self, s):
# Override base class write
self.tkconsole.console.write(s)
-
-class PyShell(PyShellEditorWindow):
+
+class PyShell(OutputWindow):
# Override classes
ColorDelegator = ModifiedColorDelegator
- IOBinding = ModifiedIOBinding
-
+
# Override menu bar specs
menu_specs = PyShellEditorWindow.menu_specs[:]
- menu_specs.insert(len(menu_specs)-1, ("debug", "Debug"))
-
+ menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug"))
+
# New classes
from History import History
- from PopupMenu import PopupMenu
def __init__(self, flist=None):
self.interp = ModifiedInterpreter(self)
@@ -242,23 +247,24 @@ class PyShell(PyShellEditorWindow):
root.withdraw()
flist = PyShellFileList(root)
- PyShellEditorWindow.__init__(self, flist, None, None)
- self.config_colors()
+ 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("<<goto-traceback-line>>", self.goto_traceback_line)
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)
sys.stdout = PseudoFile(self, "stdout")
sys.stderr = PseudoFile(self, "stderr")
@@ -266,31 +272,12 @@ class PyShell(PyShellEditorWindow):
self.console = PseudoFile(self, "console")
self.history = self.History(self.text)
- self.popup = self.PopupMenu(self.text, self.flist)
-
- tagdefs = {
- ##"stdin": {"background": "yellow"},
- "stdout": {"foreground": "blue"},
- "stderr": {"foreground": "#007700"},
- "console": {"foreground": "red"},
- "ERROR": {"background": "#FF7777"},
- None: {"foreground": "purple"}, # default
- }
-
- def config_colors(self):
- for tag, cnf in self.tagdefs.items():
- if cnf:
- if not tag:
- apply(self.text.configure, (), cnf)
- else:
- apply(self.text.tag_configure, (tag,), cnf)
- self.text.tag_raise("sel")
reading = 0
executing = 0
canceled = 0
endoffile = 0
-
+
def toggle_debugger(self, event=None):
if self.executing:
tkMessageBox.showerror("Don't debug now",
@@ -362,14 +349,8 @@ class PyShell(PyShellEditorWindow):
# Override this so EditorWindow never removes the colorizer
return 1
- def saved_change_hook(self):
- # Override this to get the title right
- title = "Python Shell"
- if self.io.filename:
- title = title + ": " + self.io.filename
- if not self.undo.get_saved():
- title = title + " *"
- self.top.wm_title(title)
+ def short_title(self):
+ return "Python Shell"
def begin(self):
self.resetoutput()
@@ -382,7 +363,7 @@ class PyShell(PyShellEditorWindow):
self.showprompt()
import Tkinter
Tkinter._default_root = None
-
+
def interact(self):
self.begin()
self.top.mainloop()
@@ -457,7 +438,7 @@ class PyShell(PyShellEditorWindow):
self.text.insert("insert", "\n")
self.text.see("insert")
else:
- self.auto.autoindent(event)
+ self.auto.auto_indent(event)
return "break"
def enter_callback(self, event):
@@ -468,7 +449,7 @@ class PyShell(PyShellEditorWindow):
try:
sel = self.text.get("sel.first", "sel.last")
if sel:
- if self.text.compare("self.last", "<=", "iomark"):
+ if self.text.compare("sel.last", "<=", "iomark"):
self.recall(sel)
return "break"
except:
@@ -492,7 +473,7 @@ class PyShell(PyShellEditorWindow):
# 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.autoindent(event)
+ 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")
@@ -500,7 +481,7 @@ class PyShell(PyShellEditorWindow):
self.text.insert("insert", "\n")
self.text.see("insert")
else:
- self.auto.autoindent(event)
+ self.auto.auto_indent(event)
self.text.tag_add("stdin", "iomark", "end-1c")
self.text.update_idletasks()
if self.reading:
@@ -545,49 +526,7 @@ class PyShell(PyShellEditorWindow):
self.canceled = 0
raise KeyboardInterrupt
return self._cancel_check
-
- file_line_pats = [
- r'File "([^"]*)", line (\d+)',
- r'([^\s]+)\((\d+)\)',
- r'([^\s]+):\s*(\d+):',
- ]
-
- file_line_progs = None
-
- def goto_traceback_line(self, event=None):
- if self.file_line_progs is None:
- l = []
- for pat in self.file_line_pats:
- l.append(re.compile(pat))
- self.file_line_progs = l
- # x, y = self.event.x, self.event.y
- # self.text.mark_set("insert", "@%d,%d" % (x, y))
- line = self.text.get("insert linestart", "insert lineend")
- for prog in self.file_line_progs:
- m = prog.search(line)
- if m:
- break
- else:
- tkMessageBox.showerror("No traceback line",
- "The line you point at doesn't look "
- "like an error message.",
- master=self.text)
- return
- filename, lineno = m.group(1, 2)
- try:
- f = open(filename, "r")
- f.close()
- except IOError, msg:
- self.text.bell()
- return
- edit = self.flist.open(filename)
- try:
- lineno = int(lineno)
- except ValueError, msg:
- self.text.bell()
- return
- edit.gotoline(lineno)
-
+
def open_stack_viewer(self, event=None):
try:
sys.last_traceback
@@ -618,26 +557,22 @@ class PyShell(PyShellEditorWindow):
self.text.mark_set("iomark", "end-1c")
sys.stdout.softspace = 0
- def write(self, s):
- # Overrides base class write
- self.console.write(s)
+ 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, interp, tags):
- self.interp = interp
- self.text = interp.text
+ def __init__(self, shell, tags):
+ self.shell = shell
self.tags = tags
def write(self, s):
- self.text.mark_gravity("iomark", "right")
- self.text.insert("iomark", str(s), self.tags)
- self.text.mark_gravity("iomark", "left")
- self.text.see("iomark")
- self.text.update()
- if self.interp.canceled:
- self.interp.canceled = 0
- raise KeyboardInterrupt
+ self.shell.write(s, self.tags)
def writelines(self, l):
map(self.write, l)