Skip to content

Commit 8d84178

Browse files
committed
autocomplete: Accept emoji queries for 👍 and with dashes
This makes this logic a bit more complicated, but also more explicitly related to the set of possible emoji names, and more fully aligned with that set.
1 parent 2673b6a commit 8d84178

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

lib/model/autocomplete.dart

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,48 @@ final RegExp _emojiIntentRegex = (() {
114114
// meaning "whitespace and punctuation, except not `:`":
115115
// r'(?<=^|[[\s\p{Punctuation}]--[:]])'
116116

117-
/// Characters that might be meant as part of (a query for) an emoji's name,
118-
/// other than whitespace.
117+
// What possible emoji queries do we want to anticipate?
118+
//
119+
// First, look only for queries aimed at emoji names (and aliases);
120+
// there's little point in searching by literal emoji here, because once the
121+
// user has entered a literal emoji they can simply leave it in.
122+
// (Searching by literal emoji is useful, by contrast, for adding a reaction.)
123+
//
124+
// Then, what are the possible names (including aliases)?
125+
// For custom emoji, the names the server allows are r'^[0-9a-z_-]*[0-9a-z]$';
126+
// see check_valid_emoji_name in zerver/lib/emoji.py.
127+
// So only ASCII lowercase alnum, underscore, and dash.
128+
// A few Unicode emoji have more general names in the server's list:
129+
// Latin letters with diacritics, a few kana and kanji, and the name "+1".
130+
// (And the only "Zulip extra emoji" has one name, "zulip".)
131+
// Details: https://github.com/zulip/zulip-flutter/pull/1069#discussion_r1855964953
132+
//
133+
// We generalize [0-9a-z] to "any letter or number".
134+
// That handles the existing names except "+1", plus a potential future
135+
// loosening of the constraints on custom emoji's names.
136+
//
137+
// Then "+1" we take as a special case, without generalizing,
138+
// in order to recognize that name without adding false positives.
139+
//
140+
// Even though there could be a custom emoji whose name begins with "-",
141+
// we reject queries that begin that way: ":-" is much more likely to be
142+
// the start of an emoticon.
143+
144+
/// Characters that might be meant as part of (a query for) an emoji's name
145+
/// at any point in the query.
119146
const nameCharacters = r'_\p{Letter}\p{Number}';
120147

121148
return RegExp(unicode: true,
122149
before
123150
+ r':'
124151
+ r'(|'
152+
// Recognize '+' only as part of '+1', the only emoji name that has it.
153+
+ r'\+1?|'
125154
// Reject on whitespace right after ':'; interpret that
126155
// as the user choosing to get out of the emoji autocomplete.
127-
+ r'[' + nameCharacters + r']'
128-
+ r'[\s' + nameCharacters + r']*'
156+
// Similarly reject starting with ':-', which is common for emoticons.
157+
+ r'[' + nameCharacters + r']'
158+
+ r'[-\s' + nameCharacters + r']*'
129159
+ r')$');
130160
})();
131161

test/model/autocomplete_test.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ void main() {
224224
doTest('~:1^', emoji('1')); // U+FF11 FULLWIDTH DIGIT ONE
225225
doTest('~:٢^', emoji('٢')); // U+0662 ARABIC-INDIC DIGIT TWO
226226

227+
// Emoji names may have dashes '-'.
228+
doTest('~:e-m^', emoji('e-m'));
229+
doTest('~:jack-o-l^', emoji('jack-o-l'));
230+
231+
// Just one emoji has a '+' in its name, namely ':+1:'.
232+
doTest('~:+^', emoji('+'));
233+
doTest('~:+1^', emoji('+1'));
234+
doTest(':+2^', null);
235+
doTest(':+100^', null);
236+
doTest(':+1 ^', null);
237+
doTest(':1+1^', null);
238+
227239
// Accept punctuation before the emoji: opening…
228240
doTest('(~:^', emoji('')); doTest('(~:a^', emoji('a'));
229241
doTest('[~:^', emoji('')); doTest('[~:a^', emoji('a'));

0 commit comments

Comments
 (0)