Merge pull request #1134 from splinterofchaos/getreg-nl

vim-patch:7.4.242 + vim-patch:7.4.243
This commit is contained in:
Justin M. Keyes 2014-12-11 21:35:34 -05:00
commit 4c7fe20bef
7 changed files with 469 additions and 156 deletions

View File

@ -1835,7 +1835,7 @@ ex_let_one (
p = get_tv_string_chk(tv); p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') { if (p != NULL && op != NULL && *op == '.') {
s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE); s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
if (s != NULL) { if (s != NULL) {
p = ptofree = concat_str(s, p); p = ptofree = concat_str(s, p);
free(s); free(s);
@ -4076,7 +4076,7 @@ eval7 (
case '@': ++*arg; case '@': ++*arg;
if (evaluate) { if (evaluate) {
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE); rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc);
} }
if (**arg != NUL) if (**arg != NUL)
++*arg; ++*arg;
@ -6458,7 +6458,7 @@ static struct fst {
{"getpid", 0, 0, f_getpid}, {"getpid", 0, 0, f_getpid},
{"getpos", 1, 1, f_getpos}, {"getpos", 1, 1, f_getpos},
{"getqflist", 0, 0, f_getqflist}, {"getqflist", 0, 0, f_getqflist},
{"getreg", 0, 2, f_getreg}, {"getreg", 0, 3, f_getreg},
{"getregtype", 0, 1, f_getregtype}, {"getregtype", 0, 1, f_getregtype},
{"gettabvar", 2, 3, f_gettabvar}, {"gettabvar", 2, 3, f_gettabvar},
{"gettabwinvar", 3, 4, f_gettabwinvar}, {"gettabwinvar", 3, 4, f_gettabwinvar},
@ -9518,30 +9518,44 @@ static void f_getqflist(typval_T *argvars, typval_T *rettv)
(void)get_errorlist(wp, rettv->vval.v_list); (void)get_errorlist(wp, rettv->vval.v_list);
} }
/* /// "getreg()" function
* "getreg()" function
*/
static void f_getreg(typval_T *argvars, typval_T *rettv) static void f_getreg(typval_T *argvars, typval_T *rettv)
{ {
char_u *strregname; char_u *strregname;
int regname; int regname;
int arg2 = FALSE; int arg2 = false;
int error = FALSE; bool return_list = false;
int error = false;
if (argvars[0].v_type != VAR_UNKNOWN) { if (argvars[0].v_type != VAR_UNKNOWN) {
strregname = get_tv_string_chk(&argvars[0]); strregname = get_tv_string_chk(&argvars[0]);
error = strregname == NULL; error = strregname == NULL;
if (argvars[1].v_type != VAR_UNKNOWN) if (argvars[1].v_type != VAR_UNKNOWN) {
arg2 = get_tv_number_chk(&argvars[1], &error); arg2 = get_tv_number_chk(&argvars[1], &error);
} else if (!error && argvars[2].v_type != VAR_UNKNOWN) {
return_list = get_tv_number_chk(&argvars[2], &error);
}
}
} else {
strregname = vimvars[VV_REG].vv_str; strregname = vimvars[VV_REG].vv_str;
}
if (error) {
return;
}
regname = (strregname == NULL ? '"' : *strregname); regname = (strregname == NULL ? '"' : *strregname);
if (regname == 0) if (regname == 0)
regname = '"'; regname = '"';
rettv->v_type = VAR_STRING; if (return_list) {
rettv->vval.v_string = error ? NULL : rettv->v_type = VAR_LIST;
get_reg_contents(regname, TRUE, arg2); rettv->vval.v_list =
get_reg_contents(regname, (arg2 ? kGRegExprSrc : 0) | kGRegList);
} else {
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_reg_contents(regname, arg2 ? kGRegExprSrc : 0);
}
} }
/* /*
@ -13306,7 +13320,6 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
int regname; int regname;
char_u *strregname; char_u *strregname;
char_u *stropt; char_u *stropt;
char_u *strval;
int append; int append;
char_u yank_type; char_u yank_type;
long block_len; long block_len;
@ -13323,8 +13336,6 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
regname = *strregname; regname = *strregname;
if (regname == 0 || regname == '@') if (regname == 0 || regname == '@')
regname = '"'; regname = '"';
else if (regname == '=')
return;
if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) {
stropt = get_tv_string_chk(&argvars[2]); stropt = get_tv_string_chk(&argvars[2]);
@ -13352,10 +13363,46 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
} }
} }
strval = get_tv_string_chk(&argvars[1]); if (argvars[1].v_type == VAR_LIST) {
if (strval != NULL) int len = argvars[1].vval.v_list->lv_len;
write_reg_contents_ex(regname, strval, -1, // First half: use for pointers to result lines; second half: use for
append, yank_type, block_len); // pointers to allocated copies.
char_u **lstval = xmalloc(sizeof(char_u *) * ((len + 1) * 2));
char_u **curval = lstval;
char_u **allocval = lstval + len + 2;
char_u **curallocval = allocval;
char_u buf[NUMBUFLEN];
for (listitem_T *li = argvars[1].vval.v_list->lv_first;
li != NULL;
li = li->li_next) {
char_u *strval = get_tv_string_buf_chk(&li->li_tv, buf);
if (strval == NULL) {
goto free_lstval;
}
if (strval == buf) {
// Need to make a copy,
// next get_tv_string_buf_chk() will overwrite the string.
strval = vim_strsave(buf);
*curallocval++ = strval;
}
*curval++ = strval;
}
*curval++ = NULL;
write_reg_contents_lst(regname, lstval, -1, append, yank_type, block_len);
free_lstval:
while (curallocval > allocval)
free(*--curallocval);
free(lstval);
} else {
char_u *strval = get_tv_string_chk(&argvars[1]);
if (strval == NULL) {
return;
}
write_reg_contents_ex(regname, strval, -1, append, yank_type, block_len);
}
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
} }
@ -16279,28 +16326,33 @@ static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
* get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return * get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
* NULL on error. * NULL on error.
*/ */
static char_u *get_tv_string(typval_T *varp) static char_u *get_tv_string(const typval_T *varp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{ {
static char_u mybuf[NUMBUFLEN]; static char_u mybuf[NUMBUFLEN];
return get_tv_string_buf(varp, mybuf); return get_tv_string_buf(varp, mybuf);
} }
static char_u *get_tv_string_buf(typval_T *varp, char_u *buf) static char_u *get_tv_string_buf(const typval_T *varp, char_u *buf)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{ {
char_u *res = get_tv_string_buf_chk(varp, buf); char_u *res = get_tv_string_buf_chk(varp, buf);
return res != NULL ? res : (char_u *)""; return res != NULL ? res : (char_u *)"";
} }
char_u *get_tv_string_chk(typval_T *varp) /// Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
char_u *get_tv_string_chk(const typval_T *varp)
FUNC_ATTR_NONNULL_ALL
{ {
static char_u mybuf[NUMBUFLEN]; static char_u mybuf[NUMBUFLEN];
return get_tv_string_buf_chk(varp, mybuf); return get_tv_string_buf_chk(varp, mybuf);
} }
static char_u *get_tv_string_buf_chk(typval_T *varp, char_u *buf) static char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf)
FUNC_ATTR_NONNULL_ALL
{ {
switch (varp->v_type) { switch (varp->v_type) {
case VAR_NUMBER: case VAR_NUMBER:

View File

@ -234,6 +234,43 @@ void memchrsub(void *data, char c, char x, size_t len)
} }
} }
/// Counts the number of occurrences of `c` in `str`.
///
/// @warning Unsafe if `c == NUL`.
///
/// @param str Pointer to the string to search.
/// @param c The byte to search for.
/// @returns the number of occurrences of `c` in `str`.
size_t strcnt(const char *str, char c, size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
assert(c != 0);
size_t cnt = 0;
while ((str = strchr(str, c))) {
cnt++;
str++; // Skip the instance of c.
}
return cnt;
}
/// Counts the number of occurrences of byte `c` in `data[len]`.
///
/// @param data Pointer to the data to search.
/// @param c The byte to search for.
/// @param len The length of `data`.
/// @returns the number of occurrences of `c` in `data[len]`.
size_t memcnt(const void *data, char c, size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
size_t cnt = 0;
const char *ptr = data, *end = ptr + len;
while ((ptr = memchr(ptr, c, (size_t)(end - ptr))) != NULL) {
cnt++;
ptr++; // Skip the instance of c.
}
return cnt;
}
/// The xstpcpy() function shall copy the string pointed to by src (including /// The xstpcpy() function shall copy the string pointed to by src (including
/// the terminating NUL character) into the array pointed to by dst. /// the terminating NUL character) into the array pointed to by dst.
/// ///

View File

@ -4654,30 +4654,43 @@ char_u get_reg_type(int regname, long *reglen)
return MAUTO; return MAUTO;
} }
/* /// When `flags` has `kGRegList` return a list with text `s`.
* Return the contents of a register as a single allocated string. /// Otherwise just return `s`.
* Used for "@r" in expressions and for getreg(). ///
* Returns NULL for error. /// Returns a void * for use in get_reg_contents().
*/ static void *get_reg_wrap_one_line(char_u *s, int flags)
char_u * {
get_reg_contents ( if (!(flags & kGRegList)) {
int regname, return s;
int allowexpr, /* allow "=" register */ }
int expr_src /* get expression for "=" register */ list_T *list = list_alloc();
) list_append_string(list, NULL, -1);
list->lv_first->li_tv.vval.v_string = s;
return list;
}
/// Gets the contents of a register.
/// @remark Used for `@r` in expressions and for `getreg()`.
///
/// @param regname The register.
/// @param flags see @ref GRegFlags
///
/// @returns The contents of the register as an allocated string.
/// @returns A linked list when `flags` contains @ref kGRegList.
/// @returns NULL for error.
void *get_reg_contents(int regname, int flags)
{ {
long i; long i;
char_u *retval;
int allocated;
/* Don't allow using an expression register inside an expression */ // Don't allow using an expression register inside an expression.
if (regname == '=') { if (regname == '=') {
if (allowexpr) { if (flags & kGRegNoExpr) {
if (expr_src) return NULL;
return get_expr_line_src();
return get_expr_line();
} }
return NULL; if (flags & kGRegExprSrc) {
return get_reg_wrap_one_line(get_expr_line_src(), flags);
}
return get_reg_wrap_one_line(get_expr_line(), flags);
} }
if (regname == '@') /* "@@" is used for unnamed register */ if (regname == '@') /* "@@" is used for unnamed register */
@ -4689,18 +4702,30 @@ get_reg_contents (
get_clipboard(regname); get_clipboard(regname);
char_u *retval;
int allocated;
if (get_spec_reg(regname, &retval, &allocated, FALSE)) { if (get_spec_reg(regname, &retval, &allocated, FALSE)) {
if (retval == NULL) if (retval == NULL)
return NULL; return NULL;
if (!allocated) if (allocated) {
retval = vim_strsave(retval); return get_reg_wrap_one_line(retval, flags);
return retval; }
return get_reg_wrap_one_line(vim_strsave(retval), flags);
} }
get_yank_register(regname, FALSE); get_yank_register(regname, FALSE);
if (y_current->y_array == NULL) if (y_current->y_array == NULL)
return NULL; return NULL;
if (flags & kGRegList) {
list_T *list = list_alloc();
for (int i = 0; i < y_current->y_size; ++i) {
list_append_string(list, y_current->y_array[i], -1);
}
return list;
}
/* /*
* Compute length of resulting string. * Compute length of resulting string.
*/ */
@ -4737,17 +4762,77 @@ get_reg_contents (
return retval; return retval;
} }
static bool init_write_reg(int name, struct yankreg **old_y_previous,
struct yankreg **old_y_current, int must_append)
{
if (!valid_yank_reg(name, true)) { // check for valid reg name
emsg_invreg(name);
return false;
}
// Don't want to change the current (unnamed) register.
*old_y_previous = y_previous;
*old_y_current = y_current;
get_yank_register(name, true);
if (!y_append && !must_append) {
free_yank_all();
}
return true;
}
static void finish_write_reg(int name, struct yankreg *old_y_previous,
struct yankreg *old_y_current)
{
// Send text of clipboard register to the clipboard.
set_clipboard(name);
// ':let @" = "val"' should change the meaning of the "" register
if (name != '"') {
y_previous = old_y_previous;
}
y_current = old_y_current;
}
/// write_reg_contents - store `str` in register `name` /// write_reg_contents - store `str` in register `name`
/// ///
/// @see write_reg_contents_ex /// @see write_reg_contents_ex
void write_reg_contents(int name, void write_reg_contents(int name, const char_u *str, ssize_t len,
const char_u *str,
ssize_t len,
int must_append) int must_append)
{ {
write_reg_contents_ex(name, str, len, must_append, MAUTO, 0L); write_reg_contents_ex(name, str, len, must_append, MAUTO, 0L);
} }
void write_reg_contents_lst(int name, char_u **strings, int maxlen,
int must_append, int yank_type, long block_len)
{
if (name == '/' || name == '=') {
char_u *s = strings[0];
if (strings[0] == NULL) {
s = (char_u *)"";
} else if (strings[1] != NULL) {
EMSG(_("E883: search pattern and expression register may not "
"contain two or more lines"));
return;
}
write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
return;
}
// black hole: nothing to do
if (name == '_') {
return;
}
struct yankreg *old_y_previous, *old_y_current;
if (!init_write_reg(name, &old_y_previous, &old_y_current, must_append)) {
return;
}
str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, true);
finish_write_reg(name, old_y_previous, old_y_current);
}
/// write_reg_contents_ex - store `str` in register `name` /// write_reg_contents_ex - store `str` in register `name`
/// ///
/// If `str` ends in '\n' or '\r', use linewise, otherwise use /// If `str` ends in '\n' or '\r', use linewise, otherwise use
@ -4774,8 +4859,6 @@ void write_reg_contents_ex(int name,
int yank_type, int yank_type,
long block_len) long block_len)
{ {
struct yankreg *old_y_previous, *old_y_current;
if (len < 0) { if (len < 0) {
len = (ssize_t) STRLEN(str); len = (ssize_t) STRLEN(str);
} }
@ -4809,29 +4892,16 @@ void write_reg_contents_ex(int name,
return; return;
} }
if (!valid_yank_reg(name, TRUE)) { /* check for valid reg name */ if (name == '_') { // black hole: nothing to do
emsg_invreg(name);
return; return;
} }
if (name == '_') /* black hole: nothing to do */ struct yankreg *old_y_previous, *old_y_current;
return; if (!init_write_reg(name, &old_y_previous, &old_y_current, must_append)) {
return;
/* Don't want to change the current (unnamed) register */ }
old_y_previous = y_previous; str_to_reg(y_current, yank_type, str, len, block_len, false);
old_y_current = y_current; finish_write_reg(name, old_y_previous, old_y_current);
get_yank_register(name, TRUE);
if (!y_append && !must_append)
free_yank_all();
str_to_reg(y_current, yank_type, str, len, block_len);
set_clipboard(name);
/* ':let @" = "val"' should change the meaning of the "" register */
if (name != '"')
y_previous = old_y_previous;
y_current = old_y_current;
} }
/// str_to_reg - Put a string into a register. /// str_to_reg - Put a string into a register.
@ -4840,100 +4910,100 @@ void write_reg_contents_ex(int name,
/// ///
/// @param y_ptr pointer to yank register /// @param y_ptr pointer to yank register
/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO /// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
/// @param str string to put in register /// @param str string or list of strings to put in register
/// @param len length of the string /// @param len length of the string (Ignored when str_list=true.)
/// @param blocklen width of visual block /// @param blocklen width of visual block, or -1 for "I don't know."
static void str_to_reg(struct yankreg *y_ptr, /// @param str_list True if str is `char_u **`.
int yank_type, static void str_to_reg(struct yankreg *y_ptr, int yank_type, const char_u *str,
const char_u *str, size_t len, colnr_T blocklen, bool str_list)
long len, FUNC_ATTR_NONNULL_ALL
long blocklen)
{ {
int type; /* MCHAR, MLINE or MBLOCK */ if (y_ptr->y_array == NULL) { // NULL means empty register
int lnum;
long start;
long i;
int extra;
size_t newlines; /* number of lines added */
int extraline = 0; /* extra line at the end */
int append = FALSE; /* append to last line in register */
char_u *s;
char_u **pp;
long maxlen;
if (y_ptr->y_array == NULL) /* NULL means empty register */
y_ptr->y_size = 0; y_ptr->y_size = 0;
}
if (yank_type == MAUTO) int type = yank_type; // MCHAR, MLINE or MBLOCK
type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)) if (yank_type == MAUTO) {
type = ((str_list ||
(len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
? MLINE : MCHAR); ? MLINE : MCHAR);
else
type = yank_type;
/*
* Count the number of lines within the string
*/
newlines = 0;
for (i = 0; i < len; i++)
if (str[i] == '\n')
++newlines;
if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
extraline = 1;
++newlines; /* count extra newline at the end */
}
if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) {
append = TRUE;
--newlines; /* uncount newline when appending first line */
} }
/* size_t newlines = 0;
* Allocate an array to hold the pointers to the new register lines. bool extraline = false; // extra line at the end
* If the register was not empty, move the existing lines to the new array. bool append = false; // append to last line in register
*/
pp = xcalloc((y_ptr->y_size + newlines), sizeof(char_u *));
for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
pp[lnum] = y_ptr->y_array[lnum];
free(y_ptr->y_array);
y_ptr->y_array = pp;
maxlen = 0;
/* // Count the number of lines within the string
* Find the end of each line and save it into the array. if (str_list) {
*/ for (char_u **ss = (char_u **) str; *ss != NULL; ++ss) {
for (start = 0; start < len + extraline; start += i + 1) { newlines++;
// Let i represent the length of one line. }
const char_u *p = str + start; } else {
i = (char_u *)xmemscan(p, '\n', len - start) - p; newlines = memcnt(str, '\n', len);
if (i > maxlen) if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
maxlen = i; extraline = 1;
if (append) { ++newlines; // count extra newline at the end
--lnum; }
extra = (int)STRLEN(y_ptr->y_array[lnum]); if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) {
} else append = true;
extra = 0; --newlines; // uncount newline when appending first line
s = xmalloc(i + extra + 1); }
if (extra) }
memmove(s, y_ptr->y_array[lnum], (size_t)extra);
if (append)
free(y_ptr->y_array[lnum]); // Grow the register array to hold the pointers to the new lines.
if (i) char_u **pp = xrealloc(y_ptr->y_array,
memmove(s + extra, str + start, (size_t)i); (y_ptr->y_size + newlines) * sizeof(char_u *));
extra += i; y_ptr->y_array = pp;
s[extra] = NUL;
y_ptr->y_array[lnum++] = s; linenr_T lnum = y_ptr->y_size; // The current line number.
while (--extra >= 0) {
if (*s == NUL) // If called with `blocklen < 0`, we have to update the yank reg's width.
*s = '\n'; /* replace NUL with newline */ size_t maxlen = 0;
++s;
// Find the end of each line and save it into the array.
if (str_list) {
for (char_u **ss = (char_u **) str; *ss != NULL; ++ss, ++lnum) {
size_t ss_len = STRLEN(*ss);
pp[lnum] = xmemdupz(*ss, ss_len);
if (ss_len > maxlen) {
maxlen = ss_len;
}
}
} else {
size_t line_len;
for (const char_u *start = str, *end = str + len;
start < end + extraline;
start += line_len + 1, lnum++) {
line_len = (const char_u *) xmemscan(start, '\n', end - start) - start;
if (line_len > maxlen) {
maxlen = line_len;
}
// When appending, copy the previous line and free it after.
size_t extra = append ? STRLEN(pp[--lnum]) : 0;
char_u *s = xmallocz(line_len + extra);
memcpy(s, pp[lnum], extra);
memcpy(s + extra, start, line_len);
ssize_t s_len = extra + line_len;
if (append) {
free(pp[lnum]);
append = false; // only first line is appended
}
pp[lnum] = s;
// Convert NULs to '\n' to prevent truncation.
memchrsub(pp[lnum], NUL, '\n', s_len);
} }
append = FALSE; /* only first line is appended */
} }
y_ptr->y_type = type; y_ptr->y_type = type;
y_ptr->y_size = lnum; y_ptr->y_size = lnum;
if (type == MBLOCK) if (type == MBLOCK) {
y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen); y_ptr->y_width = (blocklen == -1 ? (colnr_T) maxlen - 1 : blocklen);
else } else {
y_ptr->y_width = 0; y_ptr->y_width = 0;
}
} }
void clear_oparg(oparg_T *oap) void clear_oparg(oparg_T *oap)

View File

@ -47,6 +47,13 @@ typedef int (*Indenter)(void);
#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */ #define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
#define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */ #define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */
/// Flags for get_reg_contents().
enum GRegFlags {
kGRegNoExpr = 1, ///< Do not allow expression register.
kGRegExprSrc = 2, ///< Return expression itself for "=" register.
kGRegList = 4 ///< Return list.
};
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.h.generated.h" # include "ops.h.generated.h"
#endif #endif

View File

@ -1,7 +1,154 @@
Test for various eval features. vim: set ft=vim :
Note: system clipboard support is not tested. I do not think anybody will thank
me for messing with clipboard.
STARTTEST STARTTEST
:so small.vim :so small.vim
:set encoding=latin1 :set encoding=latin1
:set noswapfile :set noswapfile
:lang C
:fun AppendRegContents(reg)
call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1))))
endfun
:command -nargs=? AR :call AppendRegContents(<q-args>)
:fun SetReg(...)
call call('setreg', a:000)
call append('$', printf('{{{2 setreg(%s)', string(a:000)[1:-2]))
call AppendRegContents(a:1)
if a:1 isnot# '='
execute "silent normal! Go==\n==\e\"".a:1."P"
endif
endfun
:fun ErrExe(str)
call append('$', 'Executing '.a:str)
try
execute a:str
catch
$put =v:exception
endtry
endfun
:fun Test()
$put ='{{{1 let tests'
let @" = 'abc'
AR "
let @" = "abc\n"
AR "
let @" = "abc\<C-m>"
AR "
let @= = '"abc"'
AR =
$put ='{{{1 Basic setreg tests'
call SetReg('a', 'abcA', 'c')
call SetReg('b', 'abcB', 'v')
call SetReg('c', 'abcC', 'l')
call SetReg('d', 'abcD', 'V')
call SetReg('e', 'abcE', 'b')
call SetReg('f', 'abcF', "\<C-v>")
call SetReg('g', 'abcG', 'b10')
call SetReg('h', 'abcH', "\<C-v>10")
call SetReg('I', 'abcI')
$put ='{{{1 Appending single lines with setreg()'
call SetReg('A', 'abcAc', 'c')
call SetReg('A', 'abcAl', 'l')
call SetReg('A', 'abcAc2','c')
call SetReg('b', 'abcBc', 'ca')
call SetReg('b', 'abcBb', 'ba')
call SetReg('b', 'abcBc2','ca')
call SetReg('b', 'abcBb2','b50a')
call SetReg('C', 'abcCl', 'l')
call SetReg('C', 'abcCc', 'c')
call SetReg('D', 'abcDb', 'b')
call SetReg('E', 'abcEb', 'b')
call SetReg('E', 'abcEl', 'l')
call SetReg('F', 'abcFc', 'c')
$put ='{{{1 Appending NL with setreg()'
call setreg('a', 'abcA2', 'c')
call setreg('b', 'abcB2', 'v')
call setreg('c', 'abcC2', 'l')
call setreg('d', 'abcD2', 'V')
call setreg('e', 'abcE2', 'b')
call setreg('f', 'abcF2', "\<C-v>")
call setreg('g', 'abcG2', 'b10')
call setreg('h', 'abcH2', "\<C-v>10")
call setreg('I', 'abcI2')
call SetReg('A', "\n")
call SetReg('B', "\n", 'c')
call SetReg('C', "\n")
call SetReg('D', "\n", 'l')
call SetReg('E', "\n")
call SetReg('F', "\n", 'b')
$put ='{{{1 Setting lists with setreg()'
call SetReg('a', ['abcA3'], 'c')
call SetReg('b', ['abcB3'], 'l')
call SetReg('c', ['abcC3'], 'b')
call SetReg('d', ['abcD3'])
call SetReg('e', [1, 2, 'abc', 3])
call SetReg('f', [1, 2, 3])
$put ='{{{1 Appending lists with setreg()'
call SetReg('A', ['abcA3c'], 'c')
call SetReg('b', ['abcB3l'], 'la')
call SetReg('C', ['abcC3b'], 'lb')
call SetReg('D', ['abcD32'])
call SetReg('A', ['abcA32'])
call SetReg('B', ['abcB3c'], 'c')
call SetReg('C', ['abcC3l'], 'l')
call SetReg('D', ['abcD3b'], 'b')
$put ='{{{1 Appending lists with NL with setreg()'
call SetReg('A', ["\n", 'abcA3l2'], 'l')
call SetReg('B', ["\n", 'abcB3c2'], 'c')
call SetReg('C', ["\n", 'abcC3b2'], 'b')
call SetReg('D', ["\n", 'abcD3b50'],'b50')
$put ='{{{1 Setting lists with NLs with setreg()'
call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])
call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')
call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')
call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')
call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')
$put ='{{{1 Search and expressions'
call SetReg('/', ['abc/'])
call SetReg('/', ["abc/\n"])
call SetReg('=', ['"abc/"'])
call SetReg('=', ["\"abc/\n\""])
$put ='{{{1 Errors'
call ErrExe('call setreg()')
call ErrExe('call setreg(1)')
call ErrExe('call setreg(1, 2, 3, 4)')
call ErrExe('call setreg([], 2)')
call ErrExe('call setreg(1, {})')
call ErrExe('call setreg(1, 2, [])')
call ErrExe('call setreg("/", ["1", "2"])')
call ErrExe('call setreg("=", ["1", "2"])')
call ErrExe('call setreg(1, ["", "", [], ""])')
endfun
:"
:call Test()
:"
:delfunction SetReg
:delfunction AppendRegContents
:delfunction ErrExe
:delfunction Test
:delcommand AR
:call garbagecollect(1)
:"
:/^start:/+1,$wq! test.out
:" vim: et ts=4 isk-=\: fmr=???,???
:call getchar()
:e test.out
:%d
:" function name not starting with a capital :" function name not starting with a capital
:try :try

Binary file not shown.

View File

@ -416,14 +416,14 @@ static int included_patches[] = {
//252 NA //252 NA
251, 251,
//250 NA //250 NA
//249, 249,
248, 248,
247, 247,
//246, //246,
245, 245,
//244, //244,
//243, 243,
//242, 242,
241, 241,
240, 240,
239, 239,