summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1999-01-28 22:02:47 (GMT)
committerGuido van Rossum <guido@python.org>1999-01-28 22:02:47 (GMT)
commit07ec8967078a966365a44db301a9063f70c7f474 (patch)
treef97b034c2f3489958e47ae03a3cb41c5312a745c
parent85ef9dce9f4b1982c1f26daa0fe9f4af08e124a6 (diff)
downloadcpython-07ec8967078a966365a44db301a9063f70c7f474.zip
cpython-07ec8967078a966365a44db301a9063f70c7f474.tar.gz
cpython-07ec8967078a966365a44db301a9063f70c7f474.tar.bz2
Move menu/key binding code from Bindings.py to EditorWindow.py,
with changed APIs -- it makes much more sense there. Also add a new feature: if the first character of a menu label is a '!', it gets a checkbox. Checkboxes are bound to Boolean Tcl variables that can be accessed through the new getvar/setvar/getrawvar API; the variable is named after the event to which the menu is bound.
-rw-r--r--Tools/idle/Bindings.py62
-rw-r--r--Tools/idle/EditorWindow.py115
-rw-r--r--Tools/idle/PyShell.py29
3 files changed, 127 insertions, 79 deletions
diff --git a/Tools/idle/Bindings.py b/Tools/idle/Bindings.py
index e365032..e0a2570 100644
--- a/Tools/idle/Bindings.py
+++ b/Tools/idle/Bindings.py
@@ -7,7 +7,6 @@
import sys
import string
-import re
from keydefs import *
menudefs = [
@@ -42,9 +41,9 @@ menudefs = [
]),
('debug', [
('_Go to file/line', '<<goto-file-line>>'),
- ('_Open stack viewer', '<<open-stack-viewer>>'),
- ('_Debugger toggle', '<<toggle-debugger>>'),
- ('_JIT Stack viewer toggle', '<<toggle-jit-stack-viewer>>' ),
+ ('_Stack viewer', '<<open-stack-viewer>>'),
+ ('!_Debugger', '<<toggle-debugger>>'),
+ ('!_Auto-open stack viewer', '<<toggle-jit-stack-viewer>>' ),
]),
('help', [
('_Help...', '<<help>>'),
@@ -53,62 +52,7 @@ menudefs = [
]),
]
-def prepstr(s):
- # Helper to extract the underscore from a string,
- # e.g. prepstr("Co_py") returns (2, "Copy").
- i = string.find(s, '_')
- if i >= 0:
- s = s[:i] + s[i+1:]
- return i, s
-
-keynames = {
- 'bracketleft': '[',
- 'bracketright': ']',
- 'slash': '/',
-}
-
-def get_accelerator(keydefs, event):
- keylist = keydefs.get(event)
- if not keylist:
- return ""
- s = keylist[0]
- s = re.sub(r"-[a-z]\b", lambda m: string.upper(m.group()), s)
- s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s)
- s = re.sub("Key-", "", s)
- s = re.sub("Control-", "Ctrl-", s)
- s = re.sub("-", "+", s)
- s = re.sub("><", " ", s)
- s = re.sub("<", "", s)
- s = re.sub(">", "", s)
- return s
-
if sys.platform == 'win32':
default_keydefs = windows_keydefs
else:
default_keydefs = unix_keydefs
-
-def apply_bindings(text, keydefs=default_keydefs):
- text.keydefs = keydefs
- for event, keylist in keydefs.items():
- if keylist:
- apply(text.event_add, (event,) + tuple(keylist))
-
-def fill_menus(text, menudict, defs=menudefs, keydefs=default_keydefs):
- # Fill the menus for the given text widget. The menudict argument is
- # a dictionary containing the menus, keyed by their lowercased name.
- # Menus that are absent or None are ignored.
- for mname, itemlist in defs:
- menu = menudict.get(mname)
- if not menu:
- continue
- for item in itemlist:
- if not item:
- menu.add_separator()
- else:
- label, event = item
- underline, label = prepstr(label)
- accelerator = get_accelerator(keydefs, event)
- def command(text=text, event=event):
- text.event_generate(event)
- menu.add_command(label=label, underline=underline,
- command=command, accelerator=accelerator)
diff --git a/Tools/idle/EditorWindow.py b/Tools/idle/EditorWindow.py
index 96a56de..17f23ca 100644
--- a/Tools/idle/EditorWindow.py
+++ b/Tools/idle/EditorWindow.py
@@ -1,6 +1,7 @@
import sys
import os
import string
+import re
import imp
from Tkinter import *
import tkSimpleDialog
@@ -93,7 +94,7 @@ class EditorWindow:
background="white", wrap="none")
self.createmenubar()
- self.Bindings.apply_bindings(text)
+ self.apply_bindings()
self.top.protocol("WM_DELETE_WINDOW", self.close)
self.top.bind("<<close-window>>", self.close_event)
@@ -172,15 +173,19 @@ class EditorWindow:
def createmenubar(self):
mbar = self.menubar
- self.menudict = mdict = {}
+ self.menudict = menudict = {}
for name, label in self.menu_specs:
- underline, label = self.Bindings.prepstr(label)
- mdict[name] = menu = Menu(mbar, name=name)
+ underline, label = prepstr(label)
+ menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline)
- self.Bindings.fill_menus(self.text, mdict)
+ self.fill_menus()
def postwindowsmenu(self):
# Only called when Windows menu exists
+ # XXX Actually, this Just-In-Time updating interferes
+ # XXX badly with the tear-off feature. It would be better
+ # XXX to update all Windows menus whenever the list of windows
+ # XXX changes.
menu = self.menudict['windows']
end = menu.index("end")
if end is None:
@@ -477,7 +482,7 @@ class EditorWindow:
if hasattr(ins, kdname):
keydefs.update(getattr(ins, kdname))
if keydefs:
- self.Bindings.apply_bindings(self.text, keydefs)
+ self.apply_bindings(keydefs)
for vevent in keydefs.keys():
methodname = string.replace(vevent, "-", "_")
while methodname[:1] == '<':
@@ -488,10 +493,104 @@ class EditorWindow:
if hasattr(ins, methodname):
self.text.bind(vevent, getattr(ins, methodname))
if hasattr(ins, "menudefs"):
- self.Bindings.fill_menus(self.text, self. menudict,
- ins.menudefs, keydefs)
+ self.fill_menus(ins.menudefs, keydefs)
return ins
+ def apply_bindings(self, keydefs=None):
+ if keydefs is None:
+ keydefs = self.Bindings.default_keydefs
+ text = self.text
+ text.keydefs = keydefs
+ for event, keylist in keydefs.items():
+ if keylist:
+ apply(text.event_add, (event,) + tuple(keylist))
+
+ def fill_menus(self, defs=None, keydefs=None):
+ # Fill the menus.
+ # Menus that are absent or None in self.menudict are ignored.
+ if defs is None:
+ defs = self.Bindings.menudefs
+ if keydefs is None:
+ keydefs = self.Bindings.default_keydefs
+ menudict = self.menudict
+ text = self.text
+ for mname, itemlist in defs:
+ menu = menudict.get(mname)
+ if not menu:
+ continue
+ for item in itemlist:
+ if not item:
+ menu.add_separator()
+ else:
+ label, event = item
+ checkbutton = (label[:1] == '!')
+ if checkbutton:
+ label = label[1:]
+ underline, label = prepstr(label)
+ accelerator = get_accelerator(keydefs, event)
+ def command(text=text, event=event):
+ text.event_generate(event)
+ if checkbutton:
+ var = self.getrawvar(event, BooleanVar)
+ menu.add_checkbutton(label=label, underline=underline,
+ command=command, accelerator=accelerator,
+ variable=var)
+ else:
+ menu.add_command(label=label, underline=underline,
+ command=command, accelerator=accelerator)
+
+ def getvar(self, name):
+ var = self.getrawvar(name)
+ if var:
+ return var.get()
+
+ def setvar(self, name, value, vartype=None):
+ var = self.getrawvar(name, vartype)
+ if var:
+ var.set(value)
+
+ def getrawvar(self, name, vartype=None):
+ key = ".VARS."
+ vars = self.menudict.get(key)
+ if not vars and vartype:
+ self.menudict[key] = vars = {}
+ if vars is not None:
+ var = vars.get(name)
+ if not var and vartype:
+ vars[name] = var = vartype(self.text)
+ return var
+
+
+def prepstr(s):
+ # Helper to extract the underscore from a string,
+ # e.g. prepstr("Co_py") returns (2, "Copy").
+ i = string.find(s, '_')
+ if i >= 0:
+ s = s[:i] + s[i+1:]
+ return i, s
+
+
+keynames = {
+ 'bracketleft': '[',
+ 'bracketright': ']',
+ 'slash': '/',
+}
+
+def get_accelerator(keydefs, event):
+ keylist = keydefs.get(event)
+ if not keylist:
+ return ""
+ s = keylist[0]
+ s = re.sub(r"-[a-z]\b", lambda m: string.upper(m.group()), s)
+ s = re.sub(r"\b\w+\b", lambda m: keynames.get(m.group(), m.group()), s)
+ s = re.sub("Key-", "", s)
+ s = re.sub("Control-", "Ctrl-", s)
+ s = re.sub("-", "+", s)
+ s = re.sub("><", " ", s)
+ s = re.sub("<", "", s)
+ s = re.sub(">", "", s)
+ return s
+
def fixwordbreaks(root):
# Make sure that Tk's double-click and next/previous word
diff --git a/Tools/idle/PyShell.py b/Tools/idle/PyShell.py
index f484fb8..115d96f 100644
--- a/Tools/idle/PyShell.py
+++ b/Tools/idle/PyShell.py
@@ -217,11 +217,11 @@ class ModifiedInterpreter(InteractiveInterpreter):
raise
else:
self.showtraceback()
- if self.tkconsole.jit_stack_view:
+ if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
self.tkconsole.open_stack_viewer()
except:
self.showtraceback()
- if self.tkconsole.jit_stack_view:
+ if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
self.tkconsole.open_stack_viewer()
finally:
@@ -289,17 +289,20 @@ class PyShell(OutputWindow):
tkMessageBox.showerror("Don't debug now",
"You can only toggle the debugger when idle",
master=self.text)
+ self.set_debugger_indicator()
return "break"
- db = self.interp.getdebugger()
- if db:
- self.close_debugger()
else:
- self.open_debugger()
-
- jit_stack_view = 0
-
+ 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):
- self.jit_stack_view = not self.jit_stack_view
+ pass # All we need is the variable
def close_debugger(self):
db = self.interp.getdebugger()
@@ -310,12 +313,14 @@ class PyShell(OutputWindow):
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
@@ -335,8 +340,8 @@ class PyShell(OutputWindow):
if self.executing:
# XXX Need to ask a question here
if not tkMessageBox.askokcancel(
- "Cancel?",
- "The program is still running; do you want to cancel it?",
+ "Kill?",
+ "The program is still running; do you want to kill it?",
default="ok",
master=self.text):
return "cancel"