Patch 8.1.0902
Problem:    Incomplete set of assignment operators.
Solution:   Add /=, *= and %=. (Ozaki Kiichi, closes #3931)
Files:      runtime/doc/eval.txt src/eval.c src/testdir/test_vimscript.vim


*** ../vim-8.1.0901/runtime/doc/eval.txt        2019-02-10 23:18:49.034187552 
+0100
--- runtime/doc/eval.txt        2019-02-12 22:21:20.627600700 +0100
***************
*** 10774,10782 ****
                        When the selected range of items is partly past the
                        end of the list, items will be added.
  
!                                       *:let+=* *:let-=* *:let.=* *E734*
  :let {var} += {expr1} Like ":let {var} = {var} + {expr1}".
  :let {var} -= {expr1} Like ":let {var} = {var} - {expr1}".
  :let {var} .= {expr1} Like ":let {var} = {var} . {expr1}".
                        These fail if {var} was not set yet and when the type
                        of {var} and {expr1} don't fit the operator.
--- 10836,10848 ----
                        When the selected range of items is partly past the
                        end of the list, items will be added.
  
!                                             *:let+=* *:let-=* *:letstar=*
!                                             *:let/=* *:let%=* *:let.=* *E734*
  :let {var} += {expr1} Like ":let {var} = {var} + {expr1}".
  :let {var} -= {expr1} Like ":let {var} = {var} - {expr1}".
+ :let {var} *= {expr1} Like ":let {var} = {var} * {expr1}".
+ :let {var} /= {expr1} Like ":let {var} = {var} / {expr1}".
+ :let {var} %= {expr1} Like ":let {var} = {var} % {expr1}".
  :let {var} .= {expr1} Like ":let {var} = {var} . {expr1}".
                        These fail if {var} was not set yet and when the type
                        of {var} and {expr1} don't fit the operator.
*** ../vim-8.1.0901/src/eval.c  2019-02-12 20:48:06.646810620 +0100
--- src/eval.c  2019-02-12 22:25:01.466416885 +0100
***************
*** 1197,1202 ****
--- 1197,1205 ----
   * ":let var = expr"          assignment command.
   * ":let var += expr"         assignment command.
   * ":let var -= expr"         assignment command.
+  * ":let var *= expr"         assignment command.
+  * ":let var /= expr"         assignment command.
+  * ":let var %= expr"         assignment command.
   * ":let var .= expr"         assignment command.
   * ":let [var1, var2] = expr" unpack list.
   */
***************
*** 1216,1225 ****
      argend = skip_var_list(arg, &var_count, &semicolon);
      if (argend == NULL)
        return;
!     if (argend > arg && argend[-1] == '.')  /* for var.='str' */
        --argend;
      expr = skipwhite(argend);
!     if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
                          && expr[1] == '='))
      {
        /*
--- 1219,1228 ----
      argend = skip_var_list(arg, &var_count, &semicolon);
      if (argend == NULL)
        return;
!     if (argend > arg && argend[-1] == '.')  // for var.='str'
        --argend;
      expr = skipwhite(argend);
!     if (*expr != '=' && !(vim_strchr((char_u *)"+-*/%.", *expr) != NULL
                          && expr[1] == '='))
      {
        /*
***************
*** 1249,1256 ****
        op[1] = NUL;
        if (*expr != '=')
        {
!           if (vim_strchr((char_u *)"+-.", *expr) != NULL)
!               op[0] = *expr;   /* +=, -= or .= */
            expr = skipwhite(expr + 2);
        }
        else
--- 1252,1259 ----
        op[1] = NUL;
        if (*expr != '=')
        {
!           if (vim_strchr((char_u *)"+-*/%.", *expr) != NULL)
!               op[0] = *expr;   // +=, -=, *=, /=, %= or .=
            expr = skipwhite(expr + 2);
        }
        else
***************
*** 1671,1677 ****
            semsg(_(e_invarg2), name - 1);
        else
        {
!           if (op != NULL && (*op == '+' || *op == '-'))
                semsg(_(e_letwrong), op);
            else if (endchars != NULL
                             && vim_strchr(endchars, *skipwhite(arg)) == NULL)
--- 1674,1680 ----
            semsg(_(e_invarg2), name - 1);
        else
        {
!           if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
                semsg(_(e_letwrong), op);
            else if (endchars != NULL
                             && vim_strchr(endchars, *skipwhite(arg)) == NULL)
***************
*** 1744,1761 ****
                        || (opt_type == 0 && *op != '.'))
                {
                    semsg(_(e_letwrong), op);
!                   s = NULL;  /* don't set the value */
                }
                else
                {
!                   if (opt_type == 1)  /* number */
                    {
!                       if (*op == '+')
!                           n = numval + n;
!                       else
!                           n = numval - n;
                    }
!                   else if (opt_type == 0 && stringval != NULL) /* string */
                    {
                        s = concat_str(stringval, s);
                        vim_free(stringval);
--- 1747,1768 ----
                        || (opt_type == 0 && *op != '.'))
                {
                    semsg(_(e_letwrong), op);
!                   s = NULL;  // don't set the value
                }
                else
                {
!                   if (opt_type == 1)  // number
                    {
!                       switch (*op)
!                       {
!                           case '+': n = numval + n; break;
!                           case '-': n = numval - n; break;
!                           case '*': n = numval * n; break;
!                           case '/': n = numval / n; break;
!                           case '%': n = numval % n; break;
!                       }
                    }
!                   else if (opt_type == 0 && stringval != NULL) // string
                    {
                        s = concat_str(stringval, s);
                        vim_free(stringval);
***************
*** 1779,1785 ****
      else if (*arg == '@')
      {
        ++arg;
!       if (op != NULL && (*op == '+' || *op == '-'))
            semsg(_(e_letwrong), op);
        else if (endchars != NULL
                         && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
--- 1786,1792 ----
      else if (*arg == '@')
      {
        ++arg;
!       if (op != NULL && vim_strchr((char_u *)"+-*/%", *op) != NULL)
            semsg(_(e_letwrong), op);
        else if (endchars != NULL
                         && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL)
***************
*** 2254,2260 ****
  /*
   * Set a variable that was parsed by get_lval() to "rettv".
   * "endp" points to just after the parsed name.
!  * "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
   */
      static void
  set_var_lval(
--- 2261,2268 ----
  /*
   * Set a variable that was parsed by get_lval() to "rettv".
   * "endp" points to just after the parsed name.
!  * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
!  * "%" for "%=", "." for ".=" or "=" for "=".
   */
      static void
  set_var_lval(
***************
*** 2327,2333 ****
        {
            typval_T tv;
  
!           /* handle +=, -= and .= */
            di = NULL;
            if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
                                             &tv, &di, TRUE, FALSE) == OK)
--- 2335,2341 ----
        {
            typval_T tv;
  
!           // handle +=, -=, *=, /=, %= and .=
            di = NULL;
            if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
                                             &tv, &di, TRUE, FALSE) == OK)
***************
*** 2448,2454 ****
  }
  
  /*
!  * Handle "tv1 += tv2", "tv1 -= tv2" and "tv1 .= tv2"
   * Returns OK or FAIL.
   */
      static int
--- 2456,2463 ----
  }
  
  /*
!  * Handle "tv1 += tv2", "tv1 -= tv2", "tv1 *= tv2", "tv1 /= tv2", "tv1 %= tv2"
!  * and "tv1 .= tv2"
   * Returns OK or FAIL.
   */
      static int
***************
*** 2490,2496 ****
            case VAR_LIST:
                if (*op != '+' || tv2->v_type != VAR_LIST)
                    break;
!               /* List += List */
                if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
                    list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
                return OK;
--- 2499,2505 ----
            case VAR_LIST:
                if (*op != '+' || tv2->v_type != VAR_LIST)
                    break;
!               // List += List
                if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL)
                    list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
                return OK;
***************
*** 2499,2517 ****
            case VAR_STRING:
                if (tv2->v_type == VAR_LIST)
                    break;
!               if (*op == '+' || *op == '-')
                {
!                   /* nr += nr  or  nr -= nr*/
                    n = tv_get_number(tv1);
  #ifdef FEAT_FLOAT
                    if (tv2->v_type == VAR_FLOAT)
                    {
                        float_T f = n;
  
!                       if (*op == '+')
!                           f += tv2->vval.v_float;
!                       else
!                           f -= tv2->vval.v_float;
                        clear_tv(tv1);
                        tv1->v_type = VAR_FLOAT;
                        tv1->vval.v_float = f;
--- 2508,2531 ----
            case VAR_STRING:
                if (tv2->v_type == VAR_LIST)
                    break;
!               if (vim_strchr((char_u *)"+-*/%", *op) != NULL)
                {
!                   // nr += nr , nr -= nr , nr *=nr , nr /= nr , nr %= nr
                    n = tv_get_number(tv1);
  #ifdef FEAT_FLOAT
                    if (tv2->v_type == VAR_FLOAT)
                    {
                        float_T f = n;
  
!                       if (*op == '%')
!                           break;
!                       switch (*op)
!                       {
!                           case '+': f += tv2->vval.v_float; break;
!                           case '-': f -= tv2->vval.v_float; break;
!                           case '*': f *= tv2->vval.v_float; break;
!                           case '/': f /= tv2->vval.v_float; break;
!                       }
                        clear_tv(tv1);
                        tv1->v_type = VAR_FLOAT;
                        tv1->vval.v_float = f;
***************
*** 2519,2528 ****
                    else
  #endif
                    {
!                       if (*op == '+')
!                           n += tv_get_number(tv2);
!                       else
!                           n -= tv_get_number(tv2);
                        clear_tv(tv1);
                        tv1->v_type = VAR_NUMBER;
                        tv1->vval.v_number = n;
--- 2533,2546 ----
                    else
  #endif
                    {
!                       switch (*op)
!                       {
!                           case '+': n += tv_get_number(tv2); break;
!                           case '-': n -= tv_get_number(tv2); break;
!                           case '*': n *= tv_get_number(tv2); break;
!                           case '/': n /= tv_get_number(tv2); break;
!                           case '%': n %= tv_get_number(tv2); break;
!                       }
                        clear_tv(tv1);
                        tv1->v_type = VAR_NUMBER;
                        tv1->vval.v_number = n;
***************
*** 2533,2539 ****
                    if (tv2->v_type == VAR_FLOAT)
                        break;
  
!                   /* str .= str */
                    s = tv_get_string(tv1);
                    s = concat_str(s, tv_get_string_buf(tv2, numbuf));
                    clear_tv(tv1);
--- 2551,2557 ----
                    if (tv2->v_type == VAR_FLOAT)
                        break;
  
!                   // str .= str
                    s = tv_get_string(tv1);
                    s = concat_str(s, tv_get_string_buf(tv2, numbuf));
                    clear_tv(tv1);
***************
*** 2547,2553 ****
                {
                    float_T f;
  
!                   if (*op == '.' || (tv2->v_type != VAR_FLOAT
                                    && tv2->v_type != VAR_NUMBER
                                    && tv2->v_type != VAR_STRING))
                        break;
--- 2565,2572 ----
                {
                    float_T f;
  
!                   if (*op == '%' || *op == '.'
!                                  || (tv2->v_type != VAR_FLOAT
                                    && tv2->v_type != VAR_NUMBER
                                    && tv2->v_type != VAR_STRING))
                        break;
***************
*** 2555,2564 ****
                        f = tv2->vval.v_float;
                    else
                        f = tv_get_number(tv2);
!                   if (*op == '+')
!                       tv1->vval.v_float += f;
!                   else
!                       tv1->vval.v_float -= f;
                }
  #endif
                return OK;
--- 2574,2586 ----
                        f = tv2->vval.v_float;
                    else
                        f = tv_get_number(tv2);
!                   switch (*op)
!                   {
!                       case '+': tv1->vval.v_float += f; break;
!                       case '-': tv1->vval.v_float -= f; break;
!                       case '*': tv1->vval.v_float *= f; break;
!                       case '/': tv1->vval.v_float /= f; break;
!                   }
                }
  #endif
                return OK;
*** ../vim-8.1.0901/src/testdir/test_vimscript.vim      2019-01-09 
23:00:58.001176090 +0100
--- src/testdir/test_vimscript.vim      2019-02-12 22:21:20.627600700 +0100
***************
*** 1441,1446 ****
--- 1441,1524 ----
    enew! | close
  endfunc
  
+ func Test_compound_assignment_operators()
+     " Test for number
+     let x = 1
+     let x += 10
+     call assert_equal(11, x)
+     let x -= 5
+     call assert_equal(6, x)
+     let x *= 4
+     call assert_equal(24, x)
+     let x /= 3
+     call assert_equal(8, x)
+     let x %= 3
+     call assert_equal(2, x)
+     let x .= 'n'
+     call assert_equal('2n', x)
+ 
+     " Test for string
+     let x = 'str'
+     let x .= 'ing'
+     call assert_equal('string', x)
+     let x += 1
+     call assert_equal(1, x)
+     let x -= 1.5
+     call assert_equal(-0.5, x)
+ 
+     if has('float')
+         " Test for float
+         let x = 0.5
+         let x += 4.5
+         call assert_equal(5.0, x)
+         let x -= 1.5
+         call assert_equal(3.5, x)
+         let x *= 3.0
+         call assert_equal(10.5, x)
+         let x /= 2.5
+         call assert_equal(4.2, x)
+         call assert_fails('let x %= 0.5', 'E734')
+         call assert_fails('let x .= "f"', 'E734')
+     endif
+ 
+     " Test for environment variable
+     let $FOO = 1
+     call assert_fails('let $FOO += 1', 'E734')
+     call assert_fails('let $FOO -= 1', 'E734')
+     call assert_fails('let $FOO *= 1', 'E734')
+     call assert_fails('let $FOO /= 1', 'E734')
+     call assert_fails('let $FOO %= 1', 'E734')
+     let $FOO .= 's'
+     call assert_equal('1s', $FOO)
+     unlet $FOO
+ 
+     " Test for option variable (type: number)
+     let &scrolljump = 1
+     let &scrolljump += 5
+     call assert_equal(6, &scrolljump)
+     let &scrolljump -= 2
+     call assert_equal(4, &scrolljump)
+     let &scrolljump *= 3
+     call assert_equal(12, &scrolljump)
+     let &scrolljump /= 2
+     call assert_equal(6, &scrolljump)
+     let &scrolljump %= 5
+     call assert_equal(1, &scrolljump)
+     call assert_fails('let &scrolljump .= "j"', 'E734')
+     set scrolljump&vim
+ 
+     " Test for register
+     let @/ = 1
+     call assert_fails('let @/ += 1', 'E734')
+     call assert_fails('let @/ -= 1', 'E734')
+     call assert_fails('let @/ *= 1', 'E734')
+     call assert_fails('let @/ /= 1', 'E734')
+     call assert_fails('let @/ %= 1', 'E734')
+     let @/ .= 's'
+     call assert_equal('1s', @/)
+     let @/ = ''
+ endfunc
+ 
  
"-------------------------------------------------------------------------------
  " Modelines                                                               {{{1
  " vim: ts=8 sw=4 tw=80 fdm=marker
*** ../vim-8.1.0901/src/version.c       2019-02-12 22:15:03.073282144 +0100
--- src/version.c       2019-02-12 22:22:34.399217184 +0100
***************
*** 785,786 ****
--- 785,788 ----
  {   /* Add new patch number below this line */
+ /**/
+     902,
  /**/

-- 
This message contains 78% recycled characters.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui