diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.lua | 40 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 49 |
2 files changed, 52 insertions, 37 deletions
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index e03ee77141..8dc282cd43 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -4356,16 +4356,27 @@ M.funcs = { signature = 'getreginfo([{regname}])', }, getregion = { - args = 3, + args = { 2, 3 }, base = 1, desc = [=[ - Returns the list of strings from {pos1} to {pos2} as if it's - selected in visual mode of {type}. - For possible values of {pos1} and {pos2} see |line()|. - {type} is the selection type: - "v" for |charwise| mode - "V" for |linewise| mode - "<CTRL-V>" for |blockwise-visual| mode + Returns the list of strings from {pos1} to {pos2} in current + buffer. + + {pos1} and {pos2} must both be |List|s with four numbers. + See |getpos()| for the format of the list. + + The optional argument {opts} is a Dict and supports the + following items: + + type Specify the selection type + (default: "v"): + "v" for |charwise| mode + "V" for |linewise| mode + "<CTRL-V>" for |blockwise-visual| mode + + exclusive If |TRUE|, use exclusive selection + for the end position 'selection'. + You can get the last selection type by |visualmode()|. If Visual mode is active, use |mode()| to get the Visual mode (e.g., in a |:vmap|). @@ -4383,22 +4394,19 @@ M.funcs = { - If the selection starts or ends in the middle of a multibyte character, it is not included but its selected part is substituted with spaces. - - If {pos1} or {pos2} equals "v" (see |line()|) and it is not in - |visual-mode|, an empty list is returned. - - If {pos1}, {pos2} or {type} is an invalid string, an empty - list is returned. - - If {pos1} or {pos2} is a mark in different buffer, an empty + - If {pos1} or {pos2} is not current in the buffer, an empty list is returned. Examples: > :xnoremap <CR> - \ <Cmd>echom getregion('v', '.', mode())<CR> + \ <Cmd>echom getregion( + \ getpos('v'), getpos('.'), #{ type: mode() })<CR> < ]=], name = 'getregion', - params = { { 'pos1', 'string' }, { 'pos2', 'string' }, { 'type', 'string' } }, + params = { { 'pos1', 'table' }, { 'pos2', 'table' }, { 'opts', 'table' } }, returns = 'string[]', - signature = 'getregion({pos1}, {pos2}, {type})', + signature = 'getregion({pos1}, {pos2} [, {opts}])', }, getregtype = { args = { 0, 1 }, 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); |