comparison src/evalfunc.c @ 20743:a672feb8fc4f v8.2.0924

patch 8.2.0924: cannot save and restore a register properly Commit: https://github.com/vim/vim/commit/bb861e293e0170455184079fa537278754b07911 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 7 18:16:36 2020 +0200 patch 8.2.0924: cannot save and restore a register properly Problem: Cannot save and restore a register properly. Solution: Add getreginfo() and make setreg() accept a dictionary. (Andy Massimino, closes #3370)
author Bram Moolenaar <Bram@vim.org>
date Sun, 07 Jun 2020 18:30:03 +0200
parents ab27db64f1fb
children d9a2e5dcfd9f
comparison
equal deleted inserted replaced
20742:8c304b9fcb1a 20743:a672feb8fc4f
92 static void f_getjumplist(typval_T *argvars, typval_T *rettv); 92 static void f_getjumplist(typval_T *argvars, typval_T *rettv);
93 static void f_getpid(typval_T *argvars, typval_T *rettv); 93 static void f_getpid(typval_T *argvars, typval_T *rettv);
94 static void f_getcurpos(typval_T *argvars, typval_T *rettv); 94 static void f_getcurpos(typval_T *argvars, typval_T *rettv);
95 static void f_getpos(typval_T *argvars, typval_T *rettv); 95 static void f_getpos(typval_T *argvars, typval_T *rettv);
96 static void f_getreg(typval_T *argvars, typval_T *rettv); 96 static void f_getreg(typval_T *argvars, typval_T *rettv);
97 static void f_getreginfo(typval_T *argvars, typval_T *rettv);
97 static void f_getregtype(typval_T *argvars, typval_T *rettv); 98 static void f_getregtype(typval_T *argvars, typval_T *rettv);
98 static void f_gettagstack(typval_T *argvars, typval_T *rettv); 99 static void f_gettagstack(typval_T *argvars, typval_T *rettv);
99 static void f_haslocaldir(typval_T *argvars, typval_T *rettv); 100 static void f_haslocaldir(typval_T *argvars, typval_T *rettv);
100 static void f_hasmapto(typval_T *argvars, typval_T *rettv); 101 static void f_hasmapto(typval_T *argvars, typval_T *rettv);
101 static void f_hlID(typval_T *argvars, typval_T *rettv); 102 static void f_hlID(typval_T *argvars, typval_T *rettv);
584 {"getmousepos", 0, 0, 0, ret_dict_number, f_getmousepos}, 585 {"getmousepos", 0, 0, 0, ret_dict_number, f_getmousepos},
585 {"getpid", 0, 0, 0, ret_number, f_getpid}, 586 {"getpid", 0, 0, 0, ret_number, f_getpid},
586 {"getpos", 1, 1, FEARG_1, ret_list_number, f_getpos}, 587 {"getpos", 1, 1, FEARG_1, ret_list_number, f_getpos},
587 {"getqflist", 0, 1, 0, ret_list_dict_any, f_getqflist}, 588 {"getqflist", 0, 1, 0, ret_list_dict_any, f_getqflist},
588 {"getreg", 0, 3, FEARG_1, ret_string, f_getreg}, 589 {"getreg", 0, 3, FEARG_1, ret_string, f_getreg},
590 {"getreginfo", 0, 1, FEARG_1, ret_dict_any, f_getreginfo},
589 {"getregtype", 0, 1, FEARG_1, ret_string, f_getregtype}, 591 {"getregtype", 0, 1, FEARG_1, ret_string, f_getregtype},
590 {"gettabinfo", 0, 1, FEARG_1, ret_list_dict_any, f_gettabinfo}, 592 {"gettabinfo", 0, 1, FEARG_1, ret_list_dict_any, f_gettabinfo},
591 {"gettabvar", 2, 3, FEARG_1, ret_any, f_gettabvar}, 593 {"gettabvar", 2, 3, FEARG_1, ret_any, f_gettabvar},
592 {"gettabwinvar", 3, 4, FEARG_1, ret_any, f_gettabwinvar}, 594 {"gettabwinvar", 3, 4, FEARG_1, ret_any, f_gettabwinvar},
593 {"gettagstack", 0, 1, FEARG_1, ret_dict_any, f_gettagstack}, 595 {"gettagstack", 0, 1, FEARG_1, ret_dict_any, f_gettagstack},
6225 for (i = start; stride > 0 ? i <= end : i >= end; i += stride) 6227 for (i = start; stride > 0 ? i <= end : i >= end; i += stride)
6226 if (list_append_number(list, (varnumber_T)i) == FAIL) 6228 if (list_append_number(list, (varnumber_T)i) == FAIL)
6227 break; 6229 break;
6228 } 6230 }
6229 6231
6232 /*
6233 * "getreginfo()" function
6234 */
6235 static void
6236 f_getreginfo(typval_T *argvars, typval_T *rettv)
6237 {
6238 char_u *strregname;
6239 int regname;
6240 char_u buf[NUMBUFLEN + 2];
6241 long reglen = 0;
6242 dict_T *dict;
6243 list_T *list;
6244
6245 if (argvars[0].v_type != VAR_UNKNOWN)
6246 {
6247 strregname = tv_get_string_chk(&argvars[0]);
6248 if (strregname == NULL)
6249 return;
6250 }
6251 else
6252 strregname = get_vim_var_str(VV_REG);
6253
6254 regname = (strregname == NULL ? '"' : *strregname);
6255 if (regname == 0 || regname == '@')
6256 regname = '"';
6257
6258 if (rettv_dict_alloc(rettv) == FAIL)
6259 return;
6260 dict = rettv->vval.v_dict;
6261
6262 list = (list_T *)get_reg_contents(regname, GREG_EXPR_SRC | GREG_LIST);
6263 if (list == NULL)
6264 return;
6265 dict_add_list(dict, "regcontents", list);
6266
6267 buf[0] = NUL;
6268 buf[1] = NUL;
6269 switch (get_reg_type(regname, &reglen))
6270 {
6271 case MLINE: buf[0] = 'V'; break;
6272 case MCHAR: buf[0] = 'v'; break;
6273 case MBLOCK:
6274 vim_snprintf((char *)buf, sizeof(buf), "%c%ld", Ctrl_V,
6275 reglen + 1);
6276 break;
6277 }
6278 dict_add_string(dict, (char *)"regtype", buf);
6279
6280 buf[0] = get_register_name(get_unname_register());
6281 buf[1] = NUL;
6282 if (regname == '"')
6283 dict_add_string(dict, (char *)"points_to", buf);
6284 else
6285 {
6286 dictitem_T *item = dictitem_alloc((char_u *)"isunnamed");
6287
6288 if (item != NULL)
6289 {
6290 item->di_tv.v_type = VAR_SPECIAL;
6291 item->di_tv.vval.v_number = regname == buf[0]
6292 ? VVAL_TRUE : VVAL_FALSE;
6293 dict_add(dict, item);
6294 }
6295 }
6296 }
6297
6230 static void 6298 static void
6231 return_register(int regname, typval_T *rettv) 6299 return_register(int regname, typval_T *rettv)
6232 { 6300 {
6233 char_u buf[2] = {0, 0}; 6301 char_u buf[2] = {0, 0};
6234 6302
7201 char_u *stropt; 7269 char_u *stropt;
7202 char_u *strval; 7270 char_u *strval;
7203 int append; 7271 int append;
7204 char_u yank_type; 7272 char_u yank_type;
7205 long block_len; 7273 long block_len;
7206 7274 typval_T *regcontents;
7275 int pointreg;
7276
7277 pointreg = 0;
7278 regcontents = NULL;
7207 block_len = -1; 7279 block_len = -1;
7208 yank_type = MAUTO; 7280 yank_type = MAUTO;
7209 append = FALSE; 7281 append = FALSE;
7210 7282
7211 strregname = tv_get_string_chk(argvars); 7283 strregname = tv_get_string_chk(argvars);
7214 if (strregname == NULL) 7286 if (strregname == NULL)
7215 return; // type error; errmsg already given 7287 return; // type error; errmsg already given
7216 regname = *strregname; 7288 regname = *strregname;
7217 if (regname == 0 || regname == '@') 7289 if (regname == 0 || regname == '@')
7218 regname = '"'; 7290 regname = '"';
7291
7292 if (argvars[1].v_type == VAR_DICT)
7293 {
7294 dict_T *d = argvars[1].vval.v_dict;
7295 dictitem_T *di = dict_find(d, (char_u *)"regcontents", -1);
7296 if (di != NULL)
7297 regcontents = &di->di_tv;
7298
7299 stropt = dict_get_string(d, (char_u *)"regtype", FALSE);
7300 if (stropt != NULL)
7301 switch (*stropt)
7302 {
7303 case 'v': // character-wise selection
7304 yank_type = MCHAR;
7305 break;
7306 case 'V': // line-wise selection
7307 yank_type = MLINE;
7308 break;
7309 case Ctrl_V: // block-wise selection
7310 yank_type = MBLOCK;
7311 if (VIM_ISDIGIT(stropt[1]))
7312 {
7313 ++stropt;
7314 block_len = getdigits(&stropt) - 1;
7315 --stropt;
7316 }
7317 break;
7318 }
7319
7320 if (regname == '"')
7321 {
7322 stropt = dict_get_string(d, (char_u *)"points_to", FALSE);
7323 if (stropt != NULL)
7324 {
7325 pointreg = *stropt;
7326 regname = pointreg;
7327 }
7328 }
7329 else if (dict_get_number(d, (char_u *)"isunnamed"))
7330 pointreg = regname;
7331 }
7332 else
7333 regcontents = &argvars[1];
7219 7334
7220 if (argvars[2].v_type != VAR_UNKNOWN) 7335 if (argvars[2].v_type != VAR_UNKNOWN)
7221 { 7336 {
7222 stropt = tv_get_string_chk(&argvars[2]); 7337 stropt = tv_get_string_chk(&argvars[2]);
7223 if (stropt == NULL) 7338 if (stropt == NULL)
7244 } 7359 }
7245 break; 7360 break;
7246 } 7361 }
7247 } 7362 }
7248 7363
7249 if (argvars[1].v_type == VAR_LIST) 7364 if (regcontents && regcontents->v_type == VAR_LIST)
7250 { 7365 {
7251 char_u **lstval; 7366 char_u **lstval;
7252 char_u **allocval; 7367 char_u **allocval;
7253 char_u buf[NUMBUFLEN]; 7368 char_u buf[NUMBUFLEN];
7254 char_u **curval; 7369 char_u **curval;
7255 char_u **curallocval; 7370 char_u **curallocval;
7256 list_T *ll = argvars[1].vval.v_list; 7371 list_T *ll = regcontents->vval.v_list;
7257 listitem_T *li; 7372 listitem_T *li;
7258 int len; 7373 int len;
7259 7374
7260 // If the list is NULL handle like an empty list. 7375 // If the list is NULL handle like an empty list.
7261 len = ll == NULL ? 0 : ll->lv_len; 7376 len = ll == NULL ? 0 : ll->lv_len;
7296 free_lstval: 7411 free_lstval:
7297 while (curallocval > allocval) 7412 while (curallocval > allocval)
7298 vim_free(*--curallocval); 7413 vim_free(*--curallocval);
7299 vim_free(lstval); 7414 vim_free(lstval);
7300 } 7415 }
7301 else 7416 else if (regcontents)
7302 { 7417 {
7303 strval = tv_get_string_chk(&argvars[1]); 7418 strval = tv_get_string_chk(regcontents);
7304 if (strval == NULL) 7419 if (strval == NULL)
7305 return; 7420 return;
7306 write_reg_contents_ex(regname, strval, -1, 7421 write_reg_contents_ex(regname, strval, -1,
7307 append, yank_type, block_len); 7422 append, yank_type, block_len);
7308 } 7423 }
7424 if (pointreg != 0)
7425 get_yank_register(pointreg, TRUE);
7426
7309 rettv->vval.v_number = 0; 7427 rettv->vval.v_number = 0;
7310 } 7428 }
7311 7429
7312 /* 7430 /*
7313 * "settagstack()" function 7431 * "settagstack()" function