vimwiki

Personal wiki for vim
git clone https://github.com/vimwiki/vimwiki.git
Log | Files | Refs | README | LICENSE

commit 369a64cdc830526d40669fd319b09056f0b1fc4c
parent e785c6f5b4c946eba940d630c208311f574c5c5c
Author: Tinmarino <tinmarino@gmail.com>
Date:   Wed, 29 Jul 2020 00:37:44 -0400

Feature: VimwikiRenameFile 1/ to other dir 2/ take argument (completable) (Issue #926)

Diffstat:
Mautoload/vimwiki/base.vim | 130++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mftplugin/vimwiki.vim | 3++-
Mtest/command_rename_link.vader | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 173 insertions(+), 38 deletions(-)

diff --git a/autoload/vimwiki/base.vim b/autoload/vimwiki/base.vim @@ -1043,6 +1043,7 @@ endfunction " Update link for all files in dir " Param: old_url, new_url: path of the old, new url relative to ... " Param: dir: directory of the files, relative to wiki_root +" Called: rename_link function! s:update_wiki_links(wiki_nr, dir, old_url, new_url) abort " Get list of wiki files let wiki_root = vimwiki#vars#get_wikilocal('path', a:wiki_nr) @@ -1055,9 +1056,13 @@ function! s:update_wiki_links(wiki_nr, dir, old_url, new_url) abort let cache_dict = {} " Regex from path - function! s:compute_old_url_r(wiki_nr, dir_rel_fsource, old_url) abort - " Old url - let old_url_r = a:dir_rel_fsource . a:old_url + " Param: wiki_nr <int> to get the syntax template + " Param: old_location <string> relative to the current wiki fsource + function! s:compute_old_url_r(wiki_nr, old_location) abort + " Start, Read param + let old_url_r = a:old_location + " Escape the '\\/' + let old_url_r = escape(old_url_r, '\/') " Add potential ./ let old_url_r = '\%(\.[/\\]\)\?' . old_url_r " Compute old url regex with filename between \zs and \ze @@ -1087,14 +1092,14 @@ function! s:update_wiki_links(wiki_nr, dir, old_url, new_url) abort endif " New url - let new_url = dir_rel_fsource . a:new_url + let new_url = simplify(dir_rel_fsource . a:new_url) " Old url " Avoid E713 let key = empty(dir_rel_fsource) ? 'NaF' : dir_rel_fsource if index(keys(cache_dict), key) == -1 let cache_dict[key] = s:compute_old_url_r( - \ a:wiki_nr, dir_rel_fsource, a:old_url) + \ a:wiki_nr, dir_rel_fsource . a:old_url) endif let old_url_r = cache_dict[key] @@ -1536,57 +1541,84 @@ function! vimwiki#base#delete_link() abort endfunction -" Rename current file, update all links to it -function! vimwiki#base#rename_link() abort - " Get filename relative to wiki root - let subdir = vimwiki#vars#get_bufferlocal('subdir') - let old_fname = subdir.expand('%:t') - - " Get current path - let old_dir = expand('%:p:h') - - " there is no file (new one maybe) - if glob(expand('%:p')) ==? '' - echomsg 'Vimwiki Error: Cannot rename "'.expand('%:p'). - \'". It does not exist! (New file? Save it before renaming.)' - return - endif - +" Ask user for a new filepath +" Returns: '' if fails +" Called: rename_link +function! s:input_rename_link() abort + " Ask confirmation let val = input('Rename "'.expand('%:t:r').'" [y]es/[N]o? ') if val !~? '^y' return endif + " Ask new name let new_link = input('Enter new name: ') + " Guard: Check link if new_link =~# '[/\\]' echomsg 'Vimwiki Error: Cannot rename to a filename with path!' return endif - if substitute(new_link, '\s', '', 'g') ==? '' echomsg 'Vimwiki Error: Cannot rename to an empty filename!' return endif + " Check if new file well formed let url = matchstr(new_link, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl')) if url !=? '' - let new_link = url + return url endif + return new_link +endfunction + + +" Rename current file, update all links to it +" Param: [new_filepath <string>] +function! vimwiki#base#rename_link(...) abort + " Get filename and dir relative to wiki root + let subdir = vimwiki#vars#get_bufferlocal('subdir') + " Get old file directory relative to current path + let old_dir = expand('%:p:h') + let old_fname = subdir.expand('%:t') + let wikiroot_path = vimwiki#vars#get_wikilocal('path') + + " Clause: Check if there current buffer is a file (new buffer maybe) + if glob(expand('%:p')) ==? '' + echomsg 'Vimwiki Error: Cannot rename "'.expand('%:p'). + \'". Current file does not exist! (New file? Save it before renaming.)' + return + endif + + " Read new_link <- command line || input() + let new_link = a:0 > 0 ? a:1 : s:input_rename_link() + if new_link ==# '' | return | endif + let new_link = subdir.new_link let wiki_nr = vimwiki#vars#get_bufferlocal('wiki_nr') - let new_fname = vimwiki#vars#get_wikilocal('path') . new_link . vimwiki#vars#get_wikilocal('ext') + let new_fname = simplify(wikiroot_path . new_link . vimwiki#vars#get_wikilocal('ext')) - " do not rename if file with such name exists + " Guard: Do not rename if file with such name exists let fname = glob(new_fname) if fname !=? '' echomsg 'Vimwiki Error: Cannot rename to "'.new_fname.'". File with that name exist!' return endif - " rename wiki link file + + " TODO Check new_file is in a wiki dir and warn user if not + " Create new directory if needed + let new_dir = fnamemodify(new_fname, ':h') + if exists('*mkdir') + " Sometimes complaining E739 if directory exists + try + call mkdir(new_dir, 'p') + catch | endtry + endif + + " Rename wiki link file try - echomsg 'Vimwiki: Renaming '.vimwiki#vars#get_wikilocal('path').old_fname.' to '.new_fname + echomsg 'Vimwiki: Renaming '.wikiroot_path.old_fname.' to '.new_fname let res = rename(expand('%:p'), expand(new_fname)) if res != 0 throw 'Cannot rename!' @@ -1598,11 +1630,13 @@ function! vimwiki#base#rename_link() abort let &buftype='nofile' + " Save current buffer: [file_name, buffer_name] let cur_buffer = [expand('%:p'), vimwiki#vars#get_bufferlocal('prev_links')] + " Get all wiki buffer let blist = s:get_wiki_buffers() - " save wiki buffers + " Save wiki buffers for bitem in blist execute ':b '.escape(bitem[0], ' ') execute ':update' @@ -1610,30 +1644,39 @@ function! vimwiki#base#rename_link() abort execute ':b '.escape(cur_buffer[0], ' ') - " remove wiki buffers + " Remove wiki buffers for bitem in blist execute 'bwipeout '.escape(bitem[0], ' ') endfor - let setting_more = &more + let more_save = &more setlocal nomore - " update links - call s:update_wiki_links(wiki_nr, old_dir, s:tail_name(old_fname), s:tail_name(new_fname)) - - " restore wiki buffers + " Update links + let old_fname_abs = wikiroot_path . old_fname + let old_fname_rel_dir = vimwiki#path#relpath(old_dir, old_fname_abs) + let new_fname_rel_dir = vimwiki#path#relpath(old_dir, new_fname) + call s:update_wiki_links( + \ wiki_nr, old_dir, + \ fnamemodify(old_fname_rel_dir, ':r'), + \ fnamemodify(new_fname_rel_dir, ':r') + \ ) + + " Restore wiki buffers for bitem in blist if !vimwiki#path#is_equal(bitem[0], cur_buffer[0]) call s:open_wiki_buffer(bitem) endif endfor + " Open the new buffer call s:open_wiki_buffer([new_fname, cur_buffer[1]]) " execute 'bwipeout '.escape(cur_buffer[0], ' ') + " Log success echomsg 'Vimwiki: '.old_fname.' is renamed to '.new_fname - let &more = setting_more + let &more = more_save endfunction @@ -2442,6 +2485,23 @@ function! vimwiki#base#complete_links_escaped(ArgLead, CmdLine, CursorPos) abort endfunction +" Complete filename relatie to current file +" Called: rename_link +function! vimwiki#base#complete_file(ArgLead, CmdLine, CursorPos) abort + " Start from current file + let base_path = expand('%:h') + + " Get every file you can + let completion_pattern = base_path . '/' . a:ArgLead . '*' + let completion_list = split(glob(completion_pattern), '\n') + + " Remove base_path prefix from the result + let base_len = len(base_path) + let completion_list = map(completion_list, 'v:val[base_len+1:]') + return completion_list +endfunction + + " Read caption " Called: by generate_links function! vimwiki#base#read_caption(file) abort diff --git a/ftplugin/vimwiki.vim b/ftplugin/vimwiki.vim @@ -264,7 +264,8 @@ command! -buffer VimwikiDeleteFile call vimwiki#base#delete_link() command! -buffer VimwikiDeleteLink \ call vimwiki#base#deprecate("VimwikiDeleteLink", "VimwikiDeleteFile") | \ call vimwiki#base#delete_link() -command! -buffer VimwikiRenameFile call vimwiki#base#rename_link() +command! -buffer -nargs=? -complete=customlist,vimwiki#base#complete_file + \ VimwikiRenameFile call vimwiki#base#rename_link(<f-args>) command! -buffer VimwikiRenameLink \ call vimwiki#base#deprecate("VimwikiRenameLink", "VimwikiRenameFile") | \ call vimwiki#base#rename_link() diff --git a/test/command_rename_link.vader b/test/command_rename_link.vader @@ -1,6 +1,9 @@ Include: vader_includes/vader_setup.vader +# Create directories I remove at end {{{1 +########################################## + Execute (Copy Wiki's Resources): Log "Start: Copy Resources" call CopyResources() @@ -13,6 +16,74 @@ Execute (Mkdir dir1 dir2 dir11 dir12): call system("mkdir $HOME/testmarkdown/dir2") +# Test Transdirectory and argument {{{1 +# New feature #926 + +# Create smaller unit {{{2 + +# we stick all along with these 3 files, +# Follow them ! +Execute (Create 3 files): + edit $HOME/testmarkdown/Test-Rename-zzz.md + call WriteMe() + edit $HOME/testmarkdown/dir1/dir11/Test-Rename.md + call WriteMe() + edit $HOME/testmarkdown/Test-Rename-Completion.md + call WriteMe() + +Do (Testing Completion {{{2): +# Rename and test (zzz) + :VimwikiRenameFile Test-Rename-z\<C-l>1\<Cr> + :AssertEqual $HOME . '/testmarkdown/Test-Rename-zzz1.md', expand('%')\<CR>\<Esc> +# Restore old name + :call WriteMe()\<Cr> + :VimwikiRenameFile Test-Rename-zzz\<Cr> + + +Do (Testing transforward {{{2): + :Log 'Forward: root -> dir1/dir11 {{{3'\<Cr> +# Create dir1/dir11/Test-Rename and link to it + :edit $HOME/testmarkdown/Test-Rename-Completion.md\<Cr> + idir1/dir11/Test-Rename.md\<Esc> + \<Cr>\<Cr> + :VimwikiRenameFile ../Test-Rename-2\<Cr> + :AssertEqual expand('%'), $HOME . '/testmarkdown/dir1/Test-Rename-2.md'\<CR>\<Esc> + +# See what happend in root + :call WriteMe()\<Cr> + :edit $HOME/testmarkdown/Test-Rename-Completion.md\<Cr> + :AssertEqual getline(1), '[dir1 dir11 Test Rename](dir1/Test-Rename-2.md)'\<Cr> + + :Log 'Backward dir1/dir11 -> root {{{3'\<Cr> +# See what happend in dir1/dir11 +# I am in root so pressing Enter sends me to dir1/dir11 + \<Cr> +# Write forward path + dd + i../Test-Rename-Completion\<Esc> +# Convert it to link + 0\<Cr>\<Cr> + +# Now in root + :AssertEqual expand('%'), $HOME . '/testmarkdown/Test-Rename-Completion.md'\<Cr> + :VimwikiRenameFile dir1/Test-Rename-Completion-2\<Cr> + :AssertEqual expand('%'), $HOME . '/testmarkdown/dir1/Test-Rename-Completion-2.md'\<Cr> + +# Delete smaller unit changed {{{2 + +Execute (Clean): + call DeleteFile('$HOME/testmarkdown/Test-Rename-zzz.md') + call DeleteFile('$HOME/testmarkdown/dir1/Test-Rename-Completion_2.md') + call DeleteFile('$HOME/testmarkdown/dir1/Test-Rename-2.md') + + +# VimwikiRename Test same directory {{{1 +# Old big conf, from bad unit test design +# Changing file in a single dir +# Feel free to modify but as long as it works +# I delay the cleaning +#################################### + Given vimwiki (Void): @@ -86,7 +157,10 @@ Execute (Fill in_dir11 content): call WriteMe() -Do (RenameLink in_dir11 -> new_dir11): +# Rename local {{{1 +################### + +Do (RenameLink in_dir11 -> in_dir11_new): :edit $HOME/testmarkdown/dir1/dir11/in_dir11.md\<CR> :AssertEqual 'file ' . $HOME . '/testmarkdown/dir1/dir11/in_dir11.md', 'file ' . expand('%')\<CR> :AssertEqual 1, vimwiki#vars#get_bufferlocal('wiki_nr')\<CR> @@ -185,4 +259,4 @@ Execute (Clean dir1 and dir2): Include: vader_includes/vader_teardown.vader -# vim: sw=2 foldmethod=indent foldlevel=30 foldignore=# +# vim: sw=2 foldmethod=marker foldlevel=30 foldignore=#