From 092042b43d58254807c9e1151d8b6efb4d6410c4 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 4 Nov 2024 14:07:10 +0100 Subject: [PATCH] fix(cmdline): simplify and correct grapheme cluster adjustment --- src/nvim/ex_getln.c | 36 ++++---------------- test/functional/editor/mode_cmdline_spec.lua | 21 ++++++++++++ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index dda1a18fa6..9c606c9606 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3596,38 +3596,14 @@ void put_on_cmdline(const char *str, int len, bool redraw) memmove(ccline.cmdbuff + ccline.cmdpos, str, (size_t)len); ccline.cmdbuff[ccline.cmdlen] = NUL; - { - // When the inserted text starts with a composing character, - // backup to the character before it. There could be two of them. - int i = 0; - int c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos); - // TODO(bfredl): this can be corrected/simplified as utf_head_off implements the - // correct grapheme cluster breaks - while (ccline.cmdpos > 0 && utf_iscomposing_legacy(c)) { - i = utf_head_off(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos - 1) + 1; + // When the inserted text starts with a composing character, + // backup to the character before it. + if (ccline.cmdpos > 0 && (uint8_t)ccline.cmdbuff[ccline.cmdpos] >= 0x80) { + int i = utf_head_off(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos); + if (i != 0) { ccline.cmdpos -= i; len += i; - c = utf_ptr2char(ccline.cmdbuff + ccline.cmdpos); - } - if (i == 0 && ccline.cmdpos > 0 && arabic_maycombine(c)) { - // Check the previous character for Arabic combining pair. - i = utf_head_off(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos - 1) + 1; - if (arabic_combine(utf_ptr2char(ccline.cmdbuff + ccline.cmdpos - i), c)) { - ccline.cmdpos -= i; - len += i; - } else { - i = 0; - } - } - if (i != 0) { - // Also backup the cursor position. - i = ptr2cells(ccline.cmdbuff + ccline.cmdpos); - ccline.cmdspos -= i; - msg_col -= i; - if (msg_col < 0) { - msg_col += Columns; - msg_row--; - } + ccline.cmdspos = cmd_screencol(ccline.cmdpos); } } diff --git a/test/functional/editor/mode_cmdline_spec.lua b/test/functional/editor/mode_cmdline_spec.lua index efd7a37c0b..bb74dfe12f 100644 --- a/test/functional/editor/mode_cmdline_spec.lua +++ b/test/functional/editor/mode_cmdline_spec.lua @@ -38,6 +38,27 @@ describe('cmdline', function() feed([[:="foo\nbar\rbaz"]]) eq('foo\nbar\rbaz', fn.getcmdline()) end) + + it('pasting handles composing chars properly', function() + local screen = Screen.new(60, 4) + -- 'arabicshape' cheats and always redraws everything which trivially works, + -- this test is for partial redraws in 'noarabicshape' mode. + command('set noarabicshape') + screen:attach() + fn.setreg('a', '💻') + feed(':test 🧑‍') + screen:expect([[ + | + {1:~ }|*2 + :test 🧑‍^ | + ]]) + feed('a') + screen:expect([[ + | + {1:~ }|*2 + :test 🧑‍💻^ | + ]]) + end) end) it('Ctrl-Shift-V supports entering unsimplified key notations', function()