changeset 5796:f084024c0ddb v7.4.242

updated for version 7.4.242 Problem: getreg() does not distinguish between a NL used for a line break and a NL used for a NUL character. Solution: Add another argument to return a list. (ZyX)
author Bram Moolenaar <bram@vim.org>
date Wed, 02 Apr 2014 19:55:10 +0200
parents 64e4633f0751
children fa96ffb832d8
files runtime/doc/eval.txt src/Makefile src/eval.c src/ops.c src/proto/ops.pro src/testdir/Make_amiga.mak src/testdir/Make_dos.mak src/testdir/Make_ming.mak src/testdir/Make_os2.mak src/testdir/Make_vms.mms src/testdir/test_eval.in src/testdir/test_eval.ok src/version.c src/vim.h
diffstat 14 files changed, 138 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1819,7 +1819,8 @@ getmatches()			List	list of current matc
 getpid()			Number	process ID of Vim
 getpos( {expr})			List	position of cursor, mark, etc.
 getqflist()			List	list of quickfix items
-getreg( [{regname} [, 1]])	String	contents of register
+getreg( [{regname} [, 1 [, {list}]]])
+				String or List   contents of register
 getregtype( [{regname}])	String	type of register
 gettabvar( {nr}, {varname} [, {def}])
 				any	variable {varname} in tab {nr} or {def}
@@ -3467,7 +3468,7 @@ getqflist()						*getqflist()*
 			:endfor
 
 
-getreg([{regname} [, 1]])				*getreg()*
+getreg([{regname} [, 1 [, {list}]]])			*getreg()*
 		The result is a String, which is the contents of register
 		{regname}.  Example: >
 			:let cliptext = getreg('*')
@@ -3476,6 +3477,11 @@ getreg([{regname} [, 1]])				*getreg()*
 		getreg('=', 1) returns the expression itself, so that it can
 		be restored with |setreg()|.  For other registers the extra
 		argument is ignored, thus you can always give it.
+		If {list} is present and non-zero result type is changed to 
+		|List|. Each list item is one text line. Use it if you care
+		about zero bytes possibly present inside register: without
+		third argument both NLs and zero bytes are represented as NLs
+		(see |NL-used-for-Nul|).
 		If {regname} is not specified, |v:register| is used.
 
 
--- a/src/Makefile
+++ b/src/Makefile
@@ -1880,6 +1880,7 @@ unittest unittests: $(UNITTEST_TARGETS)
 
 # Run individual test, assuming that Vim was already compiled.
 test1 test2 test3 test4 test5 test6 test7 test8 test9 \
+	test_eval \
 	test_options \
 	test10 test11 test12 test13 test14 test15 test16 test17 test18 test19 \
 	test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 \
--- a/src/eval.c
+++ b/src/eval.c
@@ -2458,7 +2458,7 @@ ex_let_one(arg, tv, copy, endchars, op)
 	    p = get_tv_string_chk(tv);
 	    if (p != NULL && op != NULL && *op == '.')
 	    {
-		s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
+		s = get_reg_contents(*arg == '@' ? '"' : *arg, GREG_EXPR_SRC);
 		if (s != NULL)
 		{
 		    p = ptofree = concat_str(s, p);
@@ -5121,7 +5121,8 @@ eval7(arg, rettv, evaluate, want_string)
 		if (evaluate)
 		{
 		    rettv->v_type = VAR_STRING;
-		    rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
+		    rettv->vval.v_string = get_reg_contents(**arg,
+							    GREG_EXPR_SRC);
 		}
 		if (**arg != NUL)
 		    ++*arg;
@@ -7970,7 +7971,7 @@ static struct fst
     {"getpid",		0, 0, f_getpid},
     {"getpos",		1, 1, f_getpos},
     {"getqflist",	0, 0, f_getqflist},
-    {"getreg",		0, 2, f_getreg},
+    {"getreg",		0, 3, f_getreg},
     {"getregtype",	0, 1, f_getregtype},
     {"gettabvar",	2, 3, f_gettabvar},
     {"gettabwinvar",	3, 4, f_gettabwinvar},
@@ -11799,6 +11800,7 @@ f_getreg(argvars, rettv)
     char_u	*strregname;
     int		regname;
     int		arg2 = FALSE;
+    int		return_list = FALSE;
     int		error = FALSE;
 
     if (argvars[0].v_type != VAR_UNKNOWN)
@@ -11806,17 +11808,34 @@ f_getreg(argvars, rettv)
 	strregname = get_tv_string_chk(&argvars[0]);
 	error = strregname == NULL;
 	if (argvars[1].v_type != VAR_UNKNOWN)
+	{
 	    arg2 = get_tv_number_chk(&argvars[1], &error);
+	    if (!error && argvars[2].v_type != VAR_UNKNOWN)
+		return_list = get_tv_number_chk(&argvars[2], &error);
+	}
     }
     else
 	strregname = vimvars[VV_REG].vv_str;
+
+    if (error)
+	return;
+
     regname = (strregname == NULL ? '"' : *strregname);
     if (regname == 0)
 	regname = '"';
 
-    rettv->v_type = VAR_STRING;
-    rettv->vval.v_string = error ? NULL :
-				    get_reg_contents(regname, TRUE, arg2);
+    if (return_list)
+    {
+	rettv->v_type = VAR_LIST;
+	rettv->vval.v_list = (list_T *)get_reg_contents(regname,
+				      (arg2 ? GREG_EXPR_SRC : 0) | GREG_LIST);
+    }
+    else
+    {
+	rettv->v_type = VAR_STRING;
+	rettv->vval.v_string = get_reg_contents(regname,
+						    arg2 ? GREG_EXPR_SRC : 0);
+    }
 }
 
 /*
@@ -17891,9 +17910,6 @@ f_submatch(argvars, rettv)
     typval_T	*rettv;
 {
     int		error = FALSE;
-    char_u	**match;
-    char_u	**s;
-    listitem_T	*li;
     int		no;
     int		retList = 0;
 
--- a/src/ops.c
+++ b/src/ops.c
@@ -6166,16 +6166,49 @@ get_reg_type(regname, reglen)
     return MAUTO;
 }
 
+static char_u *getreg_wrap_one_line __ARGS((char_u *s, int flags));
+
+/*
+ * When "flags" has GREG_LIST return a list with text "s".
+ * Otherwise just return "s".
+ */
+    static char_u *
+getreg_wrap_one_line(s, flags)
+    char_u	*s;
+    int		flags;
+{
+    if (flags & GREG_LIST)
+    {
+	list_T *list = list_alloc();
+
+	if (list != NULL)
+	{
+	    if (list_append_string(list, NULL, -1) == FAIL)
+	    {
+		list_free(list, TRUE);
+		return NULL;
+	    }
+	    list->lv_first->li_tv.vval.v_string = s;
+	}
+	return (char_u *)list;
+    }
+    return s;
+}
+
 /*
  * Return the contents of a register as a single allocated string.
  * Used for "@r" in expressions and for getreg().
  * Returns NULL for error.
+ * Flags:
+ *	GREG_NO_EXPR	Do not allow expression register
+ *	GREG_EXPR_SRC	For the expression register: return expression itself,
+ *			not the result of its evaluation.
+ *	GREG_LIST	Return a list of lines in place of a single string.
  */
     char_u *
-get_reg_contents(regname, allowexpr, expr_src)
+get_reg_contents(regname, flags)
     int		regname;
-    int		allowexpr;	/* allow "=" register */
-    int		expr_src;	/* get expression for "=" register */
+    int		flags;
 {
     long	i;
     char_u	*retval;
@@ -6185,13 +6218,11 @@ get_reg_contents(regname, allowexpr, exp
     /* Don't allow using an expression register inside an expression */
     if (regname == '=')
     {
-	if (allowexpr)
-	{
-	    if (expr_src)
-		return get_expr_line_src();
-	    return get_expr_line();
-	}
-	return NULL;
+	if (flags & GREG_NO_EXPR)
+	    return NULL;
+	if (flags & GREG_EXPR_SRC)
+	    return getreg_wrap_one_line(get_expr_line_src(), flags);
+	return getreg_wrap_one_line(get_expr_line(), flags);
     }
 
     if (regname == '@')	    /* "@@" is used for unnamed register */
@@ -6209,15 +6240,33 @@ get_reg_contents(regname, allowexpr, exp
     {
 	if (retval == NULL)
 	    return NULL;
-	if (!allocated)
-	    retval = vim_strsave(retval);
-	return retval;
+	if (allocated)
+	    return getreg_wrap_one_line(retval, flags);
+	return getreg_wrap_one_line(vim_strsave(retval), flags);
     }
 
     get_yank_register(regname, FALSE);
     if (y_current->y_array == NULL)
 	return NULL;
 
+    if (flags & GREG_LIST)
+    {
+	list_T	*list = list_alloc();
+	int	error = FALSE;
+
+	if (list == NULL)
+	    return NULL;
+	for (i = 0; i < y_current->y_size; ++i)
+	    if (list_append_string(list, y_current->y_array[i], -1) == FAIL)
+		error = TRUE;
+	if (error)
+	{
+	    list_free(list, TRUE);
+	    return NULL;
+	}
+	return (char_u *)list;
+    }
+
     /*
      * Compute length of resulting string.
      */
--- a/src/proto/ops.pro
+++ b/src/proto/ops.pro
@@ -53,7 +53,7 @@ void clip_yank_selection __ARGS((int typ
 int clip_convert_selection __ARGS((char_u **str, long_u *len, VimClipboard *cbd));
 void dnd_yank_drag_data __ARGS((char_u *str, long len));
 char_u get_reg_type __ARGS((int regname, long *reglen));
-char_u *get_reg_contents __ARGS((int regname, int allowexpr, int expr_src));
+char_u *get_reg_contents __ARGS((int regname, int flags));
 void write_reg_contents __ARGS((int name, char_u *str, int maxlen, int must_append));
 void write_reg_contents_ex __ARGS((int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len));
 void clear_oparg __ARGS((oparg_T *oap));
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -36,6 +36,7 @@ SCRIPTS = test1.out test3.out test4.out 
 		test94.out test95.out test96.out test97.out test98.out \
 		test99.out test100.out test101.out test102.out test103.out \
 		test104.out test105.out test106.out \
+		test_eval.out \
 		test_options.out
 
 .SUFFIXES: .in .out
@@ -159,4 +160,5 @@ test103.out: test103.in
 test104.out: test104.in
 test105.out: test105.in
 test106.out: test106.in
+test_eval.out: test_eval.in
 test_options.out: test_options.in
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -35,6 +35,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test94.out test95.out test96.out test98.out test99.out \
 		test100.out test101.out test102.out test103.out test104.out \
 		test105.out test106.out \
+		test_eval.out \
 		test_options.out
 
 SCRIPTS32 =	test50.out test70.out
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -55,6 +55,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test94.out test95.out test96.out test98.out test99.out \
 		test100.out test101.out test102.out test103.out test104.out \
 		test105.out test106.out \
+		test_eval.out \
 		test_options.out
 
 SCRIPTS32 =	test50.out test70.out
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -37,6 +37,7 @@ SCRIPTS = test1.out test3.out test4.out 
 		test94.out test95.out test96.out test98.out test99.out \
 		test100.out test101.out test102.out test103.out test104.out \
 		test105.out test106.out \
+		test_eval.out \
 		test_options.out
 
 .SUFFIXES: .in .out
--- a/src/testdir/Make_vms.mms
+++ b/src/testdir/Make_vms.mms
@@ -96,6 +96,7 @@ SCRIPT = test1.out  test2.out  test3.out
 	 test95.out test96.out test98.out test99.out \
 	 test100.out test101.out test103.out test104.out \
 	 test105.out test106.out \
+	 test_eval.out \
 	 test_options.out
 
 # Known problems:
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_eval.in
@@ -0,0 +1,21 @@
+Test for various eval features.
+
+STARTTEST
+:so small.vim
+:"
+:" test getreg()
+/^one
+"ay3j:$put =string(getreg('a'))
+:$put =string(getreg('a', 1, 1))
+:"
+:/^result/,$w! test.out
+:qa!
+ENDTEST
+
+one
+two
+three
+four
+five
+
+result
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_eval.ok
@@ -0,0 +1,7 @@
+result
+'one
+two
+three
+four
+'
+['one', 'two', 'three', 'four']
--- a/src/version.c
+++ b/src/version.c
@@ -735,6 +735,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    242,
+/**/
     241,
 /**/
     240,
--- a/src/vim.h
+++ b/src/vim.h
@@ -2259,6 +2259,11 @@ typedef int VimClipboard;	/* This is req
 #define SREQ_WIN	1	/* Request window-local option */
 #define SREQ_BUF	2	/* Request buffer-local option */
 
+/* Flags for get_reg_contents */
+#define GREG_NO_EXPR	1	/* Do not allow expression register */
+#define GREG_EXPR_SRC	2	/* Return expression itself for "=" register */
+#define GREG_LIST	4	/* Return list */
+
 /* Character used as separated in autoload function/variable names. */
 #define AUTOLOAD_CHAR '#'