diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/option.c | 65 | ||||
-rw-r--r-- | src/nvim/testdir/test_mksession.vim | 26 |
2 files changed, 80 insertions, 11 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index eae52ff260..d7675f48d7 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5402,8 +5402,9 @@ int makeset(FILE *fd, int opt_flags, int local_only) do_endif = true; } if (put_setstring(fd, cmd, p->fullname, (char_u **)varp, - (p->flags & P_EXPAND) != 0) == FAIL) + p->flags) == FAIL) { return FAIL; + } if (do_endif) { if (put_line(fd, "endif") == FAIL) { return FAIL; @@ -5421,12 +5422,12 @@ int makeset(FILE *fd, int opt_flags, int local_only) /// 'sessionoptions' or 'viewoptions' contains "folds" but not "options". int makefoldset(FILE *fd) { - if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, false) == FAIL - || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, false) + if (put_setstring(fd, "setlocal", "fdm", &curwin->w_p_fdm, 0) == FAIL + || put_setstring(fd, "setlocal", "fde", &curwin->w_p_fde, 0) == FAIL - || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, false) + || put_setstring(fd, "setlocal", "fmr", &curwin->w_p_fmr, 0) == FAIL - || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, false) + || put_setstring(fd, "setlocal", "fdi", &curwin->w_p_fdi, 0) == FAIL || put_setnum(fd, "setlocal", "fdl", &curwin->w_p_fdl) == FAIL || put_setnum(fd, "setlocal", "fml", &curwin->w_p_fml) == FAIL @@ -5439,10 +5440,13 @@ int makefoldset(FILE *fd) return OK; } -static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int expand) +static int put_setstring(FILE *fd, char *cmd, char *name, + char_u **valuep, uint64_t flags) { char_u *s; - char_u *buf; + char_u *buf = NULL; + char_u *part = NULL; + char_u *p; if (fprintf(fd, "%s %s=", cmd, name) < 0) { return FAIL; @@ -5460,9 +5464,46 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e return FAIL; } } - } else if (expand) { - buf = xmalloc(MAXPATHL); - home_replace(NULL, *valuep, buf, MAXPATHL, false); + } else if ((flags & P_EXPAND) != 0) { + size_t size = (size_t)STRLEN(*valuep) + 1; + + // replace home directory in the whole option value into "buf" + buf = xmalloc(size); + if (buf == NULL) { + goto fail; + } + home_replace(NULL, *valuep, buf, size, false); + + // If the option value is longer than MAXPATHL, we need to append + // earch comma separated part of the option sperately, so that it + // can be expanded when read back. + if (size >= MAXPATHL && (flags & P_COMMA) != 0 + && vim_strchr(*valuep, ',') != NULL) { + part = xmalloc(size); + if (part == NULL) { + goto fail; + } + + // write line break to clear the option, e.g. ':set rtp=' + if (put_eol(fd) == FAIL) { + goto fail; + } + p = buf; + while (*p != NUL) { + // for each comma seperated option part, append value to + // the option, :set rtp+=value + if (fprintf(fd, "%s %s+=", cmd, name) < 0) { + goto fail; + } + (void)copy_option_part(&p, part, size, ","); + if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) { + goto fail; + } + } + xfree(buf); + xfree(part); + return OK; + } if (put_escstr(fd, buf, 2) == FAIL) { xfree(buf); return FAIL; @@ -5476,6 +5517,10 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char_u **valuep, int e return FAIL; } return OK; +fail: + xfree(buf); + xfree(part); + return FAIL; } static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep) diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim index b7169444d1..8b20ad0c62 100644 --- a/src/nvim/testdir/test_mksession.vim +++ b/src/nvim/testdir/test_mksession.vim @@ -2,7 +2,7 @@ scriptencoding latin1 -if !has('multi_byte') || !has('mksession') +if !has('mksession') finish endif @@ -122,6 +122,30 @@ func Test_mksession_large_winheight() call delete('Xtest_mks_winheight.out') endfunc +func Test_mksession_rtp() + new + set sessionoptions+=options + let _rtp=&rtp + " Make a real long (invalid) runtimepath value, + " that should exceed PATH_MAX (hopefully) + let newrtp=&rtp.',~'.repeat('/foobar', 1000) + let newrtp.=",".expand("$HOME")."/.vim" + let &rtp=newrtp + + " determine expected value + let expected=split(&rtp, ',') + let expected = map(expected, '"set runtimepath+=".v:val') + let expected = ['set runtimepath='] + expected + let expected = map(expected, {v,w -> substitute(w, $HOME, "~", "g")}) + + mksession! Xtest_mks.out + let &rtp=_rtp + let li = filter(readfile('Xtest_mks.out'), 'v:val =~# "runtimepath"') + call assert_equal(expected, li) + + call delete('Xtest_mks.out') +endfunc + " Verify that arglist is stored correctly to the session file. func Test_mksession_arglist() argdel * |