| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -613,6 +613,12 @@ keywords, builtin class and function names, names following ``class`` and | |||
| 613 | 613 | ``def``, strings, and comments. For any text window, these are the cursor (when | |
| 614 | 614 | present), found text (when possible), and selected text. | |
| 615 | 615 | ||
| 616 | + IDLE also highlights the :ref:`soft keywords <soft-keywords>` :keyword:`match`, | ||
| 617 | + :keyword:`case <match>`, and :keyword:`_ <wildcard-patterns>` in | ||
| 618 | + pattern-matching statements. However, this highlighting is not perfect and | ||
| 619 | + will be incorrect in some rare cases, including some ``_``-s in ``case`` | ||
| 620 | + patterns. | ||
| 621 | + | ||
| 616 | 622 | Text coloring is done in the background, so uncolorized text is occasionally | |
| 617 | 623 | visible. To change the color scheme, use the Configure IDLE dialog | |
| 618 | 624 | Highlighting tab. The marking of debugger breakpoint lines in the editor and | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1030,6 +1030,12 @@ Terry Jan Reedy in :issue:`37892`.) | |||
| 1030 | 1030 | We expect to backport these shell changes to a future 3.9 maintenance | |
| 1031 | 1031 | release. | |
| 1032 | 1032 | ||
| 1033 | + Highlight the new :ref:`soft keywords <soft-keywords>` :keyword:`match`, | ||
| 1034 | + :keyword:`case <match>`, and :keyword:`_ <wildcard-patterns>` in | ||
| 1035 | + pattern-matching statements. However, this highlighting is not perfect | ||
| 1036 | + and will be incorrect in some rare cases, including some ``_``-s in | ||
| 1037 | + ``case`` patterns. (Contributed by Tal Einat in bpo-44010.) | ||
| 1038 | + | ||
| 1033 | 1039 | importlib.metadata | |
| 1034 | 1040 | ------------------ | |
| 1035 | 1041 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,6 +16,32 @@ def any(name, alternates): | |||
| 16 | 16 | ||
| 17 | 17 | def make_pat(): | |
| 18 | 18 | kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" | |
| 19 | + match_softkw = ( | ||
| 20 | + r"^[ \t]*" + # at beginning of line + possible indentation | ||
| 21 | + r"(?P<MATCH_SOFTKW>match)\b" + | ||
| 22 | + r"(?![ \t]*(?:" + "|".join([ # not followed by ... | ||
| 23 | + r"[:,;=^&|@~)\]}]", # a character which means it can't be a | ||
| 24 | + # pattern-matching statement | ||
| 25 | + r"\b(?:" + r"|".join(keyword.kwlist) + r")\b", # a keyword | ||
| 26 | + ]) + | ||
| 27 | + r"))" | ||
| 28 | + ) | ||
| 29 | + case_default = ( | ||
| 30 | + r"^[ \t]*" + # at beginning of line + possible indentation | ||
| 31 | + r"(?P<CASE_SOFTKW>case)" + | ||
| 32 | + r"[ \t]+(?P<CASE_DEFAULT_UNDERSCORE>_\b)" | ||
| 33 | + ) | ||
| 34 | + case_softkw_and_pattern = ( | ||
| 35 | + r"^[ \t]*" + # at beginning of line + possible indentation | ||
| 36 | + r"(?P<CASE_SOFTKW2>case)\b" + | ||
| 37 | + r"(?![ \t]*(?:" + "|".join([ # not followed by ... | ||
| 38 | + r"_\b", # a lone underscore | ||
| 39 | + r"[:,;=^&|@~)\]}]", # a character which means it can't be a | ||
| 40 | + # pattern-matching case | ||
| 41 | + r"\b(?:" + r"|".join(keyword.kwlist) + r")\b", # a keyword | ||
| 42 | + ]) + | ||
| 43 | + r"))" | ||
| 44 | + ) | ||
| 19 | 45 | builtinlist = [str(name) for name in dir(builtins) | |
| 20 | 46 | if not name.startswith('_') and | |
| 21 | 47 | name not in keyword.kwlist] | |
@@ -27,12 +53,29 @@ def make_pat(): | |||
| 27 | 53 | sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?" | |
| 28 | 54 | dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?' | |
| 29 | 55 | string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) | |
| 30 | - return (kw + "|" + builtin + "|" + comment + "|" + string + | ||
| 31 | - "|" + any("SYNC", [r"\n"])) | ||
| 56 | + prog = re.compile("|".join([ | ||
| 57 | + builtin, comment, string, kw, | ||
| 58 | + match_softkw, case_default, | ||
| 59 | + case_softkw_and_pattern, | ||
| 60 | + any("SYNC", [r"\n"]), | ||
| 61 | + ]), | ||
| 62 | + re.DOTALL | re.MULTILINE) | ||
| 63 | + return prog | ||
| 32 | 64 | ||
| 33 | 65 | ||
| 34 | - prog = re.compile(make_pat(), re.S) | ||
| 35 | - idprog = re.compile(r"\s+(\w+)", re.S) | ||
| 66 | + prog = make_pat() | ||
| 67 | + idprog = re.compile(r"\s+(\w+)") | ||
| 68 | + prog_group_name_to_tag = { | ||
| 69 | + "MATCH_SOFTKW": "KEYWORD", | ||
| 70 | + "CASE_SOFTKW": "KEYWORD", | ||
| 71 | + "CASE_DEFAULT_UNDERSCORE": "KEYWORD", | ||
| 72 | + "CASE_SOFTKW2": "KEYWORD", | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + | ||
| 76 | + def matched_named_groups(re_match): | ||
| 77 | + "Get only the non-empty named groups from an re.Match object." | ||
| 78 | + return ((k, v) for (k, v) in re_match.groupdict().items() if v) | ||
| 36 | 79 | ||
| 37 | 80 | ||
| 38 | 81 | def color_config(text): | |
@@ -231,14 +274,10 @@ def recolorize(self): | |||
| 231 | 274 | def recolorize_main(self): | |
| 232 | 275 | "Evaluate text and apply colorizing tags." | |
| 233 | 276 | next = "1.0" | |
| 234 | - while True: | ||
| 235 | - item = self.tag_nextrange("TODO", next) | ||
| 236 | - if not item: | ||
| 237 | - break | ||
| 238 | - head, tail = item | ||
| 239 | - self.tag_remove("SYNC", head, tail) | ||
| 240 | - item = self.tag_prevrange("SYNC", head) | ||
| 241 | - head = item[1] if item else "1.0" | ||
| 277 | + while todo_tag_range := self.tag_nextrange("TODO", next): | ||
| 278 | + self.tag_remove("SYNC", todo_tag_range[0], todo_tag_range[1]) | ||
| 279 | + sync_tag_range = self.tag_prevrange("SYNC", todo_tag_range[0]) | ||
| 280 | + head = sync_tag_range[1] if sync_tag_range else "1.0" | ||
| 242 | 281 | ||
| 243 | 282 | chars = "" | |
| 244 | 283 | next = head | |
@@ -256,23 +295,8 @@ def recolorize_main(self): | |||
| 256 | 295 | return | |
| 257 | 296 | for tag in self.tagdefs: | |
| 258 | 297 | self.tag_remove(tag, mark, next) | |
| 259 | - chars = chars + line | ||
| 260 | - m = self.prog.search(chars) | ||
| 261 | - while m: | ||
| 262 | - for key, value in m.groupdict().items(): | ||
| 263 | - if value: | ||
| 264 | - a, b = m.span(key) | ||
| 265 | - self.tag_add(key, | ||
| 266 | - head + "+%dc" % a, | ||
| 267 | - head + "+%dc" % b) | ||
| 268 | - if value in ("def", "class"): | ||
| 269 | - m1 = self.idprog.match(chars, b) | ||
| 270 | - if m1: | ||
| 271 | - a, b = m1.span(1) | ||
| 272 | - self.tag_add("DEFINITION", | ||
| 273 | - head + "+%dc" % a, | ||
| 274 | - head + "+%dc" % b) | ||
| 275 | - m = self.prog.search(chars, m.end()) | ||
| 298 | + chars += line | ||
| 299 | + self._add_tags_in_section(chars, head) | ||
| 276 | 300 | if "SYNC" in self.tag_names(next + "-1c"): | |
| 277 | 301 | head = next | |
| 278 | 302 | chars = "" | |
@@ -291,6 +315,40 @@ def recolorize_main(self): | |||
| 291 | 315 | if DEBUG: print("colorizing stopped") | |
| 292 | 316 | return | |
| 293 | 317 | ||
| 318 | + def _add_tag(self, start, end, head, matched_group_name): | ||
| 319 | + """Add a tag to a given range in the text widget. | ||
| 320 | + | ||
| 321 | + This is a utility function, receiving the range as `start` and | ||
| 322 | + `end` positions, each of which is a number of characters | ||
| 323 | + relative to the given `head` index in the text widget. | ||
| 324 | + | ||
| 325 | + The tag to add is determined by `matched_group_name`, which is | ||
| 326 | + the name of a regular expression "named group" as matched by | ||
| 327 | + by the relevant highlighting regexps. | ||
| 328 | + """ | ||
| 329 | + tag = prog_group_name_to_tag.get(matched_group_name, | ||
| 330 | + matched_group_name) | ||
| 331 | + self.tag_add(tag, | ||
| 332 | + f"{head}+{start:d}c", | ||
| 333 | + f"{head}+{end:d}c") | ||
| 334 | + | ||
| 335 | + def _add_tags_in_section(self, chars, head): | ||
| 336 | + """Parse and add highlighting tags to a given part of the text. | ||
| 337 | + | ||
| 338 | + `chars` is a string with the text to parse and to which | ||
| 339 | + highlighting is to be applied. | ||
| 340 | + | ||
| 341 | + `head` is the index in the text widget where the text is found. | ||
| 342 | + """ | ||
| 343 | + for m in self.prog.finditer(chars): | ||
| 344 | + for name, matched_text in matched_named_groups(m): | ||
| 345 | + a, b = m.span(name) | ||
| 346 | + self._add_tag(a, b, head, name) | ||
| 347 | + if matched_text in ("def", "class"): | ||
| 348 | + if m1 := self.idprog.match(chars, b): | ||
| 349 | + a, b = m1.span(1) | ||
| 350 | + self._add_tag(a, b, head, "DEFINITION") | ||
| 351 | + | ||
| 294 | 352 | def removecolors(self): | |
| 295 | 353 | "Remove all colorizing tags." | |
| 296 | 354 | for tag in self.tagdefs: | |
@@ -299,27 +357,14 @@ def removecolors(self): | |||
| 299 | 357 | ||
| 300 | 358 | def _color_delegator(parent): # htest # | |
| 301 | 359 | from tkinter import Toplevel, Text | |
| 360 | + from idlelib.idle_test.test_colorizer import source | ||
| 302 | 361 | from idlelib.percolator import Percolator | |
| 303 | 362 | ||
| 304 | 363 | top = Toplevel(parent) | |
| 305 | 364 | top.title("Test ColorDelegator") | |
| 306 | 365 | x, y = map(int, parent.geometry().split('+')[1:]) | |
| 307 | - top.geometry("700x250+%d+%d" % (x + 20, y + 175)) | ||
| 308 | - source = ( | ||
| 309 | - "if True: int ('1') # keyword, builtin, string, comment\n" | ||
| 310 | - "elif False: print(0)\n" | ||
| 311 | - "else: float(None)\n" | ||
| 312 | - "if iF + If + IF: 'keyword matching must respect case'\n" | ||
| 313 | - "if'': x or'' # valid keyword-string no-space combinations\n" | ||
| 314 | - "async def f(): await g()\n" | ||
| 315 | - "# All valid prefixes for unicode and byte strings should be colored.\n" | ||
| 316 | - "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" | ||
| 317 | - "r'x', u'x', R'x', U'x', f'x', F'x'\n" | ||
| 318 | - "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" | ||
| 319 | - "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'\n" | ||
| 320 | - "# Invalid combinations of legal characters should be half colored.\n" | ||
| 321 | - "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" | ||
| 322 | - ) | ||
| 366 | + top.geometry("700x550+%d+%d" % (x + 20, y + 175)) | ||
| 367 | + | ||
| 323 | 368 | text = Text(top, background="white") | |
| 324 | 369 | text.pack(expand=1, fill="both") | |
| 325 | 370 | text.insert("insert", source) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,7 +5,7 @@ | |||
| 5 | 5 | <head> | |
| 6 | 6 | <meta charset="utf-8" /> | |
| 7 | 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| 8 | - <title>IDLE — Python 3.10.0a6 documentation</title> | ||
| 8 | + <title>IDLE — Python 3.11.0a0 documentation</title> | ||
| 9 | 9 | <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" /> | |
| 10 | 10 | <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> | |
| 11 | 11 | ||
@@ -18,7 +18,7 @@ | |||
| 18 | 18 | <script src="../_static/sidebar.js"></script> | |
| 19 | 19 | ||
| 20 | 20 | <link rel="search" type="application/opensearchdescription+xml" | |
| 21 | - title="Search within Python 3.10.0a6 documentation" | ||
| 21 | + title="Search within Python 3.11.0a0 documentation" | ||
| 22 | 22 | href="../_static/opensearch.xml"/> | |
| 23 | 23 | <link rel="author" title="About these documents" href="../about.html" /> | |
| 24 | 24 | <link rel="index" title="Index" href="../genindex.html" /> | |
@@ -71,7 +71,7 @@ <h3>Navigation</h3> | |||
| 71 | 71 | ||
| 72 | 72 | ||
| 73 | 73 | <li id="cpython-language-and-version"> | |
| 74 | - <a href="../index.html">3.10.0a6 Documentation</a> » | ||
| 74 | + <a href="../index.html">3.11.0a0 Documentation</a> » | ||
| 75 | 75 | </li> | |
| 76 | 76 | ||
| 77 | 77 | <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> | |
@@ -102,7 +102,7 @@ <h3>Navigation</h3> | |||
| 102 | 102 | ||
| 103 | 103 | <div class="section" id="idle"> | |
| 104 | 104 | <span id="id1"></span><h1>IDLE<a class="headerlink" href="#idle" title="Permalink to this headline">¶</a></h1> | |
| 105 | - <p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/master/Lib/idlelib/">Lib/idlelib/</a></p> | ||
| 105 | + <p><strong>Source code:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/main/Lib/idlelib/">Lib/idlelib/</a></p> | ||
| 106 | 106 | <hr class="docutils" id="index-0" /> | |
| 107 | 107 | <p>IDLE is Python’s Integrated Development and Learning Environment.</p> | |
| 108 | 108 | <p>IDLE has the following features:</p> | |
@@ -581,6 +581,11 @@ <h3>Text colors<a class="headerlink" href="#text-colors" title="Permalink to thi | |||
| 581 | 581 | keywords, builtin class and function names, names following <code class="docutils literal notranslate"><span class="pre">class</span></code> and | |
| 582 | 582 | <code class="docutils literal notranslate"><span class="pre">def</span></code>, strings, and comments. For any text window, these are the cursor (when | |
| 583 | 583 | present), found text (when possible), and selected text.</p> | |
| 584 | + <p>IDLE also highlights the <a class="reference internal" href="../reference/lexical_analysis.html#soft-keywords"><span class="std std-ref">soft keywords</span></a> <a class="reference internal" href="../reference/compound_stmts.html#match"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">match</span></code></a>, | ||
| 585 | + <a class="reference internal" href="../reference/compound_stmts.html#match"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">case</span></code></a>, and <a class="reference internal" href="../reference/compound_stmts.html#wildcard-patterns"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">_</span></code></a> in | ||
| 586 | + pattern-matching statements. However, this highlighting is not perfect and | ||
| 587 | + will be incorrect in some rare cases, including some <code class="docutils literal notranslate"><span class="pre">_</span></code>-s in <code class="docutils literal notranslate"><span class="pre">case</span></code> | ||
| 588 | + patterns.</p> | ||
| 584 | 589 | <p>Text coloring is done in the background, so uncolorized text is occasionally | |
| 585 | 590 | visible. To change the color scheme, use the Configure IDLE dialog | |
| 586 | 591 | Highlighting tab. The marking of debugger breakpoint lines in the editor and | |
@@ -685,7 +690,7 @@ <h3>Running user code<a class="headerlink" href="#running-user-code" title="Perm | |||
| 685 | 690 | directly with Python in a text-mode system console or terminal window. | |
| 686 | 691 | However, the different interface and operation occasionally affect | |
| 687 | 692 | visible results. For instance, <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> starts with more entries, | |
| 688 | - and <code class="docutils literal notranslate"><span class="pre">threading.activeCount()</span></code> returns 2 instead of 1.</p> | ||
| 693 | + and <code class="docutils literal notranslate"><span class="pre">threading.active_count()</span></code> returns 2 instead of 1.</p> | ||
| 689 | 694 | <p>By default, IDLE runs user code in a separate OS process rather than in | |
| 690 | 695 | the user interface process that runs the shell and editor. In the execution | |
| 691 | 696 | process, it replaces <code class="docutils literal notranslate"><span class="pre">sys.stdin</span></code>, <code class="docutils literal notranslate"><span class="pre">sys.stdout</span></code>, and <code class="docutils literal notranslate"><span class="pre">sys.stderr</span></code> | |
@@ -939,7 +944,7 @@ <h3>This Page</h3> | |||
| 939 | 944 | <ul class="this-page-menu"> | |
| 940 | 945 | <li><a href="../bugs.html">Report a Bug</a></li> | |
| 941 | 946 | <li> | |
| 942 | - <a href="https://github.com/python/cpython/blob/master/Doc/library/idle.rst" | ||
| 947 | + <a href="https://github.com/python/cpython/blob/main/Doc/library/idle.rst" | ||
| 943 | 948 | rel="nofollow">Show Source | |
| 944 | 949 | </a> | |
| 945 | 950 | </li> | |
@@ -971,7 +976,7 @@ <h3>Navigation</h3> | |||
| 971 | 976 | ||
| 972 | 977 | ||
| 973 | 978 | <li id="cpython-language-and-version"> | |
| 974 | - <a href="../index.html">3.10.0a6 Documentation</a> » | ||
| 979 | + <a href="../index.html">3.11.0a0 Documentation</a> » | ||
| 975 | 980 | </li> | |
| 976 | 981 | ||
| 977 | 982 | <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> | |
@@ -997,13 +1002,19 @@ <h3>Navigation</h3> | |||
| 997 | 1002 | <div class="footer"> | |
| 998 | 1003 | © <a href="../copyright.html">Copyright</a> 2001-2021, Python Software Foundation. | |
| 999 | 1004 | <br /> | |
| 1005 | + This page is licensed under the Python Software Foundation License Version 2. | ||
| 1006 | + <br /> | ||
| 1007 | + Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License. | ||
| 1008 | + <br /> | ||
| 1009 | + See <a href="">History and License</a> for more information. | ||
| 1010 | + <br /><br /> | ||
| 1000 | 1011 | ||
| 1001 | 1012 | The Python Software Foundation is a non-profit corporation. | |
| 1002 | 1013 | <a href="https://www.python.org/psf/donations/">Please donate.</a> | |
| 1003 | 1014 | <br /> | |
| 1004 | 1015 | <br /> | |
| 1005 | 1016 | ||
| 1006 | - Last updated on Mar 29, 2021. | ||
| 1017 | + Last updated on May 11, 2021. | ||
| 1007 | 1018 | <a href="https://docs.python.org/3/bugs.html">Found a bug</a>? | |
| 1008 | 1019 | <br /> | |
| 1009 | 1020 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments