diff src/list.c @ 26578:06693d1afc48

patch 8.2.3818: cannot filter or map characters in a string Commit: https://github.com/vim/vim/commit/c479ce032f5d4d14bab9e479acbf42d758879893 Author: rbtnn <naru123456789@gmail.com> Date: Wed Dec 15 19:14:54 2021 +0000 patch 8.2.3818: cannot filter or map characters in a string Problem: Cannot filter or map characters in a string. Solution: Make filter() and map() work on a string. (Naruhiko Nishino, closes #9327)
author Bram Moolenaar <Bram@vim.org>
date Wed, 15 Dec 2021 20:15:03 +0100
parents 28745eec1dda
children 0d2a709e2ff0
line wrap: on
line diff
--- a/src/list.c
+++ b/src/list.c
@@ -2329,9 +2329,15 @@ filter_map(typval_T *argvars, typval_T *
 			    && value_check_lock(d->dv_lock, arg_errmsg, TRUE)))
 	    goto theend;
     }
+    else if (argvars[0].v_type == VAR_STRING)
+    {
+	rettv->v_type = VAR_STRING;
+	rettv->vval.v_string = NULL;
+    }
     else
     {
-	semsg(_(e_listdictblobarg), func_name);
+	semsg(_(e_argument_of_str_must_be_list_string_dictionary_or_blob),
+								    func_name);
 	goto theend;
     }
 
@@ -2480,6 +2486,66 @@ filter_map(typval_T *argvars, typval_T *
 		++idx;
 	    }
 	}
+	else if (argvars[0].v_type == VAR_STRING)
+	{
+	    char_u	*p;
+	    typval_T	tv;
+	    garray_T	ga;
+	    char_u	buf[MB_MAXBYTES + 1];
+	    int		len;
+
+	    // set_vim_var_nr() doesn't set the type
+	    set_vim_var_type(VV_KEY, VAR_NUMBER);
+
+	    ga_init2(&ga, (int)sizeof(char), 80);
+	    for (p = tv_get_string(&argvars[0]); *p != NUL; p += len)
+	    {
+	        typval_T newtv;
+
+		if (has_mbyte)
+		    len = mb_ptr2len(p);
+		else
+		    len = 1;
+
+		STRNCPY(buf, p, len);
+		buf[len] = NUL;
+
+		tv.v_type = VAR_STRING;
+		tv.vval.v_string = vim_strsave(buf);
+
+		set_vim_var_nr(VV_KEY, idx);
+		if (filter_map_one(&tv, expr, filtermap, &newtv, &rem) == FAIL
+								   || did_emsg)
+		    break;
+		if (did_emsg)
+		{
+		    clear_tv(&newtv);
+		    clear_tv(&tv);
+		    break;
+		}
+		else if (filtermap != FILTERMAP_FILTER)
+		{
+		    if (newtv.v_type != VAR_STRING)
+		    {
+			clear_tv(&newtv);
+			clear_tv(&tv);
+			emsg(_(e_stringreq));
+			break;
+		    }
+		    else
+			ga_concat(&ga, newtv.vval.v_string);
+		}
+		else if (!rem)
+		    ga_concat(&ga, tv.vval.v_string);
+
+		clear_tv(&newtv);
+		clear_tv(&tv);
+
+	        ++idx;
+	    }
+	    ga_append(&ga, NUL);
+	    rettv->vval.v_string = ga.ga_data;
+	}
 	else // argvars[0].v_type == VAR_LIST
 	{
 	    int	    prev_lock = l->lv_lock;