To: vim_dev@googlegroups.com Subject: Patch 9.0.1007 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 "^" 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]^" 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 . '\\"', '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 -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///