-
Notifications
You must be signed in to change notification settings - Fork 1
/
auto_select_lines.py
executable file
·81 lines (61 loc) · 2.72 KB
/
auto_select_lines.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#################################### IMPORTS ###################################
# Std Libs
import os
import sys
# Sublime Libs
import sublime
import sublime_plugin
#################################### HELPERS ###################################
def direction_iterator():
yield -1, 'backward', False
yield 1, 'forward', True
def x_key(view, r):
x,y = view.text_to_layout(r.begin())
return (x, (r, y))
################################### COMMANDS ###################################
class auto_select_lines(sublime_plugin.TextCommand):
def run(self, edit, check_scope=True):
"""
Stop conditions:
Different start x value
New area doesnt match start scope
Behind cursor is not space but is on new cursor
Behind cursor is space but behind new cursor isn't
Cursor is space but new cursor isn't
Cursor isn't space but new cursor is
"""
view = self.view
start_selections = list(view.sel())
line_height = view.line_height()
unique_pts_first_sels = dict( x_key(view, s) for s
in reversed(start_selections ))
additional_selections = []
x_extent, y_extent = view.layout_extent()
for leader_x_val, (leader_sel, leader_y) in unique_pts_first_sels.items():
leader_is_space = []
start_scope = view.scope_name(leader_sel.begin()).rstrip()
for offset in (0, -1):
leader_is_space.append (
view.substr(leader_sel.begin() + offset).isspace())
for direction, direction_repr, forward in direction_iterator():
n = 0
while True:
n+=1
y_offset = (n * direction * line_height)
y_val = leader_y + y_offset
if y_val < 0 or y_val > y_extent: break
# candidate point
cp = view.layout_to_text((leader_x_val, y_val))
check_x, check_y = view.text_to_layout(cp)
if check_x != leader_x_val: break
try:
for offset in (0, -1):
candidate_is_space = (view.substr(cp + offset)
.isspace())
if leader_is_space[offset] != candidate_is_space:
raise ValueError
except ValueError: break
if check_scope and not view.match_selector(cp, start_scope):
break
additional_selections.append(sublime.Region(cp))
view.sel().add_all(additional_selections)