66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			66 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python
 | |
| #coding: utf8
 | |
| #################################### IMPORTS ###################################
 | |
| 
 | |
| # Std Libs
 | |
| import re
 | |
| 
 | |
| # Sublime Libs
 | |
| import sublime
 | |
| import sublime_plugin
 | |
| 
 | |
| from collections import defaultdict
 | |
| 
 | |
| ################################### CONSTANTS ##################################
 | |
| 
 | |
| # Directions for tracker
 | |
| BACK         =  -1
 | |
| FORWARD      =   1
 | |
| 
 | |
| ###################### VIEW TRACKERS ( CONTEXT SCANNERS ) ######################
 | |
| 
 | |
| def pt_range(view, start_pt, direction):
 | |
|     end_pt = direction
 | |
|     if end_pt != -1: end_pt = view.size()
 | |
|     return xrange(start_pt, end_pt, direction)
 | |
| 
 | |
| def region_from_pt_list(l):
 | |
|     if l:
 | |
|         l = sorted(l)
 | |
|         return sublime.Region(l[0], l[-1]+1)
 | |
| 
 | |
| def view_tracker(view, start_pt, *conds):
 | |
|     pts = defaultdict(list)
 | |
|     failed = False
 | |
| 
 | |
|     for i, (direction, condition) in enumerate(conds):
 | |
|         for pt in pt_range(view, start_pt, direction):
 | |
|             if failed: break
 | |
| 
 | |
|             if not condition(view, pt):
 | |
|                 if not pts[i]: failed = True
 | |
|                 start_pt = pt
 | |
|                 break
 | |
| 
 | |
|             if len(pts[i]) < 2:
 | |
|                 pts[i].append(pt)
 | |
|             else:
 | |
|                 pts[i][-1] = pt
 | |
| 
 | |
|     return [ region_from_pt_list(pt_list) for pt_list in pts.values() ]
 | |
| 
 | |
| def tracker_success(regions):
 | |
|     return all(r is not None for r in regions)
 | |
| 
 | |
| def back_track(view, start_pt, *conds):
 | |
|     return view_tracker(view, start_pt -1, *((BACK, c) for c in conds))
 | |
| 
 | |
| ################################### TRACKERS ###################################
 | |
| 
 | |
| def track_regex(r, cond=True):
 | |
|     return lambda v, p: bool(re.match(r, v.substr(p))) is cond
 | |
| 
 | |
| def track_scope(s, cond=True):
 | |
|     return lambda v, p: bool(v.match_selector(p, s)) is cond
 | |
| 
 | |
| ################################################################################ |