|
40 | 40 | from .completing_reader import CompletingReader |
41 | 41 | from .console import Console as ConsoleType |
42 | 42 | from ._module_completer import ModuleCompleter, make_default_module_completer |
| 43 | +from .utils import gen_colors |
43 | 44 |
|
44 | 45 | Console: type[ConsoleType] |
45 | 46 | _error: tuple[type[Exception], ...] | type[Exception] |
@@ -251,57 +252,23 @@ def _get_first_indentation(buffer: list[str]) -> str | None: |
251 | 252 | return ''.join(buffer[indented_line_start : i]) |
252 | 253 | return None |
253 | 254 |
|
254 | | - |
255 | 255 | def _should_auto_indent(buffer: list[str], pos: int) -> bool: |
256 | | - # check if last character before "pos" is a colon, ignoring |
257 | | - # whitespaces and comments. |
258 | | - last_char = None |
259 | | - # A stack to keep track of string delimiters. Push a quote when entering a |
260 | | - # string, pop it when the string ends. If the stack is empty, we're not |
261 | | - # inside a string. When see a '#', it's a comment start if we're not inside |
262 | | - # a string; otherwise, it's just a '#' character within a string. |
263 | | - str_delims: list[str] = [] |
264 | | - in_comment = False |
265 | | - char_line_indent_start = None |
266 | | - char_line_indent = 0 |
267 | | - lastchar_line_indent = 0 |
268 | | - cursor_line_indent = 0 |
269 | | - |
270 | | - i = -1 |
271 | | - while i < pos - 1: |
272 | | - i += 1 |
273 | | - char = buffer[i] |
274 | | - |
275 | | - # update last_char |
276 | | - if char == "#": |
277 | | - if str_delims: |
278 | | - last_char = char # '#' inside a string is just a character |
279 | | - else: |
280 | | - in_comment = True |
281 | | - elif char == "\n": |
282 | | - # newline ends a comment |
283 | | - in_comment = False |
284 | | - if i < pos - 1 and buffer[i + 1] in " \t": |
285 | | - char_line_indent_start = i + 1 |
286 | | - else: |
287 | | - char_line_indent_start = None # clear last line's line_indent_start |
288 | | - char_line_indent = 0 |
289 | | - elif char not in " \t": |
290 | | - if char_line_indent_start is not None: |
291 | | - char_line_indent = i - char_line_indent_start |
292 | | - if not in_comment and not str_delims: |
293 | | - # update last_char with non-whitespace chars outside comments and strings |
294 | | - last_char = char |
295 | | - lastchar_line_indent = char_line_indent |
296 | | - |
297 | | - # update stack |
298 | | - if char in "\"'" and (i == 0 or buffer[i - 1] != "\\"): |
299 | | - if str_delims and str_delims[-1] == char: |
300 | | - str_delims.pop() |
301 | | - else: |
302 | | - str_delims.append(char) |
303 | | - cursor_line_indent = char_line_indent |
304 | | - return last_char == ":" and cursor_line_indent <= lastchar_line_indent |
| 256 | + buffer_str = ''.join(buffer) |
| 257 | + colors = tuple(gen_colors(buffer_str)) |
| 258 | + string_spans = tuple(c.span for c in colors if c.tag == "string") |
| 259 | + comment_spans = tuple(c.span for c in colors if c.tag == "comment") |
| 260 | + def in_span(i, spans): |
| 261 | + return any(s.start <= i <= s.end for s in spans) |
| 262 | + i = pos - 1 |
| 263 | + while i >= 0: |
| 264 | + if buffer_str[i] in " \t\n": |
| 265 | + i -= 1 |
| 266 | + continue |
| 267 | + if in_span(i, string_spans) or in_span(i, comment_spans): |
| 268 | + i -= 1 |
| 269 | + continue |
| 270 | + break |
| 271 | + return i >= 0 and buffer_str[i] == ":" |
305 | 272 |
|
306 | 273 |
|
307 | 274 | class maybe_accept(commands.Command): |
|
0 commit comments