From cf67f19ac2104ece76d040c8184bc287428299b3 Mon Sep 17 00:00:00 2001 From: Alexandre Dubray Date: Tue, 9 Jan 2018 12:01:02 +0100 Subject: mksession: restore same :term buf in split windows Problem: When session-restore creates a terminal buffer with command like `:edit term://.//16450:/bin/bash`, the buffer gets a different name (depends on PID). Thus the later call to `bufexists('term://.//16450:/bin/bash)` will return false. Solution: Force the buffer name with :file. This as least ensures the same buffer will show in multiple windows correctly, as expected when saving the session. But it still has problems: 1. the PID in the buffer name is bogus 2. redundant :terminal buffers still hang around fix #5250 --- src/nvim/ex_docmd.c | 27 +++++++++++++++++++++++++++ test/functional/ex_cmds/mksession_spec.lua | 19 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 02bee838d5..0732409666 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9346,6 +9346,10 @@ makeopens( /* * Restore the view of the window (options, file, cursor, etc.). */ + if (put_line(fd, "let s:buffer_names = []") == FAIL) { + return FAIL; + } + for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (!ses_do_win(wp)) continue; @@ -9357,6 +9361,16 @@ makeopens( next_arg_idx = wp->w_arg_idx; } + if (put_line(fd, "for [s:name, s:tbuf] in s:buffer_names") == FAIL + || put_line(fd, " if buflisted(s:tbuf)") == FAIL + || put_line(fd, " execute 'buffer' fnameescape(s:tbuf)") == FAIL + || put_line(fd, " execute 'file' fnameescape(s:name)") == FAIL + || put_line(fd, " endif") == FAIL + || put_line(fd, "endfor") == FAIL + || put_line(fd, "unlet! s:buffer_names s:tbuf s:name") == FAIL) { + return FAIL; + } + /* The argument index in the first tab page is zero, need to set it in * each window. For further tab pages it's the window where we do * "tabedit". */ @@ -9662,6 +9676,19 @@ put_view( || put_eol(fd) == FAIL) { return FAIL; } + + if (fputs("call add(s:buffer_names, [bufname('%'),'", fd) < 0 + || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL + || fputs("'])", fd) < 0 + || put_eol(fd) == FAIL) { + return FAIL; + } + + if (fputs("file ", fd) < 0 + || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL + || put_eol(fd) == FAIL) { + return FAIL; + } } else { // No file in this buffer, just make it empty. if (put_line(fd, "enew") == FAIL) { diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 855f8105aa..726cfe7fe5 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -91,4 +91,23 @@ describe(':mksession', function() matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%')) command('qall!') end) + + it('restores multiple windows with same terminal instances', function() + -- Create a view with two buffers referencing the same terminal instance + command('terminal') + command('split') + command('mksession ' .. session_file) + + clear() + + command('source ' .. session_file) + -- Getting the name of the buffer shown to compare with the other window + local eval = helpers.eval + + command('exe 1 . "wincmd w"') + local expected_pid = eval('b:terminal_job_pid') + + command('exe 2 . "wincmd w"') + eq(expected_pid, eval('b:terminal_job_pid')) + end) end) -- cgit From 1e103b3c12597a9dd2f20d45686822ab6ee089b0 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 02:43:12 -0800 Subject: mksession: simplify generated commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doing ":file …" immediately after is enough to fixup the :terminal buffer name. ref #5250 --- src/nvim/ex_docmd.c | 78 ++++++++++-------------------- test/functional/ex_cmds/mksession_spec.lua | 40 +++++++-------- 2 files changed, 47 insertions(+), 71 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 0732409666..5253233c15 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8090,14 +8090,12 @@ static void close_redir(void) static int mksession_nl = FALSE; /* use NL only in put_eol() */ #endif -/* - * ":mkexrc", ":mkvimrc", ":mkview" and ":mksession". - */ +/// ":mkexrc", ":mkvimrc", ":mkview", ":mksession". static void ex_mkrc(exarg_T *eap) { FILE *fd; int failed = false; - int view_session = false; + int view_session = false; // :mkview, :mksession int using_vdir = false; // using 'viewdir'? char *viewFile = NULL; unsigned *flagp; @@ -8159,11 +8157,11 @@ static void ex_mkrc(exarg_T *eap) failed = TRUE; } - if (!view_session - || (eap->cmdidx == CMD_mksession - && (*flagp & SSOP_OPTIONS))) + if (!view_session || (eap->cmdidx == CMD_mksession + && (*flagp & SSOP_OPTIONS))) { failed |= (makemap(fd, NULL) == FAIL || makeset(fd, OPT_GLOBAL, FALSE) == FAIL); + } if (!failed && view_session) { if (put_line(fd, @@ -9119,15 +9117,13 @@ char_u *expand_sfile(char_u *arg) } -/* - * Write openfile commands for the current buffers to an .exrc file. - * Return FAIL on error, OK otherwise. - */ -static int -makeopens( - FILE *fd, - char_u *dirnow /* Current directory name */ -) +/// Writes commands for restoring the current buffers, for :mksession. +/// +/// @param dirnow Current directory name +/// @param fd File descriptor to write to +/// +/// @return FAIL on error, OK otherwise. +static int makeopens(FILE *fd, char_u *dirnow) { int only_save_windows = TRUE; int nr; @@ -9240,12 +9236,11 @@ makeopens( restore_stal = TRUE; } - /* - * May repeat putting Windows for each tab, when "tabpages" is in - * 'sessionoptions'. - * Don't use goto_tabpage(), it may change directory and trigger - * autocommands. - */ + // + // For each tab: + // - Put windows for each tab, when "tabpages" is in 'sessionoptions'. + // - Don't use goto_tabpage(), it may change CWD and trigger autocommands. + // tab_firstwin = firstwin; /* first window in tab page "tabnr" */ tab_topframe = topframe; for (tabnr = 1;; tabnr++) { @@ -9269,11 +9264,11 @@ makeopens( need_tabnew = TRUE; } - /* - * Before creating the window layout, try loading one file. If this - * is aborted we don't end up with a number of useless windows. - * This may have side effects! (e.g., compressed or network file). - */ + // + // Before creating the window layout, try loading one file. If this + // is aborted we don't end up with a number of useless windows. + // This may have side effects! (e.g., compressed or network file). + // for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (ses_do_win(wp) && wp->w_buffer->b_ffname != NULL @@ -9343,13 +9338,9 @@ makeopens( return FAIL; } - /* - * Restore the view of the window (options, file, cursor, etc.). - */ - if (put_line(fd, "let s:buffer_names = []") == FAIL) { - return FAIL; - } - + // + // Restore the view of the window (options, file, cursor, etc.). + // for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (!ses_do_win(wp)) continue; @@ -9361,16 +9352,6 @@ makeopens( next_arg_idx = wp->w_arg_idx; } - if (put_line(fd, "for [s:name, s:tbuf] in s:buffer_names") == FAIL - || put_line(fd, " if buflisted(s:tbuf)") == FAIL - || put_line(fd, " execute 'buffer' fnameescape(s:tbuf)") == FAIL - || put_line(fd, " execute 'file' fnameescape(s:name)") == FAIL - || put_line(fd, " endif") == FAIL - || put_line(fd, "endfor") == FAIL - || put_line(fd, "unlet! s:buffer_names s:tbuf s:name") == FAIL) { - return FAIL; - } - /* The argument index in the first tab page is zero, need to set it in * each window. For further tab pages it's the window where we do * "tabedit". */ @@ -9677,14 +9658,7 @@ put_view( return FAIL; } - if (fputs("call add(s:buffer_names, [bufname('%'),'", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL - || fputs("'])", fd) < 0 - || put_eol(fd) == FAIL) { - return FAIL; - } - - if (fputs("file ", fd) < 0 + if (fputs("silent file ", fd) < 0 || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL || put_eol(fd) == FAIL) { return FAIL; diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 726cfe7fe5..305850a09e 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -26,6 +26,27 @@ describe(':mksession', function() rmdir(tab_dir) end) + it('restores same :terminal buf in splits', function() + -- If the same :terminal is displayed in multiple windows, :mksession + -- should restore it as such. + + -- Create two windows showing the same :terminal buffer. + command('terminal') + command('split') + command('terminal') + command('split') + command('mksession '..session_file) + + -- Create a new test instance of Nvim. + command('qall!') + clear() + -- Restore session. + command('source '..session_file) + + eq({3,3,2}, + {funcs.winbufnr(1), funcs.winbufnr(2), funcs.winbufnr(3)}) + end) + it('restores tab-local working directories', function() local tmpfile_base = file_prefix .. '-tmpfile' local cwd_dir = funcs.getcwd() @@ -91,23 +112,4 @@ describe(':mksession', function() matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%')) command('qall!') end) - - it('restores multiple windows with same terminal instances', function() - -- Create a view with two buffers referencing the same terminal instance - command('terminal') - command('split') - command('mksession ' .. session_file) - - clear() - - command('source ' .. session_file) - -- Getting the name of the buffer shown to compare with the other window - local eval = helpers.eval - - command('exe 1 . "wincmd w"') - local expected_pid = eval('b:terminal_job_pid') - - command('exe 2 . "wincmd w"') - eq(expected_pid, eval('b:terminal_job_pid')) - end) end) -- cgit From 598a1cd7c5b9b0f4e4b175f55b58bdb0e1a398eb Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 03:09:18 -0800 Subject: mksession: avoid ":file …" when restoring non-terminal bufs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nvim/ex_docmd.c | 84 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 34 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 5253233c15..6791bbd34c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8160,7 +8160,7 @@ static void ex_mkrc(exarg_T *eap) if (!view_session || (eap->cmdidx == CMD_mksession && (*flagp & SSOP_OPTIONS))) { failed |= (makemap(fd, NULL) == FAIL - || makeset(fd, OPT_GLOBAL, FALSE) == FAIL); + || makeset(fd, OPT_GLOBAL, false) == FAIL); } if (!failed && view_session) { @@ -9241,7 +9241,7 @@ static int makeopens(FILE *fd, char_u *dirnow) // - Put windows for each tab, when "tabpages" is in 'sessionoptions'. // - Don't use goto_tabpage(), it may change CWD and trigger autocommands. // - tab_firstwin = firstwin; /* first window in tab page "tabnr" */ + tab_firstwin = firstwin; // First window in tab page "tabnr". tab_topframe = topframe; for (tabnr = 1;; tabnr++) { tabpage_T *tp = find_tabpage(tabnr); @@ -9658,11 +9658,18 @@ put_view( return FAIL; } - if (fputs("silent file ", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL - || put_eol(fd) == FAIL) { + char *fname_esc = + ses_escape_fname(ses_get_fname(wp->w_buffer, flagp, false), flagp); + // Fixup :terminal buffer name. + if (fprintf(fd, + "if &buftype ==# 'terminal'\n" + " silent file %s\n" + "endif\n", + fname_esc) < 0) { + xfree(fname_esc); return FAIL; } + xfree(fname_esc); } else { // No file in this buffer, just make it empty. if (put_line(fd, "enew") == FAIL) { @@ -9828,44 +9835,45 @@ ses_arglist( return OK; } -/// Write a buffer name to the session file. -/// Also ends the line, if "add_eol" is true. -/// Returns FAIL if writing fails. -static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, bool add_eol) +/// Gets the buffer name for `buf`. +static char *ses_get_fname(buf_T *buf, unsigned *flagp, bool add_eol) { - char_u *name; - - /* Use the short file name if the current directory is known at the time - * the session file will be sourced. - * Don't do this for ":mkview", we don't know the current directory. - * Don't do this after ":lcd", we don't keep track of what the current - * directory is. */ + // Use the short file name if the current directory is known at the time + // the session file will be sourced. + // Don't do this for ":mkview", we don't know the current directory. + // Don't do this after ":lcd", we don't keep track of what the current + // directory is. if (buf->b_sfname != NULL && flagp == &ssop_flags && (ssop_flags & (SSOP_CURDIR | SSOP_SESDIR)) && !p_acd - && !did_lcd) - name = buf->b_sfname; - else - name = buf->b_ffname; - if (ses_put_fname(fd, name, flagp) == FAIL + && !did_lcd) { + return (char *)buf->b_sfname; + } + return (char *)buf->b_ffname; +} +/// Write a buffer name to the session file. +/// Also ends the line, if "add_eol" is true. +/// Returns FAIL if writing fails. +static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, bool add_eol) +{ + char *name = ses_get_fname(buf, flagp, add_eol); + if (ses_put_fname(fd, (char_u *)name, flagp) == FAIL || (add_eol && put_eol(fd) == FAIL)) { return FAIL; } return OK; } -/* - * Write a file name to the session file. - * Takes care of the "slash" option in 'sessionoptions' and escapes special - * characters. - * Returns FAIL if writing fails. - */ -static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) +// Escapes a filename for session writing. +// Takes care of "slash" flag in 'sessionoptions' and escapes special +// characters. +// +// Returns allocated string or NULL. +static char *ses_escape_fname(char *name, unsigned *flagp) { - char_u *p; - - char_u *sname = home_replace_save(NULL, name); + char *p; + char *sname = (char *)home_replace_save(NULL, (char_u *)name); if (*flagp & SSOP_SLASH) { // change all backslashes to forward slashes @@ -9877,11 +9885,19 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) } // Escape special characters. - p = (char_u *)vim_strsave_fnameescape((const char *)sname, false); + p = vim_strsave_fnameescape(sname, false); xfree(sname); + return p; +} - /* write the result */ - bool retval = fputs((char *)p, fd) < 0 ? FAIL : OK; +// Write a file name to the session file. +// Takes care of the "slash" option in 'sessionoptions' and escapes special +// characters. +// Returns FAIL if writing fails. +static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) +{ + char *p = ses_escape_fname((char *)name, flagp); + bool retval = fputs(p, fd) < 0 ? FAIL : OK; xfree(p); return retval; } -- cgit From 2c1d12d0beda7b359fec94c00746b7206ae8fedd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 03:18:45 -0800 Subject: mksession: always write LF "\n" line-endings - remove `MKSESSION_NL`, `mksession_nl` - deprecate the "unix" flag of 'sessionoptions' There is no reason to choose CRLF or LF for session files. Instead just always write LF. --- src/nvim/ex_docmd.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 6791bbd34c..2950b2950c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8085,11 +8085,6 @@ static void close_redir(void) } } -#ifdef USE_CRNL -# define MKSESSION_NL -static int mksession_nl = FALSE; /* use NL only in put_eol() */ -#endif - /// ":mkexrc", ":mkvimrc", ":mkview", ":mksession". static void ex_mkrc(exarg_T *eap) { @@ -8142,12 +8137,6 @@ static void ex_mkrc(exarg_T *eap) else flagp = &ssop_flags; -#ifdef MKSESSION_NL - /* "unix" in 'sessionoptions': use NL line separator */ - if (view_session && (*flagp & SSOP_UNIX)) - mksession_nl = TRUE; -#endif - /* Write the version command for :mkvimrc */ if (eap->cmdidx == CMD_mkvimrc) (void)put_line(fd, "version 6.0"); @@ -8236,9 +8225,6 @@ static void ex_mkrc(exarg_T *eap) } xfree(tbuf); } -#ifdef MKSESSION_NL - mksession_nl = FALSE; -#endif } xfree(viewFile); @@ -9964,19 +9950,11 @@ static char *get_view_file(int c) } -/* - * Write end-of-line character(s) for ":mkexrc", ":mkvimrc" and ":mksession". - * Return FAIL for a write error. - */ +/// TODO(justinmk): remove this. Formerly used to choose CRLF or LF for session +// files, but that's useless--instead we always write LF. int put_eol(FILE *fd) { -#if defined(USE_CRNL) && defined(MKSESSION_NL) - if ((!mksession_nl && putc('\r', fd) < 0) || putc('\n', fd) < 0) { -#elif defined(USE_CRNL) - if (putc('\r', fd) < 0 || putc('\n', fd) < 0) { -#else if (putc('\n', fd) < 0) { -#endif return FAIL; } return OK; -- cgit From 2070c082b516361161dba04e72fcaafad8bc3860 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 03:45:48 -0800 Subject: cleanup/ex_docmd.c: remove most put_line() calls - prefer fprintf() instead of put_line() - PUTLINE_FAIL macro to avoid some boilerplate --- src/nvim/ex_docmd.c | 349 ++++++++++++++++++++++++------------------------- src/nvim/option_defs.h | 2 +- 2 files changed, 170 insertions(+), 181 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 2950b2950c..2b952b3f15 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8085,6 +8085,9 @@ static void close_redir(void) } } +#define PUTLINE_FAIL(s) \ + do { if (FAIL == put_line(fd, (s))) { return FAIL; } } while (0) + /// ":mkexrc", ":mkvimrc", ":mkview", ":mksession". static void ex_mkrc(exarg_T *eap) { @@ -8137,9 +8140,10 @@ static void ex_mkrc(exarg_T *eap) else flagp = &ssop_flags; - /* Write the version command for :mkvimrc */ - if (eap->cmdidx == CMD_mkvimrc) + // Write the version command for :mkvimrc + if (eap->cmdidx == CMD_mkvimrc) { (void)put_line(fd, "version 6.0"); + } if (eap->cmdidx == CMD_mksession) { if (put_line(fd, "let SessionLoad = 1") == FAIL) @@ -8200,14 +8204,17 @@ static void ex_mkrc(exarg_T *eap) failed |= (put_view(fd, curwin, !using_vdir, flagp, -1) == FAIL); } - if (put_line(fd, "let &so = s:so_save | let &siso = s:siso_save") - == FAIL) - failed = TRUE; - if (put_line(fd, "doautoall SessionLoadPost") == FAIL) - failed = TRUE; + if (fprintf(fd, + "%s", + "let &so = s:so_save | let &siso = s:siso_save\n" + "doautoall SessionLoadPost\n") + < 0) { + failed = true; + } if (eap->cmdidx == CMD_mksession) { - if (put_line(fd, "unlet SessionLoad") == FAIL) - failed = TRUE; + if (fprintf(fd, "unlet SessionLoad\n") < 0) { + failed = true; + } } } if (put_line(fd, "\" vim: set ft=vim :") == FAIL) @@ -9127,28 +9134,21 @@ static int makeopens(FILE *fd, char_u *dirnow) only_save_windows = FALSE; /* Save ALL buffers */ // Begin by setting v:this_session, and then other sessionable variables. - if (put_line(fd, "let v:this_session=expand(\":p\")") == FAIL) { - return FAIL; - } + PUTLINE_FAIL("let v:this_session=expand(\":p\")"); if (ssop_flags & SSOP_GLOBALS) { if (store_session_globals(fd) == FAIL) { return FAIL; } } - /* - * Close all windows but one. - */ - if (put_line(fd, "silent only") == FAIL) - return FAIL; + // Close all windows but one. + PUTLINE_FAIL("silent only"); - /* - * Now a :cd command to the session directory or the current directory - */ + // + // Now a :cd command to the session directory or the current directory + // if (ssop_flags & SSOP_SESDIR) { - if (put_line(fd, "exe \"cd \" . escape(expand(\":p:h\"), ' ')") - == FAIL) - return FAIL; + PUTLINE_FAIL("exe \"cd \" . escape(expand(\":p:h\"), ' ')"); } else if (ssop_flags & SSOP_CURDIR) { sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow); if (fputs("cd ", fd) < 0 @@ -9160,27 +9160,20 @@ static int makeopens(FILE *fd, char_u *dirnow) xfree(sname); } - /* - * If there is an empty, unnamed buffer we will wipe it out later. - * Remember the buffer number. - */ - if (put_line(fd, - "if expand('%') == '' && !&modified && line('$') <= 1 && getline(1) == ''") - == - FAIL) - return FAIL; - if (put_line(fd, " let s:wipebuf = bufnr('%')") == FAIL) - return FAIL; - if (put_line(fd, "endif") == FAIL) - return FAIL; - - /* - * Now save the current files, current buffer first. - */ - if (put_line(fd, "set shortmess=aoO") == FAIL) + if (fprintf(fd, + "%s", + // If there is an empty, unnamed buffer we will wipe it out later. + // Remember the buffer number. + "if expand('%') == '' && !&modified && line('$') <= 1" + " && getline(1) == ''\n" + " let s:wipebuf = bufnr('%')\n" + "endif\n" + // Now save the current files, current buffer first. + "set shortmess=aoO\n") < 0) { return FAIL; + } - /* Now put the other buffers into the buffer list */ + // Now put the other buffers into the buffer list. FOR_ALL_BUFFERS(buf) { if (!(only_save_windows && buf->b_nwindows == 0) && !(buf->b_help && !(ssop_flags & SSOP_HELP)) @@ -9216,9 +9209,7 @@ static int makeopens(FILE *fd, char_u *dirnow) // in the first tab, which may cause problems. Set 'showtabline' to 2 // temporarily to avoid that. if (p_stal == 1 && first_tabpage->tp_next != NULL) { - if (put_line(fd, "set stal=2") == FAIL) { - return FAIL; - } + PUTLINE_FAIL("set stal=2"); restore_stal = TRUE; } @@ -9273,26 +9264,29 @@ static int makeopens(FILE *fd, char_u *dirnow) } } - /* If no file got edited create an empty tab page. */ - if (need_tabnew && put_line(fd, "tabnew") == FAIL) + // If no file got edited create an empty tab page. + if (need_tabnew && put_line(fd, "tabnew") == FAIL) { return FAIL; + } - /* - * Save current window layout. - */ - if (put_line(fd, "set splitbelow splitright") == FAIL) - return FAIL; - if (ses_win_rec(fd, tab_topframe) == FAIL) + // + // Save current window layout. + // + PUTLINE_FAIL("set splitbelow splitright"); + if (ses_win_rec(fd, tab_topframe) == FAIL) { return FAIL; - if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL) + } + if (!p_sb && put_line(fd, "set nosplitbelow") == FAIL) { return FAIL; - if (!p_spr && put_line(fd, "set nosplitright") == FAIL) + } + if (!p_spr && put_line(fd, "set nosplitright") == FAIL) { return FAIL; + } - /* - * Check if window sizes can be restored (no windows omitted). - * Remember the window number of the current window after restoring. - */ + // + // Check if window sizes can be restored (no windows omitted). + // Remember the window number of the current window after restoring. + // nr = 0; for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { if (ses_do_win(wp)) @@ -9303,9 +9297,8 @@ static int makeopens(FILE *fd, char_u *dirnow) cnr = nr; } - /* Go to the first window. */ - if (put_line(fd, "wincmd t") == FAIL) - return FAIL; + // Go to the first window. + PUTLINE_FAIL("wincmd t"); // If more than one window, see if sizes can be restored. // First set 'winheight' and 'winwidth' to 1 to avoid the windows being @@ -9314,10 +9307,11 @@ static int makeopens(FILE *fd, char_u *dirnow) // cursor can be set. This is done again below. // winminheight and winminwidth need to be set to avoid an error if the // user has set winheight or winwidth. - if (put_line(fd, "set winminheight=0") == FAIL - || put_line(fd, "set winheight=1") == FAIL - || put_line(fd, "set winminwidth=0") == FAIL - || put_line(fd, "set winwidth=1") == FAIL) { + if (fprintf(fd, + "set winminheight=0\n" + "set winheight=1\n" + "set winminwidth=0\n" + "set winwidth=1\n") < 0) { return FAIL; } if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) { @@ -9328,34 +9322,39 @@ static int makeopens(FILE *fd, char_u *dirnow) // Restore the view of the window (options, file, cursor, etc.). // for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) { - if (!ses_do_win(wp)) + if (!ses_do_win(wp)) { continue; - if (put_view(fd, wp, wp != edited_win, &ssop_flags, - cur_arg_idx) == FAIL) + } + if (put_view(fd, wp, wp != edited_win, &ssop_flags, cur_arg_idx) + == FAIL) { return FAIL; - if (nr > 1 && put_line(fd, "wincmd w") == FAIL) + } + if (nr > 1 && put_line(fd, "wincmd w") == FAIL) { return FAIL; + } next_arg_idx = wp->w_arg_idx; } - /* The argument index in the first tab page is zero, need to set it in - * each window. For further tab pages it's the window where we do - * "tabedit". */ + // The argument index in the first tab page is zero, need to set it in + // each window. For further tab pages it's the window where we do + // "tabedit". cur_arg_idx = next_arg_idx; - /* - * Restore cursor to the current window if it's not the first one. - */ + // + // Restore cursor to the current window if it's not the first one. + // if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0 - || put_eol(fd) == FAIL)) + || put_eol(fd) == FAIL)) { return FAIL; + } - /* - * Restore window sizes again after jumping around in windows, because - * the current window has a minimum size while others may not. - */ - if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) + // + // Restore window sizes again after jumping around in windows, because + // the current window has a minimum size while others may not. + // + if (nr > 1 && ses_winsizes(fd, restore_size, tab_firstwin) == FAIL) { return FAIL; + } // Take care of tab-local working directories if applicable if (tp->tp_localdir) { @@ -9368,34 +9367,33 @@ static int makeopens(FILE *fd, char_u *dirnow) did_lcd = true; } - /* Don't continue in another tab page when doing only the current one - * or when at the last tab page. */ - if (!(ssop_flags & SSOP_TABPAGES)) + // Don't continue in another tab page when doing only the current one + // or when at the last tab page. + if (!(ssop_flags & SSOP_TABPAGES)) { break; + } } if (ssop_flags & SSOP_TABPAGES) { - if (fprintf(fd, "tabnext %d", tabpage_index(curtab)) < 0 - || put_eol(fd) == FAIL) + if (fprintf(fd, "tabnext %d\n", tabpage_index(curtab)) < 0) { return FAIL; + } } if (restore_stal && put_line(fd, "set stal=1") == FAIL) { return FAIL; } - /* - * Wipe out an empty unnamed buffer we started in. - */ - if (put_line(fd, "if exists('s:wipebuf') " - "&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'") - == FAIL) - return FAIL; - if (put_line(fd, " silent exe 'bwipe ' . s:wipebuf") == FAIL) - return FAIL; - if (put_line(fd, "endif") == FAIL) - return FAIL; - if (put_line(fd, "unlet! s:wipebuf") == FAIL) + // + // Wipe out an empty unnamed buffer we started in. + // + if (fprintf(fd, "%s", + "if exists('s:wipebuf') " + "&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'\n" + " silent exe 'bwipe ' . s:wipebuf\n" + "endif\n" + "unlet! s:wipebuf\n") < 0) { return FAIL; + } // Re-apply options. if (fprintf(fd, "set winheight=%" PRId64 " winwidth=%" PRId64 @@ -9410,14 +9408,16 @@ static int makeopens(FILE *fd, char_u *dirnow) return FAIL; } - /* - * Lastly, execute the x.vim file if it exists. - */ - if (put_line(fd, "let s:sx = expand(\":p:r\").\"x.vim\"") == FAIL - || put_line(fd, "if file_readable(s:sx)") == FAIL - || put_line(fd, " exe \"source \" . fnameescape(s:sx)") == FAIL - || put_line(fd, "endif") == FAIL) + // + // Lastly, execute the x.vim file if it exists. + // + if (fprintf(fd, "%s", + "let s:sx = expand(\":p:r\").\"x.vim\"\n" + "if file_readable(s:sx)\n" + " exe \"source \" . fnameescape(s:sx)\n" + "endif\n") < 0) { return FAIL; + } return OK; } @@ -9457,53 +9457,50 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) } } } else { - // Just equalise window sizes - if (put_line(fd, "wincmd =") == FAIL) { - return FAIL; - } + // Just equalize window sizes. + PUTLINE_FAIL("wincmd ="); } return OK; } -/* - * Write commands to "fd" to recursively create windows for frame "fr", - * horizontally and vertically split. - * After the commands the last window in the frame is the current window. - * Returns FAIL when writing the commands to "fd" fails. - */ +// Write commands to "fd" to recursively create windows for frame "fr", +// horizontally and vertically split. +// After the commands the last window in the frame is the current window. +// Returns FAIL when writing the commands to "fd" fails. static int ses_win_rec(FILE *fd, frame_T *fr) { frame_T *frc; int count = 0; if (fr->fr_layout != FR_LEAF) { - /* Find first frame that's not skipped and then create a window for - * each following one (first frame is already there). */ + // Find first frame that's not skipped and then create a window for + // each following one (first frame is already there). frc = ses_skipframe(fr->fr_child); if (frc != NULL) while ((frc = ses_skipframe(frc->fr_next)) != NULL) { - /* Make window as big as possible so that we have lots of room - * to split. */ - if (put_line(fd, "wincmd _ | wincmd |") == FAIL - || put_line(fd, fr->fr_layout == FR_COL - ? "split" : "vsplit") == FAIL) + // Make window as big as possible so that we have lots of room + // to split. + if (fprintf(fd, "%s%s", + "wincmd _ | wincmd |\n", + (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n") + ) < 0) { return FAIL; + } ++count; } - /* Go back to the first window. */ + // Go back to the first window. if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL ? "%dwincmd k" : "%dwincmd h", count) < 0 || put_eol(fd) == FAIL)) return FAIL; - /* Recursively create frames/windows in each window of this column or - * row. */ + // Recursively create frames/windows in each window of this column or row. frc = ses_skipframe(fr->fr_child); while (frc != NULL) { ses_win_rec(fd, frc); frc = ses_skipframe(frc->fr_next); - /* Go to next window. */ + // Go to next window. if (frc != NULL && put_line(fd, "wincmd w") == FAIL) return FAIL; } @@ -9511,10 +9508,8 @@ static int ses_win_rec(FILE *fd, frame_T *fr) return OK; } -/* - * Skip frames that don't contain windows we want to save in the Session. - * Returns NULL when there none. - */ +// Skip frames that don't contain windows we want to save in the Session. +// Returns NULL when there none. static frame_T *ses_skipframe(frame_T *fr) { frame_T *frc; @@ -9598,14 +9593,14 @@ put_view( * Local argument list. */ if (wp->w_alist == &global_alist) { - if (put_line(fd, "argglobal") == FAIL) - return FAIL; + PUTLINE_FAIL("argglobal"); } else { if (ses_arglist(fd, "arglocal", &wp->w_alist->al_ga, - flagp == &vop_flags - || !(*flagp & SSOP_CURDIR) - || wp->w_localdir != NULL, flagp) == FAIL) + flagp == &vop_flags + || !(*flagp & SSOP_CURDIR) + || wp->w_localdir != NULL, flagp) == FAIL) { return FAIL; + } } /* Only when part of a session: restore the argument index. Some @@ -9658,9 +9653,7 @@ put_view( xfree(fname_esc); } else { // No file in this buffer, just make it empty. - if (put_line(fd, "enew") == FAIL) { - return FAIL; - } + PUTLINE_FAIL("enew"); if (wp->w_buffer->b_ffname != NULL) { // The buffer does have a name, but it's not a file name. if (fputs("file ", fd) < 0 @@ -9717,41 +9710,41 @@ put_view( */ if (do_cursor) { - /* Restore the cursor line in the file and relatively in the - * window. Don't use "G", it changes the jumplist. */ + // Restore the cursor line in the file and relatively in the + // window. Don't use "G", it changes the jumplist. if (fprintf(fd, "let s:l = %" PRId64 " - ((%" PRId64 - " * winheight(0) + %" PRId64 ") / %" PRId64 ")", + " * winheight(0) + %" PRId64 ") / %" PRId64 ")\n" + "if s:l < 1 | let s:l = 1 | endif\n" + "exe s:l\n" + "normal! zt\n" + "%" PRId64 "\n" + , (int64_t)wp->w_cursor.lnum, (int64_t)(wp->w_cursor.lnum - wp->w_topline), (int64_t)(wp->w_height_inner / 2), - (int64_t)wp->w_height_inner) < 0 - || put_eol(fd) == FAIL - || put_line(fd, "if s:l < 1 | let s:l = 1 | endif") == FAIL - || put_line(fd, "exe s:l") == FAIL - || put_line(fd, "normal! zt") == FAIL - || fprintf(fd, "%" PRId64, (int64_t)wp->w_cursor.lnum) < 0 - || put_eol(fd) == FAIL) + (int64_t)wp->w_height_inner, + (int64_t)wp->w_cursor.lnum + ) < 0) { return FAIL; - /* Restore the cursor column and left offset when not wrapping. */ + } + // Restore the cursor column and left offset when not wrapping. if (wp->w_cursor.col == 0) { - if (put_line(fd, "normal! 0") == FAIL) - return FAIL; + PUTLINE_FAIL("normal! 0"); } else { if (!wp->w_p_wrap && wp->w_leftcol > 0 && wp->w_width > 0) { if (fprintf(fd, "let s:c = %" PRId64 " - ((%" PRId64 - " * winwidth(0) + %" PRId64 ") / %" PRId64 ")", + " * winwidth(0) + %" PRId64 ") / %" PRId64 ")\n" + "if s:c > 0\n" + " exe 'normal! ' . s:c . '|zs' . %" PRId64 " . '|'\n" + "else\n" + , (int64_t)wp->w_virtcol + 1, (int64_t)(wp->w_virtcol - wp->w_leftcol), (int64_t)(wp->w_width / 2), - (int64_t)wp->w_width) < 0 - || put_eol(fd) == FAIL - || put_line(fd, "if s:c > 0") == FAIL - || fprintf(fd, " exe 'normal! ' . s:c . '|zs' . %" PRId64 " . '|'", - (int64_t)wp->w_virtcol + 1) < 0 - || put_eol(fd) == FAIL - || put_line(fd, "else") == FAIL + (int64_t)wp->w_width, + (int64_t)wp->w_virtcol + 1) < 0 || put_view_curpos(fd, wp, " ") == FAIL || put_line(fd, "endif") == FAIL) { return FAIL; @@ -9779,18 +9772,17 @@ put_view( return OK; } -/* - * Write an argument list to the session file. - * Returns FAIL if writing fails. - */ -static int -ses_arglist( - FILE *fd, - char *cmd, - garray_T *gap, - int fullname, /* TRUE: use full path name */ - unsigned *flagp -) +/// Writes an :argument list to the session file. +/// +/// @param fd +/// @param cmd +/// @param gap +/// @param fullname true: use full path name +/// @param flagp +/// +/// @returns FAIL if writing fails. +static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, + unsigned *flagp) { char_u *buf = NULL; char_u *s; @@ -9798,9 +9790,7 @@ ses_arglist( if (fputs(cmd, fd) < 0 || put_eol(fd) == FAIL) { return FAIL; } - if (put_line(fd, "%argdel") == FAIL) { - return FAIL; - } + PUTLINE_FAIL("%argdel"); for (int i = 0; i < gap->ga_len; ++i) { /* NULL file names are skipped (only happens when out of memory). */ s = alist_name(&((aentry_T *)gap->ga_data)[i]); @@ -9838,6 +9828,7 @@ static char *ses_get_fname(buf_T *buf, unsigned *flagp, bool add_eol) } return (char *)buf->b_ffname; } + /// Write a buffer name to the session file. /// Also ends the line, if "add_eol" is true. /// Returns FAIL if writing fails. @@ -9960,14 +9951,12 @@ int put_eol(FILE *fd) return OK; } -/* - * Write a line to "fd". - * Return FAIL for a write error. - */ +// TODO(justinmk): remove this, not needed after 823750fef315. int put_line(FILE *fd, char *s) { - if (fputs(s, fd) < 0 || put_eol(fd) == FAIL) + if (0 > fprintf(fd, "%s\n", s)) { return FAIL; + } return OK; } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index fcad6836bf..5f7d0b0614 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -578,7 +578,7 @@ static char *(p_ssop_values[]) = { # define SSOP_BLANK 0x080 # define SSOP_GLOBALS 0x100 # define SSOP_SLASH 0x200 -# define SSOP_UNIX 0x400 +# define SSOP_UNIX 0x400 /* Deprecated, not used. */ # define SSOP_SESDIR 0x800 # define SSOP_CURDIR 0x1000 # define SSOP_FOLDS 0x2000 -- cgit From 90486278061f114eba8703d2f058678bb6e247e6 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 05:08:12 -0800 Subject: lint --- src/nvim/ex_docmd.c | 38 ++++++++++++++++++-------------------- src/nvim/option_defs.h | 2 +- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 2b952b3f15..47c42c001e 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9210,7 +9210,7 @@ static int makeopens(FILE *fd, char_u *dirnow) // temporarily to avoid that. if (p_stal == 1 && first_tabpage->tp_next != NULL) { PUTLINE_FAIL("set stal=2"); - restore_stal = TRUE; + restore_stal = true; } // @@ -9482,18 +9482,18 @@ static int ses_win_rec(FILE *fd, frame_T *fr) // to split. if (fprintf(fd, "%s%s", "wincmd _ | wincmd |\n", - (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n") - ) < 0) { + (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n")) < 0) { return FAIL; } - ++count; + count++; } // Go back to the first window. if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL - ? "%dwincmd k" : "%dwincmd h", count) < 0 - || put_eol(fd) == FAIL)) + ? "%dwincmd k" : "%dwincmd h", count) < 0 + || put_eol(fd) == FAIL)) { return FAIL; + } // Recursively create frames/windows in each window of this column or row. frc = ses_skipframe(fr->fr_child); @@ -9501,8 +9501,9 @@ static int ses_win_rec(FILE *fd, frame_T *fr) ses_win_rec(fd, frc); frc = ses_skipframe(frc->fr_next); // Go to next window. - if (frc != NULL && put_line(fd, "wincmd w") == FAIL) + if (frc != NULL && put_line(fd, "wincmd w") == FAIL) { return FAIL; + } } } return OK; @@ -9694,9 +9695,9 @@ put_view( if (f == FAIL) return FAIL; - /* - * Save Folds when 'buftype' is empty and for help files. - */ + // + // Save Folds when 'buftype' is empty and for help files. + // if ((*flagp & SSOP_FOLDS) && wp->w_buffer->b_ffname != NULL && (bt_normal(wp->w_buffer) || bt_help(wp->w_buffer)) @@ -9705,11 +9706,10 @@ put_view( return FAIL; } - /* - * Set the cursor after creating folds, since that moves the cursor. - */ + // + // Set the cursor after creating folds, since that moves the cursor. + // if (do_cursor) { - // Restore the cursor line in the file and relatively in the // window. Don't use "G", it changes the jumplist. if (fprintf(fd, @@ -9718,14 +9718,12 @@ put_view( "if s:l < 1 | let s:l = 1 | endif\n" "exe s:l\n" "normal! zt\n" - "%" PRId64 "\n" - , + "%" PRId64 "\n", (int64_t)wp->w_cursor.lnum, (int64_t)(wp->w_cursor.lnum - wp->w_topline), (int64_t)(wp->w_height_inner / 2), (int64_t)wp->w_height_inner, - (int64_t)wp->w_cursor.lnum - ) < 0) { + (int64_t)wp->w_cursor.lnum) < 0) { return FAIL; } // Restore the cursor column and left offset when not wrapping. @@ -9791,8 +9789,8 @@ static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, return FAIL; } PUTLINE_FAIL("%argdel"); - for (int i = 0; i < gap->ga_len; ++i) { - /* NULL file names are skipped (only happens when out of memory). */ + for (int i = 0; i < gap->ga_len; i++) { + // NULL file names are skipped (only happens when out of memory). s = alist_name(&((aentry_T *)gap->ga_data)[i]); if (s != NULL) { if (fullname) { diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 5f7d0b0614..227c0fec4d 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -578,7 +578,7 @@ static char *(p_ssop_values[]) = { # define SSOP_BLANK 0x080 # define SSOP_GLOBALS 0x100 # define SSOP_SLASH 0x200 -# define SSOP_UNIX 0x400 /* Deprecated, not used. */ +# define SSOP_UNIX 0x400 // Deprecated, not used. # define SSOP_SESDIR 0x800 # define SSOP_CURDIR 0x1000 # define SSOP_FOLDS 0x2000 -- cgit From c4f4719ced9101195a84b350249ab2a105de627c Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 05:36:20 -0800 Subject: cleanup/ex_docmd.c: remove most put_eol() calls --- src/nvim/ex_docmd.c | 121 ++++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 66 deletions(-) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 47c42c001e..79cf1794b1 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -9151,12 +9151,13 @@ static int makeopens(FILE *fd, char_u *dirnow) PUTLINE_FAIL("exe \"cd \" . escape(expand(\":p:h\"), ' ')"); } else if (ssop_flags & SSOP_CURDIR) { sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow); - if (fputs("cd ", fd) < 0 - || ses_put_fname(fd, sname, &ssop_flags) == FAIL - || put_eol(fd) == FAIL) { + char *fname_esc = ses_escape_fname((char *)sname, &ssop_flags); + if (fprintf(fd, "cd %s\n", fname_esc) < 0) { + xfree(fname_esc); xfree(sname); return FAIL; } + xfree(fname_esc); xfree(sname); } @@ -9196,11 +9197,11 @@ static int makeopens(FILE *fd, char_u *dirnow) } if (ssop_flags & SSOP_RESIZE) { - /* Note: after the restore we still check it worked!*/ - if (fprintf(fd, "set lines=%" PRId64 " columns=%" PRId64, - (int64_t)Rows, (int64_t)Columns) < 0 - || put_eol(fd) == FAIL) + // Note: after the restore we still check it worked! + if (fprintf(fd, "set lines=%" PRId64 " columns=%" PRId64 "\n", + (int64_t)Rows, (int64_t)Columns) < 0) { return FAIL; + } } int restore_stal = FALSE; @@ -9343,8 +9344,7 @@ static int makeopens(FILE *fd, char_u *dirnow) // // Restore cursor to the current window if it's not the first one. // - if (cnr > 1 && (fprintf(fd, "%dwincmd w", cnr) < 0 - || put_eol(fd) == FAIL)) { + if (cnr > 1 && (fprintf(fd, "%dwincmd w\n", cnr) < 0)) { return FAIL; } @@ -9360,8 +9360,7 @@ static int makeopens(FILE *fd, char_u *dirnow) if (tp->tp_localdir) { if (fputs("if exists(':tcd') == 2 | tcd ", fd) < 0 || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL - || fputs(" | endif", fd) < 0 - || put_eol(fd) == FAIL) { + || fputs(" | endif\n", fd) < 0) { return FAIL; } did_lcd = true; @@ -9396,15 +9395,15 @@ static int makeopens(FILE *fd, char_u *dirnow) } // Re-apply options. - if (fprintf(fd, "set winheight=%" PRId64 " winwidth=%" PRId64 - " winminheight=%" PRId64 " winminwidth=%" PRId64 - " shortmess=%s", + if (fprintf(fd, + "set winheight=%" PRId64 " winwidth=%" PRId64 + " winminheight=%" PRId64 " winminwidth=%" PRId64 + " shortmess=%s\n", (int64_t)p_wh, (int64_t)p_wiw, (int64_t)p_wmh, (int64_t)p_wmw, - p_shm) < 0 - || put_eol(fd) == FAIL) { + p_shm) < 0) { return FAIL; } @@ -9438,10 +9437,9 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) if (wp->w_height + wp->w_status_height < topframe->fr_height && (fprintf(fd, "exe '%dresize ' . ((&lines * %" PRId64 - " + %" PRId64 ") / %" PRId64 ")", + " + %" PRId64 ") / %" PRId64 ")\n", n, (int64_t)wp->w_height, - (int64_t)Rows / 2, (int64_t)Rows) < 0 - || put_eol(fd) == FAIL)) { + (int64_t)Rows / 2, (int64_t)Rows) < 0)) { return FAIL; } @@ -9449,10 +9447,9 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin) if (wp->w_width < Columns && (fprintf(fd, "exe 'vert %dresize ' . ((&columns * %" PRId64 - " + %" PRId64 ") / %" PRId64 ")", + " + %" PRId64 ") / %" PRId64 ")\n", n, (int64_t)wp->w_width, (int64_t)Columns / 2, - (int64_t)Columns) < 0 - || put_eol(fd) == FAIL)) { + (int64_t)Columns) < 0)) { return FAIL; } } @@ -9490,8 +9487,7 @@ static int ses_win_rec(FILE *fd, frame_T *fr) // Go back to the first window. if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL - ? "%dwincmd k" : "%dwincmd h", count) < 0 - || put_eol(fd) == FAIL)) { + ? "%dwincmd k\n" : "%dwincmd h\n", count) < 0)) { return FAIL; } @@ -9560,11 +9556,11 @@ static int put_view_curpos(FILE *fd, const win_T *wp, char *spaces) int r; if (wp->w_curswant == MAXCOL) { - r = fprintf(fd, "%snormal! $", spaces); + r = fprintf(fd, "%snormal! $\n", spaces); } else { - r = fprintf(fd, "%snormal! 0%d|", spaces, wp->w_virtcol + 1); + r = fprintf(fd, "%snormal! 0%d|\n", spaces, wp->w_virtcol + 1); } - return r < 0 || put_eol(fd) == FAIL ? FAIL : OK; + return r >= 0; } /* @@ -9608,18 +9604,19 @@ put_view( * arguments may have been deleted, check if the index is valid. */ if (wp->w_arg_idx != current_arg_idx && wp->w_arg_idx < WARGCOUNT(wp) && flagp == &ssop_flags) { - if (fprintf(fd, "%" PRId64 "argu", (int64_t)wp->w_arg_idx + 1) < 0 - || put_eol(fd) == FAIL) { + if (fprintf(fd, "%" PRId64 "argu\n", (int64_t)wp->w_arg_idx + 1) < 0) { return FAIL; } did_next = true; } - /* Edit the file. Skip this when ":next" already did it. */ + // Edit the file. Skip this when ":next" already did it. if (add_edit && (!did_next || wp->w_arg_idx_invalid)) { - /* - * Load the file. - */ + char *fname_esc = + ses_escape_fname(ses_get_fname(wp->w_buffer, flagp), flagp); + // + // Load the file. + // if (wp->w_buffer->b_ffname != NULL && (!bt_nofile(wp->w_buffer) || wp->w_buffer->terminal) ) { @@ -9629,49 +9626,41 @@ put_view( // Note, if a buffer for that file already exists, use :badd to // edit that buffer, to not lose folding information (:edit resets // folds in other buffers) - if (fputs("if bufexists(\"", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL - || fputs("\") | buffer ", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL - || fputs(" | else | edit ", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, false) == FAIL - || fputs(" | endif", fd) < 0 - || put_eol(fd) == FAIL) { - return FAIL; - } - - char *fname_esc = - ses_escape_fname(ses_get_fname(wp->w_buffer, flagp, false), flagp); - // Fixup :terminal buffer name. if (fprintf(fd, + "if bufexists(\"%s\") | buffer %s | else | edit %s | endif\n" + // Fixup :terminal buffer name. #7836 "if &buftype ==# 'terminal'\n" " silent file %s\n" "endif\n", + fname_esc, + fname_esc, + fname_esc, fname_esc) < 0) { xfree(fname_esc); return FAIL; } - xfree(fname_esc); } else { // No file in this buffer, just make it empty. PUTLINE_FAIL("enew"); if (wp->w_buffer->b_ffname != NULL) { // The buffer does have a name, but it's not a file name. - if (fputs("file ", fd) < 0 - || ses_fname(fd, wp->w_buffer, flagp, true) == FAIL) { + if (fprintf(fd, "file %s\n", fname_esc) < 0) { + xfree(fname_esc); return FAIL; } } do_cursor = false; } + xfree(fname_esc); } /* * Local mappings and abbreviations. */ if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS)) - && makemap(fd, wp->w_buffer) == FAIL) + && makemap(fd, wp->w_buffer) == FAIL) { return FAIL; + } /* * Local options. Need to go to the window temporarily. @@ -9692,8 +9681,9 @@ put_view( f = OK; curwin = save_curwin; curbuf = curwin->w_buffer; - if (f == FAIL) + if (f == FAIL) { return FAIL; + } // // Save Folds when 'buftype' is empty and for help files. @@ -9736,8 +9726,7 @@ put_view( " * winwidth(0) + %" PRId64 ") / %" PRId64 ")\n" "if s:c > 0\n" " exe 'normal! ' . s:c . '|zs' . %" PRId64 " . '|'\n" - "else\n" - , + "else\n", (int64_t)wp->w_virtcol + 1, (int64_t)(wp->w_virtcol - wp->w_leftcol), (int64_t)(wp->w_width / 2), @@ -9761,7 +9750,7 @@ put_view( && (flagp != &vop_flags || (*flagp & SSOP_CURDIR))) { if (fputs("lcd ", fd) < 0 || ses_put_fname(fd, wp->w_localdir, flagp) == FAIL - || put_eol(fd) == FAIL) { + || fprintf(fd, "\n") < 0) { return FAIL; } did_lcd = true; @@ -9785,10 +9774,9 @@ static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, char_u *buf = NULL; char_u *s; - if (fputs(cmd, fd) < 0 || put_eol(fd) == FAIL) { + if (fprintf(fd, "%s\n%s\n", cmd, "%argdel") < 0) { return FAIL; } - PUTLINE_FAIL("%argdel"); for (int i = 0; i < gap->ga_len; i++) { // NULL file names are skipped (only happens when out of memory). s = alist_name(&((aentry_T *)gap->ga_data)[i]); @@ -9798,11 +9786,13 @@ static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, (void)vim_FullName((char *)s, (char *)buf, MAXPATHL, FALSE); s = buf; } - if (fputs("$argadd ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL - || put_eol(fd) == FAIL) { + char *fname_esc = ses_escape_fname((char *)s, flagp); + if (fprintf(fd, "$argadd %s\n", fname_esc) < 0) { + xfree(fname_esc); xfree(buf); return FAIL; } + xfree(fname_esc); xfree(buf); } } @@ -9810,7 +9800,7 @@ static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, } /// Gets the buffer name for `buf`. -static char *ses_get_fname(buf_T *buf, unsigned *flagp, bool add_eol) +static char *ses_get_fname(buf_T *buf, unsigned *flagp) { // Use the short file name if the current directory is known at the time // the session file will be sourced. @@ -9832,9 +9822,9 @@ static char *ses_get_fname(buf_T *buf, unsigned *flagp, bool add_eol) /// Returns FAIL if writing fails. static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, bool add_eol) { - char *name = ses_get_fname(buf, flagp, add_eol); + char *name = ses_get_fname(buf, flagp); if (ses_put_fname(fd, (char_u *)name, flagp) == FAIL - || (add_eol && put_eol(fd) == FAIL)) { + || (add_eol && fprintf(fd, "\n") < 0)) { return FAIL; } return OK; @@ -9939,8 +9929,7 @@ static char *get_view_file(int c) } -/// TODO(justinmk): remove this. Formerly used to choose CRLF or LF for session -// files, but that's useless--instead we always write LF. +// TODO(justinmk): remove this, not needed after 5ba3cecb68cd. int put_eol(FILE *fd) { if (putc('\n', fd) < 0) { @@ -9949,10 +9938,10 @@ int put_eol(FILE *fd) return OK; } -// TODO(justinmk): remove this, not needed after 823750fef315. +// TODO(justinmk): remove this, not needed after 5ba3cecb68cd. int put_line(FILE *fd, char *s) { - if (0 > fprintf(fd, "%s\n", s)) { + if (fprintf(fd, "%s\n", s) < 0) { return FAIL; } return OK; -- cgit From 1c3ca4f18fdc403813d8959b49626ac1c99e2c59 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Sun, 26 Jan 2020 14:26:01 -0800 Subject: mksession: always unix slashes "/" for filepaths --- ci/build.ps1 | 3 +++ runtime/doc/usr_21.txt | 15 --------------- src/nvim/ex_docmd.c | 16 ++++++++++------ src/nvim/option_defs.h | 4 ++-- test/functional/ex_cmds/mksession_spec.lua | 5 +++-- test/functional/helpers.lua | 2 +- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/ci/build.ps1 b/ci/build.ps1 index 627dc69e88..a7a456f67a 100644 --- a/ci/build.ps1 +++ b/ci/build.ps1 @@ -173,6 +173,9 @@ if (-not $NoTests) { # Functional tests # The $LastExitCode from MSBuild can't be trusted $failed = $false + + # Run only this test file: + # $env:TEST_FILE = "test\functional\foo.lua" cmake --build . --config $cmakeBuildType --target functionaltest -- $cmakeGeneratorArgs 2>&1 | foreach { $failed = $failed -or $_ -match 'functional tests failed with error'; $_ } diff --git a/runtime/doc/usr_21.txt b/runtime/doc/usr_21.txt index 99a78e7b05..44d653a1a7 100644 --- a/runtime/doc/usr_21.txt +++ b/runtime/doc/usr_21.txt @@ -339,21 +339,6 @@ window, move the cursor to the filename and press "O". Double clicking with the mouse will also do this. -UNIX AND MS-WINDOWS - -Some people have to do work on MS-Windows systems one day and on Unix another -day. If you are one of them, consider adding "slash" and "unix" to -'sessionoptions'. The session files will then be written in a format that can -be used on both systems. This is the command to put in your |init.vim| file: -> - :set sessionoptions+=unix,slash - -Vim will use the Unix format then, because the MS-Windows Vim can read and -write Unix files, but Unix Vim can't read MS-Windows format session files. -Similarly, MS-Windows Vim understands file names with / to separate names, but -Unix Vim doesn't understand \. - - SESSIONS AND SHADA Sessions store many things, but not the position of marks, contents of diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 79cf1794b1..d87dd29f88 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -8089,6 +8089,10 @@ static void close_redir(void) do { if (FAIL == put_line(fd, (s))) { return FAIL; } } while (0) /// ":mkexrc", ":mkvimrc", ":mkview", ":mksession". +/// +/// Legacy 'sessionoptions' flags SSOP_UNIX, SSOP_SLASH are always enabled. +/// - SSOP_UNIX: line-endings are always LF +/// - SSOP_SLASH: filenames are always written with "/" slash static void ex_mkrc(exarg_T *eap) { FILE *fd; @@ -9112,6 +9116,8 @@ char_u *expand_sfile(char_u *arg) /// Writes commands for restoring the current buffers, for :mksession. /// +/// Legacy 'sessionoptions' flags SSOP_UNIX, SSOP_SLASH are always enabled. +/// /// @param dirnow Current directory name /// @param fd File descriptor to write to /// @@ -9840,12 +9846,10 @@ static char *ses_escape_fname(char *name, unsigned *flagp) char *p; char *sname = (char *)home_replace_save(NULL, (char_u *)name); - if (*flagp & SSOP_SLASH) { - // change all backslashes to forward slashes - for (p = sname; *p != NUL; MB_PTR_ADV(p)) { - if (*p == '\\') { - *p = '/'; - } + // Always SSOP_SLASH: change all backslashes to forward slashes. + for (p = sname; *p != NUL; MB_PTR_ADV(p)) { + if (*p == '\\') { + *p = '/'; } } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 227c0fec4d..c5d8b134c4 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -577,8 +577,8 @@ static char *(p_ssop_values[]) = { # define SSOP_HELP 0x040 # define SSOP_BLANK 0x080 # define SSOP_GLOBALS 0x100 -# define SSOP_SLASH 0x200 -# define SSOP_UNIX 0x400 // Deprecated, not used. +# define SSOP_SLASH 0x200 // Deprecated, always set. +# define SSOP_UNIX 0x400 // Deprecated, always set. # define SSOP_SESDIR 0x800 # define SSOP_CURDIR 0x1000 # define SSOP_FOLDS 0x2000 diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 305850a09e..949724bb53 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -96,7 +96,8 @@ describe(':mksession', function() it('restores CWD for :terminal buffers #11288', function() local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '') - local session_path = cwd_dir..get_pathsep()..session_file + cwd_dir = cwd_dir:gsub([[\]], '/') -- :mksession always uses unix slashes. + local session_path = cwd_dir..'/'..session_file command('cd '..tab_dir) command('terminal echo $PWD') @@ -108,7 +109,7 @@ describe(':mksession', function() clear() command('silent source '..session_path) - local expected_cwd = cwd_dir..get_pathsep()..tab_dir + local expected_cwd = cwd_dir..'/'..tab_dir matches('^term://'..pesc(expected_cwd)..'//%d+:', funcs.expand('%')) command('qall!') end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 3ffc6137d6..53c4d140b6 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -794,7 +794,7 @@ function module.alter_slashes(obj) end return ret else - assert(false, 'Could only alter slashes for tables of strings and strings') + assert(false, 'expected string or table of strings, got '..type(obj)) end end -- cgit