patch 9.2.0645: Composing chars no longer accepted in end-id abbr
Commit:
https://github.com/vim/vim/commit/23a84d28a8c4acfda1d01bde2b5366a496431d88
Author: zeertzjq <
zeer...@outlook.com>
Date: Sun Jun 14 15:39:26 2026 +0000
patch 9.2.0645: Composing chars no longer accepted in end-id abbr
Problem: Composing chars are no longer accepted in end-id abbreviation
(after 9.2.0629).
Solution: Unescape all chars using vim_unescape_csi() instead of using
mb_unescape() on individual chars, so that mb_ptr2len() and
MB_PTR_ADV() can still be used.
closes: #20514
Signed-off-by: zeertzjq <
zeer...@outlook.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/map.c b/src/map.c
index 50d7ee4bc..5970b3f5a 100644
--- a/src/map.c
+++ b/src/map.c
@@ -660,26 +660,26 @@ do_map(
// vi-compatible way.
if (has_mbyte)
{
- int first, last;
- int same = -1;
- char_u *p_char;
-
- p = keys;
- p_char = mb_unescape(&p);
- if (p_char == NULL)
- p_char = p++;
- first = vim_iswordp(p_char);
+ int first, last;
+ int same = -1;
+ char_u keys_unescaped[MAXMAPLEN + 1];
+ size_t keys_unescaped_len;
+
+ mch_memmove(keys_unescaped, keys, (size_t)(len + 1));
+ keys_unescaped_len = vim_unescape_csi(keys_unescaped);
+ p = keys_unescaped;
+
+ first = vim_iswordp(p);
last = first;
+ MB_PTR_ADV(p);
n = 1;
- while (p < keys + len)
+ while (p < keys_unescaped + keys_unescaped_len)
{
- ++n; // nr of (multi-byte) chars
- p_char = mb_unescape(&p);
- if (p_char == NULL)
- p_char = p++;
- last = vim_iswordp(p_char); // type of last char
+ ++n; // nr of (multi-byte) chars
+ last = vim_iswordp(p); // type of last char
if (same == -1 && last != first)
- same = n - 1; // count of same char type
+ same = n - 1; // count of same char type
+ MB_PTR_ADV(p);
}
if (last && n > 2 && same >= 0 && same < n - 1)
{
@@ -1687,8 +1687,7 @@ check_abbr(
if (qe != NULL)
{
q = qe;
- vim_unescape_csi(q);
- qlen = (int)STRLEN(q);
+ qlen = (int)vim_unescape_csi(q);
}
}
@@ -1908,8 +1907,9 @@ vim_strsave_escape_csi(char_u *p)
/*
* Remove escaping from CSI and K_SPECIAL characters. Reverse of
* vim_strsave_escape_csi(). Works in-place.
+ * Returns the number of bytes in the unescaped string.
*/
- void
+ size_t
vim_unescape_csi(char_u *p)
{
char_u *s = p, *d = p;
@@ -1931,6 +1931,7 @@ vim_unescape_csi(char_u *p)
*d++ = *s++;
}
*d = NUL;
+ return (size_t)(d - p);
}
/*
diff --git a/src/proto/
map.pro b/src/proto/
map.pro
index d696aabcd..5f736f504 100644
--- a/src/proto/
map.pro
+++ b/src/proto/
map.pro
@@ -12,7 +12,7 @@ int ExpandMappings(char_u *pat, regmatch_T *regmatch, int *numMatches, char_u **
int check_abbr(int c, char_u *ptr, int col, int mincol);
char_u *eval_map_expr(mapblock_T *mp, int c);
char_u *vim_strsave_escape_csi(char_u *p);
-void vim_unescape_csi(char_u *p);
+size_t vim_unescape_csi(char_u *p);
int makemap(FILE *fd, buf_T *buf);
int put_escstr(FILE *fd, char_u *strstart, int what);
void check_map_keycodes(void);
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index 635193ebd..d181bbf39 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -28,6 +28,18 @@ func Test_abbreviation()
iunab abc;
iunab ;
+ " abbreviation with composing chars (end-id)
+ inoreab ..ã a^~
+ inoreab ..β̃ β^~
+ inoreab ..π̃ π^~
+ inoreab ..Λ̃ Λ^~
+ call feedkeys("Go..ã ..β̃ ..π̃ ..Λ̃ \<Esc>", "xt")
+ call assert_equal('a^~ β^~ π^~ Λ^~ ', getline('$'))
+ iunab ..ã
+ iunab ..β̃
+ iunab ..π̃
+ iunab ..Λ̃
+
bwipe!
endfunc
diff --git a/src/version.c b/src/version.c
index f00b31d09..4a8bfe821 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 645,
/**/
644,
/**/