editor: Do not run brace completion on empty text. (#2965)

Piotr Osiewicz created

Users of keyboard layout with IME complained about the peculiar
behaviour where typing in "sss" and then removing all of it left behind
one 's' and also appended a closing brace. This was not reproducible on
a buffer without language, so I've suspected that brace insertion might
be a problem here. For whatever reason when the user removes the last
character from a run that triggered IME, we receive a notification about
an empty insertion. Sadly, brace completion does not handle an empty
input properly and we erroneously insert a closing brace when deleting
the followup characters. In fact, the brace inserted is always the
closing brace for the first entry in language's config.toml 'brackets'
field (see Scheme vs Markdown). This guard also allows for the proper
removal of the first character.

Closes community tickets zed-industries/community#877
zed-industries/community#1329

Z-2869

Release Notes:
- Fixed handling of bracket completion for international keyboard
layouts that use IME. This led to Zed erroneously inserting the `}`
character while removing the first character that triggered IME.

Change summary

crates/editor/src/editor.rs | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -2289,14 +2289,18 @@ impl Editor {
                 // bracket of any of this language's bracket pairs.
                 let mut bracket_pair = None;
                 let mut is_bracket_pair_start = false;
-                for (pair, enabled) in scope.brackets() {
-                    if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
-                        bracket_pair = Some(pair.clone());
-                        is_bracket_pair_start = true;
-                        break;
-                    } else if pair.end.as_str() == text.as_ref() {
-                        bracket_pair = Some(pair.clone());
-                        break;
+                if !text.is_empty() {
+                    // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
+                    //  and they are removing the character that triggered IME popup.
+                    for (pair, enabled) in scope.brackets() {
+                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
+                            bracket_pair = Some(pair.clone());
+                            is_bracket_pair_start = true;
+                            break;
+                        } else if pair.end.as_str() == text.as_ref() {
+                            bracket_pair = Some(pair.clone());
+                            break;
+                        }
                     }
                 }