]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.1035: setreg() does not always clear the register v8.2.1035
authorBram Moolenaar <Bram@vim.org>
Mon, 22 Jun 2020 17:10:56 +0000 (19:10 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 22 Jun 2020 17:10:56 +0000 (19:10 +0200)
Problem:    setreg() does not always clear the register.
Solution:   Clear the register if the dict argument is empty. (Andy Massimino,
            closes #3370)

src/evalfunc.c
src/testdir/test_registers.vim
src/version.c

index 66788837575c8179adac588c9006895a9b29a44d..c4ae951b60932cdd555398ce882e3801421c21e8 100644 (file)
@@ -6002,11 +6002,11 @@ static int      srand_seed_for_testing_is_used = FALSE;
 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
@@ -7268,6 +7268,37 @@ f_setpos(typval_T *argvars, typval_T *rettv)
     }
 }
 
+/*
+ * 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
  */
@@ -7302,30 +7333,31 @@ f_setreg(typval_T *argvars, typval_T *rettv)
     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 *rettv)
 
     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 *rettv)
                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);
            }
     }
 
index 627799c49319cc7a4e805d8a07edceaa63285652..c9135628c06fc3a7f2c663c0eb8404490be7d9f4 100644 (file)
@@ -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
 
index 367972d2fc9012dea7367960c614afa69c8742ea..3c6b744b5612fefd2a083c259650bffeebfe114b 100644 (file)
@@ -754,6 +754,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1035,
 /**/
     1034,
 /**/