diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-16 06:28:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-16 06:28:52 +0800 |
commit | a245dd79a267c8b56866023e84b49d0ecffca65b (patch) | |
tree | cae7c06afdb1e10be19d08a43af13df74df3724f | |
parent | 10c5f35a8ddf2683e0c849f71c02b81556ece902 (diff) | |
download | rneovim-a245dd79a267c8b56866023e84b49d0ecffca65b.tar.gz rneovim-a245dd79a267c8b56866023e84b49d0ecffca65b.tar.bz2 rneovim-a245dd79a267c8b56866023e84b49d0ecffca65b.zip |
vim-patch:9.0.1717: virtcol2col returns last byte of a multi-byte char (#24729)
Problem: virtcol2col returns last byte of a multi-byte char
Solution: Make it return the first byte for a multi-byte char
closes: vim/vim#12786
closes: vim/vim#12799
https://github.com/vim/vim/commit/b209b86e6636a16088ccacdac98213416c065bf2
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
-rw-r--r-- | runtime/doc/builtin.txt | 3 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 3 | ||||
-rw-r--r-- | src/nvim/eval.lua | 3 | ||||
-rw-r--r-- | src/nvim/move.c | 17 | ||||
-rw-r--r-- | test/old/testdir/test_cursor_func.vim | 9 |
5 files changed, 34 insertions, 1 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index 7356f644a1..bc5f0948e2 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -8434,6 +8434,9 @@ virtcol2col({winid}, {lnum}, {col}) *virtcol2col()* {lnum}, then the byte index of the character at the last virtual column is returned. + For a multi-byte character, the column number of the first + byte in the character is returned. + The {winid} argument can be the window number or the |window-ID|. If this is zero, then the current window is used. diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index acf1b3a0f5..d1173e8a42 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -10016,6 +10016,9 @@ function vim.fn.virtcol(expr, list) end --- {lnum}, then the byte index of the character at the last --- virtual column is returned. --- +--- For a multi-byte character, the column number of the first +--- byte in the character is returned. +--- --- The {winid} argument can be the window number or the --- |window-ID|. If this is zero, then the current window is used. --- diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 8a0d7575b3..8a36509f9a 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -11931,6 +11931,9 @@ M.funcs = { {lnum}, then the byte index of the character at the last virtual column is returned. + For a multi-byte character, the column number of the first + byte in the character is returned. + The {winid} argument can be the window number or the |window-ID|. If this is zero, then the current window is used. diff --git a/src/nvim/move.c b/src/nvim/move.c index 0ed30070a5..a68f6a2d50 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1163,6 +1163,21 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_dict_add_nr(dict, S_LEN("endcol"), ecol); } +/// Convert a virtual (screen) column to a character column. The first column +/// is one. For a multibyte character, the column number of the first byte is +/// returned. +static int virtcol2col(win_T *wp, linenr_T lnum, int vcol) +{ + int offset = vcol2col(wp, lnum, vcol); + char *line = ml_get_buf(wp->w_buffer, lnum, false); + char *p = line + offset; + + // For a multibyte character, need to return the column number of the first byte. + MB_PTR_BACK(line, p); + + return (int)(p - line + 1); +} + /// "virtcol2col({winid}, {lnum}, {col})" function void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -1190,7 +1205,7 @@ void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - rettv->vval.v_number = vcol2col(wp, lnum, screencol); + rettv->vval.v_number = virtcol2col(wp, lnum, screencol); } /// Scroll the current window down by "line_count" logical lines. "CTRL-Y" diff --git a/test/old/testdir/test_cursor_func.vim b/test/old/testdir/test_cursor_func.vim index f73bd4f2b9..3d6ad8405c 100644 --- a/test/old/testdir/test_cursor_func.vim +++ b/test/old/testdir/test_cursor_func.vim @@ -531,6 +531,15 @@ func Test_virtcol2col() call assert_equal(-1, virtcol2col(0, -1, 1)) call assert_equal(-1, virtcol2col(0, 1, -1)) call assert_equal(5, virtcol2col(0, 1, 20)) + + " Multibyte character + call setline(1, ['a✅✅✅']) + call assert_equal(1, virtcol2col(0, 1, 1)) + call assert_equal(2, virtcol2col(0, 1, 3)) + call assert_equal(5, virtcol2col(0, 1, 5)) + call assert_equal(8, virtcol2col(0, 1, 7)) + call assert_equal(8, virtcol2col(0, 1, 8)) + call assert_fails('echo virtcol2col("0", 1, 20)', 'E1210:') call assert_fails('echo virtcol2col(0, "1", 20)', 'E1210:') call assert_fails('echo virtcol2col(0, 1, "1")', 'E1210:') |