aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval/funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r--src/nvim/eval/funcs.c194
1 files changed, 156 insertions, 38 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index e7fb6ed504..9feecadb6f 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -248,7 +248,7 @@ static int non_zero_arg(typval_T *argvars)
static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T f;
- float_T (*function)(float_T) = (float_T (*)(float_T))fptr;
+ float_T (*function)(float_T) = (float_T (*)(float_T)) fptr;
rettv->v_type = VAR_FLOAT;
if (tv_get_float_chk(argvars, &f)) {
@@ -1802,7 +1802,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- rettv->vval.v_number = diff_check_fill(curwin, tv_get_lnum(argvars));
+ rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars)));
}
/*
@@ -2695,13 +2695,13 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- linenr_T foldstart;
- linenr_T foldend;
+ linenr_T foldstart;
+ linenr_T foldend;
char_u *dashes;
- linenr_T lnum;
+ linenr_T lnum;
char_u *s;
char_u *r;
- int len;
+ int len;
char *txt;
rettv->v_type = VAR_STRING;
@@ -3310,10 +3310,10 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *pat;
- expand_T xpc;
- bool filtered = false;
- int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH
- | WILD_NO_BEEP;
+ expand_T xpc;
+ bool filtered = false;
+ int options = WILD_SILENT | WILD_USE_NL | WILD_ADD_SLASH
+ | WILD_NO_BEEP;
if (argvars[1].v_type != VAR_STRING) {
EMSG2(_(e_invarg2), "type must be a string");
@@ -4113,8 +4113,8 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
//
static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
{
- int dir;
- int height = wp->w_height;
+ int dir;
+ int height = wp->w_height;
win_T *oldwin = curwin;
if (wp == targetwin) {
@@ -4153,7 +4153,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp;
win_T *targetwin;
- int flags = 0, size = 0;
+ int flags = 0, size = 0;
wp = find_win_by_nr_or_id(&argvars[0]);
targetwin = find_win_by_nr_or_id(&argvars[1]);
@@ -5968,7 +5968,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
const SomeMatchType type)
{
char_u *str = NULL;
- long len = 0;
+ long len = 0;
char_u *expr = NULL;
regmatch_T regmatch;
char_u *save_cpo;
@@ -7218,6 +7218,61 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
fclose(fd);
}
+/// "getreginfo()" function
+static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ const char *strregname;
+ if (argvars[0].v_type != VAR_UNKNOWN) {
+ strregname = tv_get_string_chk(&argvars[0]);
+ if (strregname == NULL) {
+ return;
+ }
+ } else {
+ strregname = (const char *)get_vim_var_str(VV_REG);
+ }
+
+ int regname = (strregname == NULL ? '"' : *strregname);
+ if (regname == 0 || regname == '@') {
+ regname = '"';
+ }
+
+ tv_dict_alloc_ret(rettv);
+ dict_T *const dict = rettv->vval.v_dict;
+
+ list_T *const list = get_reg_contents(regname, kGRegExprSrc | kGRegList);
+ if (list == NULL) {
+ return;
+ }
+ tv_dict_add_list(dict, S_LEN("regcontents"), list);
+
+ char buf[NUMBUFLEN + 2];
+ buf[0] = NUL;
+ buf[1] = NUL;
+ colnr_T reglen = 0;
+ switch (get_reg_type(regname, &reglen)) {
+ case kMTLineWise:
+ buf[0] = 'V';
+ break;
+ case kMTCharWise:
+ buf[0] = 'v';
+ break;
+ case kMTBlockWise:
+ vim_snprintf(buf, sizeof(buf), "%c%d", Ctrl_V, reglen + 1);
+ break;
+ case kMTUnknown:
+ abort();
+ }
+ tv_dict_add_str(dict, S_LEN("regtype"), buf);
+
+ buf[0] = get_register_name(get_unname_register());
+ buf[1] = NUL;
+ if (regname == '"') {
+ tv_dict_add_str(dict, S_LEN("points_to"), buf);
+ } else {
+ tv_dict_add_bool(dict, S_LEN("isunnamed"), regname == buf[0] ? kBoolVarTrue : kBoolVarFalse);
+ }
+}
+
// "reg_executing()" function
static void f_reg_executing(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
@@ -9001,7 +9056,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T pos;
int fnum;
- colnr_T curswant = -1;
+ colnr_T curswant = -1;
rettv->vval.v_number = -1;
const char *const name = tv_get_string_chk(argvars);
@@ -9039,6 +9094,36 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
set_qf_ll_list(NULL, argvars, rettv);
}
+/// Translate a register type string to the yank type and block length
+static int get_yank_type(char_u **const pp, MotionType *const yank_type, long *const block_len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char_u *stropt = *pp;
+ switch (*stropt) {
+ case 'v':
+ case 'c': // character-wise selection
+ *yank_type = kMTCharWise;
+ break;
+ case 'V':
+ case 'l': // line-wise selection
+ *yank_type = kMTLineWise;
+ break;
+ case 'b':
+ case Ctrl_V: // block-wise selection
+ *yank_type = kMTBlockWise;
+ if (ascii_isdigit(stropt[1])) {
+ stropt++;
+ *block_len = getdigits_long(&stropt, false, 0) - 1;
+ stropt--;
+ }
+ break;
+ default:
+ return FAIL;
+ }
+ *pp = stropt;
+ return OK;
+}
+
/*
* "setreg()" function
*/
@@ -9063,8 +9148,53 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
regname = '"';
}
+ const typval_T *regcontents = NULL;
+ int pointreg = 0;
+ if (argvars[1].v_type == VAR_DICT) {
+ dict_T *const d = argvars[1].vval.v_dict;
+
+ if (tv_dict_len(d) == 0) {
+ // Empty dict, clear the register (like setreg(0, []))
+ char_u *lstval[2] = { NULL, NULL };
+ write_reg_contents_lst(regname, lstval, false, kMTUnknown, -1);
+ return;
+ }
+
+ dictitem_T *const di = tv_dict_find(d, "regcontents", -1);
+ if (di != NULL) {
+ regcontents = &di->di_tv;
+ }
+
+ const char *stropt = tv_dict_get_string(d, "regtype", false);
+ if (stropt != NULL) {
+ const int ret = get_yank_type((char_u **)&stropt, &yank_type, &block_len);
+
+ if (ret == FAIL || *(++stropt) != NUL) {
+ EMSG2(_(e_invargval), "value");
+ return;
+ }
+ }
+
+ if (regname == '"') {
+ stropt = tv_dict_get_string(d, "points_to", false);
+ if (stropt != NULL) {
+ pointreg = *stropt;
+ regname = pointreg;
+ }
+ } else if (tv_dict_get_number(d, "isunnamed")) {
+ pointreg = regname;
+ }
+ } else {
+ regcontents = &argvars[1];
+ }
+
bool set_unnamed = false;
if (argvars[2].v_type != VAR_UNKNOWN) {
+ if (yank_type != kMTUnknown) {
+ EMSG2(_(e_toomanyarg), "setreg");
+ return;
+ }
+
const char *stropt = tv_get_string_chk(&argvars[2]);
if (stropt == NULL) {
return; // Type error.
@@ -9075,33 +9205,18 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
case 'A': // append
append = true;
break;
- case 'v':
- case 'c': // character-wise selection
- yank_type = kMTCharWise;
- break;
- case 'V':
- case 'l': // line-wise selection
- yank_type = kMTLineWise;
- break;
- case 'b':
- case Ctrl_V: // block-wise selection
- yank_type = kMTBlockWise;
- if (ascii_isdigit(stropt[1])) {
- stropt++;
- block_len = getdigits_long((char_u **)&stropt, true, 0) - 1;
- stropt--;
- }
- break;
case 'u':
case '"': // unnamed register
set_unnamed = true;
break;
+ default:
+ get_yank_type((char_u **)&stropt, &yank_type, &block_len);
}
}
}
- if (argvars[1].v_type == VAR_LIST) {
- list_T *ll = argvars[1].vval.v_list;
+ if (regcontents != NULL && regcontents->v_type == VAR_LIST) {
+ list_T *const ll = regcontents->vval.v_list;
// If the list is NULL handle like an empty list.
const int len = tv_list_len(ll);
@@ -9137,14 +9252,17 @@ free_lstval:
xfree(*--curallocval);
}
xfree(lstval);
- } else {
- const char *strval = tv_get_string_chk(&argvars[1]);
+ } else if (regcontents != NULL) {
+ const char *const strval = tv_get_string_chk(regcontents);
if (strval == NULL) {
return;
}
write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval),
append, yank_type, block_len);
}
+ if (pointreg != 0) {
+ get_yank_register(pointreg, YREG_YANK);
+ }
rettv->vval.v_number = 0;
if (set_unnamed) {
@@ -9201,7 +9319,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static char *e_invact2 = N_("E962: Invalid action: '%s'");
win_T *wp;
dict_T *d;
- int action = 'r';
+ int action = 'r';
rettv->vval.v_number = -1;
@@ -10683,7 +10801,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0]));
+ rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0]), true);
}
/*