]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0868: trim() always trims both ends v8.2.0868
authorBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 20:20:36 +0000 (22:20 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 20:20:36 +0000 (22:20 +0200)
Problem:    trim() always trims both ends.
Solution:   Add an argument to only trim the beginning or end. (Yegappan
            Lakshmanan, closes #6126)

runtime/doc/eval.txt
src/evalfunc.c
src/testdir/test_functions.vim
src/version.c

index fb5ef738c8526ce109c07145044506ad714e8a34..b753aae62975c43e3624cd974ae445d34fa06322 100644 (file)
@@ -2898,7 +2898,8 @@ tolower({expr})                   String  the String {expr} switched to lowercase
 toupper({expr})                        String  the String {expr} switched to uppercase
 tr({src}, {fromstr}, {tostr})  String  translate chars of {src} in {fromstr}
                                        to chars in {tostr}
-trim({text} [, {mask}])                String  trim characters in {mask} from {text}
+trim({text} [, {mask} [, {dir}]])
+                               String  trim characters in {mask} from {text}
 trunc({expr})                  Float   truncate Float {expr}
 type({name})                   Number  type of variable {name}
 undofile({name})               String  undo file name for {name}
@@ -10245,13 +10246,22 @@ tr({src}, {fromstr}, {tostr})                         *tr()*
                Can also be used as a |method|: >
                        GetText()->tr(from, to)
 
-trim({text} [, {mask}])                                                *trim()*
+trim({text} [, {mask} [, {dir}]])                              *trim()*
                Return {text} as a String where any character in {mask} is
-               removed from the beginning and end of {text}.
+               removed from the beginning and/or end of {text}.
+
                If {mask} is not given, {mask} is all characters up to 0x20,
                which includes Tab, space, NL and CR, plus the non-breaking
                space character 0xa0.
-               This code deals with multibyte characters properly.
+
+               The optional {dir} argument specifies where to remove the
+               characters:
+                       0       remove from the beginning and end of {text}
+                       1       remove only at the beginning of {text}
+                       2       remove only at the end of {text}
+               When omitted both ends are trimmed.
+
+               This function deals with multibyte characters properly.
 
                Examples: >
                        echo trim("   some text ")
@@ -10259,7 +10269,9 @@ trim({text} [, {mask}])                                         *trim()*
                        echo trim("  \r\t\t\r RESERVE \t\n\x0B\xA0") . "_TAIL"
 <              returns "RESERVE_TAIL" >
                        echo trim("rm<Xrm<>X>rrm", "rm<>")
-<              returns "Xrm<>X" (characters in the middle are not removed)
+<              returns "Xrm<>X" (characters in the middle are not removed) >
+                       echo trim("  vim  ", " ", 2)
+<              returns "  vim"
 
                Can also be used as a |method|: >
                        GetText()->trim()
index f40a2ee6d09f4053bf6d725ed47dfad12f5e5562..92d6c066714059e910e7ef61a3ac2b78af48906c 100644 (file)
@@ -976,7 +976,7 @@ static funcentry_T global_functions[] =
     {"tolower",                1, 1, FEARG_1,    ret_string,   f_tolower},
     {"toupper",                1, 1, FEARG_1,    ret_string,   f_toupper},
     {"tr",             3, 3, FEARG_1,    ret_string,   f_tr},
-    {"trim",           1, 2, FEARG_1,    ret_string,   f_trim},
+    {"trim",           1, 3, FEARG_1,    ret_string,   f_trim},
     {"trunc",          1, 1, FEARG_1,    ret_float,    FLOAT_FUNC(f_trunc)},
     {"type",           1, 1, FEARG_1,    ret_number,   f_type},
     {"undofile",       1, 1, FEARG_1,    ret_string,   f_undofile},
@@ -8637,53 +8637,78 @@ f_trim(typval_T *argvars, typval_T *rettv)
     char_u     *prev;
     char_u     *p;
     int                c1;
+    int                dir = 0;
 
     rettv->v_type = VAR_STRING;
+    rettv->vval.v_string = NULL;
     if (head == NULL)
-    {
-       rettv->vval.v_string = NULL;
        return;
-    }
 
     if (argvars[1].v_type == VAR_STRING)
+    {
        mask = tv_get_string_buf_chk(&argvars[1], buf2);
 
-    while (*head != NUL)
-    {
-       c1 = PTR2CHAR(head);
-       if (mask == NULL)
+       if (argvars[2].v_type != VAR_UNKNOWN)
        {
-           if (c1 > ' ' && c1 != 0xa0)
-               break;
+           int error = 0;
+
+           // leading or trailing characters to trim
+           dir = (int)tv_get_number_chk(&argvars[2], &error);
+           if (error)
+               return;
+           if (dir < 0 || dir > 2)
+           {
+               semsg(_(e_invarg2), tv_get_string(&argvars[2]));
+               return;
+           }
        }
-       else
+    }
+
+    if (dir == 0 || dir == 1)
+    {
+       // Trim leading characters
+       while (*head != NUL)
        {
-           for (p = mask; *p != NUL; MB_PTR_ADV(p))
-               if (c1 == PTR2CHAR(p))
+           c1 = PTR2CHAR(head);
+           if (mask == NULL)
+           {
+               if (c1 > ' ' && c1 != 0xa0)
                    break;
-           if (*p == NUL)
-               break;
+           }
+           else
+           {
+               for (p = mask; *p != NUL; MB_PTR_ADV(p))
+                   if (c1 == PTR2CHAR(p))
+                       break;
+               if (*p == NUL)
+                   break;
+           }
+           MB_PTR_ADV(head);
        }
-       MB_PTR_ADV(head);
     }
 
-    for (tail = head + STRLEN(head); tail > head; tail = prev)
+    tail = head + STRLEN(head);
+    if (dir == 0 || dir == 2)
     {
-       prev = tail;
-       MB_PTR_BACK(head, prev);
-       c1 = PTR2CHAR(prev);
-       if (mask == NULL)
+       // Trim trailing characters
+       for (; tail > head; tail = prev)
        {
-           if (c1 > ' ' && c1 != 0xa0)
-               break;
-       }
-       else
-       {
-           for (p = mask; *p != NUL; MB_PTR_ADV(p))
-               if (c1 == PTR2CHAR(p))
+           prev = tail;
+           MB_PTR_BACK(head, prev);
+           c1 = PTR2CHAR(prev);
+           if (mask == NULL)
+           {
+               if (c1 > ' ' && c1 != 0xa0)
                    break;
-           if (*p == NUL)
-               break;
+           }
+           else
+           {
+               for (p = mask; *p != NUL; MB_PTR_ADV(p))
+                   if (c1 == PTR2CHAR(p))
+                       break;
+               if (*p == NUL)
+                   break;
+           }
        }
     }
     rettv->vval.v_string = vim_strnsave(head, (int)(tail - head));
index 9b5d97679da6f84dbf9123e0fc4e3d823d115b42..b25d98861608cdeb4fbc87ddc6ebf401e601bc72 100644 (file)
@@ -1497,6 +1497,13 @@ func Test_trim()
   call assert_equal("a", trim("a", ""))
   call assert_equal("", trim("", "a"))
 
+  call assert_equal("vim", trim("  vim  ", " ", 0))
+  call assert_equal("vim  ", trim("  vim  ", " ", 1))
+  call assert_equal("  vim", trim("  vim  ", " ", 2))
+  call assert_fails('eval trim("  vim  ", " ", [])', 'E745:')
+  call assert_fails('eval trim("  vim  ", " ", -1)', 'E475:')
+  call assert_fails('eval trim("  vim  ", " ", 3)', 'E475:')
+
   let chars = join(map(range(1, 0x20) + [0xa0], {n -> n->nr2char()}), '')
   call assert_equal("x", trim(chars . "x" . chars))
 
index 4b09557705676a0bee27634c1600b066ae7665e2..c75283f9f19dada0db424d4b0f4b5305b5d8c35d 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    868,
 /**/
     867,
 /**/