-
-
Notifications
You must be signed in to change notification settings - Fork 87
Expand file tree
/
Copy pathview_utils.py
More file actions
185 lines (134 loc) · 5.11 KB
/
view_utils.py
File metadata and controls
185 lines (134 loc) · 5.11 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
from sublime import Region
from sublime import RegionFlags
__all__ = ['has_file_ext', 'base_scope',
'coorded_substr', 'get_text',
'get_viewport_coords', 'set_viewport',
'extract_selector']
def has_file_ext(view, ext):
"""Returns `True` if `view` has file extension `ext`.
`ext` may be specified with or without leading ".".
"""
if not view.file_name() or not ext.strip().replace('.', ''):
return False
if not ext.startswith('.'):
ext = '.' + ext
return view.file_name().endswith(ext)
def base_scope(view):
"""Returns the view's base scope.
"""
return view.scope_name(0).split(' ', 1)[0]
def rowcount(view):
"""Returns the 1-based number of rows in ``view``.
"""
return view.rowcol(view.size())[0] + 1
def rowwidth(view, row):
"""Returns the 1-based number of characters of ``row`` in ``view``.
"""
return view.rowcol(view.line(view.text_point(row, 0)).end())[1] + 1
def relative_point(view, row=0, col=0, p=None):
"""Returns a point (int) to the given coordinates.
Supports relative (negative) parameters and checks if they are in the
bounds (other than `View.text_point()`).
If p (indexable -> `p[0]`, `len(p) == 2`; preferrably a tuple) is
specified, row and col parameters are overridden.
"""
if p is not None:
if len(p) != 2:
raise TypeError("Coordinates have 2 dimensions, not %d" % len(p))
(row, col) = p
# shortcut
if row == -1 and col == -1:
return view.size()
# calc absolute coords and check if coords are in the bounds
rowc = rowcount(view)
if row < 0:
row = max(rowc + row, 0)
else:
row = min(row, rowc - 1)
roww = rowwidth(view, row)
if col < 0:
col = max(roww + col, 0)
else:
col = min(col, roww - 1)
return view.text_point(row, col)
def coorded_region(view, reg1=None, reg2=None, rel=None):
"""Turn two coordinate pairs into a region.
The pairs are checked for boundaries by `relative_point`.
You may also supply a `rel` parameter which will determine the
Region's end point relative to `reg1`, as a pair. The pairs are
supposed to be indexable and have a length of 2. Tuples are preferred.
Defaults to the whole buffer (`reg1=(0, 0), reg2=(-1, -1)`).
Examples:
coorded_region(view, (20, 0), (22, -1)) # normal usage
coorded_region(view, (20, 0), rel=(2, -1)) # relative, works because 0-1=-1
coorded_region(view, (22, 6), rel=(2, 15)) # relative, ~ more than 3 lines,
# if line 25 is long enough
"""
reg1 = reg1 or (0, 0)
if rel:
reg2 = (reg1[0] + rel[0], reg1[1] + rel[1])
else:
reg2 = reg2 or (-1, -1)
p1 = relative_point(view, p=reg1)
p2 = relative_point(view, p=reg2)
return Region(p1, p2)
def coorded_substr(view, reg1=None, reg2=None, rel=None):
"""Returns the string of two coordinate pairs forming a region.
The pairs are supporsed to be indexable and have a length of 2.
Tuples are preferred.
Defaults to the whole buffer.
For examples, see `coorded_region`.
"""
return view.substr(coorded_region(view, reg1, reg2))
def get_text(view):
"""Returns the whole string of a buffer. Alias for `coorded_substr(view)`.
"""
return coorded_substr(view)
def get_viewport_point(view):
"""Returns the text point of the current viewport.
"""
return view.layout_to_text(view.viewport_position())
def get_viewport_coords(view):
"""Returns the text coordinates of the current viewport.
"""
return view.rowcol(get_viewport_point(view))
def set_viewport(view, row, col=None):
"""Sets the current viewport from either a text point or relative coords.
set_viewport(view, 892) # point
set_viewport(view, 2, 27) # coords1
set_viewport(view, (2, 27)) # coords2
"""
if col is None:
pos = row
if isinstance(row, tuple):
pos = relative_point(view, p=row)
else:
pos = relative_point(view, row, col)
view.set_viewport_position(view.text_to_layout(pos))
def extract_selector(view, selector, point):
"""Works similar to view.extract_scope except that you may define the
selector (scope) on your own and it does not use the point's scope by
default.
Example:
extract_selector(view, "source string", view.sel()[0].begin())
Returns the Region for the out-most "source string" which contains the
beginning of the first selection.
"""
regs = view.find_by_selector(selector)
for reg in regs:
if reg.contains(point):
return reg
return None
def region_flags_from_strings(flag_names):
"""Convert a list of strings into ``sublime.RegionFlags`` object.
Note: Invalid flag names are silently ignored.
Example:
flags: sublime.RegionFlags = region_flags_from_strings(["DRAW_EMPTY", "DRAW_NO_FILL"])
"""
result = RegionFlags.NONE
for name in flag_names:
try:
result |= RegionFlags[name]
except KeyError:
continue
return result