diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-02-29 07:19:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 07:19:26 +0800 |
commit | ce7c51a1a3b2b38cdba730aeb53840d0ace32173 (patch) | |
tree | ef0e92b160cff29436591b0cf5d531620ef10850 /src/nvim/eval/funcs.c | |
parent | e592657df8f727a3ce3b254fc72c027e36e08739 (diff) | |
download | rneovim-ce7c51a1a3b2b38cdba730aeb53840d0ace32173.tar.gz rneovim-ce7c51a1a3b2b38cdba730aeb53840d0ace32173.tar.bz2 rneovim-ce7c51a1a3b2b38cdba730aeb53840d0ace32173.zip |
vim-patch:9.1.0142: getregion() can be improved (#27662)
Problem: getregion() can be improved (after v9.1.120)
Solution: change getregion() implementation to use pos as lists and
one optional {opt} dictionary (Shougo Matsushita)
Note: The following is a breaking change!
Currently, the getregion() function (included as of patch v9.1.120) takes
3 arguments: the first 2 arguments are strings, describing a position,
arg3 is the type string.
However, that is slightly inflexible, there is no way to specify
additional arguments. So let's instead change the function signature to:
getregion(pos1, pos2 [, {Dict}]) where both pos1 and pos2 are lists.
This is slightly cleaner, and gives us the flexibility to specify
additional arguments as key/value pairs to the optional Dict arg.
Now it supports the "type" key to specify the selection type
(characterwise, blockwise or linewise) and now in addition one can also
define the selection type, independently of what the 'selection' option
actually is.
Technically, this is a breaking change, but since the getregion()
Vimscript function is still quite new, this should be fine.
closes: vim/vim#14090
https://github.com/vim/vim/commit/19b718828d8d5fab52d94c6cdba694641879ab38
Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r-- | src/nvim/eval/funcs.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c16fc1d708..3b387e3fd6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2821,35 +2821,38 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_list_alloc_ret(rettv, kListLenMayKnow); - if (tv_check_for_string_arg(argvars, 0) == FAIL - || tv_check_for_string_arg(argvars, 1) == FAIL - || tv_check_for_string_arg(argvars, 2) == FAIL) { + if (tv_check_for_list_arg(argvars, 0) == FAIL + || tv_check_for_list_arg(argvars, 1) == FAIL + || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) { return; } int fnum = -1; - // NOTE: var2fpos() returns static pointer. - pos_T *fp = var2fpos(&argvars[0], true, &fnum, false); - if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { + pos_T p1; + if (list2fpos(&argvars[0], &p1, &fnum, NULL, false) != OK + || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } - pos_T p1 = *fp; - fp = var2fpos(&argvars[1], true, &fnum, false); - if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum)) { + pos_T p2; + if (list2fpos(&argvars[1], &p2, &fnum, NULL, false) != OK + || (fnum >= 0 && fnum != curbuf->b_fnum)) { return; } - pos_T p2 = *fp; - - const char *pos1 = tv_get_string(&argvars[0]); - const char *pos2 = tv_get_string(&argvars[1]); - const char *type = tv_get_string(&argvars[2]); - - const bool is_visual - = (pos1[0] == 'v' && pos1[1] == NUL) || (pos2[0] == 'v' && pos2[1] == NUL); - if (is_visual && !VIsual_active) { - return; + bool is_select_exclusive; + char *type; + char default_type[] = "v"; + if (argvars[2].v_type == VAR_DICT) { + is_select_exclusive = tv_dict_get_bool(argvars[2].vval.v_dict, "exclusive", + *p_sel == 'e'); + type = tv_dict_get_string(argvars[2].vval.v_dict, "type", false); + if (type == NULL) { + type = default_type; + } + } else { + is_select_exclusive = *p_sel == 'e'; + type = default_type; } MotionType region_type = kMTUnknown; @@ -2866,6 +2869,10 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const TriState save_virtual = virtual_op; virtual_op = virtual_active(); + // NOTE: Adjust is needed. + p1.col--; + p2.col--; + if (!lt(p1, p2)) { // swap position pos_T p = p1; @@ -2878,7 +2885,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (region_type == kMTCharWise) { // handle 'selection' == "exclusive" - if (*p_sel == 'e' && !equalpos(p1, p2)) { + if (is_select_exclusive && !equalpos(p1, p2)) { if (p2.coladd > 0) { p2.coladd--; } else if (p2.col > 0) { @@ -2907,7 +2914,7 @@ static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) oa.start = p1; oa.end = p2; oa.start_vcol = MIN(sc1, sc2); - if (*p_sel == 'e' && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { + if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { oa.end_vcol = sc2 - 1; } else { oa.end_vcol = MAX(ec1, ec2); |