Hey Walter, Thanks for the report.
On Thu, Apr 03, 2025 at 02:55:11PM +0200, Walter Alejandro Iglesias wrote: > Using vi mode in ksh I noticed that the command endword (vi.c) gets > staked when the last character in a word is a UTF-8 character. > > To reproduce: > > In the line bellow, using vi mode, first move your cursor to the first > character, then hit "e" several times. You'll see the cursor get > stacked in the euro sign. > > $ word word€ word > ^ this is an euro sign. It also happens with E command. > The following diff is one of my intuitive C newbie solutions, some > expert will surely find a better one. The patch isn't correct: you're calling isspace (expects a character) with the result of isu8cont (which is a boolean). The right places to fix this seem to be endword and Endword. The patch below fixes the issue for me. The approach taken is first skipping all the UTF-8 continuation bytes after the cursor, before considering skipping spaces. OK? Too close for release? Lucas diff refs/heads/master 6fa8b54754b6fba159a065d3fc32b57caae81275 commit - 58fd8d0bdc1e6222119987e7aaad111eae245668 commit + 6fa8b54754b6fba159a065d3fc32b57caae81275 blob - cdda9cb24b1a4a395547e081ff3adca380d3b6c1 blob + 7f09c75e44c37f7ecc247df5ac187b4816a99cc3 --- bin/ksh/vi.c +++ bin/ksh/vi.c @@ -1590,15 +1590,18 @@ backword(int argcnt) static int endword(int argcnt) { - int ncursor, skip_space, want_letnum; + int ncursor, skip_space, skip_utf8_cont, want_letnum; unsigned char uc; ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { - skip_space = 1; + skip_space = skip_utf8_cont = 1; want_letnum = -1; while (++ncursor < es->linelen) { uc = es->cbuf[ncursor]; + if (isu8cont(uc)) + continue; + skip_utf8_cont = 0; if (isspace(uc)) { if (skip_space) continue; @@ -1663,6 +1666,9 @@ Endword(int argcnt) ncursor = es->cursor; while (ncursor < es->linelen && argcnt--) { while (++ncursor < es->linelen && + isu8cont((unsigned char)es->cbuf[ncursor])) + ; + while (++ncursor < es->linelen && isspace((unsigned char)es->cbuf[ncursor])) ; while (ncursor < es->linelen &&