# HG changeset patch # User Bram Moolenaar # Date 1396461310 -7200 # Node ID f084024c0ddbba46aabfafa2996c3f7d13080ab6 # Parent 64e4633f0751c1978d13aebd0795aa2b97b976de 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) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- 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. diff --git a/src/Makefile b/src/Makefile --- 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 \ diff --git a/src/eval.c b/src/eval.c --- 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; diff --git a/src/ops.c b/src/ops.c --- 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. */ diff --git a/src/proto/ops.pro b/src/proto/ops.pro --- 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)); diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak --- 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 diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak --- 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 diff --git a/src/testdir/Make_ming.mak b/src/testdir/Make_ming.mak --- 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 diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak --- 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 diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms --- 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: diff --git a/src/testdir/test_eval.in b/src/testdir/test_eval.in 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 diff --git a/src/testdir/test_eval.ok b/src/testdir/test_eval.ok 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'] diff --git a/src/version.c b/src/version.c --- 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, diff --git a/src/vim.h b/src/vim.h --- 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 '#'