@@ -254,19 +254,37 @@ def _should_auto_indent(buffer: list[str], pos: int) -> bool:
254
254
# check if last character before "pos" is a colon, ignoring
255
255
# whitespaces and comments.
256
256
last_char = None
257
- while pos > 0 :
258
- pos -= 1
259
- if last_char is None :
260
- if buffer [pos ]not in "\t \n #" :# ignore whitespaces and comments
261
- last_char = buffer [pos ]
262
- else :
263
- # even if we found a non-whitespace character before
264
- # original pos, we keep going back until newline is reached
265
- # to make sure we ignore comments
266
- if buffer [pos ]== "\n " :
267
- break
268
- if buffer [pos ]== "#" :
269
- last_char = None
257
+ # A stack to keep track of string delimiters (quotes). Push a quote when
258
+ # entering a string, and pop it when the string ends. When the stack is
259
+ # empty, we're not inside a string. If encounter a '#' while not inside a
260
+ # string, it's a comment start; otherwise, it's just a '#' character within
261
+ # a string.
262
+ in_string :list [str ]= []
263
+ in_comment = False
264
+ i = - 1
265
+ while i < pos - 1 :
266
+ i += 1
267
+ char = buffer [i ]
268
+
269
+ # update last_char
270
+ if char == "#" :
271
+ if in_string :
272
+ last_char = char # '#' inside a string is just a character
273
+ else :
274
+ in_comment = True
275
+ elif char == "\n " :
276
+ # newline ends a comment
277
+ in_comment = False
278
+ elif char not in "\t " and not in_comment and not in_string :
279
+ # update last_char with non-whitespace chars outside comments and strings
280
+ last_char = char
281
+
282
+ # update stack
283
+ if char in "\" '" and (i == 0 or buffer [i - 1 ]!= "\\ " ):
284
+ if in_string and in_string [- 1 ]== char :
285
+ in_string .pop ()
286
+ else :
287
+ in_string .append (char )
270
288
return last_char == ":"
271
289
272
290