diff --git a/Doc/library/rlcompleter.rst b/Doc/library/rlcompleter.rst index 40b09ce897880e..9f1adc3bad7adb 100644 --- a/Doc/library/rlcompleter.rst +++ b/Doc/library/rlcompleter.rst @@ -5,6 +5,7 @@ :synopsis: Python identifier completion, suitable for the GNU readline library. .. sectionauthor:: Moshe Zadka +.. sectionauthor:: Madhusudhan Kasula **Source code:** :source:`Lib/rlcompleter.py` @@ -59,3 +60,19 @@ Completer objects have the following method: :func:`dir` function. Any exception raised during the evaluation of the expression is caught, silenced and :const:`None` is returned. + +.. _case-sensitivity: + +Case Sensitivity +----------------- + +You can change the Completer's default case sensitive selection to case insensitive using the following method: + + +.. function:: rlcompleter.set_ignore_case(option) + + Return the *None*. + + If called with *True*, it will set rlcompleter for case insensitive completions. + + If called with *False*, it will set to default case sensitive completions. diff --git a/Lib/rlcompleter.py b/Lib/rlcompleter.py index bca4a7bc5218a9..f5c8ea7baa4453 100644 --- a/Lib/rlcompleter.py +++ b/Lib/rlcompleter.py @@ -11,6 +11,10 @@ readline.parse_and_bind("tab: complete") +And to make completion with case insensitive, call + + rlcompleter.set_ignore_case(True) + Notes: - Exceptions raised by the completer function are *ignored* (and generally cause @@ -106,12 +110,13 @@ def global_matches(self, text): defined in self.namespace that match. """ + import re import keyword matches = [] seen = {"__builtins__"} n = len(text) for word in keyword.kwlist: - if word[:n] == text: + if re.match(text, word[:n], flags=_re_ignorecase_flags): seen.add(word) if word in {'finally', 'try'}: word = word + ':' @@ -122,7 +127,8 @@ def global_matches(self, text): matches.append(word) for nspace in [self.namespace, builtins.__dict__]: for word, val in nspace.items(): - if word[:n] == text and word not in seen: + if (re.match(text, word[:n], flags=_re_ignorecase_flags) and + word not in seen): seen.add(word) matches.append(self._callable_postfix(val, word)) return matches @@ -166,7 +172,7 @@ def attr_matches(self, text): noprefix = None while True: for word in words: - if (word[:n] == attr and + if (re.match(attr, word[:n], flags=_re_ignorecase_flags) and not (noprefix and word[:n+1] == noprefix)): match = "%s.%s" % (expr, word) try: @@ -185,6 +191,12 @@ def attr_matches(self, text): matches.sort() return matches +_re_ignorecase_flags = 0 +def set_ignore_case(option): + import re + global _re_ignorecase_flags + _re_ignorecase_flags = re.IGNORECASE if option else 0 + def get_class_members(klass): ret = dir(klass) if hasattr(klass,'__bases__'): diff --git a/Lib/test/test_rlcompleter.py b/Lib/test/test_rlcompleter.py index 0dc1080ca32093..9c5a841b90e84f 100644 --- a/Lib/test/test_rlcompleter.py +++ b/Lib/test/test_rlcompleter.py @@ -137,5 +137,31 @@ def test_duplicate_globals(self): self.assertEqual(completer.complete('Ellipsis', 0), 'Ellipsis(') self.assertIsNone(completer.complete('Ellipsis', 1)) + def test_case_insentive_matches(self): + # add an additional attr for testing + CompleteMe.SpAm = 2 + # enable the case insensitive option + rlcompleter.set_ignore_case(True) + # test globals + self.assertEqual(self.completer.global_matches('completem'), + ['CompleteMe(']) + # test attr + self.assertNotEqual(self.completer.attr_matches('CompleteMe.spa'), + ['CompleteMe.spam', 'CompleteMe.SpAm']) + # disable the case insensitive option + rlcompleter.set_ignore_case(False) + # test globals + self.assertNotEqual(self.completer.global_matches('completem'), + ['CompleteMe(']) + self.assertEqual(self.completer.global_matches('CompleteM'), + ['CompleteMe(']) + # test attr + self.assertNotEqual(self.completer.attr_matches('CompleteMe.spa'), + ['CompleteMe.spam', 'CompleteMe.SpAm']) + self.assertEqual(self.completer.attr_matches('CompleteMe.sp'), + ['CompleteMe.spam']) + # delete the additional attr + del(CompleteMe.SpAm) + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2020-05-06-12-46-16.bpo-40529.cZSTKu.rst b/Misc/NEWS.d/next/Library/2020-05-06-12-46-16.bpo-40529.cZSTKu.rst new file mode 100644 index 00000000000000..a54c4e4bae71ec --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-05-06-12-46-16.bpo-40529.cZSTKu.rst @@ -0,0 +1 @@ +Added an option to the user to make rl completions with case insensitive / sensitive.