Mercurial > cpython-lru_cache-weakref
annotate Mac/Tools/IDE/PyFontify.py @ 25838:8540887bcec6 2.2
Backport of 2.183:
Fix memory leak in add_subclass() found by NealN with valgrind.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Fri, 18 Oct 2002 13:42:21 +0000 |
| parents | e78a51268c81 |
| children | 71a294bd7950 |
| rev | line source |
|---|---|
| 10047 | 1 """Module to analyze Python source code; for syntax coloring tools. |
| 2 | |
| 3 Interface: | |
| 4 tags = fontify(pytext, searchfrom, searchto) | |
| 5 | |
| 6 The 'pytext' argument is a string containing Python source code. | |
| 7 The (optional) arguments 'searchfrom' and 'searchto' may contain a slice in pytext. | |
| 8 The returned value is a list of tuples, formatted like this: | |
| 9 [('keyword', 0, 6, None), ('keyword', 11, 17, None), ('comment', 23, 53, None), etc. ] | |
| 10 The tuple contents are always like this: | |
| 11 (tag, startindex, endindex, sublist) | |
| 12 tag is one of 'keyword', 'string', 'comment' or 'identifier' | |
| 13 sublist is not used, hence always None. | |
| 14 """ | |
| 15 | |
| 16 # Based on FontText.py by Mitchell S. Chapman, | |
| 17 # which was modified by Zachary Roadhouse, | |
| 18 # then un-Tk'd by Just van Rossum. | |
| 19 # Many thanks for regular expression debugging & authoring are due to: | |
| 20 # Tim (the-incredib-ly y'rs) Peters and Cristian Tismer | |
| 21 # So, who owns the copyright? ;-) How about this: | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
22 # Copyright 1996-2001: |
| 10047 | 23 # Mitchell S. Chapman, |
| 24 # Zachary Roadhouse, | |
| 25 # Tim Peters, | |
| 26 # Just van Rossum | |
| 27 | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
28 __version__ = "0.4" |
| 10047 | 29 |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
30 import string |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
31 import re |
| 10047 | 32 |
| 33 # First a little helper, since I don't like to repeat things. (Tismer speaking) | |
| 34 import string | |
| 35 def replace(where, what, with): | |
| 36 return string.join(string.split(where, what), with) | |
| 37 | |
| 38 # This list of keywords is taken from ref/node13.html of the | |
| 39 # Python 1.3 HTML documentation. ("access" is intentionally omitted.) | |
| 40 keywordsList = [ | |
|
12305
1f7c32801dc1
oops, keyword list missed exec... doh! thanks to Maik Roeder (jvr)
Just van Rossum <just@lettererror.com>
parents:
10047
diff
changeset
|
41 "assert", "exec", |
| 10047 | 42 "del", "from", "lambda", "return", |
| 43 "and", "elif", "global", "not", "try", | |
| 44 "break", "else", "if", "or", "while", | |
| 45 "class", "except", "import", "pass", | |
| 46 "continue", "finally", "in", "print", | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
47 "def", "for", "is", "raise", "yield"] |
| 10047 | 48 |
| 49 # Build up a regular expression which will match anything | |
| 50 # interesting, including multi-line triple-quoted strings. | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
51 commentPat = r"#[^\n]*" |
| 10047 | 52 |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
53 pat = r"q[^\\q\n]*(\\[\000-\377][^\\q\n]*)*q" |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
54 quotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"') |
| 10047 | 55 |
| 56 # Way to go, Tim! | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
57 pat = r""" |
| 10047 | 58 qqq |
| 59 [^\\q]* | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
60 ( |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
61 ( \\[\000-\377] |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
62 | q |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
63 ( \\[\000-\377] |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
64 | [^\q] |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
65 | q |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
66 ( \\[\000-\377] |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
67 | [^\\q] |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
68 ) |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
69 ) |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
70 ) |
| 10047 | 71 [^\\q]* |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
72 )* |
| 10047 | 73 qqq |
| 74 """ | |
| 75 pat = string.join(string.split(pat), '') # get rid of whitespace | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
76 tripleQuotePat = replace(pat, "q", "'") + "|" + replace(pat, 'q', '"') |
| 10047 | 77 |
| 78 # Build up a regular expression which matches all and only | |
| 79 # Python keywords. This will let us skip the uninteresting | |
| 80 # identifier references. | |
| 81 # nonKeyPat identifies characters which may legally precede | |
| 82 # a keyword pattern. | |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
83 nonKeyPat = r"(^|[^a-zA-Z0-9_.\"'])" |
| 10047 | 84 |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
85 keyPat = nonKeyPat + "(" + "|".join(keywordsList) + ")" + nonKeyPat |
| 10047 | 86 |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
87 matchPat = commentPat + "|" + keyPat + "|" + tripleQuotePat + "|" + quotePat |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
13291
diff
changeset
|
88 matchRE = re.compile(matchPat) |
| 10047 | 89 |
| 90 idKeyPat = "[ \t]*[A-Za-z_][A-Za-z_0-9.]*" # Ident w. leading whitespace. | |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
13291
diff
changeset
|
91 idRE = re.compile(idKeyPat) |
| 10047 | 92 |
| 93 | |
| 94 def fontify(pytext, searchfrom = 0, searchto = None): | |
| 95 if searchto is None: | |
| 96 searchto = len(pytext) | |
| 97 # Cache a few attributes for quicker reference. | |
| 98 search = matchRE.search | |
| 99 idSearch = idRE.search | |
| 100 | |
| 101 tags = [] | |
| 102 tags_append = tags.append | |
| 103 commentTag = 'comment' | |
| 104 stringTag = 'string' | |
| 105 keywordTag = 'keyword' | |
| 106 identifierTag = 'identifier' | |
| 107 | |
| 108 start = 0 | |
| 109 end = searchfrom | |
| 110 while 1: | |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
13291
diff
changeset
|
111 m = search(pytext, end) |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
112 if m is None: |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
113 break # EXIT LOOP |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
114 start = m.start() |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
115 if start >= searchto: |
| 10047 | 116 break # EXIT LOOP |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
13291
diff
changeset
|
117 match = m.group(0) |
| 10047 | 118 end = start + len(match) |
| 119 c = match[0] | |
| 120 if c not in "#'\"": | |
| 121 # Must have matched a keyword. | |
| 122 if start <> searchfrom: | |
| 123 # there's still a redundant char before and after it, strip! | |
| 124 match = match[1:-1] | |
| 125 start = start + 1 | |
| 126 else: | |
| 127 # this is the first keyword in the text. | |
| 128 # Only a space at the end. | |
| 129 match = match[:-1] | |
| 130 end = end - 1 | |
| 131 tags_append((keywordTag, start, end, None)) | |
| 132 # If this was a defining keyword, look ahead to the | |
| 133 # following identifier. | |
| 134 if match in ["def", "class"]: | |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
13291
diff
changeset
|
135 m = idSearch(pytext, end) |
|
18453
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
136 if m is not None: |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
137 start = m.start() |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
138 if start == end: |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
139 match = m.group(0) |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
140 end = start + len(match) |
|
e78a51268c81
- fixed some re usage, partly so it'll still work when re uses pre instead
Just van Rossum <just@letterror.com>
parents:
16725
diff
changeset
|
141 tags_append((identifierTag, start, end, None)) |
| 10047 | 142 elif c == "#": |
| 143 tags_append((commentTag, start, end, None)) | |
| 144 else: | |
| 145 tags_append((stringTag, start, end, None)) | |
| 146 return tags | |
| 147 | |
| 148 | |
| 149 def test(path): | |
| 150 f = open(path) | |
| 151 text = f.read() | |
| 152 f.close() | |
| 153 tags = fontify(text) | |
| 154 for tag, start, end, sublist in tags: | |
| 155 print tag, `text[start:end]` |
