diff options
Diffstat (limited to 'src/nvim/eval/funcs.c')
-rw-r--r-- | src/nvim/eval/funcs.c | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e7fb6ed504..a6d858cfa9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -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, ®len)) { + 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) { @@ -9063,6 +9118,48 @@ 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; + 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) { + switch (*stropt) { + case 'v': // character-wise selection + yank_type = kMTCharWise; + break; + case 'V': // line-wise selection + yank_type = kMTLineWise; + break; + 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; + } + } + + 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) { const char *stropt = tv_get_string_chk(&argvars[2]); @@ -9100,8 +9197,8 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - 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 +9234,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) { |