# HG changeset patch # User Bram Moolenaar # Date 1592846106 -7200 # Node ID 1c36b96522aee61a67c90cee271e907ca587839f # Parent e4473542807d25339cb778c6e04af1fe12c453c4 patch 8.2.1035: setreg() does not always clear the register Commit: https://github.com/vim/vim/commit/7633fe595e6a27d6bb376548ff89f0dcce481600 Author: Bram Moolenaar Date: Mon Jun 22 19:10:56 2020 +0200 patch 8.2.1035: setreg() does not always clear the register Problem: setreg() does not always clear the register. Solution: Clear the register if the dict argument is empty. (Andy Massimino, closes #3370) diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -6002,11 +6002,11 @@ static int srand_seed_for_testing_is_use f_test_srand_seed(typval_T *argvars, typval_T *rettv UNUSED) { if (argvars[0].v_type == VAR_UNKNOWN) - srand_seed_for_testing_is_used = FALSE; + srand_seed_for_testing_is_used = FALSE; else { - srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]); - srand_seed_for_testing_is_used = TRUE; + srand_seed_for_testing = (UINT32_T)tv_get_number(&argvars[0]); + srand_seed_for_testing_is_used = TRUE; } } @@ -6019,7 +6019,7 @@ init_srand(UINT32_T *x) if (srand_seed_for_testing_is_used) { - *x = srand_seed_for_testing; + *x = srand_seed_for_testing; return; } #ifndef MSWIN @@ -7269,6 +7269,37 @@ f_setpos(typval_T *argvars, typval_T *re } /* + * Translate a register type string to the yank type and block length + */ + static int +get_yank_type(char_u **pp, char_u *yank_type, long *block_len) +{ + char_u *stropt = *pp; + switch (*stropt) + { + case 'v': case 'c': // character-wise selection + *yank_type = MCHAR; + break; + case 'V': case 'l': // line-wise selection + *yank_type = MLINE; + break; + case 'b': case Ctrl_V: // block-wise selection + *yank_type = MBLOCK; + if (VIM_ISDIGIT(stropt[1])) + { + ++stropt; + *block_len = getdigits(&stropt) - 1; + --stropt; + } + break; + default: + return FAIL; + } + *pp = stropt; + return OK; +} + +/* * "setreg()" function */ static void @@ -7302,30 +7333,31 @@ f_setreg(typval_T *argvars, typval_T *re if (argvars[1].v_type == VAR_DICT) { dict_T *d = argvars[1].vval.v_dict; - dictitem_T *di = dict_find(d, (char_u *)"regcontents", -1); + dictitem_T *di; + + if (d == NULL || d->dv_hashtab.ht_used == 0) + { + // Empty dict, clear the register (like setreg(0, [])) + char_u *lstval[2] = {NULL, NULL}; + write_reg_contents_lst(regname, lstval, 0, FALSE, MAUTO, -1); + return; + } + + di = dict_find(d, (char_u *)"regcontents", -1); if (di != NULL) regcontents = &di->di_tv; stropt = dict_get_string(d, (char_u *)"regtype", FALSE); if (stropt != NULL) - switch (*stropt) + { + int ret = get_yank_type(&stropt, &yank_type, &block_len); + + if (ret == FAIL || *++stropt != NUL) { - case 'v': // character-wise selection - yank_type = MCHAR; - break; - case 'V': // line-wise selection - yank_type = MLINE; - break; - case Ctrl_V: // block-wise selection - yank_type = MBLOCK; - if (VIM_ISDIGIT(stropt[1])) - { - ++stropt; - block_len = getdigits(&stropt) - 1; - --stropt; - } - break; + semsg(_(e_invargval), "value"); + return; } + } if (regname == '"') { @@ -7344,6 +7376,12 @@ f_setreg(typval_T *argvars, typval_T *re if (argvars[2].v_type != VAR_UNKNOWN) { + if (yank_type != MAUTO) + { + semsg(_(e_toomanyarg), "setreg"); + return; + } + stropt = tv_get_string_chk(&argvars[2]); if (stropt == NULL) return; // type error @@ -7353,21 +7391,8 @@ f_setreg(typval_T *argvars, typval_T *re case 'a': case 'A': // append append = TRUE; break; - case 'v': case 'c': // character-wise selection - yank_type = MCHAR; - break; - case 'V': case 'l': // line-wise selection - yank_type = MLINE; - break; - case 'b': case Ctrl_V: // block-wise selection - yank_type = MBLOCK; - if (VIM_ISDIGIT(stropt[1])) - { - ++stropt; - block_len = getdigits(&stropt) - 1; - --stropt; - } - break; + default: + get_yank_type(&stropt, &yank_type, &block_len); } } diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -485,6 +485,14 @@ func Test_set_register_dict() call assert_equal(['six'], getreginfo('0').regcontents) call assert_equal(['six'], getreginfo('"').regcontents) + let @x = 'one' + call setreg('x', {}) + call assert_equal(1, len(split(execute('reg x'), '\n'))) + + call assert_fails("call setreg('0', #{regtype: 'V'}, 'v')", 'E118:') + call assert_fails("call setreg('0', #{regtype: 'X'})", 'E475:') + call assert_fails("call setreg('0', #{regtype: 'vy'})", 'E475:') + bwipe! endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -755,6 +755,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1035, +/**/ 1034, /**/ 1033,