Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Lib/idlelib/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
TK_TABWIDTH_DEFAULT = 8
darwin = sys.platform == 'darwin'

# A letter keysym in a key sequence, such as "s" in "<Control-Key-s>".
_letter_key_re = re.compile(r'(?<=-Key-)[a-zA-Z](?=>)')


class EditorWindow:
is_shell = False # PyShell overrides.
from idlelib.percolator import Percolator
Expand Down Expand Up @@ -1186,6 +1190,12 @@ def apply_bindings(self, keydefs=None):
for event, keylist in keydefs.items():
if keylist:
text.event_add(event, *keylist)
# Caps Lock changes the case of letter keysyms, so bind
# the sequences with the other case too (gh-56596).
for keys in keylist:
other = _letter_key_re.sub(lambda m: m[0].swapcase(), keys)
if other not in keylist:
text.event_add(event, other)

def fill_menus(self, menudefs=None, keydefs=None):
"""Fill in dropdown menus used by this window.
Expand Down
20 changes: 20 additions & 0 deletions Lib/idlelib/idle_test/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ def test_init(self):
self.assertEqual(e.root, self.root)
e._close()

def test_apply_bindings_caps_lock(self):
# gh-56596: Caps Lock changes the case of letter keysyms, so the
# sequences are bound with both cases.
e = Editor(root=self.root)
try:
e.apply_bindings({'<<spam>>': ('<Control-Key-s>', '<Key-F1>'),
'<<eggs>>': ('<Control-Key-x><Alt-Shift-Key-S>',),
'<<ham>>': ('<Control-Key-h>', '<Control-Key-H>')})
self.assertEqual(set(e.text.event_info('<<spam>>')),
{'<Control-KeyPress-s>', '<Control-KeyPress-S>',
'<KeyPress-F1>'})
# Existing variants are not added again.
self.assertEqual(e.text.event_info('<<ham>>'),
('<Control-KeyPress-h>', '<Control-KeyPress-H>'))
self.assertEqual(set(e.text.event_info('<<eggs>>')),
{'<Control-Key-x><Shift-Alt-Key-S>',
'<Control-Key-X><Shift-Alt-Key-s>'})
finally:
e._close()

def test_set_width_zero_char_width(self):
# A zero-width '0' must not raise ZeroDivisionError (gh-90304).
e = Editor(root=self.root)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Make IDLE keyboard shortcuts with ascii letters work when Caps Lock is on even when only one
of the upper and lowercase versions are defined.
Loading