editor: Fix auto-closing quotes after word character (#26803)

Closes #14349

When typing quotes immediately after a word character, it resulted in
auto-closing the quote.

```js
const thing = this is text^;
```

Typing a quote resulted in `this is text""^;` which is not correct, and
should be `this is text"^;`.

This PR changes logic for auto close:

1. We now prevent auto-closing in case of brackets where start == end
when they're typed immediately after a word character. i.e. For, ``` `,
", ' ```.
2. Other bracket pairs like `{}, (), etc` continue to auto-close
regardless of preceding character. So, `func^` to `func()^` will keep
working.
3. Auto-closing in other contexts like after spaces, punctuation, etc.
will still work.

Before:

![before](https://github.com/user-attachments/assets/6be02c95-4c71-488b-901d-b7b98c4170a4)

After:

![after](https://github.com/user-attachments/assets/680ece4d-20cb-428c-b430-846da3a2d643)

Release Notes:

- Fixed auto-paired quotes being inserted when typing a quote
immediately next to a word character.
This commit is contained in:
Smit Barmase 2025-03-14 21:16:57 +00:00 committed by GitHub
parent f40b22c02a
commit 3ad9074e63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 3 deletions

View file

@ -2918,6 +2918,17 @@ impl Editor {
.next()
.map_or(true, |c| scope.should_autoclose_before(c));
let preceding_text_allows_autoclose = selection.start.column == 0
|| snapshot.reversed_chars_at(selection.start).next().map_or(
true,
|c| {
bracket_pair.start != bracket_pair.end
|| !snapshot
.char_classifier_at(selection.start)
.is_word(c)
},
);
let is_closing_quote = if bracket_pair.end == bracket_pair.start
&& bracket_pair.start.len() == 1
{
@ -2935,6 +2946,7 @@ impl Editor {
if autoclose
&& bracket_pair.close
&& following_text_allows_autoclose
&& preceding_text_allows_autoclose
&& !is_closing_quote
{
let anchor = snapshot.anchor_before(selection.end);

View file

@ -6357,12 +6357,29 @@ async fn test_autoclose_and_auto_surround_pairs(cx: &mut TestAppContext) {
cx.update_editor(|editor, window, cx| editor.handle_input("{", window, cx));
cx.assert_editor_state("{«aˇ»} b");
// Autclose pair where the start and end characters are the same
// Autoclose when not immediately after a word character
cx.set_state("a ˇ");
cx.update_editor(|editor, window, cx| editor.handle_input("\"", window, cx));
cx.assert_editor_state("a \"ˇ\"");
// Autoclose pair where the start and end characters are the same
cx.update_editor(|editor, window, cx| editor.handle_input("\"", window, cx));
cx.assert_editor_state("a \"\"ˇ");
// Don't autoclose when immediately after a word character
cx.set_state("");
cx.update_editor(|editor, window, cx| editor.handle_input("\"", window, cx));
cx.assert_editor_state("a\"ˇ\"");
cx.assert_editor_state("a\"ˇ");
// Do autoclose when after a non-word character
cx.set_state("");
cx.update_editor(|editor, window, cx| editor.handle_input("\"", window, cx));
cx.assert_editor_state("a\"\"ˇ");
cx.assert_editor_state("{\"ˇ\"");
// Non identical pairs autoclose regardless of preceding character
cx.set_state("");
cx.update_editor(|editor, window, cx| editor.handle_input("{", window, cx));
cx.assert_editor_state("a{ˇ}");
// Don't autoclose pair if autoclose is disabled
cx.set_state("ˇ");