aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/ex_session.c')
-rw-r--r--src/nvim/ex_session.c150
1 files changed, 54 insertions, 96 deletions
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 3de5e1db52..71c01922bc 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -1,21 +1,16 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
// Functions for creating a session file, i.e. implementing:
// :mkexrc
// :mkvimrc
// :mkview
// :mksession
-#include <assert.h>
#include <inttypes.h>
-#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "nvim/arglist.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds_defs.h"
@@ -25,20 +20,22 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
-#include "nvim/mark_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_vars.h"
+#include "nvim/os/fs.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
-#include "nvim/pos.h"
+#include "nvim/pos_defs.h"
#include "nvim/runtime.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -65,11 +62,9 @@ static int put_view_curpos(FILE *fd, const win_T *wp, char *spaces)
static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
{
- int n = 0;
- win_T *wp;
-
if (restore_size && (ssop_flags & SSOP_WINSIZE)) {
- for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
+ int n = 0;
+ for (win_T *wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
if (!ses_do_win(wp)) {
continue;
}
@@ -109,7 +104,6 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
/// @return 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) {
@@ -118,7 +112,7 @@ static int ses_win_rec(FILE *fd, frame_T *fr)
// 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);
+ frame_T *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
@@ -218,14 +212,13 @@ static int ses_do_win(win_T *wp)
static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp)
{
char *buf = NULL;
- char *s;
if (fprintf(fd, "%s\n%s\n", cmd, "%argdel") < 0) {
return FAIL;
}
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]);
+ char *s = alist_name(&((aentry_T *)gap->ga_data)[i]);
if (s != NULL) {
if (fullname) {
buf = xmalloc(MAXPATHL);
@@ -321,18 +314,14 @@ static int ses_put_fname(FILE *fd, char *name, unsigned *flagp)
/// @param current_arg_idx current argument index of the window, use -1 if unknown
static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx)
{
- win_T *save_curwin;
int f;
- int do_cursor;
int did_next = false;
// Always restore cursor position for ":mksession". For ":mkview" only
// when 'viewoptions' contains "cursor".
- do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
+ int do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
- //
// Local argument list.
- //
if (wp->w_alist == &global_alist) {
PUTLINE_FAIL("argglobal");
} else {
@@ -425,22 +414,18 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
}
}
- //
// Local mappings and abbreviations.
- //
if ((*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS))
&& makemap(fd, wp->w_buffer) == FAIL) {
return FAIL;
}
- //
// Local options. Need to go to the window temporarily.
// Store only local values when using ":mkview" and when ":mksession" is
// used and 'sessionoptions' doesn't include "nvim/options".
// Some folding options are always stored when "folds" is included,
// otherwise the folds would not be restored correctly.
- //
- save_curwin = curwin;
+ win_T *save_curwin = curwin;
curwin = wp;
curbuf = curwin->w_buffer;
if (*flagp & (SSOP_OPTIONS | SSOP_LOCALOPTIONS)) {
@@ -457,9 +442,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
return FAIL;
}
- //
// 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)
@@ -469,9 +452,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
}
}
- //
// 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.
@@ -522,10 +503,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
}
}
- //
// Local directory, if the current flag is not view options or the "curdir"
// option is included.
- //
if (wp->w_localdir != NULL
&& (flagp != &vop_flags || (*flagp & SSOP_CURDIR))) {
if (fputs("lcd ", fd) < 0
@@ -551,12 +530,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
static int makeopens(FILE *fd, char *dirnow)
{
int only_save_windows = true;
- int nr;
int restore_size = true;
- win_T *wp;
- char *sname;
win_T *edited_win = NULL;
- int tabnr;
win_T *tab_firstwin;
frame_T *tab_topframe;
int cur_arg_idx = 0;
@@ -581,13 +556,11 @@ static int makeopens(FILE *fd, char *dirnow)
return FAIL;
}
- //
// Now a :cd command to the session directory or the current directory
- //
if (ssop_flags & SSOP_SESDIR) {
PUTLINE_FAIL("exe \"cd \" . escape(expand(\"<sfile>:p:h\"), ' ')");
} else if (ssop_flags & SSOP_CURDIR) {
- sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
+ char *sname = home_replace_save(NULL, globaldir != NULL ? globaldir : dirnow);
char *fname_esc = ses_escape_fname(sname, &ssop_flags);
if (fprintf(fd, "cd %s\n", fname_esc) < 0) {
xfree(fname_esc);
@@ -633,7 +606,7 @@ static int makeopens(FILE *fd, char *dirnow)
&& buf->b_p_bl) {
if (fprintf(fd, "badd +%" PRId64 " ",
buf->b_wininfo == NULL
- ? (int64_t)1L
+ ? 1
: (int64_t)buf->b_wininfo->wi_mark.mark.lnum) < 0
|| ses_fname(fd, buf, &ssop_flags, true) == FAIL) {
return FAIL;
@@ -665,16 +638,10 @@ static int makeopens(FILE *fd, char *dirnow)
restore_stal = true;
}
- //
- // 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;
if ((ssop_flags & SSOP_TABPAGES)) {
- // Similar to ses_win_rec() below, populate the tab pages first so
- // later local options won't be copied to the new tabs.
+ // "tabpages" is in 'sessionoptions': Similar to ses_win_rec() below,
+ // populate the tab pages first so later local options won't be copied
+ // to the new tabs.
FOR_ALL_TABS(tp) {
// Use `bufhidden=wipe` to remove empty "placeholder" buffers once
// they are not needed. This prevents creating extra buffers (see
@@ -688,15 +655,17 @@ static int makeopens(FILE *fd, char *dirnow)
return FAIL;
}
}
- for (tabnr = 1;; tabnr++) {
- tabpage_T *tp = find_tabpage(tabnr);
- if (tp == NULL) {
- break; // done all tab pages
- }
+ // Assume "tabpages" is in 'sessionoptions'. If not then we only do
+ // "curtab" and bail out of the loop.
+ FOR_ALL_TABS(tp) {
bool need_tabnext = false;
int cnr = 1;
+ // May repeat putting Windows for each tab, when "tabpages" is in
+ // 'sessionoptions'.
+ // Don't use goto_tabpage(), it may change directory and trigger
+ // autocommands.
if ((ssop_flags & SSOP_TABPAGES)) {
if (tp == curtab) {
tab_firstwin = firstwin;
@@ -705,17 +674,19 @@ static int makeopens(FILE *fd, char *dirnow)
tab_firstwin = tp->tp_firstwin;
tab_topframe = tp->tp_topframe;
}
- if (tabnr > 1) {
+ if (tp != first_tabpage) {
need_tabnext = true;
}
+ } else {
+ tp = curtab;
+ tab_firstwin = firstwin;
+ tab_topframe = topframe;
}
- //
// 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) {
+ for (win_T *wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
if (ses_do_win(wp)
&& wp->w_buffer->b_ffname != NULL
&& !bt_help(wp->w_buffer)
@@ -753,12 +724,10 @@ static int makeopens(FILE *fd, char *dirnow)
PUTLINE_FAIL("let &splitright = s:save_splitright");
}
- //
// 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) {
+ int nr = 0;
+ for (win_T *wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
if (ses_do_win(wp)) {
nr++;
} else {
@@ -794,10 +763,20 @@ static int makeopens(FILE *fd, char *dirnow)
return FAIL;
}
- //
+ // Restore the tab-local working directory if specified
+ // Do this before the windows, so that the window-local directory can
+ // override the tab-local directory.
+ if ((ssop_flags & SSOP_CURDIR) && tp->tp_localdir != NULL) {
+ if (fputs("tcd ", fd) < 0
+ || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
+ || put_eol(fd) == FAIL) {
+ return FAIL;
+ }
+ did_lcd = true;
+ }
+
// Restore the view of the window (options, file, cursor, etc.).
- //
- for (wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
+ for (win_T *wp = tab_firstwin; wp != NULL; wp = wp->w_next) {
if (!ses_do_win(wp)) {
continue;
}
@@ -816,31 +795,17 @@ static int makeopens(FILE *fd, char *dirnow)
// "tabedit".
cur_arg_idx = next_arg_idx;
- //
// Restore cursor to the current window if it's not the first one.
- //
if (cnr > 1 && (fprintf(fd, "%dwincmd w\n", cnr) < 0)) {
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) {
return FAIL;
}
- // Take care of tab-local working directories if applicable
- 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\n", fd) < 0) {
- return FAIL;
- }
- 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)) {
@@ -857,9 +822,7 @@ static int makeopens(FILE *fd, char *dirnow)
return FAIL;
}
- //
// Wipe out an empty unnamed buffer we started in.
- //
if (fprintf(fd, "%s",
"if exists('s:wipebuf') "
"&& len(win_findbuf(s:wipebuf)) == 0 "
@@ -891,9 +854,7 @@ static int makeopens(FILE *fd, char *dirnow)
PUTLINE_FAIL("let &winminwidth = s:save_winminwidth");
}
- //
// Lastly, execute the x.vim file if it exists.
- //
if (fprintf(fd, "%s",
"let s:sx = expand(\"<sfile>:p:r\").\"x.vim\"\n"
"if filereadable(s:sx)\n"
@@ -913,7 +874,7 @@ void ex_loadview(exarg_T *eap)
return;
}
- if (do_source(fname, false, DOSO_NONE) == FAIL) {
+ if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) {
semsg(_(e_notopen), fname);
}
xfree(fname);
@@ -926,12 +887,9 @@ void ex_loadview(exarg_T *eap)
/// - SSOP_SLASH: filenames are written with "/" slash
void ex_mkrc(exarg_T *eap)
{
- FILE *fd;
- int failed = false;
int view_session = false; // :mkview, :mksession
int using_vdir = false; // using 'viewdir'?
char *viewFile = NULL;
- unsigned *flagp;
if (eap->cmdidx == CMD_mksession || eap->cmdidx == CMD_mkview) {
view_session = true;
@@ -965,11 +923,13 @@ void ex_mkrc(exarg_T *eap)
// When using 'viewdir' may have to create the directory.
if (using_vdir && !os_isdir(p_vdir)) {
- vim_mkdir_emsg((const char *)p_vdir, 0755);
+ vim_mkdir_emsg(p_vdir, 0755);
}
- fd = open_exfile(fname, eap->forceit, WRITEBIN);
+ FILE *fd = open_exfile(fname, eap->forceit, WRITEBIN);
if (fd != NULL) {
+ int failed = false;
+ unsigned *flagp;
if (eap->cmdidx == CMD_mkview) {
flagp = &vop_flags;
} else {
@@ -1008,9 +968,8 @@ void ex_mkrc(exarg_T *eap)
char *dirnow; // current directory
dirnow = xmalloc(MAXPATHL);
- //
+
// Change to session file's dir.
- //
if (os_dirname(dirnow, MAXPATHL) == FAIL
|| os_chdir(dirnow) != 0) {
*dirnow = NUL;
@@ -1084,7 +1043,7 @@ void ex_mkrc(exarg_T *eap)
}
/// @return the name of the view file for the current buffer.
-static char *get_view_file(int c)
+static char *get_view_file(char c)
{
if (curbuf->b_ffname == NULL) {
emsg(_(e_noname));
@@ -1123,8 +1082,7 @@ static char *get_view_file(int c)
}
}
*s++ = '=';
- assert(c >= CHAR_MIN && c <= CHAR_MAX);
- *s++ = (char)c;
+ *s++ = c;
xstrlcpy(s, ".vim", 5);
xfree(sname);