Patch 9.0.1007
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.
Files:      runtime/doc/builtin.txt, runtime/doc/usr_41.txt, src/evalfunc.c,
            src/memline.c, src/proto/memline.pro, src/main.c,
            src/testdir/test_swap.vim, src/testdir/runtest.vim,
            src/testdir/test_suspend.vim, src/testdir/test_tagjump.vim,
            src/testdir/test_tcl.vim, src/testdir/test_termcodes.vim,
            src/testdir/test_window_cmd.vim


*** ../vim-9.0.1006/runtime/doc/builtin.txt     2022-11-21 19:56:59.399412740 
+0000
--- runtime/doc/builtin.txt     2022-12-05 10:43:33.565547435 +0000
***************
*** 608,613 ****
--- 608,614 ----
                                        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}
***************
*** 9300,9305 ****
--- 9315,9331 ----
                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:
*** ../vim-9.0.1006/runtime/doc/usr_41.txt      2022-11-21 19:56:59.403412744 
+0000
--- runtime/doc/usr_41.txt      2022-12-05 10:44:11.725407324 +0000
***************
*** 1030,1035 ****
--- 1031,1037 ----
        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
  
*** ../vim-9.0.1006/src/evalfunc.c      2022-12-02 13:37:32.886620865 +0000
--- src/evalfunc.c      2022-12-05 10:50:20.488368596 +0000
***************
*** 168,173 ****
--- 168,174 ----
  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,2584 ****
--- 2580,2587 ----
                        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,
***************
*** 10171,10176 ****
--- 10174,10190 ----
  }
  
  /*
+  * "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
   */
      static void
*** ../vim-9.0.1006/src/memline.c       2022-08-31 14:46:07.911016920 +0100
--- src/memline.c       2022-12-05 11:09:12.694715729 +0000
***************
*** 1208,1214 ****
        directly = FALSE;
  
        // count the number of matching swap files
!       len = recover_names(fname, FALSE, 0, NULL);
        if (len == 0)               // no swap files found
        {
            semsg(_(e_no_swap_file_found_for_str), fname);
--- 1208,1214 ----
        directly = FALSE;
  
        // count the number of matching swap files
!       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,1225 ****
        else                        // several swap files found, choose
        {
            // list the names of the swap files
!           (void)recover_names(fname, TRUE, 0, NULL);
            msg_putchar('\n');
            msg_puts(_("Enter number of swap file to use (0 to quit): "));
            i = get_number(FALSE, NULL);
--- 1219,1225 ----
        else                        // several swap files found, choose
        {
            // list the names of the swap files
!           (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,1233 ****
                goto theend;
        }
        // get the swap file name that will be used
!       (void)recover_names(fname, FALSE, i, &fname_used);
      }
      if (fname_used == NULL)
        goto theend;                    // out of memory
--- 1227,1233 ----
                goto theend;
        }
        // get the swap file name that will be used
!       (void)recover_names(fname, FALSE, NULL, i, &fname_used);
      }
      if (fname_used == NULL)
        goto theend;                    // out of memory
***************
*** 1801,1812 ****
   * - list the swap files for "vim -r"
   * - count the number of swap files when recovering
   * - list the swap files when recovering
   * - 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               nr,             // when non-zero, return nr'th swap 
file name
      char_u    **fname_out)    // result when "nr" > 0
  {
--- 1801,1814 ----
   * - 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               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,1823 ****
      int               num_files;
      int               file_count = 0;
      char_u    **files;
-     int               i;
      char_u    *dirp;
      char_u    *dir_name;
      char_u    *fname_res = NULL;
--- 1819,1824 ----
***************
*** 1837,1843 ****
            fname_res = fname;
      }
  
!     if (list)
      {
        // use msg() to start the scrolling properly
        msg(_("Swap files found:"));
--- 1838,1844 ----
            fname_res = fname;
      }
  
!     if (do_list)
      {
        // use msg() to start the scrolling properly
        msg(_("Swap files found:"));
***************
*** 1938,1944 ****
        }
  
        // check for out-of-memory
!       for (i = 0; i < num_names; ++i)
        {
            if (names[i] == NULL)
            {
--- 1939,1945 ----
        }
  
        // check for out-of-memory
!       for (int i = 0; i < num_names; ++i)
        {
            if (names[i] == NULL)
            {
***************
*** 1987,1998 ****
        }
  
        /*
!        * remove swapfile name of the current buffer, it must be ignored
         */
        if (curbuf->b_ml.ml_mfp != NULL
!                              && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
        {
!           for (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)
--- 1988,2001 ----
        }
  
        /*
!        * 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
!                              && ret_list == NULL)
        {
!           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,2024 ****
                dirp = (char_u *)"";                // stop searching
            }
        }
!       else if (list)
        {
            if (dir_name[0] == '.' && dir_name[1] == NUL)
            {
--- 2021,2027 ----
                dirp = (char_u *)"";                // stop searching
            }
        }
!       else if (do_list)
        {
            if (dir_name[0] == '.' && dir_name[1] == NUL)
            {
***************
*** 2036,2042 ****
  
            if (num_files)
            {
!               for (i = 0; i < num_files; ++i)
                {
                    // print the swap file name
                    msg_outnum((long)++file_count);
--- 2039,2045 ----
  
            if (num_files)
            {
!               for (int i = 0; i < num_files; ++i)
                {
                    // print the swap file name
                    msg_outnum((long)++file_count);
***************
*** 2050,2059 ****
                msg_puts(_("      -- none --\n"));
            out_flush();
        }
        else
            file_count += num_files;
  
!       for (i = 0; i < num_names; ++i)
            vim_free(names[i]);
        if (num_files > 0)
            FreeWild(num_files, files);
--- 2053,2076 ----
                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 (int i = 0; i < num_names; ++i)
            vim_free(names[i]);
        if (num_files > 0)
            FreeWild(num_files, files);
*** ../vim-9.0.1006/src/proto/memline.pro       2022-06-27 23:15:15.000000000 
+0100
--- src/proto/memline.pro       2022-12-05 10:56:40.935666007 +0000
***************
*** 10,16 ****
  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);
  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);
--- 10,16 ----
  void ml_close_notmod(void);
  void ml_timestamp(buf_T *buf);
  void ml_recover(int checkext);
! 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);
*** ../vim-9.0.1006/src/main.c  2022-12-01 12:03:42.263227523 +0000
--- src/main.c  2022-12-05 10:50:30.320346862 +0000
***************
*** 507,513 ****
       */
      if (recoverymode && params.fname == NULL)
      {
!       recover_names(NULL, TRUE, 0, NULL);
        mch_exit(0);
      }
  
--- 507,513 ----
       */
      if (recoverymode && params.fname == NULL)
      {
!       recover_names(NULL, TRUE, NULL, 0, NULL);
        mch_exit(0);
      }
  
*** ../vim-9.0.1006/src/testdir/test_swap.vim   2022-10-10 22:39:38.207545888 
+0100
--- src/testdir/test_swap.vim   2022-12-05 11:10:18.894644423 +0000
***************
*** 110,115 ****
--- 110,124 ----
    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)
*** ../vim-9.0.1006/src/testdir/runtest.vim     2022-09-23 20:25:52.160091657 
+0100
--- src/testdir/runtest.vim     2022-12-05 13:01:42.873483221 +0000
***************
*** 160,165 ****
--- 160,173 ----
    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,191 ****
--- 194,215 ----
    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,344 ****
--- 363,378 ----
    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)
*** ../vim-9.0.1006/src/testdir/test_suspend.vim        2022-12-04 
23:30:15.934615162 +0000
--- src/testdir/test_suspend.vim        2022-12-05 13:12:13.105961130 +0000
***************
*** 28,36 ****
      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, '.'))})
--- 28,33 ----
***************
*** 69,75 ****
  
    exe buf . 'bwipe!'
    call delete('Xfoo')
-   call delete('.Xfoo.swp')
  endfunc
  
  func Test_suspend_autocmd()
--- 66,71 ----
***************
*** 82,90 ****
      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, '.'))})
--- 78,83 ----
***************
*** 123,129 ****
  
    exe buf . 'bwipe!'
    call delete('Xfoo')
-   call delete('.Xfoo.swp')
  endfunc
  
  " vim: shiftwidth=2 sts=2 expandtab
--- 116,121 ----
*** ../vim-9.0.1006/src/testdir/test_tagjump.vim        2022-12-04 
23:00:37.782742180 +0000
--- src/testdir/test_tagjump.vim        2022-12-05 13:13:29.429988257 +0000
***************
*** 733,741 ****
  
  " 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)/",
--- 733,738 ----
***************
*** 772,780 ****
  
  " 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",
--- 769,774 ----
***************
*** 802,810 ****
  
  " 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/",
--- 796,801 ----
***************
*** 831,839 ****
  
  " 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",
--- 822,827 ----
***************
*** 871,879 ****
  " 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() {}/",
--- 859,864 ----
***************
*** 902,910 ****
  
  " 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 .. ";$/"]
--- 887,892 ----
***************
*** 967,975 ****
  
  " 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",
--- 949,954 ----
***************
*** 1015,1023 ****
  
  " 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",
--- 994,999 ----
***************
*** 1066,1074 ****
  
  " 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",
--- 1042,1047 ----
***************
*** 1096,1104 ****
  
  " 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",
--- 1069,1074 ----
***************
*** 1116,1124 ****
  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:",
--- 1086,1091 ----
***************
*** 1500,1508 ****
  
  " 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([
--- 1467,1472 ----
*** ../vim-9.0.1006/src/testdir/test_tcl.vim    2022-12-04 23:00:37.782742180 
+0000
--- src/testdir/test_tcl.vim    2022-12-05 13:13:40.065991717 +0000
***************
*** 638,646 ****
  
  " 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"]
--- 638,643 ----
*** ../vim-9.0.1006/src/testdir/test_termcodes.vim      2022-12-04 
23:00:37.782742180 +0000
--- src/testdir/test_termcodes.vim      2022-12-05 13:14:00.909998305 +0000
***************
*** 665,673 ****
    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
--- 665,670 ----
*** ../vim-9.0.1006/src/testdir/test_window_cmd.vim     2022-12-04 
23:00:37.782742180 +0000
--- src/testdir/test_window_cmd.vim     2022-12-05 13:14:26.366005977 +0000
***************
*** 137,145 ****
  
  " 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:')
--- 137,142 ----
***************
*** 172,180 ****
  
  " 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:')
--- 169,174 ----
*** ../vim-9.0.1006/src/version.c       2022-12-04 23:30:15.934615162 +0000
--- src/version.c       2022-12-05 10:42:55.413695572 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1007,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
233. You start dreaming about web pages...in html.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221205135129.826A91C1D84%40moolenaar.net.

Raspunde prin e-mail lui