diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-09-12 18:10:13 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-12 18:10:13 +0800 |
commit | 2ea6584a1b798bc7bb77d97735c77c0c7ce38706 (patch) | |
tree | ca90a565370f46fd84ddf052c5769e04ede33e00 /src | |
parent | 738c204523e4da07468268ae89741f2c86887031 (diff) | |
parent | 245ac6f263b6017c050f885212ee80e5738d3b9f (diff) | |
download | rneovim-2ea6584a1b798bc7bb77d97735c77c0c7ce38706.tar.gz rneovim-2ea6584a1b798bc7bb77d97735c77c0c7ce38706.tar.bz2 rneovim-2ea6584a1b798bc7bb77d97735c77c0c7ce38706.zip |
Merge pull request #20163 from zeertzjq/vim-8.2.5034
vim-patch:8.2.5034: there is no way to get the byte index from a virtual column
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 26 | ||||
-rw-r--r-- | src/nvim/eval/typval.c | 13 | ||||
-rw-r--r-- | src/nvim/move.c | 59 | ||||
-rw-r--r-- | src/nvim/testdir/test_cursor_func.vim | 22 |
5 files changed, 95 insertions, 26 deletions
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 3e89489459..5c500af899 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -425,6 +425,7 @@ return { uniq={args={1, 3}, base=1}, values={args=1, base=1}, virtcol={args=1, base=1}, + virtcol2col={args=3, base=1}, visualmode={args={0, 1}}, wait={args={2,3}}, wildmenumode={}, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index bff4361dcb..4a139c85d1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7057,32 +7057,6 @@ static void f_screencol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = ui_current_col() + 1; } -/// "screenpos({winid}, {lnum}, {col})" function -static void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_dict_alloc_ret(rettv); - dict_T *dict = rettv->vval.v_dict; - - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - return; - } - - pos_T pos = { - .lnum = (linenr_T)tv_get_number(&argvars[1]), - .col = (colnr_T)tv_get_number(&argvars[2]) - 1, - .coladd = 0 - }; - int row = 0; - int scol = 0, ccol = 0, ecol = 0; - textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false); - - tv_dict_add_nr(dict, S_LEN("row"), row); - tv_dict_add_nr(dict, S_LEN("col"), scol); - tv_dict_add_nr(dict, S_LEN("curscol"), ccol); - tv_dict_add_nr(dict, S_LEN("endcol"), ecol); -} - /// "screenrow()" function static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c75d16e4fc..2089415ffa 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -44,6 +44,8 @@ static char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); static char e_non_empty_string_required_for_argument_nr[] = N_("E1142: Non-empty string required for argument %d"); +static char e_number_required_for_argument_nr[] + = N_("E1210: Number required for argument %d"); bool tv_in_free_unref_items = false; @@ -3830,6 +3832,17 @@ int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx) return OK; } +/// Give an error and return FAIL unless "args[idx]" is a number. +int tv_check_for_number_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_NUMBER) { + semsg(_(e_number_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Get the string value of a "stringish" VimL object. /// /// @param[in] tv Object to get value of. diff --git a/src/nvim/move.c b/src/nvim/move.c index 0e2550352d..481746881b 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -21,12 +21,15 @@ #include "nvim/diff.h" #include "nvim/drawscreen.h" #include "nvim/edit.h" +#include "nvim/eval.h" +#include "nvim/eval/typval.h" #include "nvim/fold.h" #include "nvim/getchar.h" #include "nvim/grid.h" #include "nvim/highlight.h" #include "nvim/mbyte.h" #include "nvim/memline.h" +#include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/plines.h" @@ -977,6 +980,62 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, *ecolp = ecol + coloff; } +/// "screenpos({winid}, {lnum}, {col})" function +void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_dict_alloc_ret(rettv); + dict_T *dict = rettv->vval.v_dict; + + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; + } + + pos_T pos = { + .lnum = (linenr_T)tv_get_number(&argvars[1]), + .col = (colnr_T)tv_get_number(&argvars[2]) - 1, + .coladd = 0 + }; + int row = 0; + int scol = 0, ccol = 0, ecol = 0; + textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false); + + tv_dict_add_nr(dict, S_LEN("row"), row); + tv_dict_add_nr(dict, S_LEN("col"), scol); + tv_dict_add_nr(dict, S_LEN("curscol"), ccol); + tv_dict_add_nr(dict, S_LEN("endcol"), ecol); +} + +/// "virtcol2col({winid}, {lnum}, {col})" function +void f_virtcol2col(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + + if (tv_check_for_number_arg(argvars, 0) == FAIL + || tv_check_for_number_arg(argvars, 1) == FAIL + || tv_check_for_number_arg(argvars, 2) == FAIL) { + return; + } + + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + return; + } + + bool error = false; + linenr_T lnum = (linenr_T)tv_get_number_chk(&argvars[1], &error); + if (error || lnum < 0 || lnum > wp->w_buffer->b_ml.ml_line_count) { + return; + } + + int screencol = (int)tv_get_number_chk(&argvars[2], &error); + if (error || screencol < 0) { + return; + } + + rettv->vval.v_number = vcol2col(wp, lnum, screencol); +} + /// Scroll the current window down by "line_count" logical lines. "CTRL-Y" /// /// @param line_count number of lines to scroll diff --git a/src/nvim/testdir/test_cursor_func.vim b/src/nvim/testdir/test_cursor_func.vim index f13842edc8..2e625f2388 100644 --- a/src/nvim/testdir/test_cursor_func.vim +++ b/src/nvim/testdir/test_cursor_func.vim @@ -373,4 +373,26 @@ func Test_setcursorcharpos() %bw! endfunc +" Test for virtcol2col() +func Test_virtcol2col() + new + call setline(1, ["a\tb\tc"]) + call assert_equal(1, virtcol2col(0, 1, 1)) + call assert_equal(2, virtcol2col(0, 1, 2)) + call assert_equal(2, virtcol2col(0, 1, 8)) + call assert_equal(3, virtcol2col(0, 1, 9)) + call assert_equal(4, virtcol2col(0, 1, 10)) + call assert_equal(4, virtcol2col(0, 1, 16)) + call assert_equal(5, virtcol2col(0, 1, 17)) + call assert_equal(-1, virtcol2col(10, 1, 1)) + call assert_equal(-1, virtcol2col(0, 10, 1)) + call assert_equal(-1, virtcol2col(0, -1, 1)) + call assert_equal(-1, virtcol2col(0, 1, -1)) + call assert_equal(5, virtcol2col(0, 1, 20)) + 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:') + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab |