diff options
| author | Justin M. Keyes <justinkz@gmail.com> | 2023-10-04 06:31:25 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-04 06:31:25 -0700 |
| commit | 29fe883aa9166bdbcae3f935523c75a8aa56fe45 (patch) | |
| tree | 40c1179d6d854acec5d044a94cc6111dc54883c7 | |
| parent | 1e7e9ee91f73c62b8c5ba9dbdabba3a3b6dc0130 (diff) | |
| download | rneovim-29fe883aa9166bdbcae3f935523c75a8aa56fe45.tar.gz rneovim-29fe883aa9166bdbcae3f935523c75a8aa56fe45.tar.bz2 rneovim-29fe883aa9166bdbcae3f935523c75a8aa56fe45.zip | |
feat: ignore swapfile for running Nvim processes #25336
Problem:
The swapfile "E325: ATTENTION" dialog is displayed when editing a file
already open in another (running) Nvim. Usually this behavior is
annoying and irrelevant:
- "Recover" and the other options ("Open readonly", "Quit", "Abort") are
almost never wanted.
- swapfiles are less relevant for "multi-Nvim" since 'autoread' is
enabled by default.
- Even less relevant if user enables 'autowrite'.
Solution:
Define a default SwapExists handler which does the following:
1. If the swapfile is owned by a running Nvim process, automatically
chooses "(E)dit anyway" (caveat: this creates a new, extra swapfile,
which is mostly harmless and ignored except by `:recover` or `nvim -r`.
2. Shows a 1-line "ignoring swapfile..." message.
3. Users can disable the default SwapExists handler via `autocmd! nvim_swapfile`.
| -rw-r--r-- | runtime/doc/autocmd.txt | 2 | ||||
| -rw-r--r-- | runtime/doc/builtin.txt | 4 | ||||
| -rw-r--r-- | runtime/doc/editing.txt | 39 | ||||
| -rw-r--r-- | runtime/doc/eval.txt | 7 | ||||
| -rw-r--r-- | runtime/doc/news.txt | 6 | ||||
| -rw-r--r-- | runtime/doc/recover.txt | 9 | ||||
| -rw-r--r-- | runtime/doc/vim_diff.txt | 5 | ||||
| -rw-r--r-- | runtime/lua/vim/_editor.lua | 17 | ||||
| -rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 4 | ||||
| -rw-r--r-- | src/nvim/eval.lua | 4 | ||||
| -rw-r--r-- | src/nvim/eval/funcs.c | 2 | ||||
| -rw-r--r-- | src/nvim/eval/userfunc.c | 2 | ||||
| -rw-r--r-- | src/nvim/memline.c | 258 | ||||
| -rw-r--r-- | src/nvim/message.c | 28 | ||||
| -rw-r--r-- | test/functional/ex_cmds/swapfile_preserve_recover_spec.lua | 58 |
15 files changed, 267 insertions, 178 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 90211fc5db..7ca9996e15 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -118,7 +118,7 @@ manually. Mostly the screen will not scroll up, thus there is no hit-enter prompt. When one command outputs two messages this can happen anyway. ============================================================================== -3. Removing autocommands *autocmd-remove* +3. Removing autocommands *autocmd!* *autocmd-remove* :au[tocmd]! [group] {event} {aupat} [++once] [++nested] {cmd} Remove all autocommands associated with {event} and diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c5c941a4bf..6de7166f83 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -7843,8 +7843,8 @@ swapinfo({fname}) *swapinfo()* user user name host host name fname original file name - pid PID of the Vim process that created the swap - file + pid PID of the Nvim process that created the swap + file, or zero if not running. mtime last modification time in seconds inode Optional: INODE number of the file dirty 1 if file was modified, 0 if not diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 10b578fc73..7df2eb9742 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -169,33 +169,26 @@ If you want to keep the changed buffer without saving it, switch on the 2. Editing a file *edit-a-file* *:e* *:edit* *reload* -:e[dit] [++opt] [+cmd] Edit the current file. This is useful to re-edit the +:e[dit][!] [++opt] [+cmd] + Edit the current file. This is useful to re-edit the current file, when it has been changed outside of Vim. - This fails when changes have been made to the current - buffer and 'autowriteall' isn't set or the file can't - be written. - Also see |++opt| and |+cmd|. - *:edit!* *discard* -:e[dit]! [++opt] [+cmd] - Edit the current file always. Discard any changes to - the current buffer. This is useful if you want to - start all over again. + If [!] is given, unsaved changes in the current buffer + are discarded. Without [!] the command fails if there + are unsaved changes, unless 'autowriteall' is set and + the file can be written. Also see |++opt| and |+cmd|. *:edit_f* -:e[dit] [++opt] [+cmd] {file} +:e[dit][!] [++opt] [+cmd] {file} Edit {file}. - This fails when changes have been made to the current - buffer, unless 'hidden' is set or 'autowriteall' is - set and the file can be written. - Also see |++opt| and |+cmd|. - *:edit!_f* -:e[dit]! [++opt] [+cmd] {file} - Edit {file} always. Discard any changes to the - current buffer. + If [!] is given, unsaved changes in the current buffer + are discarded. Without [!] the command fails if there + are unsaved changes, unless 'hidden' is set or + 'autowriteall' is set and the file can be written. Also see |++opt| and |+cmd|. + *:edit_#* *:e#* :e[dit] [++opt] [+cmd] #[count] Edit the [count]th buffer (as shown by |:files|). @@ -1224,10 +1217,10 @@ MULTIPLE WINDOWS AND BUFFERS *window-exit* *:confirm* *:conf* :conf[irm] {command} Execute {command}, and use a dialog when an operation has to be confirmed. Can be used on the - |:q|, |:qa| and |:w| commands (the latter to override - a read-only setting), and any other command that can - fail in such a way, such as |:only|, |:buffer|, - |:bdelete|, etc. + |:edit|, |:q|, |:qa| and |:w| commands (the latter to + override a read-only setting), and any commands that + can fail because of unsaved changes, such as |:only|, + |:buffer|, |:bdelete|, etc. Examples: > :confirm w foo diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 3cd5ea13f6..c41237b862 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2276,12 +2276,13 @@ v:stderr |channel-id| corresponding to stderr. The value is always 2; :call chansend(v:stderr, "error: toaster empty\n") < *v:swapname* *swapname-variable* -v:swapname Only valid when executing |SwapExists| autocommands: Name of - the swap file found. Read-only. +v:swapname Name of the swapfile found. + Only valid during |SwapExists| event. + Read-only. *v:swapchoice* *swapchoice-variable* v:swapchoice |SwapExists| autocommands can set this to the selected choice - for handling an existing swap file: + for handling an existing swapfile: 'o' Open read-only 'e' Edit anyway 'r' Recover diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 3c20e52155..f0d01f92e7 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -114,6 +114,12 @@ The following new APIs and features were added. • Builtin TUI can now recognize "super" (|<D-|) and "meta" (|<T-|) modifiers in a terminal emulator that supports |tui-csiu|. +• Editor + • By default, the swapfile "ATTENTION" |E325| dialog is skipped if the + swapfile is owned by a running Nvim process, instead of prompting. If you + always want the swapfile dialog, delete the default SwapExists handler: + `autocmd! nvim_swapfile`. |default-autocmds| + • LSP • LSP method names are available in |vim.lsp.protocol.Methods|. • Implemented LSP inlay hints: |vim.lsp.inlay_hint()| diff --git a/runtime/doc/recover.txt b/runtime/doc/recover.txt index b05bcd6bc8..e6b5b06744 100644 --- a/runtime/doc/recover.txt +++ b/runtime/doc/recover.txt @@ -83,6 +83,15 @@ Detecting an existing swap file ~ You can find this in the user manual, section |11.3|. + *W325* +The default |SwapExists| handler (|default-autocmds|) skips the |E325| prompt +(selects "(E)dit") if the swapfile owner process (1) is still running and (2) +was started by the current user. This presumes that you normally don't want +to be bothered with the |ATTENTION| message just because you happen to edit +the same file from multiple Nvim instances. In the worst case (a system +crash) there will be more than one swapfile for the file; use |:recover| to +inspect all of its swapfiles. + Updating the swapfile ~ diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 3bf844a139..e9c04443a6 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -139,6 +139,11 @@ nvim_terminal: nvim_cmdwin: - CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|. +nvim_swapfile: +- SwapExists: Skips the swapfile prompt (sets |v:swapchoice| to "e") when the + swapfile is owned by a running Nvim process. Shows |W325| "Ignoring + swapfile…" message. + ============================================================================== New Features *nvim-features* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 7f09fc8038..1ba7d6163d 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -1147,11 +1147,28 @@ function vim._init_default_autocmds() end end, }) + vim.api.nvim_create_autocmd({ 'CmdwinEnter' }, { pattern = '[:>]', group = vim.api.nvim_create_augroup('nvim_cmdwin', {}), command = 'syntax sync minlines=1 maxlines=1', }) + + vim.api.nvim_create_autocmd({ 'SwapExists' }, { + pattern = '*', + group = vim.api.nvim_create_augroup('nvim_swapfile', {}), + callback = function() + local info = vim.fn.swapinfo(vim.v.swapname) + local user = vim.uv.os_get_passwd().username + local iswin = 1 == vim.fn.has('win32') + if info.error or info.pid <= 0 or (not iswin and info.user ~= user) then + vim.v.swapchoice = '' -- Show the prompt. + return + end + vim.v.swapchoice = 'e' -- Choose "(E)dit". + vim.notify(('W325: Ignoring swapfile from Nvim process %d'):format(info.pid)) + end, + }) end function vim._init_defaults() diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 55c324d739..5a3a5f3890 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -9312,8 +9312,8 @@ function vim.fn.swapfilelist() end --- user user name --- host host name --- fname original file name ---- pid PID of the Vim process that created the swap ---- file +--- pid PID of the Nvim process that created the swap +--- file, or zero if not running. --- mtime last modification time in seconds --- inode Optional: INODE number of the file --- dirty 1 if file was modified, 0 if not diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 30278bed1b..28fb9c6a5c 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -11123,8 +11123,8 @@ M.funcs = { user user name host host name fname original file name - pid PID of the Vim process that created the swap - file + pid PID of the Nvim process that created the swap + file, or zero if not running. mtime last modification time in seconds inode Optional: INODE number of the file dirty 1 if file was modified, 0 if not diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ee70731c7c..4dd3f193e6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8236,7 +8236,7 @@ static void f_swapfilelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr static void f_swapinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_dict_alloc_ret(rettv); - get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict); + swapfile_dict(tv_get_string(argvars), rettv->vval.v_dict); } /// "swapname(expr)" function diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e4adf9f340..ca98aad6bc 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2491,7 +2491,7 @@ void ex_function(exarg_T *eap) } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) { nextcmd = line_arg; } else if (*p != NUL && *p != '"' && p_verbose > 0) { - give_warning2(_("W22: Text found after :endfunction: %s"), p, true); + swmsg(true, _("W22: Text found after :endfunction: %s"), p); } if (nextcmd != NULL) { // Another command follows. If the line came from "eap" we diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 5898e6aa7d..716d05e27a 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -168,17 +168,15 @@ enum { B0_MAGIC_CHAR = 0x55, }; -// Block zero holds all info about the swap file. This is the first block in -// the file. +// Block zero holds all info about the swapfile. This is the first block in the file. // -// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing -// swap files unusable! +// NOTE: DEFINITION OF BLOCK 0 SHOULD NOT CHANGE! It would make all existing swapfiles unusable! // // If size of block0 changes anyway, adjust MIN_SWAP_PAGE_SIZE in vim.h!! // // This block is built up of single bytes, to make it portable across // different machines. b0_magic_* is used to check the byte order and size of -// variables, because the rest of the swap file is not portable. +// variables, because the rest of the swapfile is not portable. typedef struct { char b0_id[2]; ///< ID for block 0: BLOCK0_ID0 and BLOCK0_ID1. char b0_version[10]; // Vim version string @@ -210,8 +208,7 @@ typedef struct { // EOL_MAC + 1. #define B0_FF_MASK 3 -// Swap file is in directory of edited file. Used to find the file from -// different mount points. +// Swapfile is in directory of edited file. Used to find the file from different mount points. #define B0_SAME_DIR 4 // The 'fileencoding' is at the end of b0_fname[], with a NUL in front of it. @@ -289,14 +286,14 @@ int ml_open(buf_T *buf) buf->b_p_swf = false; } - // When 'updatecount' is non-zero swap file may be opened later. + // When 'updatecount' is non-zero swapfile may be opened later. if (!buf->terminal && p_uc && buf->b_p_swf) { buf->b_may_swap = true; } else { buf->b_may_swap = false; } - // Open the memfile. No swap file is created yet. + // Open the memfile. No swapfile is created yet. memfile_T *mfp = mf_open(NULL, 0); if (mfp == NULL) { goto error; @@ -335,7 +332,7 @@ int ml_open(buf_T *buf) } // Always sync block number 0 to disk, so we can check the file name in - // the swap file in findswapname(). Don't do this for a help files or + // the swapfile in findswapname(). Don't do this for a help files or // a spell buffer though. // Only works when there's a swapfile, otherwise it's done when the file // is created. @@ -386,17 +383,17 @@ error: } /// ml_setname() is called when the file name of "buf" has been changed. -/// It may rename the swap file. +/// It may rename the swapfile. void ml_setname(buf_T *buf) { bool success = false; memfile_T *mfp = buf->b_ml.ml_mfp; - if (mfp->mf_fd < 0) { // there is no swap file yet - // When 'updatecount' is 0 and 'noswapfile' there is no swap file. - // For help files we will make a swap file now. + if (mfp->mf_fd < 0) { // there is no swapfile yet + // When 'updatecount' is 0 and 'noswapfile' there is no swapfile. + // For help files we will make a swapfile now. if (p_uc != 0 && (cmdmod.cmod_flags & CMOD_NOSWAPFILE) == 0) { - ml_open_file(buf); // create a swap file + ml_open_file(buf); // create a swapfile } return; } @@ -423,13 +420,13 @@ void ml_setname(buf_T *buf) success = true; break; } - // need to close the swap file before renaming + // need to close the swapfile before renaming if (mfp->mf_fd >= 0) { close(mfp->mf_fd); mfp->mf_fd = -1; } - // try to rename the swap file + // try to rename the swapfile if (vim_rename(mfp->mf_fname, fname) == 0) { success = true; mf_free_fnames(mfp); @@ -440,10 +437,10 @@ void ml_setname(buf_T *buf) xfree(fname); // this fname didn't work, try another } - if (mfp->mf_fd == -1) { // need to (re)open the swap file + if (mfp->mf_fd == -1) { // need to (re)open the swapfile mfp->mf_fd = os_open(mfp->mf_fname, O_RDWR, 0); if (mfp->mf_fd < 0) { - // could not (re)open the swap file, what can we do???? + // could not (re)open the swapfile, what can we do???? emsg(_("E301: Oops, lost the swap file!!!")); return; } @@ -466,7 +463,7 @@ void ml_open_files(void) } } -/// Open a swap file for an existing memfile, if there is no swap file yet. +/// Open a swapfile for an existing memfile, if there is no swapfile yet. /// If we are unable to find a file name, mf_fname will be NULL /// and the memfile will be in memory only (no recovery possible). void ml_open_file(buf_T *buf) @@ -495,7 +492,7 @@ void ml_open_file(buf_T *buf) if (*dirp == NUL) { break; } - // There is a small chance that between choosing the swap file name + // There is a small chance that between choosing the swapfile name // and creating it, another Vim creates the file. In that case the // creation will fail and we will use another directory. char *fname = findswapname(buf, &dirp, NULL, &found_existing_dir); @@ -514,7 +511,7 @@ void ml_open_file(buf_T *buf) if (mf_sync(mfp, MFS_ZERO) == OK) { // Mark all blocks that should be in the swapfile as dirty. // Needed for when the 'swapfile' option was reset, so that - // the swap file was deleted, and then on again. + // the swapfile was deleted, and then on again. mf_set_dirty(mfp); break; } @@ -531,12 +528,12 @@ void ml_open_file(buf_T *buf) no_wait_return--; } - // don't try to open a swap file again + // don't try to open a swapfile again buf->b_may_swap = false; } -/// If still need to create a swap file, and starting to edit a not-readonly -/// file, or reading into an existing buffer, create a swap file now. +/// If still need to create a swapfile, and starting to edit a not-readonly +/// file, or reading into an existing buffer, create a swapfile now. /// /// @param newfile reading file into new buffer void check_need_swap(bool newfile) @@ -553,7 +550,7 @@ void check_need_swap(bool newfile) /// Close memline for buffer 'buf'. /// -/// @param del_file if true, delete the swap file +/// @param del_file if true, delete the swapfile void ml_close(buf_T *buf, int del_file) { if (buf->b_ml.ml_mfp == NULL) { // not open @@ -643,7 +640,7 @@ static void ml_upd_block0(buf_T *buf, upd_block0_T what) mf_put(mfp, hp, true, false); } -/// Write file name and timestamp into block 0 of a swap file. +/// Write file name and timestamp into block 0 of a swapfile. /// Also set buf->b_mtime. /// Don't use NameBuff[]!!! static void set_b0_fname(ZeroBlock *b0p, buf_T *buf) @@ -695,7 +692,7 @@ static void set_b0_fname(ZeroBlock *b0p, buf_T *buf) add_b0_fenc(b0p, curbuf); } -/// Update the B0_SAME_DIR flag of the swap file. It's set if the file and the +/// Update the B0_SAME_DIR flag of the swapfile. It's set if the file and the /// swapfile for "buf" are in the same directory. /// This is fail safe: if we are not sure the directories are equal the flag is /// not set. @@ -724,27 +721,30 @@ static void add_b0_fenc(ZeroBlock *b0p, buf_T *buf) } } -/// Return true if the process with number "b0p->b0_pid" is still running. -/// "swap_fname" is the name of the swap file, if it's from before a reboot then -/// the result is false; -static bool swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname) +/// Returns the PID of the process that owns the swapfile, if it is running. +/// +/// @param b0p swapfile data +/// @param swap_fname Name of the swapfile. If it's from before a reboot, the result is 0. +/// +/// @return PID, or 0 if process is not running or the swapfile is from before a reboot. +static int swapfile_process_running(const ZeroBlock *b0p, const char *swap_fname) { FileInfo st; double uptime; - // If the system rebooted after when the swap file was written then the + // If the system rebooted after when the swapfile was written then the // process can't be running now. if (os_fileinfo(swap_fname, &st) && uv_uptime(&uptime) == 0 && (Timestamp)st.stat.st_mtim.tv_sec < os_time() - (Timestamp)uptime) { - return false; + return 0; } - return os_proc_running((int)char_to_long(b0p->b0_pid)); + int pid = (int)char_to_long(b0p->b0_pid); + return os_proc_running(pid) ? pid : 0; } /// Try to recover curbuf from the .swp file. /// -/// @param checkext if true, check the extension and detect whether it is a -/// swap file. +/// @param checkext if true, check the extension and detect whether it is a swapfile. void ml_recover(bool checkext) { buf_T *buf = NULL; @@ -766,8 +766,8 @@ void ml_recover(bool checkext) int called_from_main = (curbuf->b_ml.ml_mfp == NULL); int attr = HL_ATTR(HLF_E); - // If the file name ends in ".s[a-w][a-z]" we assume this is the swap file. - // Otherwise a search is done to find the swap file(s). + // If the file name ends in ".s[a-w][a-z]" we assume this is the swapfile. + // Otherwise a search is done to find the swapfile(s). char *fname = curbuf->b_fname; if (fname == NULL) { // When there is no file name fname = ""; @@ -782,17 +782,17 @@ void ml_recover(bool checkext) } else { directly = false; - // count the number of matching swap files + // count the number of matching swapfiles len = recover_names(fname, false, NULL, 0, NULL); - if (len == 0) { // no swap files found + if (len == 0) { // no swapfiles found semsg(_("E305: No swap file found for %s"), fname); goto theend; } int i; - if (len == 1) { // one swap file found, use it + if (len == 1) { // one swapfile found, use it i = 1; - } else { // several swap files found, choose - // list the names of the swap files + } else { // several swapfiles found, choose + // list the names of the swapfiles (void)recover_names(fname, true, NULL, 0, NULL); msg_putchar('\n'); msg_puts(_("Enter number of swap file to use (0 to quit): ")); @@ -801,7 +801,7 @@ void ml_recover(bool checkext) goto theend; } } - // get the swap file name that will be used + // get the swapfile name that will be used (void)recover_names(fname, false, NULL, i, &fname_used); } if (fname_used == NULL) { @@ -812,7 +812,7 @@ void ml_recover(bool checkext) getout(1); } - // Allocate a buffer structure for the swap file that is used for recovery. + // Allocate a buffer structure for the swapfile that is used for recovery. // Only the memline in it is really used. buf = xmalloc(sizeof(buf_T)); @@ -825,7 +825,7 @@ void ml_recover(bool checkext) buf->b_ml.ml_locked = NULL; // no locked block buf->b_ml.ml_flags = 0; - // open the memfile from the old swap file + // open the memfile from the old swapfile p = xstrdup(fname_used); // save "fname_used" for the message: // mf_open() will consume "fname_used"! mfp = mf_open(fname_used, O_RDONLY); @@ -837,7 +837,7 @@ void ml_recover(bool checkext) buf->b_ml.ml_mfp = mfp; // The page size set in mf_open() might be different from the page size - // used in the swap file, we must get it from block 0. But to read block + // used in the swapfile, we must get it from block 0. But to read block // 0 we need a page size. Use the minimal size for block 0 here, it will // be set to the real value below. mfp->mf_page_size = MIN_SWAP_PAGE_SIZE; @@ -910,7 +910,7 @@ void ml_recover(bool checkext) b0p = hp->bh_data; } - // If .swp file name given directly, use name from swap file for buffer. + // If .swp file name given directly, use name from swapfile for buffer. if (directly) { expand_env(b0p->b0_fname, NameBuff, MAXPATHL); if (setfname(curbuf, NameBuff, NULL, true) == FAIL) { @@ -929,7 +929,7 @@ void ml_recover(bool checkext) smsg(0, _("Original file \"%s\""), NameBuff); msg_putchar('\n'); - // check date of swap file and original file + // check date of swapfile and original file FileInfo org_file_info; FileInfo swp_file_info; long mtime = char_to_long(b0p->b0_mtime); @@ -968,7 +968,7 @@ void ml_recover(bool checkext) 0, MAXLNUM, NULL, READ_NEW, false); } - // Use the 'fileformat' and 'fileencoding' as stored in the swap file. + // Use the 'fileformat' and 'fileencoding' as stored in the swapfile. if (b0_ff != 0) { set_fileformat(b0_ff - 1, OPT_LOCAL); } @@ -1231,7 +1231,7 @@ theend: } mf_close(mfp, false); // will also xfree(mfp->mf_fname) } - if (buf != NULL) { // may be NULL if swap file not found. + if (buf != NULL) { // may be NULL if swapfile not found. xfree(buf->b_ml.ml_stack); xfree(buf); } @@ -1243,20 +1243,20 @@ theend: } } -/// Find the names of swap files in current directory and the directory given +/// Find the names of swapfiles in current directory and the directory given /// with the 'directory' option. /// /// Used to: -/// - list the swap files for "vim -r" -/// - count the number of swap files when recovering -/// - list the swap files when recovering -/// - list the swap files for swapfilelist() -/// - find the name of the n'th swap file when recovering +/// - list the swapfiles for "vim -r" +/// - count the number of swapfiles when recovering +/// - list the swapfiles when recovering +/// - list the swapfiles for swapfilelist() +/// - find the name of the n'th swapfile when recovering /// -/// @param fname base for swap file name -/// @param do_list when true, list the swap file names +/// @param fname base for swapfile name +/// @param do_list when true, list the swapfile names /// @param ret_list when not NULL add file names to it -/// @param nr when non-zero, return nr'th swap file name +/// @param nr when non-zero, return nr'th swapfile name /// @param fname_out result when "nr" > 0 int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fname_out) { @@ -1273,7 +1273,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn if (fname != NULL) { #ifdef HAVE_READLINK - // Expand symlink in the file name, because the swap file is created + // Expand symlink in the file name, because the swapfile is created // with the actual file instead of with the symlink. if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; @@ -1342,9 +1342,9 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn num_files = 0; } - // When no swap file found, wildcard expansion might have failed (e.g. + // When no swapfile found, wildcard expansion might have failed (e.g. // not able to execute the shell). - // Try finding a swap file by simply adding ".swp" to the file name. + // Try finding a swapfile by simply adding ".swp" to the file name. if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) { char *swapname = modname(fname_res, ".swp", true); if (swapname != NULL) { @@ -1402,7 +1402,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn if (num_files) { for (int i = 0; i < num_files; i++) { - // print the swap file name + // print the swapfile name msg_outnum(++file_count); msg_puts(". "); msg_puts(path_tail(files[i])); @@ -1456,12 +1456,13 @@ char *make_percent_swname(const char *dir, const char *name) return d; } -static bool process_still_running; +// PID of swapfile owner, or zero if not running. +static int process_running; -/// This is used by the swapinfo() function. +/// For Vimscript "swapinfo()". /// /// @return information found in swapfile "fname" in dictionary "d". -void get_b0_dict(const char *fname, dict_T *d) +void swapfile_dict(const char *fname, dict_T *d) { int fd; ZeroBlock b0; @@ -1482,7 +1483,7 @@ void get_b0_dict(const char *fname, dict_T *d) tv_dict_add_str_len(d, S_LEN("fname"), b0.b0_fname, B0_FNAME_SIZE_ORG); - tv_dict_add_nr(d, S_LEN("pid"), char_to_long(b0.b0_pid)); + tv_dict_add_nr(d, S_LEN("pid"), swapfile_process_running(&b0, fname)); tv_dict_add_nr(d, S_LEN("mtime"), char_to_long(b0.b0_mtime)); tv_dict_add_nr(d, S_LEN("dirty"), b0.b0_dirty ? 1 : 0); tv_dict_add_nr(d, S_LEN("inode"), char_to_long(b0.b0_ino)); @@ -1496,7 +1497,7 @@ void get_b0_dict(const char *fname, dict_T *d) } } -/// Give information about an existing swap file. +/// Loads info from swapfile `fname`, and displays it to the user. /// /// @return timestamp (0 when unknown). static time_t swapfile_info(char *fname) @@ -1509,7 +1510,7 @@ static time_t swapfile_info(char *fname) char uname[B0_UNAME_SIZE]; #endif - // print the swap file date + // print the swapfile date FileInfo file_info; if (os_fileinfo(fname, &file_info)) { #ifdef UNIX @@ -1567,9 +1568,8 @@ static time_t swapfile_info(char *fname) if (char_to_long(b0.b0_pid) != 0L) { msg_puts(_("\n process ID: ")); msg_outnum((int)char_to_long(b0.b0_pid)); - if (swapfile_process_running(&b0, fname)) { + if ((process_running = swapfile_process_running(&b0, fname))) { msg_puts(_(" (STILL RUNNING)")); - process_still_running = true; } } @@ -1589,13 +1589,12 @@ static time_t swapfile_info(char *fname) return x; } -/// @return true if the swap file looks OK and there are no changes, thus it -/// can be safely deleted. +/// @return true if the swapfile looks OK and there are no changes, thus it can be safely deleted. static bool swapfile_unchanged(char *fname) { ZeroBlock b0; - // Swap file must exist. + // Swapfile must exist. if (!os_path_exists(fname)) { return false; } @@ -1653,7 +1652,7 @@ static int recov_file_names(char **names, char *path, int prepend_dot) { int num_names = 0; - // May also add the file name with a dot prepended, for swap file in same + // May also add the file name with a dot prepended, for swapfile in same // dir as original file. if (prepend_dot) { names[num_names] = modname(path, ".sw?", true); @@ -1663,7 +1662,7 @@ static int recov_file_names(char **names, char *path, int prepend_dot) num_names++; } - // Form the normal swap file name pattern by appending ".sw?". + // Form the normal swapfile name pattern by appending ".sw?". names[num_names] = concat_fnames(path, ".sw?", false); if (num_names >= 1) { // check if we have the same name twice char *p = names[num_names - 1]; @@ -1724,7 +1723,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync) /// sync one buffer, including negative blocks /// -/// after this all the blocks are in the swap file +/// after this all the blocks are in the swapfile /// /// Used for the :preserve command and when the original file has been /// changed or deleted. @@ -3132,7 +3131,7 @@ int resolve_symlink(const char *fname, char *buf) } #endif -/// Make swap file name out of the file name and a directory name. +/// Make swapfile name out of the file name and a directory name. /// /// @return pointer to allocated memory or NULL. char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) @@ -3141,7 +3140,7 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) #ifdef HAVE_READLINK char fname_buf[MAXPATHL]; - // Expand symlink in the file name, so that we put the swap file with the + // Expand symlink in the file name, so that we put the swapfile with the // actual file instead of with the symlink. if (resolve_symlink(fname, fname_buf) == OK) { fname_res = fname_buf; @@ -3162,7 +3161,7 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) return r; } - // Prepend a '.' to the swap file name for the current directory. + // Prepend a '.' to the swapfile name for the current directory. char *r = modname(fname_res, ".swp", dir_name[0] == '.' && dir_name[1] == NUL); if (r == NULL) { // out of memory @@ -3174,14 +3173,11 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name) return s; } -/// Get file name to use for swap file or backup file. -/// Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' -/// option "dname". -/// - If "dname" is ".", return "fname" (swap file in dir of file). -/// - If "dname" starts with "./", insert "dname" in "fname" (swap file -/// relative to dir of file). -/// - Otherwise, prepend "dname" to the tail of "fname" (swap file in specific -/// dir). +/// Get file name to use for swapfile or backup file. +/// Use the name of the edited file "fname" and an entry in the 'dir' or 'bdir' option "dname". +/// - If "dname" is ".", return "fname" (swapfile in dir of file). +/// - If "dname" starts with "./", insert "dname" in "fname" (swapfile relative to dir of file). +/// - Otherwise, prepend "dname" to the tail of "fname" (swapfile in specific dir). /// /// The return value is an allocated string and can be NULL. /// @@ -3212,10 +3208,10 @@ char *get_file_in_dir(char *fname, char *dname) return retval; } -/// Print the ATTENTION message: info about an existing swap file. +/// Print the ATTENTION message: info about an existin |