summaryrefslogtreecommitdiffstats
path: root/src/evalfunc.c
diff options
context:
space:
mode:
authorShougo Matsushita <Shougo.Matsu@gmail.com>2024-02-28 22:48:12 +0100
committerChristian Brabandt <cb@256bit.org>2024-02-28 22:49:03 +0100
commit19b718828d8d5fab52d94c6cdba694641879ab38 (patch)
tree4683fa9c3cc05d02bc5e70ea5c58b2204b0de6ff /src/evalfunc.c
parentd0d4adb609064d6ca4fce111a09c2cbbcdef1cf1 (diff)
patch 9.1.0142: getregion() can be improvedv9.1.0142
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: #14090 Co-authored-by: zeertzjq <zeertzjq@outlook.com> Signed-off-by: Shougo Matsushita <Shougo.Matsu@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r--src/evalfunc.c57
1 files changed, 32 insertions, 25 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 37010d7bad..b5d8c872ed 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -1151,6 +1151,7 @@ static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_
static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number};
static argcheck_T arg3_diff[] = {arg_list_string, arg_list_string, arg_dict_any};
static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any};
+static argcheck_T arg3_list_list_dict[] = {arg_list_any, arg_list_any, arg_dict_any};
static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
static argcheck_T arg3_number_any_dict[] = {arg_number, arg_any, arg_dict_any};
@@ -2132,7 +2133,7 @@ static funcentry_T global_functions[] =
ret_getreg, f_getreg},
{"getreginfo", 0, 1, FEARG_1, arg1_string,
ret_dict_any, f_getreginfo},
- {"getregion", 3, 3, FEARG_1, arg3_string,
+ {"getregion", 2, 3, FEARG_1, arg3_list_list_dict,
ret_list_string, f_getregion},
{"getregtype", 0, 1, FEARG_1, arg1_string,
ret_string, f_getregtype},
@@ -5491,41 +5492,43 @@ f_getregion(typval_T *argvars, typval_T *rettv)
int inclusive = TRUE;
int fnum = -1;
pos_T p1, p2;
- pos_T *fp = NULL;
- char_u *pos1, *pos2, *type;
+ char_u *type;
+ char_u default_type[] = "v";
int save_virtual = -1;
int l;
int region_type = -1;
- int is_visual;
+ int is_select_exclusive;
if (rettv_list_alloc(rettv) == FAIL)
return;
- if (check_for_string_arg(argvars, 0) == FAIL
- || check_for_string_arg(argvars, 1) == FAIL
- || check_for_string_arg(argvars, 2) == FAIL)
+ if (check_for_list_arg(argvars, 0) == FAIL
+ || check_for_list_arg(argvars, 1) == FAIL
+ || check_for_opt_dict_arg(argvars, 2) == FAIL)
return;
- // NOTE: var2fpos() returns static pointer.
- fp = var2fpos(&argvars[0], TRUE, &fnum, FALSE);
- if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum))
+ if (list2fpos(&argvars[0], &p1, &fnum, NULL, FALSE) != OK
+ || (fnum >= 0 && fnum != curbuf->b_fnum))
return;
- p1 = *fp;
- fp = var2fpos(&argvars[1], TRUE, &fnum, FALSE);
- if (fp == NULL || (fnum >= 0 && fnum != curbuf->b_fnum))
+ if (list2fpos(&argvars[1], &p2, &fnum, NULL, FALSE) != OK
+ || (fnum >= 0 && fnum != curbuf->b_fnum))
return;
- p2 = *fp;
- pos1 = tv_get_string(&argvars[0]);
- pos2 = tv_get_string(&argvars[1]);
- type = tv_get_string(&argvars[2]);
-
- is_visual = (pos1[0] == 'v' && pos1[1] == NUL)
- || (pos2[0] == 'v' && pos2[1] == NUL);
-
- if (is_visual && !VIsual_active)
- return;
+ if (argvars[2].v_type == VAR_DICT)
+ {
+ is_select_exclusive = dict_get_bool(
+ argvars[2].vval.v_dict, "exclusive", *p_sel == 'e');
+ type = 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;
+ }
if (type[0] == 'v' && type[1] == NUL)
region_type = MCHAR;
@@ -5539,6 +5542,10 @@ f_getregion(typval_T *argvars, typval_T *rettv)
save_virtual = virtual_op;
virtual_op = virtual_active();
+ // NOTE: Adjust is needed.
+ p1.col--;
+ p2.col--;
+
if (!LT_POS(p1, p2))
{
// swap position
@@ -5552,7 +5559,7 @@ f_getregion(typval_T *argvars, typval_T *rettv)
if (region_type == MCHAR)
{
// handle 'selection' == "exclusive"
- if (*p_sel == 'e' && !EQUAL_POS(p1, p2))
+ if (is_select_exclusive && !EQUAL_POS(p1, p2))
{
if (p2.coladd > 0)
p2.coladd--;
@@ -5590,7 +5597,7 @@ f_getregion(typval_T *argvars, typval_T *rettv)
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);