@@ -197,6 +197,35 @@ def format(self, rgb, style=''):
197197
198198 return textFormat
199199
200+ def _iter_rule_matches (self , expression , text , nth ):
201+ if hasattr (expression , "indexIn" ):
202+ index = expression .indexIn (text , 0 )
203+ while index >= 0 :
204+ start = expression .pos (nth )
205+ length = len (expression .cap (nth ))
206+ if start >= 0 and length > 0 :
207+ yield start , length
208+ index = expression .indexIn (text , start + max (length , 1 ))
209+ else :
210+ matches = expression .globalMatch (text )
211+ while matches .hasNext ():
212+ match = matches .next ()
213+ start = match .capturedStart (nth )
214+ length = match .capturedLength (nth )
215+ if start >= 0 and length > 0 :
216+ yield start , length
217+
218+ def _regex_find (self , expression , text , start = 0 ):
219+ if hasattr (expression , "indexIn" ):
220+ index = expression .indexIn (text , start )
221+ if index >= 0 :
222+ return index , expression .matchedLength ()
223+ return - 1 , 0
224+ match = expression .match (text , start )
225+ if not match .hasMatch ():
226+ return - 1 , 0
227+ return match .capturedStart (0 ), match .capturedLength (0 )
228+
200229 def highlightBlock (self , text ):
201230 """
202231 Apply syntax highlighting to the given block of text.
@@ -207,14 +236,12 @@ def highlightBlock(self, text):
207236
208237 # apply rules
209238 for expression , nth , format in self .rules :
210- index = expression .indexIn (text , 0 )
211-
212- while index >= 0 :
213- # We actually want the index of the nth match
214- index = expression .pos (nth )
215- length = len (expression .cap (nth ))
239+ for index , length in self ._iter_rule_matches (
240+ expression ,
241+ text ,
242+ nth
243+ ):
216244 self .setFormat (index , length , format )
217- index = expression .indexIn (text , index + length )
218245
219246 # apply comment rule
220247 if '#' in text :
@@ -295,17 +322,19 @@ def match_multiline(self, text, delimiter, in_state, style):
295322 add = 0
296323 # Otherwise, look for the delimiter on this line
297324 else :
298- start = delimiter .indexIn (text )
299- # Move past this match
300- add = delimiter .matchedLength ()
325+ start , add = self ._regex_find (delimiter , text , 0 )
301326
302327 # As long as there's a delimiter match on this line...
303328 while start >= 0 :
304329 # Look for the ending delimiter
305- end = delimiter .indexIn (text , start + add )
330+ end , end_length = self ._regex_find (
331+ delimiter ,
332+ text ,
333+ start + add
334+ )
306335 # Ending delimiter on this line?
307336 if end >= add :
308- length = end - start + add + delimiter . matchedLength ()
337+ length = end - start + add + end_length
309338 self .setCurrentBlockState (0 )
310339 # No; multi-line string
311340 else :
@@ -314,7 +343,11 @@ def match_multiline(self, text, delimiter, in_state, style):
314343 # Apply formatting
315344 self .setFormat (start , length , style )
316345 # Look for the next match
317- start = delimiter .indexIn (text , start + length )
346+ start , add = self ._regex_find (
347+ delimiter ,
348+ text ,
349+ start + length
350+ )
318351
319352 # Return True if still inside a multi-line string
320353 return self .currentBlockState () == in_state
0 commit comments