]> granicus.if.org Git - vim/commitdiff
patch 9.0.1007: there is no way to get a list of swap file names v9.0.1007
authorBram Moolenaar <Bram@vim.org>
Mon, 5 Dec 2022 13:50:55 +0000 (13:50 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 5 Dec 2022 13:50:55 +0000 (13:50 +0000)
Problem:    There is no way to get a list of swap file names.
Solution:   Add the swapfilelist() function.  Use it in the test script to
            clean up.  Remove deleting individual swap files.

14 files changed:
runtime/doc/builtin.txt
runtime/doc/usr_41.txt
src/evalfunc.c
src/main.c
src/memline.c
src/proto/memline.pro
src/testdir/runtest.vim
src/testdir/test_suspend.vim
src/testdir/test_swap.vim
src/testdir/test_tagjump.vim
src/testdir/test_tcl.vim
src/testdir/test_termcodes.vim
src/testdir/test_window_cmd.vim
src/version.c

index 1d701379ca1f780322e66d8e790eae154c22e38a..7ae30822057c1d2f18bb03d90bf72447d9d19aa8 100644 (file)
@@ -608,6 +608,7 @@ submatch({nr} [, {list}])   String or List
                                        specific match in ":s" or substitute()
 substitute({expr}, {pat}, {sub}, {flags})
                                String  all {pat} in {expr} replaced with {sub}
+swapfilelist()                 List    swap files found in 'directory'
 swapinfo({fname})              Dict    information about swap file {fname}
 swapname({buf})                        String  swap file of buffer {buf}
 synID({lnum}, {col}, {trans})  Number  syntax ID at {lnum} and {col}
@@ -9314,6 +9315,17 @@ substitute({string}, {pat}, {sub}, {flags})              *substitute()*
                Can also be used as a |method|: >
                        GetString()->substitute(pat, sub, flags)
 
+swapfilelist()                                         *swapfilelist()*
+               Returns a list of swap file names, like what "vim -r" shows.
+               See the |-r| command argument.  The 'directory' option is used
+               for the directories to inspect.  If you only want to get a
+               list of swap files in the current directory then temporarily
+               set 'directory' to a dot: >
+                       let save_dir = &directory
+                       let &directory = '.'
+                       let swapfiles = swapfilelist()
+                       let &directory = save_dir
+
 swapinfo({fname})                                      *swapinfo()*
                The result is a dictionary, which holds information about the
                swapfile {fname}. The available fields are:
index 43a13d9861fa1110c330b409b2aa1d69a7dffc43..850a4c59348436af7780eaea1d9601dab5c161db 100644 (file)
@@ -1031,6 +1031,7 @@ Buffers, windows and the argument list:
        getwininfo()            get a list with window information
        getchangelist()         get a list of change list entries
        getjumplist()           get a list of jump list entries
+       swapfilelist()          list of existing swap files in 'directory'
        swapinfo()              information about a swap file
        swapname()              get the swap file path of a buffer
 
index fa63ab2e2104cfd372624fcc8774ca6b40e93ce6..0b2ba00b6e14521195565f6555592a28250b55ec 100644 (file)
@@ -168,6 +168,7 @@ static void f_split(typval_T *argvars, typval_T *rettv);
 static void f_srand(typval_T *argvars, typval_T *rettv);
 static void f_submatch(typval_T *argvars, typval_T *rettv);
 static void f_substitute(typval_T *argvars, typval_T *rettv);
+static void f_swapfilelist(typval_T *argvars, typval_T *rettv);
 static void f_swapinfo(typval_T *argvars, typval_T *rettv);
 static void f_swapname(typval_T *argvars, typval_T *rettv);
 static void f_synID(typval_T *argvars, typval_T *rettv);
@@ -2579,6 +2580,8 @@ static funcentry_T global_functions[] =
                        ret_string,         f_submatch},
     {"substitute",     4, 4, FEARG_1,      arg4_string_string_any_string,
                        ret_string,         f_substitute},
+    {"swapfilelist",   0, 0, 0,            NULL,
+                       ret_list_string,    f_swapfilelist},
     {"swapinfo",       1, 1, FEARG_1,      arg1_string,
                        ret_dict_any,       f_swapinfo},
     {"swapname",       1, 1, FEARG_1,      arg1_buffer,
@@ -10170,6 +10173,17 @@ f_substitute(typval_T *argvars, typval_T *rettv)
        rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
 }
 
+/*
+ * "swapfilelist()" function
+ */
+    static void
+f_swapfilelist(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    if (rettv_list_alloc(rettv) == FAIL)
+       return;
+    recover_names(NULL, FALSE, rettv->vval.v_list, 0, NULL);
+}
+
 /*
  * "swapinfo(swap_filename)" function
  */
index 477f3d619458aedcf65add15eca6f670beef01a9..41a509d63a4946ae4dc0da6a451f1d74f713cde6 100644 (file)
@@ -507,7 +507,7 @@ vim_main2(void)
      */
     if (recoverymode && params.fname == NULL)
     {
-       recover_names(NULL, TRUE, 0, NULL);
+       recover_names(NULL, TRUE, NULL, 0, NULL);
        mch_exit(0);
     }
 
index 42cbad25e3acc4e27f000e23b1ffa0f1ffacc4fb..16885d3bc4eb0f8357c5f6dc1f88406bc46871a0 100644 (file)
@@ -1208,7 +1208,7 @@ ml_recover(int checkext)
        directly = FALSE;
 
        // count the number of matching swap files
-       len = recover_names(fname, FALSE, 0, NULL);
+       len = recover_names(fname, FALSE, NULL, 0, NULL);
        if (len == 0)               // no swap files found
        {
            semsg(_(e_no_swap_file_found_for_str), fname);
@@ -1219,7 +1219,7 @@ ml_recover(int checkext)
        else                        // several swap files found, choose
        {
            // list the names of the swap files
-           (void)recover_names(fname, TRUE, 0, NULL);
+           (void)recover_names(fname, TRUE, NULL, 0, NULL);
            msg_putchar('\n');
            msg_puts(_("Enter number of swap file to use (0 to quit): "));
            i = get_number(FALSE, NULL);
@@ -1227,7 +1227,7 @@ ml_recover(int checkext)
                goto theend;
        }
        // get the swap file name that will be used
-       (void)recover_names(fname, FALSE, i, &fname_used);
+       (void)recover_names(fname, FALSE, NULL, i, &fname_used);
     }
     if (fname_used == NULL)
        goto theend;                    // out of memory
@@ -1801,12 +1801,14 @@ theend:
  * - 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
  */
     int
 recover_names(
     char_u     *fname,         // base for swap file name
-    int                list,           // when TRUE, list the swap file names
+    int                do_list,        // when TRUE, list the swap file names
+    list_T     *ret_list UNUSED, // when not NULL add file names to it
     int                nr,             // when non-zero, return nr'th swap file name
     char_u     **fname_out)    // result when "nr" > 0
 {
@@ -1817,7 +1819,6 @@ recover_names(
     int                num_files;
     int                file_count = 0;
     char_u     **files;
-    int                i;
     char_u     *dirp;
     char_u     *dir_name;
     char_u     *fname_res = NULL;
@@ -1837,7 +1838,7 @@ recover_names(
            fname_res = fname;
     }
 
-    if (list)
+    if (do_list)
     {
        // use msg() to start the scrolling properly
        msg(_("Swap files found:"));
@@ -1938,7 +1939,7 @@ recover_names(
        }
 
        // check for out-of-memory
-       for (i = 0; i < num_names; ++i)
+       for (int i = 0; i < num_names; ++i)
        {
            if (names[i] == NULL)
            {
@@ -1987,12 +1988,14 @@ recover_names(
        }
 
        /*
-        * remove swapfile name of the current buffer, it must be ignored
+        * Remove swapfile name of the current buffer, it must be ignored.
+        * But keep it for swapfilelist().
         */
        if (curbuf->b_ml.ml_mfp != NULL
-                              && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
+                              && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL
+                              && ret_list == NULL)
        {
-           for (i = 0; i < num_files; ++i)
+           for (int i = 0; i < num_files; ++i)
                // Do not expand wildcards, on windows would try to expand
                // "%tmp%" in "%tmp%file".
                if (fullpathcmp(p, files[i], TRUE, FALSE) & FPC_SAME)
@@ -2018,7 +2021,7 @@ recover_names(
                dirp = (char_u *)"";                // stop searching
            }
        }
-       else if (list)
+       else if (do_list)
        {
            if (dir_name[0] == '.' && dir_name[1] == NUL)
            {
@@ -2036,7 +2039,7 @@ recover_names(
 
            if (num_files)
            {
-               for (i = 0; i < num_files; ++i)
+               for (int i = 0; i < num_files; ++i)
                {
                    // print the swap file name
                    msg_outnum((long)++file_count);
@@ -2050,10 +2053,24 @@ recover_names(
                msg_puts(_("      -- none --\n"));
            out_flush();
        }
+#ifdef FEAT_EVAL
+       else if (ret_list != NULL)
+       {
+           for (int i = 0; i < num_files; ++i)
+           {
+               char_u *name = concat_fnames(dir_name, files[i], TRUE);
+               if (name != NULL)
+               {
+                   list_append_string(ret_list, name, -1);
+                   vim_free(name);
+               }
+           }
+       }
+#endif
        else
            file_count += num_files;
 
-       for (i = 0; i < num_names; ++i)
+       for (int i = 0; i < num_names; ++i)
            vim_free(names[i]);
        if (num_files > 0)
            FreeWild(num_files, files);
index 364f0aae2f8b31b1b0b0df58f465605ee9a8a4dd..3fa8707d80f03291820e847ae17a8f7e7c0636d5 100644 (file)
@@ -10,7 +10,7 @@ void ml_close_all(int del_file);
 void ml_close_notmod(void);
 void ml_timestamp(buf_T *buf);
 void ml_recover(int checkext);
-int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
+int recover_names(char_u *fname, int do_list, list_T *ret_list, int nr, char_u **fname_out);
 char_u *make_percent_swname(char_u *dir, char_u *name);
 void get_b0_dict(char_u *fname, dict_T *d);
 void ml_sync_all(int check_file, int check_char);
index e1d999912cc0ea873327247d00a20544c8561105..2eabb1a9cb0a351b90e525a1407f5c6c58871956 100644 (file)
@@ -160,6 +160,14 @@ if has('mac')
   let $BASH_SILENCE_DEPRECATION_WARNING = 1
 endif
 
+
+" A previous (failed) test run may have left swap files behind.  Delete them
+" before running tests again, they might interfere.
+for name in s:GetSwapFileList()
+  call delete(name)
+endfor
+
+
 " Prepare for calling test_garbagecollect_now().
 let v:testing = 1
 
@@ -186,6 +194,22 @@ if has('reltime')
   let g:func_start = reltime()
 endif
 
+" Get the list of swap files in the current directory.
+func s:GetSwapFileList()
+  let save_dir = &directory
+  let &directory = '.'
+  let files = swapfilelist()
+  let &directory = save_dir
+
+  " remove a match with runtest.vim
+  let idx = indexof(files, 'v:val =~ "runtest.vim."')
+  if idx >= 0
+    call remove(files, idx)
+  endif
+
+  return files
+endfunc
+
 " Invoked when a test takes too much time.
 func TestTimeout(id)
   split test.log
@@ -339,6 +363,16 @@ func RunTheTest(test)
   endif
   call add(s:messages, message)
   let s:done += 1
+
+  " Check if the test has left any swap files behind.  Delete them before
+  " running tests again, they might interfere.
+  let swapfiles = s:GetSwapFileList()
+  if len(swapfiles) > 0
+    call add(s:messages, "Found swap files: " .. string(swapfiles))
+    for name in swapfiles
+      call delete(name)
+    endfor
+  endif
 endfunc
 
 func AfterTheTest(func_name)
index c96a1a6a8f446489ac7cd5efb37fb6e3de56ec19..7538c8042e3daf3167bfcd35100e98c2e87670a2 100644 (file)
@@ -28,9 +28,6 @@ func Test_suspend()
     sleep 150m
   endif
 
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   let buf = term_start('/bin/sh')
   " Wait for shell prompt.
   call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
@@ -69,7 +66,6 @@ func Test_suspend()
 
   exe buf . 'bwipe!'
   call delete('Xfoo')
-  call delete('.Xfoo.swp')
 endfunc
 
 func Test_suspend_autocmd()
@@ -82,9 +78,6 @@ func Test_suspend_autocmd()
     sleep 150m
   endif
 
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   let buf = term_start('/bin/sh', #{term_rows: 6})
   " Wait for shell prompt.
   call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
@@ -123,7 +116,6 @@ func Test_suspend_autocmd()
 
   exe buf . 'bwipe!'
   call delete('Xfoo')
-  call delete('.Xfoo.swp')
 endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
index 5237edcfb4c4a1e101248a59d221e4b2157cd76e..c776ca57ce952b39ff93f0dcf2eec5e4a50b6dd5 100644 (file)
@@ -110,6 +110,15 @@ func Test_swapinfo()
   w
   let fname = s:swapname()
   call assert_match('Xswapinfo', fname)
+
+  let nr = 0
+  for name in swapfilelist()
+    if name =~ '[\\/]' .. fname .. '$'
+      let nr += 1
+    endif
+  endfor
+  call assert_equal(1, nr)
+
   let info = fname->swapinfo()
 
   let ver = printf('VIM %d.%d', v:version / 100, v:version % 100)
index 2c720a5b49aabcd9371e098288d4f5ae87df84aa..5185b20b77aa29720f104cd3e3b3a86123111016 100644 (file)
@@ -733,9 +733,6 @@ endfunc
 
 " Tests for guessing the tag location
 func Test_tag_guess()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile(["!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "func1\tXfoo\t/^int func1(int x)/",
         \ "func2\tXfoo\t/^int func2(int y)/",
@@ -772,9 +769,6 @@ endfunc
 
 " Test for an unsorted tags file
 func Test_tag_sort()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   let l = [
         \ "first\tXfoo\t1",
         \ "ten\tXfoo\t3",
@@ -802,9 +796,6 @@ endfunc
 
 " Test for an unsorted tags file
 func Test_tag_fold()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "!_TAG_FILE_SORTED\t2\t/0=unsorted, 1=sorted, 2=foldcase/",
@@ -831,9 +822,6 @@ endfunc
 
 " Test for the :ltag command
 func Test_ltag()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo\t1",
@@ -871,9 +859,6 @@ endfunc
 " Test for setting the last search pattern to the tag search pattern
 " when cpoptions has 't'
 func Test_tag_last_search_pat()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo\t/^int first() {}/",
@@ -902,9 +887,6 @@ endfunc
 
 " Tag stack tests
 func Test_tag_stack()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   let l = []
   for i in range(10, 31)
     let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"]
@@ -967,9 +949,6 @@ endfunc
 
 " Test for browsing multiple matching tags
 func Test_tag_multimatch()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo\t1",
@@ -1015,9 +994,6 @@ endfunc
 
 " Test for previewing multiple matching tags
 func Test_preview_tag_multimatch()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo\t1",
@@ -1066,9 +1042,6 @@ endfunc
 
 " Test for jumping to multiple matching tags across multiple :tags commands
 func Test_tnext_multimatch()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo1\t1",
@@ -1096,9 +1069,6 @@ endfunc
 
 " Test for jumping to multiple matching tags in non-existing files
 func Test_multimatch_non_existing_files()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo1\t1",
@@ -1116,9 +1086,6 @@ func Test_multimatch_non_existing_files()
 endfunc
 
 func Test_tselect_listing()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   call writefile([
         \ "!_TAG_FILE_ENCODING\tutf-8\t//",
         \ "first\tXfoo\t1" .. ';"' .. "\tv\ttyperef:typename:int\tfile:",
@@ -1500,9 +1467,6 @@ endfunc
 
 " Test for 'tagbsearch' (binary search)
 func Test_tagbsearch()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   " If a tags file header says the tags are sorted, but the tags are actually
   " unsorted, then binary search should fail and linear search should work.
   call writefile([
index 03cae0906e9c26554e1d7116bf858645028680c8..4c6537fd759872e151528452c964de6317dd412d 100644 (file)
@@ -638,9 +638,6 @@ endfunc
 
 " Test $buf delcmd {cmd} (command executed when buffer is deleted)
 func Test_buffer_delcmd()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   new Xfoo
   split
   tcl $::vim::current(buffer) delcmd [list set msg "buffer deleted"]
index 2cb20e046c745bb225c62048c5f96d16ab393c26..dd5280fba06996aa26e151ac373d1ffcc596833c 100644 (file)
@@ -665,9 +665,6 @@ func Test_term_mouse_click_tab()
   set mouse=a term=xterm
   call WaitForResponses()
 
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   let row = 1
 
   for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
index 9a042c3ca866cdc48f8c86dc9f3455b415893a9f..0a4ae493e8999ccb0e8fa652870a432d590ef4d1 100644 (file)
@@ -137,9 +137,6 @@ endfunc
 
 " Test the ":wincmd ^" and "<C-W>^" commands.
 func Test_window_split_edit_alternate()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   " Test for failure when the alternate buffer/file no longer exists.
   edit Xfoo | %bw
   call assert_fails(':wincmd ^', 'E23:')
@@ -172,9 +169,6 @@ endfunc
 
 " Test the ":[count]wincmd ^" and "[count]<C-W>^" commands.
 func Test_window_split_edit_bufnr()
-  " in case a previous failure left a swap file behind
-  call delete('.Xfoo.swp')
-
   %bwipeout
   let l:nr = bufnr('%') + 1
   call assert_fails(':execute "normal! ' . l:nr . '\<C-W>\<C-^>"', 'E92:')
index 9f400f232230113c449602c229de3cbee0e574a8..4a15f431e0fa0ba99f52c1343b60f181f8b150b6 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1007,
 /**/
     1006,
 /**/