From: Guido van Rossum Date: Fri, 27 Nov 1998 03:17:49 +0000 (+0000) Subject: New approach, separate tables for menus (platform-independent) and key X-Git-Tag: v1.5.2b1~175 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6e0a4136936c242da266a8ff7614f4861cadcb74;p=python New approach, separate tables for menus (platform-independent) and key definitions (platform-specific), and generating accelerator strings automatically from the key definitions. --- diff --git a/Tools/idle/Bindings.py b/Tools/idle/Bindings.py index 900c8504f4..5a13d22e92 100644 --- a/Tools/idle/Bindings.py +++ b/Tools/idle/Bindings.py @@ -1,174 +1,198 @@ -# The first three items of each tupel pertain to the menu bar. All -# three are None if the item is not to appeat in a menu. Otherwise, -# the first item is the menu name (in lowercase), the second item is -# the menu item label; the third item is the keyboard shortcut to be -# listed in the menu, if any. Menu items are added in the order of -# their occurrence in this table. An item of the form -# ("menu", None, None) can be used to insert a separator in the menu. -# -# The fourth item, if present is the virtual event; each of the -# remaining items is an actual key binding for the event. (Thus, -# items[3:] conveniently forms an argument list for event_add().) - -win_bindings = [ - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), +# This file defines the menu contents and key bindings. Note that +# there is additional configuration information in the EditorWindow +# class (and subclasses): the menus are created there based on the +# menu_specs (class) variable, and menus not created are silently +# skipped by the code here. This makes it possible to define the +# Debug menu here, which is only present in the PythonShell window. + +import sys +import string +import re + +menudefs = [ + # underscore prefixes character to underscore + ('file', [ + ('_New window', '<>'), + ('_Open...', '<>'), + ('Open _module...', '<>'), + ('Class _browser...', '<>'), + None, + ('_Save', '<>'), + ('Save _As...', '<>'), + ('Save Co_py As...', '<>'), + None, + ('_Close', '<>'), + ('E_xit', '<>'), + ]), + ('edit', [ + ('_Undo', '<>'), + ('_Redo', '<>'), + None, + ('Cu_t', '<>'), + ('_Copy', '<>'), + ('_Paste', '<>'), + None, + ('_Find...', '<>'), + ('Find _next', '<>'), + ('Find _same', '<>'), + ('_Go to line', '<>'), + None, + ('_Dedent region', '<>'), + ('_Indent region', '<>'), + ('Comment _out region', '<>'), + ('U_ncomment region', '<>'), + ]), + ('debug', [ + ('_Go to line from traceback', '<>'), + ('_Open stack viewer', '<>'), + ('_Debugger toggle', '<>'), + ]), + ('help', [ + ('_Help...', '<>'), + None, + ('_About IDLE...', '<>'), + ]), ] -emacs_bindings = [ - - # File menu - - ("file", "New window", "C-x C-n", - "<>", ""), - ("file", "Open...", "C-x C-f", - "<>", ""), - ("file", "Open module...", "C-x C-m", - "<>", ""), - ("file", "Class browser...", "C-x C-b", - "<>", ""), - ("file", None, None), - - ("file", "Save", "C-x C-s", - "<>", ""), - ("file", "Save As...", "C-x C-w", - "<>", ""), - ("file", "Save Copy As...", "C-x w", - "<>", ""), - ("file", None, None), - - ("file", "Close", "C-x C-0", - "<>", ""), - ("file", "Exit", "C-x C-c", - "<>", ""), - - # Edit menu - - ("edit", "Undo", "C-z", "<>", ""), - ("edit", "Redo", "Alt-z", "<>", "", ""), - ("edit", None, None), - - ("edit", "Cut", None, "<>", ""), - ("edit", "Copy", None, "<>", ""), - ("edit", "Paste", None, "<>", ""), - ("edit", None, None), - - ("edit", "Find...", "C-s", - "<>", ""), - ("edit", "Find next", "C-u C-s", - "<>", ""), - ("edit", "Find same", "C-s", "<>", ""), - ("edit", "Go to line", "Alt-g", "<>", "", ""), - ("edit", None, None), - - ("edit", "Dedent region", "Ctrl-[", "<>", - "", "", ""), - ("edit", "Indent region", "Ctrl-]", "<>", - "", "", ""), - - ("edit", "Comment out region", "Alt-3", - "<>", "", ""), - ("edit", "Uncomment region", "Alt-4", - "<>", "", ""), - - # Debug menu - - ("debug", "Go to line from traceback", None, "<>"), - ("debug", "Open stack viewer", None, "<>"), - ("debug", "Toggle debugger", None, "<>"), - - # Help menu - - ("help", "Help...", None, "<>"), - ("help", None, None), - ("help", "About IDLE...", None, "<>"), - - # Not in any menu - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - (None, None, None, "<>", ""), - - (None, None, None, "<>", "", ""), - (None, None, None, "<>", "", ""), - - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), - - (None, None, None, "<>", ""), -] - -default_bindings = emacs_bindings - -def apply_bindings(text, bindings=default_bindings): - event_add = text.event_add - for args in bindings: - args = args[3:] - if args[1:]: - apply(event_add, args) - -def fill_menus(text, dict, bindings=default_bindings): - # Fill the menus for the given text widget. The dict argument is +windows_keydefs = { + '<>': ['', ''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], +} + +emacs_keydefs = { + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': ['', + '', + ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [], + '<>': [], + '<>': ['', ''], + '<>': ['', ''], + '<>': ['', + '', + ''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [], + '<>': [''], + '<>': [''], + '<>': ['', ''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [''], + '<>': [], + '<>': ['', ''], + '<>': [''], +} + +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': ']', +} + +def getaccelerator(keydefs, event): + keylist = keydefs.get(event) + if not keylist: + return "" + s = keylist[0] + if s[:6] == "<", " ", s) + s = re.sub("<", "", s) + s = re.sub(">", "", s) + return s + +if sys.platform == 'win32': + default_keydefs = windows_keydefs +else: + default_keydefs = emacs_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): + # 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 args in bindings: - menu, label, accelerator = args[:3] - if not menu: - continue - menu = dict.get(menu) + if hasattr(text, "keydefs"): + keydefs = text.keydefs + else: + keydefs = default_keydefs + for mname, itemlist in defs: + menu = menudict.get(mname) if not menu: continue - if accelerator is None: - accelerator = "" - args = args[3:] - if args: - def command(text=text, event=args[0]): - text.event_generate(event) - menu.add_command(label=label, accelerator=accelerator, - command=command) - elif label or accelerator: - menu.add_command(label=label, accelerator=accelerator) - else: - menu.add_separator() + for item in itemlist: + if not item: + menu.add_separator() + else: + label, event = item + underline, label = prepstr(label) + accelerator = getaccelerator(keydefs, event) + def command(text=text, event=event): + text.event_generate(event) + menu.add_command(label=label, underline=underline, + command=command, accelerator=accelerator)