Krita Source Code Documentation
Loading...
Searching...
No Matches
indenter.py
Go to the documentation of this file.
2# SPDX-License-Identifier: GPL-3.0-or-later
3#
4
5import re
6
7from rope.base import codeanalyze
8
9
10class TextIndenter(object):
11
12 """A class for formatting texts"""
13
14 def __init__(self, editor, indents=4):
15 self.editor = editor
16 self.indents = indents
17 self.line_editor = editor.line_editor()
18
19 def correct_indentation(self, lineno):
20 """Correct the indentation of a line"""
21
22 def deindent(self, lineno):
23 """Deindent the a line"""
24 current_indents = self._count_line_indents(lineno)
25 new_indents = max(0, current_indents - self.indents)
26 self._set_line_indents(lineno, new_indents)
27
28 def indent(self, lineno):
29 """Indent a line"""
30 current_indents = self._count_line_indents(lineno)
31 new_indents = current_indents + self.indents
32 self._set_line_indents(lineno, new_indents)
33
34 def entering_new_line(self, lineno):
35 """Indent a line
36
37 Uses `correct_indentation` and last line indents
38 """
39 last_line = ""
40 if lineno > 1:
41 last_line = self.line_editor.get_line(lineno - 1)
42 if last_line.strip() == '':
43 self._set_line_indents(lineno, len(last_line))
44 else:
45 self.correct_indentation(lineno)
46
47 def insert_tab(self, index):
48 """Inserts a tab in the given index"""
49 self.editor.insert(index, ' ' * self.indents)
50
51 def _set_line_indents(self, lineno, indents):
52 old_indents = self._count_line_indents(lineno)
53 indent_diffs = indents - old_indents
54 self.line_editor.indent_line(lineno, indent_diffs)
55
56 def _count_line_indents(self, lineno):
57 contents = self.line_editor.get_line(lineno)
58 result = 0
59 for x in contents:
60 if x == ' ':
61 result += 1
62 elif x == '\t':
63 result += 8
64 else:
65 break
66 return result
67
68
70
71 def __init__(self, editor):
72 super(NormalIndenter, self).__init__(editor)
73
74 def correct_indentation(self, lineno):
75 prev_indents = 0
76 if lineno > 1:
77 prev_indents = self._count_line_indents(lineno - 1)
78 self._set_line_indents(lineno, prev_indents)
79
80
82
83 def __init__(self, editor, indents=4):
84 super(PythonCodeIndenter, self).__init__(editor, indents)
85
86 def _last_non_blank(self, lineno):
87 current_line = lineno - 1
88 while current_line != 1 and \
89 self.line_editorline_editor.get_line(current_line).strip() == '':
90 current_line -= 1
91 return current_line
92
93 def _get_correct_indentation(self, lineno):
94 if lineno == 1:
95 return 0
96 new_indent = self._get_base_indentation(lineno)
97
98 prev_lineno = self._last_non_blank(lineno)
99 prev_line = self.line_editorline_editor.get_line(prev_lineno)
100 if prev_lineno == lineno or prev_line.strip() == '':
101 new_indent = 0
102 current_line = self.line_editorline_editor.get_line(lineno)
103 new_indent += self._indents_caused_by_current_stmt(current_line)
104 return new_indent
105
106 def _get_base_indentation(self, lineno):
107 range_finder = _StatementRangeFinder(
109 start = range_finder.get_statement_start()
110 if not range_finder.is_line_continued():
111 changes = self._indents_caused_by_prev_stmt(
112 (start, self._last_non_blank(lineno)))
113 return self._count_line_indents(start) + changes
114 if range_finder.last_open_parens():
115 open_parens = range_finder.last_open_parens()
116 parens_line = self.line_editorline_editor.get_line(open_parens[0])
117 if parens_line[open_parens[1] + 1:].strip() == '':
118 if len(range_finder.open_parens) > 1:
119 return range_finder.open_parens[-2][1] + 1
120 else:
121 return self._count_line_indents(start) + self.indents
122 return range_finder.last_open_parens()[1] + 1
123
124 start_line = self.line_editorline_editor.get_line(start)
125 if start == lineno - 1:
126 try:
127 equals_index = start_line.index(' = ') + 1
128 if start_line[equals_index + 1:].strip() == '\\':
129 return self._count_line_indents(start) + self.indents
130 return equals_index + 2
131 except ValueError:
132 match = re.search(r'(\b )|(\.)', start_line)
133 if match:
134 return match.start() + 1
135 else:
136 return len(start_line) + 1
137 else:
138 return self._count_line_indents(self._last_non_blank(lineno))
139
140 def _indents_caused_by_prev_stmt(self, stmt_range):
141 first_line = self.line_editorline_editor.get_line(stmt_range[0])
142 last_line = self.line_editorline_editor.get_line(stmt_range[1])
143 new_indent = 0
144 if self._strip(last_line).endswith(':'):
145 new_indent += self.indents
146 if self._startswith(first_line, ('return', 'raise', 'pass',
147 'break', 'continue')):
148 new_indent -= self.indents
149 return new_indent
150
151 def _startswith(self, line, tokens):
152 line = self._strip(line)
153 for token in tokens:
154 if line == token or line.startswith(token + ' '):
155 return True
156
157 def _strip(self, line):
158 try:
159 numsign = line.rindex('#')
160 comment = line[numsign:]
161 if '\'' not in comment and '\"' not in comment:
162 line = line[:numsign]
163 except ValueError:
164 pass
165 return line.strip()
166
167 def _indents_caused_by_current_stmt(self, current_line):
168 new_indent = 0
169 if self._strip(current_line) == 'else:':
170 new_indent -= self.indents
171 if self._strip(current_line) == 'finally:':
172 new_indent -= self.indents
173 if self._startswith(current_line, ('elif',)):
174 new_indent -= self.indents
175 if self._startswith(current_line, ('except',)) and \
176 self._strip(current_line).endswith(':'):
177 new_indent -= self.indents
178 return new_indent
179
180 def correct_indentation(self, lineno):
181 """Correct the indentation of the line containing the given index"""
182 self._set_line_indents(lineno, self._get_correct_indentation(lineno))
183
184
186
187 """A method object for finding the range of a statement"""
188
189 def __init__(self, lines, lineno):
190 self.lines = lines
191 self.lineno = lineno
192 self.in_string = ''
193 self.open_count = 0
195 self.open_parens = []
196 self._analyze()
197
198 def _analyze_line(self, lineno):
199 current_line = self.lines.get_line(lineno)
200 for i, char in enumerate(current_line):
201 if char in '\'"':
202 if self.in_string == '':
203 self.in_string = char
204 if char * 3 == current_line[i:i + 3]:
205 self.in_string = char * 3
206 elif self.in_string == current_line[i:i + len(self.in_string)] and \
207 not (i > 0 and current_line[i - 1] == '\\' and
208 not (i > 1 and current_line[i - 2:i] == '\\\\')):
209 self.in_string = ''
210 if self.in_string != '':
211 continue
212 if char == '#':
213 break
214 if char in '([{':
215 self.open_count += 1
216 self.open_parens.append((lineno, i))
217 if char in ')]}':
218 self.open_count -= 1
219 if self.open_parens:
220 self.open_parens.pop()
221 if current_line and char != '#' and current_line.endswith('\\'):
222 self.explicit_continuation = True
223 else:
224 self.explicit_continuation = False
225
226 def _analyze(self):
227 last_statement = 1
228 block_start = codeanalyze.get_block_start(self.lines, self.lineno)
229 for current_line_number in range(block_start, self.lineno + 1):
230 if not self.explicit_continuation and \
231 self.open_count == 0 and self.in_string == '':
232 last_statement = current_line_number
233 self._analyze_line(current_line_number)
234 self.statement_start = last_statement
235
237 return self.statement_start
238
240 if not self.open_parens:
241 return None
242 return self.open_parens[-1]
243
245 return self.open_count != 0 or self.explicit_continuation
246
247 def get_line_indents(self, line_number):
248 return self._count_line_indents(self.lines.get_line(line_number))
__init__(self, editor, indents=4)
Definition indenter.py:83
_indents_caused_by_current_stmt(self, current_line)
Definition indenter.py:167
_set_line_indents(self, lineno, indents)
Definition indenter.py:51
__init__(self, editor, indents=4)
Definition indenter.py:14