From 3ad9074e637685497d8c75b4974653b7dca607fe Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Fri, 14 Mar 2025 21:16:57 +0000 Subject: [PATCH] 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. --- crates/editor/src/editor.rs | 12 ++++++++++++ crates/editor/src/editor_tests.rs | 23 ++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 237c68491a94f1447d38997a970ad24fcde8c7ba..809a286fb8e3899db9a14443d84c8a80da5aba1e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -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); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index c2cad6528dae13eef793b7156c512903c15afc17..a37e0efc3b389ea8c149db13358f34931cb54bff 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -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("aˇ"); 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("aˇ"); + 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("ˇ");