55
66import re
77
8+ current_word_re = re .compile (r'[\w_][\w0-9._]*[(]?' )
9+ current_dict_key_re = re .compile (r'''[\w_][\w0-9._]*\[([\w0-9._(), '"]*)''' )
10+ current_dict_re = re .compile (r'''([\w_][\w0-9._]*)\[([\w0-9._(), '"]*)''' )
11+ current_string_re = re .compile (
12+ '''(?P<open>(?:""")|"|(?:''\' )|')(?:((?P<closed>.+?)(?P=open))|(?P<unclosed>.+))''' )
13+ current_object_re = re .compile (r'([\w_][\w0-9_]*)[.]' )
14+ current_object_attribute_re = re .compile (r'([\w_][\w0-9_]*)[.]?' )
15+ current_from_import_from_re = re .compile (r'from ([\w0-9_.]*)(?:\s+import\s+([\w0-9_]+[,]?\s*)+)*' )
16+ current_from_import_import_re_1 = re .compile (r'from\s([\w0-9_.]*)\s+import' )
17+ current_from_import_import_re_2 = re .compile (r'([\w0-9_]+)' )
18+ current_from_import_import_re_3 = re .compile (r'[,][ ]([\w0-9_]*)' )
19+ current_import_re_1 = re .compile (r'import' )
20+ current_import_re_2 = re .compile (r'([\w0-9_.]+)' )
21+ current_import_re_3 = re .compile (r'[,][ ]([\w0-9_.]*)' )
22+ current_method_definition_name_re = re .compile ("def\s+([a-zA-Z_][\w]*)" )
23+ current_single_word_re = re .compile (r"(?<![.])\b([a-zA-Z_][\w]*)" )
24+ current_string_literal_attr_re = re .compile (
25+ "('''" +
26+ r'''|"""|'|")((?:(?=([^"'\\]+|\\.|(?!\1)["']))\3)*)\1[.]([a-zA-Z_]?[\w]*)''' )
27+
828def current_word (cursor_offset , line ):
929 """the object.attribute.attribute just before or under the cursor"""
1030 pos = cursor_offset
11- matches = list (re .finditer (r'[\w_][\w0-9._]*[(]?' , line ))
31+ matches = list (current_word_re .finditer (line ))
1232 start = pos
1333 end = pos
1434 word = None
@@ -23,15 +43,15 @@ def current_word(cursor_offset, line):
2343
2444def current_dict_key (cursor_offset , line ):
2545 """If in dictionary completion, return the current key"""
26- matches = list (re .finditer (r'''[\w_][\w0-9._]*\[([\w0-9._(), '"]*)''' , line ))
46+ matches = list (current_dict_key_re .finditer (line ))
2747 for m in matches :
2848 if m .start (1 ) <= cursor_offset and m .end (1 ) >= cursor_offset :
2949 return (m .start (1 ), m .end (1 ), m .group (1 ))
3050 return None
3151
3252def current_dict (cursor_offset , line ):
3353 """If in dictionary completion, return the dict that should be used"""
34- matches = list (re .finditer (r'''([\w_][\w0-9._]*)\[([\w0-9._(), '"]*)''' , line ))
54+ matches = list (current_dict_re .finditer (line ))
3555 for m in matches :
3656 if m .start (2 ) <= cursor_offset and m .end (2 ) >= cursor_offset :
3757 return (m .start (1 ), m .end (1 ), m .group (1 ))
@@ -42,7 +62,7 @@ def current_string(cursor_offset, line):
4262
4363 Weaker than bpython.Repl's current_string, because that checks that a string is a string
4464 based on previous lines in the buffer"""
45- for m in re .finditer ('''(?P<open>(?:""")|"|(?:'' \' )|')(?:((?P<closed>.+?)(?P=open))|(?P<unclosed>.+))''' , line ):
65+ for m in current_string_re .finditer (line ):
4666 i = 3 if m .group (3 ) else 4
4767 if m .start (i ) <= cursor_offset and m .end (i ) >= cursor_offset :
4868 return m .start (i ), m .end (i ), m .group (i )
@@ -53,7 +73,7 @@ def current_object(cursor_offset, line):
5373 match = current_word (cursor_offset , line )
5474 if match is None : return None
5575 start , end , word = match
56- matches = list (re .finditer (r'([\w_][\w0-9_]*)[.]' , word ))
76+ matches = list (current_object_re .finditer (word ))
5777 s = ''
5878 for m in matches :
5979 if m .end (1 ) + start < cursor_offset :
@@ -69,7 +89,7 @@ def current_object_attribute(cursor_offset, line):
6989 match = current_word (cursor_offset , line )
7090 if match is None : return None
7191 start , end , word = match
72- matches = list (re .finditer (r'([\w_][\w0-9_]*)[.]?' , word ))
92+ matches = list (current_object_attribute_re .finditer (word ))
7393 for m in matches [1 :]:
7494 if m .start (1 ) + start <= cursor_offset and m .end (1 ) + start >= cursor_offset :
7595 return m .start (1 ) + start , m .end (1 ) + start , m .group (1 )
@@ -85,7 +105,7 @@ def current_from_import_from(cursor_offset, line):
85105 tokens = line .split ()
86106 if not ('from' in tokens or 'import' in tokens ):
87107 return None
88- matches = list (re .finditer (r'from ([\w0-9_.]*)(?:\s+import\s+([\w0-9_]+[,]?\s*)+)*' , line ))
108+ matches = list (current_from_import_from_re .finditer (line ))
89109 for m in matches :
90110 if ((m .start (1 ) < cursor_offset and m .end (1 ) >= cursor_offset ) or
91111 (m .start (2 ) < cursor_offset and m .end (2 ) >= cursor_offset )):
@@ -97,13 +117,13 @@ def current_from_import_import(cursor_offset, line):
97117
98118 returns None if cursor not in or just after one of these words
99119 """
100- baseline = re .search (r'from\s([\w0-9_.]*)\s+import' , line )
120+ baseline = current_from_import_import_re_1 .search (line )
101121 if baseline is None :
102122 return None
103- match1 = re .search (r'([\w0-9_]+)' , line [baseline .end ():])
123+ match1 = current_from_import_import_re_2 .search (line [baseline .end ():])
104124 if match1 is None :
105125 return None
106- matches = list (re .finditer (r'[,][ ]([\w0-9_]*)' , line [baseline .end ():]))
126+ matches = list (current_from_import_import_re_3 .finditer (line [baseline .end ():]))
107127 for m in [match1 ] + matches :
108128 start = baseline .end () + m .start (1 )
109129 end = baseline .end () + m .end (1 )
@@ -113,13 +133,13 @@ def current_from_import_import(cursor_offset, line):
113133
114134def current_import (cursor_offset , line ):
115135 #TODO allow for multiple as's
116- baseline = re .search (r'import' , line )
136+ baseline = current_import_re_1 .search (line )
117137 if baseline is None :
118138 return None
119- match1 = re .search (r'([\w0-9_.]+)' , line [baseline .end ():])
139+ match1 = current_import_re_2 .search (line [baseline .end ():])
120140 if match1 is None :
121141 return None
122- matches = list (re .finditer (r'[,][ ]([\w0-9_.]*)' , line [baseline .end ():]))
142+ matches = list (current_import_re_3 .finditer (line [baseline .end ():]))
123143 for m in [match1 ] + matches :
124144 start = baseline .end () + m .start (1 )
125145 end = baseline .end () + m .end (1 )
@@ -128,15 +148,15 @@ def current_import(cursor_offset, line):
128148
129149def current_method_definition_name (cursor_offset , line ):
130150 """The name of a method being defined"""
131- matches = re .finditer ("def\s+([a-zA-Z_][\w]*)" , line )
151+ matches = current_method_definition_name_re .finditer (line )
132152 for m in matches :
133153 if (m .start (1 ) <= cursor_offset and m .end (1 ) >= cursor_offset ):
134154 return m .start (1 ), m .end (1 ), m .group (1 )
135155 return None
136156
137157def current_single_word (cursor_offset , line ):
138158 """the un-dotted word just before or under the cursor"""
139- matches = re .finditer (r"(?<![.])\b([a-zA-Z_][\w]*)" , line )
159+ matches = current_single_word_re .finditer (line )
140160 for m in matches :
141161 if (m .start (1 ) <= cursor_offset and m .end (1 ) >= cursor_offset ):
142162 return m .start (1 ), m .end (1 ), m .group (1 )
@@ -152,7 +172,7 @@ def current_dotted_attribute(cursor_offset, line):
152172
153173def current_string_literal_attr (cursor_offset , line ):
154174 """The attribute following a string literal"""
155- matches = re .finditer ("('''" + r'''|"""|'|")((?:(?=([^"'\\]+|\\.|(?!\1)["']))\3)*)\1[.]([a-zA-Z_]?[\w]*)''' , line )
175+ matches = current_string_literal_attr_re .finditer (line )
156176 for m in matches :
157177 if (m .start (4 ) <= cursor_offset and m .end (4 ) >= cursor_offset ):
158178 return m .start (4 ), m .end (4 ), m .group (4 )
0 commit comments