forked from shagabutdinov/sublime-local-variable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
extract_variable.py
152 lines (116 loc) · 4.46 KB
/
extract_variable.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
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
import sublime
import sublime_plugin
import re
from LocalVariable.local_variable import get_partial_statement, find_entries
try:
from Method import method
from Expression import expression
from Statement import statement
except ImportError as error:
sublime.error_message("Dependency import failed; please read readme for " +
"LocalVariable plugin for installation instructions; to disable this " +
"message remove this plugin; message: " + str(error))
raise error
class ExtractVariable(sublime_plugin.TextCommand):
def run(self, edit):
entries = None
if len(self.view.sel()) > 1:
entries = []
for overlap in self.view.sel():
entries.append([overlap.begin(), overlap.end()])
self._extract(edit, self.view.sel()[0], entries)
def _extract(self, edit, sel, entries):
if sel.empty():
variable = get_partial_statement(self.view, sel.b)
else:
variable = [sel.a, sel.b]
if variable == None:
return None
if entries == None:
entries = find_entries(self.view, variable, False)
if len(entries) == 0:
entries = [variable]
line_info = self._get_line_for_variables(entries)
if line_info == None:
return
line, indentation = line_info
self._create_variable(edit, line, entries, indentation)
def _get_line_for_variables(self, entries):
start = entries[0][0]
root_statement = statement.get_root_statement(self.view, start)
if root_statement == None:
return None
start = root_statement[0]
line, _ = self.view.rowcol(start)
indentation = self.get_indentation(start)
if not self.is_lesser_indentation_required(entries):
return line, indentation
while True:
previous_start = self.view.line(start).begin() - 1
if previous_start < 0:
return None
current = self.get_indentation(previous_start)
if len(current) < len(indentation):
line, _ = self.view.rowcol(self.view.line(previous_start).begin())
return line, current
start = previous_start
def is_lesser_indentation_required(self, entries):
if len(entries) == 1:
return False
start_line, _ = self.view.rowcol(entries[0][0])
lines = self.view.substr(self.view.line(sublime.Region(entries[0][0],
entries[len(entries) - 1][1])))
indentation = None
for index, line in enumerate(lines.split("\n")):
if line.strip() == '':
continue
point = self.view.text_point(start_line + index, 0)
in_nesting = expression.find_match(self.view, point, r'[\])]',
{'range': [point, point + 512]})
if in_nesting:
continue
if statement.is_arguments(self.view, point):
continue
current = len(self.get_indentation(line))
if indentation == None : # first overlap
indentation = current
if current < indentation:
return True
return False
def get_indentation(self, point):
if isinstance(point, str):
line = point
else:
line = self.view.substr(self.view.line(point))
return re.search(r'^\s*', line).group(0)
def _create_variable(self, edit, line, entries, indentation):
value = self.view.substr(sublime.Region(*entries[0]))
for index, overlap in enumerate(reversed(entries)):
self.view.replace(edit, sublime.Region(*overlap), '')
self.view.add_regions('local_variable_placeholder_' + str(index),
[sublime.Region(overlap[0], overlap[0])])
line_region = self.view.line(self.view.text_point(line, 0))
point = line_region.begin() - 1
offset = 0
if 'source.go' in self.view.scope_name(point):
definition = indentation + ' := ' + value + "\n"
elif 'source.js' in self.view.scope_name(point):
definition = indentation + 'var = ' + value + ";\n"
offset = 4
elif 'source.php' in self.view.scope_name(point):
definition = indentation + ' = ' + value + ";\n"
else:
definition = indentation + ' = ' + value + "\n"
if line != 0:
definition = "\n" + definition
self.view.replace(edit, sublime.Region(point, point + 1), definition)
point += len(indentation) + 1
self.view.add_regions('local_variable_placeholder_last',
[sublime.Region(point + offset, point + offset)])
self.view.sel().clear()
regions = []
for index, _ in enumerate(entries):
regions += self.view.get_regions('local_variable_placeholder_' +
str(index))
regions += self.view.get_regions('local_variable_placeholder_last')
self.view.sel().add_all(regions)