#!/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 ################################################################################