summaryrefslogtreecommitdiffstats
path: root/Tools/idle/Bindings.py
blob: e365032c768ebcdc6f60ebcc27794244ec785d9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# 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
from keydefs import *

menudefs = [
 # underscore prefixes character to underscore
 ('file', [
   ('_New window', '<<open-new-window>>'),
   ('_Open...', '<<open-window-from-file>>'),
   ('Open _module...', '<<open-module>>'),
   ('Class _browser', '<<open-class-browser>>'),
   ('Python shell', '<<open-python-shell>>'),
   None,
   ('_Save', '<<save-window>>'),
   ('Save _As...', '<<save-window-as-file>>'),
   ('Save Co_py As...', '<<save-copy-of-window-as-file>>'),
   None,
   ('_Close', '<<close-window>>'),
   ('E_xit', '<<close-all-windows>>'),
  ]),
 ('edit', [
   ('_Undo', '<<undo>>'),
   ('_Redo', '<<redo>>'),
   None,
   ('Cu_t', '<<Cut>>'),
   ('_Copy', '<<Copy>>'),
   ('_Paste', '<<Paste>>'),
   ('Select _All', '<<select-all>>'),
  ]),
 ('script', [
   ('Run module', '<<run-module>>'),
   ('Run script', '<<run-script>>'),
   ('New shell', '<<new-shell>>'),
  ]),
 ('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>>' ),
  ]),
 ('help', [
   ('_Help...', '<<help>>'),
   None,
   ('_About IDLE...', '<<about-idle>>'),
  ]),
]

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)